Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-google-resumable-media for
openSUSE:Factory checked in at 2024-01-04 16:00:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-resumable-media (Old)
and /work/SRC/openSUSE:Factory/.python-google-resumable-media.new.28375
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-resumable-media"
Thu Jan 4 16:00:10 2024 rev:19 rq:1136785 version:2.7.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-google-resumable-media/python-google-resumable-media.changes
2023-09-13 20:47:56.765311458 +0200
+++
/work/SRC/openSUSE:Factory/.python-google-resumable-media.new.28375/python-google-resumable-media.changes
2024-01-04 16:01:49.874236945 +0100
@@ -1,0 +2,11 @@
+Thu Jan 4 11:00:19 UTC 2024 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 2.7.0
+ * Add support for Python 3.12 (#407)
+ * Support brotli encoding (#403)
+- Skip online tests
+ * test_brotli
+ * test_constructor
+ * test_decompress
+
+-------------------------------------------------------------------
Old:
----
google-resumable-media-2.6.0.tar.gz
New:
----
google-resumable-media-2.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-google-resumable-media.spec ++++++
--- /var/tmp/diff_new_pack.kBLzm0/_old 2024-01-04 16:01:50.314253020 +0100
+++ /var/tmp/diff_new_pack.kBLzm0/_new 2024-01-04 16:01:50.314253020 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-google-resumable-media
#
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-google-resumable-media
-Version: 2.6.0
+Version: 2.7.0
Release: 0
Summary: Utilities for Google Media Downloads and Resumable Uploads
License: Apache-2.0
@@ -56,7 +56,11 @@
%check
export PYTEST_ADDOPTS="--import-mode=importlib"
-%pytest tests/unit
+# skip online tests
+donttest="test_brotli"
+donttest="$donttest or test_constructor"
+donttest="$donttest or test_decompress"
+%pytest tests/unit -k "not ($donttest)"
%files %{python_files}
%license LICENSE
++++++ google-resumable-media-2.6.0.tar.gz ->
google-resumable-media-2.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-resumable-media-2.6.0/PKG-INFO
new/google-resumable-media-2.7.0/PKG-INFO
--- old/google-resumable-media-2.6.0/PKG-INFO 2023-09-06 20:12:17.037366400
+0200
+++ new/google-resumable-media-2.7.0/PKG-INFO 2023-12-12 20:03:28.395511000
+0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-resumable-media
-Version: 2.6.0
+Version: 2.7.0
Summary: Utilities for Google Media Downloads and Resumable Uploads
Home-page: https://github.com/googleapis/google-resumable-media-python
Author: Google Cloud Platform
@@ -16,11 +16,17 @@
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet
Requires-Python: >= 3.7
+License-File: LICENSE
+Requires-Dist: google-crc32c<2.0dev,>=1.0
Provides-Extra: requests
+Requires-Dist: requests<3.0.0dev,>=2.18.0; extra == "requests"
Provides-Extra: aiohttp
-License-File: LICENSE
+Requires-Dist: aiohttp<4.0.0dev,>=3.6.2; extra == "aiohttp"
+Requires-Dist: google-auth<2.0dev,>=1.22.0; extra == "aiohttp"
``google-resumable-media``
==========================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-resumable-media-2.6.0/google/resumable_media/requests/download.py
new/google-resumable-media-2.7.0/google/resumable_media/requests/download.py
---
old/google-resumable-media-2.6.0/google/resumable_media/requests/download.py
2023-09-06 20:09:24.000000000 +0200
+++
new/google-resumable-media-2.7.0/google/resumable_media/requests/download.py
2023-12-12 20:00:23.000000000 +0100
@@ -584,7 +584,7 @@
This is so that we can intercept the compressed bytes before they are
decoded.
- Only patches if the content encoding is ``gzip``.
+ Only patches if the content encoding is ``gzip`` or ``br``.
Args:
response_raw (urllib3.response.HTTPResponse): The raw response for
@@ -598,12 +598,16 @@
caller will no longer need to hash to decoded bytes.
"""
encoding = response_raw.headers.get("content-encoding", "").lower()
- if encoding != "gzip":
+ if encoding == "gzip":
+ response_raw._decoder = _GzipDecoder(checksum)
+ return _helpers._DoNothingHash()
+ # Only activate if brotli is installed
+ elif encoding == "br" and _BrotliDecoder: # type: ignore
+ response_raw._decoder = _BrotliDecoder(checksum)
+ return _helpers._DoNothingHash()
+ else:
return checksum
- response_raw._decoder = _GzipDecoder(checksum)
- return _helpers._DoNothingHash()
-
class _GzipDecoder(urllib3.response.GzipDecoder):
"""Custom subclass of ``urllib3`` decoder for ``gzip``-ed bytes.
@@ -617,7 +621,7 @@
"""
def __init__(self, checksum):
- super(_GzipDecoder, self).__init__()
+ super().__init__()
self._checksum = checksum
def decompress(self, data):
@@ -630,4 +634,46 @@
bytes: The decompressed bytes from ``data``.
"""
self._checksum.update(data)
- return super(_GzipDecoder, self).decompress(data)
+ return super().decompress(data)
+
+
+# urllib3.response.BrotliDecoder might not exist depending on whether brotli is
+# installed.
+if hasattr(urllib3.response, "BrotliDecoder"):
+
+ class _BrotliDecoder:
+ """Handler for ``brotli`` encoded bytes.
+
+ Allows a checksum function to see the compressed bytes before they are
+ decoded. This way the checksum of the compressed value can be computed.
+
+ Because BrotliDecoder's decompress method is dynamically created in
+ urllib3, a subclass is not practical. Instead, this class creates a
+ captive urllib3.requests.BrotliDecoder instance and acts as a proxy.
+
+ Args:
+ checksum (object):
+ A checksum which will be updated with compressed bytes.
+ """
+
+ def __init__(self, checksum):
+ self._decoder = urllib3.response.BrotliDecoder()
+ self._checksum = checksum
+
+ def decompress(self, data):
+ """Decompress the bytes.
+
+ Args:
+ data (bytes): The compressed bytes to be decompressed.
+
+ Returns:
+ bytes: The decompressed bytes from ``data``.
+ """
+ self._checksum.update(data)
+ return self._decoder.decompress(data)
+
+ def flush(self):
+ return self._decoder.flush()
+
+else: # pragma: NO COVER
+ _BrotliDecoder = None # type: ignore # pragma: NO COVER
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-resumable-media-2.6.0/google_resumable_media.egg-info/PKG-INFO
new/google-resumable-media-2.7.0/google_resumable_media.egg-info/PKG-INFO
--- old/google-resumable-media-2.6.0/google_resumable_media.egg-info/PKG-INFO
2023-09-06 20:12:16.000000000 +0200
+++ new/google-resumable-media-2.7.0/google_resumable_media.egg-info/PKG-INFO
2023-12-12 20:03:28.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-resumable-media
-Version: 2.6.0
+Version: 2.7.0
Summary: Utilities for Google Media Downloads and Resumable Uploads
Home-page: https://github.com/googleapis/google-resumable-media-python
Author: Google Cloud Platform
@@ -16,11 +16,17 @@
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet
Requires-Python: >= 3.7
+License-File: LICENSE
+Requires-Dist: google-crc32c<2.0dev,>=1.0
Provides-Extra: requests
+Requires-Dist: requests<3.0.0dev,>=2.18.0; extra == "requests"
Provides-Extra: aiohttp
-License-File: LICENSE
+Requires-Dist: aiohttp<4.0.0dev,>=3.6.2; extra == "aiohttp"
+Requires-Dist: google-auth<2.0dev,>=1.22.0; extra == "aiohttp"
``google-resumable-media``
==========================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-resumable-media-2.6.0/google_resumable_media.egg-info/SOURCES.txt
new/google-resumable-media-2.7.0/google_resumable_media.egg-info/SOURCES.txt
---
old/google-resumable-media-2.6.0/google_resumable_media.egg-info/SOURCES.txt
2023-09-06 20:12:16.000000000 +0200
+++
new/google-resumable-media-2.7.0/google_resumable_media.egg-info/SOURCES.txt
2023-12-12 20:03:28.000000000 +0100
@@ -27,6 +27,8 @@
google_resumable_media.egg-info/requires.txt
google_resumable_media.egg-info/top_level.txt
tests/__init__.py
+tests/data/brotli.txt
+tests/data/brotli.txt.br
tests/data/favicon.ico
tests/data/file.txt
tests/data/gzipped.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-resumable-media-2.6.0/setup.py
new/google-resumable-media-2.7.0/setup.py
--- old/google-resumable-media-2.6.0/setup.py 2023-09-06 20:09:24.000000000
+0200
+++ new/google-resumable-media-2.7.0/setup.py 2023-12-12 20:00:23.000000000
+0100
@@ -35,7 +35,7 @@
setuptools.setup(
name='google-resumable-media',
- version = "2.6.0",
+ version = "2.7.0",
description='Utilities for Google Media Downloads and Resumable Uploads',
author='Google Cloud Platform',
author_email='[email protected]',
@@ -62,6 +62,8 @@
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
'Topic :: Internet',
],
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-resumable-media-2.6.0/tests/data/brotli.txt
new/google-resumable-media-2.7.0/tests/data/brotli.txt
--- old/google-resumable-media-2.6.0/tests/data/brotli.txt 1970-01-01
01:00:00.000000000 +0100
+++ new/google-resumable-media-2.7.0/tests/data/brotli.txt 2023-12-12
20:00:23.000000000 +0100
@@ -0,0 +1,64 @@
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
+abcdefghijklmnopqrstuvwxyz0123456789
Binary files old/google-resumable-media-2.6.0/tests/data/brotli.txt.br and
new/google-resumable-media-2.7.0/tests/data/brotli.txt.br differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-resumable-media-2.6.0/tests/system/requests/test_download.py
new/google-resumable-media-2.7.0/tests/system/requests/test_download.py
--- old/google-resumable-media-2.6.0/tests/system/requests/test_download.py
2023-09-06 20:09:24.000000000 +0200
+++ new/google-resumable-media-2.7.0/tests/system/requests/test_download.py
2023-12-12 20:00:23.000000000 +0100
@@ -121,6 +121,15 @@
"slices": (),
"metadata": {"contentEncoding": "gzip"},
},
+ {
+ "path": get_path("brotli.txt.br"),
+ "uncompressed": get_path("brotli.txt"),
+ "content_type": PLAIN_TEXT,
+ "md5": "MffJw7pTSX/7CVWFFPgwQA==",
+ "crc32c": "GGK0OQ==",
+ "slices": (),
+ "metadata": {"contentEncoding": "br"},
+ },
)
@@ -298,7 +307,7 @@
self, add_files, authorized_transport
):
# Retrieve the gzip compressed file
- info = ALL_FILES[-1]
+ info = ALL_FILES[-2]
actual_contents = self._get_contents(info)
blob_name = get_blob_name(info)
@@ -313,6 +322,27 @@
assert response.headers.get("X-Goog-Stored-Content-Length") is not None
assert stream.getvalue() == actual_contents
check_tombstoned(download, authorized_transport)
+
+ @pytest.mark.parametrize("checksum", ["md5", "crc32c"])
+ def test_download_brotli_w_stored_content_headers(
+ self, add_files, authorized_transport, checksum
+ ):
+ # Retrieve the br compressed file
+ info = ALL_FILES[-1]
+ actual_contents = self._get_contents(info)
+ blob_name = get_blob_name(info)
+
+ # Create the actual download object.
+ media_url = utils.DOWNLOAD_URL_TEMPLATE.format(blob_name=blob_name)
+ stream = io.BytesIO()
+ download = self._make_one(media_url, stream=stream, checksum=checksum)
+ # Consume the resource.
+ response = download.consume(authorized_transport)
+ assert response.status_code == http.client.OK
+ assert response.headers.get(_helpers._STORED_CONTENT_ENCODING_HEADER)
== "br"
+ assert response.headers.get("X-Goog-Stored-Content-Length") is not None
+ assert stream.getvalue() == actual_contents
+ check_tombstoned(download, authorized_transport)
def test_extra_headers(self, authorized_transport, secret_file):
blob_name, data, headers = secret_file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-resumable-media-2.6.0/tests/unit/requests/test_download.py
new/google-resumable-media-2.7.0/tests/unit/requests/test_download.py
--- old/google-resumable-media-2.6.0/tests/unit/requests/test_download.py
2023-09-06 20:09:24.000000000 +0200
+++ new/google-resumable-media-2.7.0/tests/unit/requests/test_download.py
2023-12-12 20:00:23.000000000 +0100
@@ -1110,6 +1110,18 @@
assert isinstance(response_raw._decoder, download_mod._GzipDecoder)
assert response_raw._decoder._checksum is mock.sentinel.md5_hash
+ def test_brotli(self):
+ headers = {"content-encoding": "br"}
+ response_raw = mock.Mock(headers=headers, spec=["headers", "_decoder"])
+ md5_hash = download_mod._add_decoder(response_raw,
mock.sentinel.md5_hash)
+
+ assert md5_hash is not mock.sentinel.md5_hash
+ assert isinstance(md5_hash, _helpers._DoNothingHash)
+ assert isinstance(response_raw._decoder, download_mod._BrotliDecoder)
+ assert response_raw._decoder._checksum is mock.sentinel.md5_hash
+ # Go ahead and exercise the flush method, added only for completion
+ response_raw._decoder.flush()
+
class Test_GzipDecoder(object):
def test_constructor(self):
@@ -1124,6 +1136,22 @@
result = decoder.decompress(data)
assert result == b""
+ md5_hash.update.assert_called_once_with(data)
+
+
+class Test_BrotliDecoder(object):
+ def test_constructor(self):
+ decoder = download_mod._BrotliDecoder(mock.sentinel.md5_hash)
+ assert decoder._checksum is mock.sentinel.md5_hash
+
+ def test_decompress(self):
+ md5_hash = mock.Mock(spec=["update"])
+ decoder = download_mod._BrotliDecoder(md5_hash)
+
+ data = b"\xc1\xf8I\xc0/\x83\xf3\xfa"
+ result = decoder.decompress(data)
+
+ assert result == b""
md5_hash.update.assert_called_once_with(data)