From 0b387227ca88b716ff3148a4ecb9af1ad29a9f35 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 8 Dec 2025 00:18:23 +0200 Subject: [PATCH 1/2] fix: add max_length support to Gzip/Brotli decoders for urllib3 v2.6+ compatibility --- google/resumable_media/requests/download.py | 22 +++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/google/resumable_media/requests/download.py b/google/resumable_media/requests/download.py index 1472c9f2..7793dad4 100644 --- a/google/resumable_media/requests/download.py +++ b/google/resumable_media/requests/download.py @@ -667,17 +667,24 @@ def __init__(self, checksum): super().__init__() self._checksum = checksum - def decompress(self, data): + def decompress(self, data, max_length=None): """Decompress the bytes. Args: data (bytes): The compressed bytes to be decompressed. + max_length (optional[int]): The maximum number of bytes to decompress. + This parameter is required for compatibility with urllib3>=2.6.0 + and is passed to the underlying urllib3 decoder. Returns: bytes: The decompressed bytes from ``data``. """ self._checksum.update(data) - return super().decompress(data) + try: + return super().decompress(data, max_length=max_length) + except TypeError: + # FB for urllib3 <2.6.0 + return super().decompress(data) # urllib3.response.BrotliDecoder might not exist depending on whether brotli is @@ -703,17 +710,24 @@ def __init__(self, checksum): self._decoder = urllib3.response.BrotliDecoder() self._checksum = checksum - def decompress(self, data): + def decompress(self, data, max_length=None): """Decompress the bytes. Args: data (bytes): The compressed bytes to be decompressed. + max_length (optional[int]): The maximum number of bytes to decompress. + This parameter is required for compatibility with urllib3>=2.6.0 + and is passed to the underlying urllib3 decoder. Returns: bytes: The decompressed bytes from ``data``. """ self._checksum.update(data) - return self._decoder.decompress(data) + try: + return self._decoder.decompress(data, max_length=max_length) + except TypeError: + # FB for urllib3 <2.6.0 + return self._decoder.decompress(data) def flush(self): return self._decoder.flush() From c5a08f6c415d42ab747e98bdadb8ed6cff777bca Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 9 Dec 2025 23:51:57 +0200 Subject: [PATCH 2/2] fix: add stream methods for urllib3 compatibility --- google/resumable_media/requests/download.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/google/resumable_media/requests/download.py b/google/resumable_media/requests/download.py index 7793dad4..4bda8d95 100644 --- a/google/resumable_media/requests/download.py +++ b/google/resumable_media/requests/download.py @@ -667,7 +667,7 @@ def __init__(self, checksum): super().__init__() self._checksum = checksum - def decompress(self, data, max_length=None): + def decompress(self, data, max_length=-1): """Decompress the bytes. Args: @@ -686,6 +686,11 @@ def decompress(self, data, max_length=None): # FB for urllib3 <2.6.0 return super().decompress(data) + @property + def has_unconsumed_tail(self) -> bool: + # Checks for buffered, unread bytes + return self._decoder.has_unconsumed_tail + # urllib3.response.BrotliDecoder might not exist depending on whether brotli is # installed. @@ -710,7 +715,7 @@ def __init__(self, checksum): self._decoder = urllib3.response.BrotliDecoder() self._checksum = checksum - def decompress(self, data, max_length=None): + def decompress(self, data, max_length=-1): """Decompress the bytes. Args: @@ -731,6 +736,11 @@ def decompress(self, data, max_length=None): def flush(self): return self._decoder.flush() + + @property + def has_unconsumed_tail(self) -> bool: + # Checks for buffered, unread bytes + return self._decoder.has_unconsumed_tail else: # pragma: NO COVER _BrotliDecoder = None # type: ignore # pragma: NO COVER