Skip to content

Commit 6ea93b8

Browse files
author
Test User
committed
fix: addressing code review comments:
* Fixed _upload.py to check and safely .decode("utf-8") header values if they are of type bytes * Fixed requests_upload.py to gracefully handle naive datetime deadlines by replacing timezone info with UTC. * Re-implemented the chunk_size property in _upload.py using the "standard formula for alignment": ((size + granularity - 1) // granularity) * granularity. * Updated the chunk transmission loop to check for state machine invalid state. * Added `requests.exceptions.ChunkedEncodingError` to the list of default retriable exceptions
1 parent a93c07e commit 6ea93b8

2 files changed

Lines changed: 17 additions & 10 deletions

File tree

packages/google-api-core/google/api_core/resumable_media/_upload.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,12 @@ def invalid(self) -> bool:
7373
@property
7474
def chunk_size(self) -> int:
7575
"""int: The block-aligned chunk size informed by server granularity."""
76-
actual_chunk_size = self._chunk_size
7776
if self._chunk_granularity:
78-
if actual_chunk_size % self._chunk_granularity != 0:
79-
actual_chunk_size = (
80-
(actual_chunk_size // self._chunk_granularity) + 1
81-
) * self._chunk_granularity
82-
return actual_chunk_size
77+
return (
78+
(self._chunk_size + self._chunk_granularity - 1)
79+
// self._chunk_granularity
80+
) * self._chunk_granularity
81+
return self._chunk_size
8382

8483
def build_initiate_request(
8584
self,
@@ -110,7 +109,7 @@ def build_initiate_request(
110109
# Merge user metadata first
111110
if stream_metadata:
112111
for k, v in stream_metadata:
113-
headers[k] = str(v)
112+
headers[k] = v.decode("utf-8") if isinstance(v, bytes) else str(v)
114113

115114
# Critical protocol headers overwrite user metadata
116115
headers[_common.UPLOAD_PROTOCOL_HEADER] = _common.UPLOAD_PROTOCOL_VALUE

packages/google-api-core/google/api_core/resumable_media/requests_upload.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,18 @@ def finished(self) -> bool:
112112
"""bool: Indicates if the upload has completed successfully."""
113113
return self._machine.finished
114114

115+
@property
116+
def invalid(self) -> bool:
117+
"""bool: Indicates if the upload has entered an unrecoverable state."""
118+
return self._machine.invalid
119+
115120
def _check_deadline(self) -> Optional[float]:
116121
if self.deadline:
117122
now = datetime.datetime.now(datetime.timezone.utc)
118-
timeout = (self.deadline - now).total_seconds()
123+
deadline = self.deadline
124+
if deadline.tzinfo is None:
125+
deadline = deadline.replace(tzinfo=datetime.timezone.utc)
126+
timeout = (deadline - now).total_seconds()
119127
if timeout <= 0:
120128
raise exceptions.DeadlineExceeded(
121129
f"Upload deadline {self.deadline} was exceeded."
@@ -128,7 +136,7 @@ def should_retry(exc):
128136
if isinstance(exc, requests.exceptions.RequestException):
129137
if isinstance(
130138
exc,
131-
(requests.exceptions.ConnectionError, requests.exceptions.Timeout),
139+
(requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError, requests.exceptions.Timeout),
132140
):
133141
return True
134142
if isinstance(exc, exceptions.GoogleAPICallError):
@@ -469,7 +477,7 @@ def make_resumable_upload(
469477
)
470478

471479
final_response = None
472-
while not upload.finished:
480+
while not upload.finished and not upload.invalid:
473481
final_response = upload.transmit_next_chunk(transport=transport)
474482
assert final_response is not None
475483
return final_response

0 commit comments

Comments
 (0)