Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-google-api-core for
openSUSE:Factory checked in at 2023-12-07 19:11:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-api-core (Old)
and /work/SRC/openSUSE:Factory/.python-google-api-core.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-api-core"
Thu Dec 7 19:11:34 2023 rev:28 rq:1131630 version:2.14.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-google-api-core/python-google-api-core.changes
2023-10-24 20:08:52.049637685 +0200
+++
/work/SRC/openSUSE:Factory/.python-google-api-core.new.25432/python-google-api-core.changes
2023-12-07 19:13:19.685727905 +0100
@@ -1,0 +2,14 @@
+Thu Dec 7 13:49:02 UTC 2023 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 2.14.0
+ * Support with_call for wrapped rpcs (#550)
+- from version 2.13.1
+ * Update async client to use async retry (#544)
+- from version 2.13.0
+ * Add caching to routing header calculation (#526)
+ * Add warning to retry target to avoid incorrect usage (#543)
+ * Drop usage of distutils (#541)
+ * Ensure exception is available when BackgroundConsumer
+ open stream fails (#357)
+
+-------------------------------------------------------------------
Old:
----
google-api-core-2.12.0.tar.gz
New:
----
google-api-core-2.14.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-google-api-core.spec ++++++
--- /var/tmp/diff_new_pack.37IJhy/_old 2023-12-07 19:13:20.141744728 +0100
+++ /var/tmp/diff_new_pack.37IJhy/_new 2023-12-07 19:13:20.145744875 +0100
@@ -27,7 +27,7 @@
%define skip_python2 1
%{?sle15_python_module_pythons}
Name: python-google-api-core
-Version: 2.12.0
+Version: 2.14.0
Release: 0
Summary: Google API client core library
License: Apache-2.0
++++++ google-api-core-2.12.0.tar.gz -> google-api-core-2.14.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/PKG-INFO
new/google-api-core-2.14.0/PKG-INFO
--- old/google-api-core-2.12.0/PKG-INFO 2023-09-25 18:31:13.247293500 +0200
+++ new/google-api-core-2.14.0/PKG-INFO 2023-11-10 00:16:17.662312300 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-api-core
-Version: 2.12.0
+Version: 2.14.0
Summary: Google API client core library
Home-page: https://github.com/googleapis/python-api-core
Author: Google LLC
@@ -20,10 +20,20 @@
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet
Requires-Python: >=3.7
+License-File: LICENSE
+Requires-Dist: googleapis-common-protos<2.0.dev0,>=1.56.2
+Requires-Dist:
protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5
+Requires-Dist: google-auth<3.0.dev0,>=2.14.1
+Requires-Dist: requests<3.0.0.dev0,>=2.18.0
Provides-Extra: grpc
+Requires-Dist: grpcio<2.0dev,>=1.33.2; extra == "grpc"
+Requires-Dist: grpcio<2.0dev,>=1.49.1; python_version >= "3.11" and extra ==
"grpc"
+Requires-Dist: grpcio-status<2.0.dev0,>=1.33.2; extra == "grpc"
+Requires-Dist: grpcio-status<2.0.dev0,>=1.49.1; python_version >= "3.11" and
extra == "grpc"
Provides-Extra: grpcgcp
+Requires-Dist: grpcio-gcp<1.0.dev0,>=0.2.2; extra == "grpcgcp"
Provides-Extra: grpcio-gcp
-License-File: LICENSE
+Requires-Dist: grpcio-gcp<1.0.dev0,>=0.2.2; extra == "grpcio-gcp"
Core Library for Google Client Libraries
========================================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/google/api_core/bidi.py
new/google-api-core-2.14.0/google/api_core/bidi.py
--- old/google-api-core-2.12.0/google/api_core/bidi.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/google/api_core/bidi.py 2023-11-10
00:14:15.000000000 +0100
@@ -92,10 +92,7 @@
# Note: there is a possibility that this starts *before* the call
# property is set. So we have to check if self.call is set before
# seeing if it's active.
- if self.call is not None and not self.call.is_active():
- return False
- else:
- return True
+ return self.call is not None and self.call.is_active()
def __iter__(self):
if self._initial_request is not None:
@@ -265,6 +262,10 @@
self._callbacks.append(callback)
def _on_call_done(self, future):
+ # This occurs when the RPC errors or is successfully terminated.
+ # Note that grpc's "future" here can also be a grpc.RpcError.
+ # See note in
https://github.com/grpc/grpc/issues/10885#issuecomment-302651331
+ # that `grpc.RpcError` is also `grpc.call`.
for callback in self._callbacks:
callback(future)
@@ -276,7 +277,13 @@
request_generator = _RequestQueueGenerator(
self._request_queue, initial_request=self._initial_request
)
- call = self._start_rpc(iter(request_generator),
metadata=self._rpc_metadata)
+ try:
+ call = self._start_rpc(iter(request_generator),
metadata=self._rpc_metadata)
+ except exceptions.GoogleAPICallError as exc:
+ # The original `grpc.RpcError` (which is usually also a
`grpc.Call`) is
+ # available from the ``response`` property on the mapped exception.
+ self._on_call_done(exc.response)
+ raise
request_generator.call = call
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/google/api_core/gapic_v1/method.py
new/google-api-core-2.14.0/google/api_core/gapic_v1/method.py
--- old/google-api-core-2.12.0/google/api_core/gapic_v1/method.py
2023-09-25 18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/google/api_core/gapic_v1/method.py
2023-11-10 00:14:15.000000000 +0100
@@ -137,6 +137,8 @@
default_timeout=None,
default_compression=None,
client_info=client_info.DEFAULT_CLIENT_INFO,
+ *,
+ with_call=False,
):
"""Wrap an RPC method with common behavior.
@@ -216,6 +218,10 @@
passed as gRPC metadata to the method. If unspecified, then
a sane default will be used. If ``None``, then no user agent
metadata will be provided to the RPC method.
+ with_call (bool): If True, wrapped grpc.UnaryUnaryMulticallables will
+ return a tuple of (response, grpc.Call) instead of just the
response.
+ This is useful for extracting trailing metadata from unary calls.
+ Defaults to False.
Returns:
Callable: A new callable that takes optional ``retry``, ``timeout``,
@@ -223,6 +229,13 @@
arguments and applies the common error mapping, retry, timeout,
compression,
and metadata behavior to the low-level RPC method.
"""
+ if with_call:
+ try:
+ func = func.with_call
+ except AttributeError as exc:
+ raise ValueError(
+ "with_call=True is only supported for unary calls."
+ ) from exc
func = grpc_helpers.wrap_errors(func)
if client_info is not None:
user_agent_metadata = [client_info.to_grpc_metadata()]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/google/api_core/gapic_v1/routing_header.py
new/google-api-core-2.14.0/google/api_core/gapic_v1/routing_header.py
--- old/google-api-core-2.12.0/google/api_core/gapic_v1/routing_header.py
2023-09-25 18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/google/api_core/gapic_v1/routing_header.py
2023-11-10 00:14:15.000000000 +0100
@@ -20,17 +20,22 @@
Generally, these headers are specified as gRPC metadata.
"""
+import functools
from enum import Enum
from urllib.parse import urlencode
ROUTING_METADATA_KEY = "x-goog-request-params"
+# This is the value for the `maxsize` argument of @functools.lru_cache
+# https://docs.python.org/3/library/functools.html#functools.lru_cache
+# This represents the number of recent function calls to store.
+ROUTING_PARAM_CACHE_SIZE = 32
def to_routing_header(params, qualified_enums=True):
"""Returns a routing header string for the given request parameters.
Args:
- params (Mapping[str, Any]): A dictionary containing the request
+ params (Mapping[str, str | bytes | Enum]): A dictionary containing the
request
parameters used for routing.
qualified_enums (bool): Whether to represent enum values
as their type-qualified symbol names instead of as their
@@ -38,19 +43,11 @@
Returns:
str: The routing header string.
-
"""
+ tuples = params.items() if isinstance(params, dict) else params
if not qualified_enums:
- if isinstance(params, dict):
- tuples = params.items()
- else:
- tuples = params
- params = [(x[0], x[1].name) if isinstance(x[1], Enum) else x for x in
tuples]
- return urlencode(
- params,
- # Per Google API policy (go/api-url-encoding), / is not encoded.
- safe="/",
- )
+ tuples = [(x[0], x[1].name) if isinstance(x[1], Enum) else x for x in
tuples]
+ return "&".join([_urlencode_param(*t) for t in tuples])
def to_grpc_metadata(params, qualified_enums=True):
@@ -58,7 +55,7 @@
request parameters.
Args:
- params (Mapping[str, Any]): A dictionary containing the request
+ params (Mapping[str, str | bytes | Enum]): A dictionary containing the
request
parameters used for routing.
qualified_enums (bool): Whether to represent enum values
as their type-qualified symbol names instead of as their
@@ -69,3 +66,22 @@
and value.
"""
return (ROUTING_METADATA_KEY, to_routing_header(params, qualified_enums))
+
+
+# use caching to avoid repeated computation
[email protected]_cache(maxsize=ROUTING_PARAM_CACHE_SIZE)
+def _urlencode_param(key, value):
+ """Cacheable wrapper over urlencode
+
+ Args:
+ key (str): The key of the parameter to encode.
+ value (str | bytes | Enum): The value of the parameter to encode.
+
+ Returns:
+ str: The encoded parameter.
+ """
+ return urlencode(
+ {key: value},
+ # Per Google API policy (go/api-url-encoding), / is not encoded.
+ safe="/",
+ )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/google/api_core/operations_v1/abstract_operations_client.py
new/google-api-core-2.14.0/google/api_core/operations_v1/abstract_operations_client.py
---
old/google-api-core-2.12.0/google/api_core/operations_v1/abstract_operations_client.py
2023-09-25 18:29:07.000000000 +0200
+++
new/google-api-core-2.14.0/google/api_core/operations_v1/abstract_operations_client.py
2023-11-10 00:14:15.000000000 +0100
@@ -14,7 +14,6 @@
# limitations under the License.
#
from collections import OrderedDict
-from distutils import util
import os
import re
from typing import Dict, Optional, Sequence, Tuple, Type, Union
@@ -294,13 +293,16 @@
client_options = client_options_lib.ClientOptions()
# Create SSL credentials for mutual TLS if needed.
- use_client_cert = bool(
- util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE",
"false"))
- )
-
+ use_client_cert = os.getenv(
+ "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
+ ).lower()
+ if use_client_cert not in ("true", "false"):
+ raise ValueError(
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must
be either `true` or `false`"
+ )
client_cert_source_func = None
is_mtls = False
- if use_client_cert:
+ if use_client_cert == "true":
if client_options.client_cert_source:
is_mtls = True
client_cert_source_func = client_options.client_cert_source
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/google/api_core/operations_v1/operations_async_client.py
new/google-api-core-2.14.0/google/api_core/operations_v1/operations_async_client.py
---
old/google-api-core-2.12.0/google/api_core/operations_v1/operations_async_client.py
2023-09-25 18:29:07.000000000 +0200
+++
new/google-api-core-2.14.0/google/api_core/operations_v1/operations_async_client.py
2023-11-10 00:14:15.000000000 +0100
@@ -26,7 +26,7 @@
from google.api_core import exceptions as core_exceptions
from google.api_core import gapic_v1, page_iterator_async
-from google.api_core import retry as retries
+from google.api_core import retry_async as retries
from google.api_core import timeout as timeouts
from google.longrunning import operations_pb2
from grpc import Compression
@@ -48,7 +48,7 @@
# Create the gRPC client stub with gRPC AsyncIO channel.
self.operations_stub = operations_pb2.OperationsStub(channel)
- default_retry = retries.Retry(
+ default_retry = retries.AsyncRetry(
initial=0.1, # seconds
maximum=60.0, # seconds
multiplier=1.3,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/google/api_core/retry.py
new/google-api-core-2.14.0/google/api_core/retry.py
--- old/google-api-core-2.12.0/google/api_core/retry.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/google/api_core/retry.py 2023-11-10
00:14:15.000000000 +0100
@@ -62,6 +62,8 @@
import random
import sys
import time
+import inspect
+import warnings
from typing import Any, Callable, TypeVar, TYPE_CHECKING
import requests.exceptions
@@ -84,6 +86,7 @@
_DEFAULT_MAXIMUM_DELAY = 60.0 # seconds
_DEFAULT_DELAY_MULTIPLIER = 2.0
_DEFAULT_DEADLINE = 60.0 * 2.0 # seconds
+_ASYNC_RETRY_WARNING = "Using the synchronous google.api_core.retry.Retry with
asynchronous calls may lead to unexpected results. Please use
google.api_core.retry_async.AsyncRetry instead."
def if_exception_type(
@@ -201,7 +204,10 @@
for sleep in sleep_generator:
try:
- return target()
+ result = target()
+ if inspect.isawaitable(result):
+ warnings.warn(_ASYNC_RETRY_WARNING)
+ return result
# pylint: disable=broad-except
# This function explicitly must deal with broad exceptions.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/google/api_core/version.py
new/google-api-core-2.14.0/google/api_core/version.py
--- old/google-api-core-2.12.0/google/api_core/version.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/google/api_core/version.py 2023-11-10
00:14:15.000000000 +0100
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-__version__ = "2.12.0"
+__version__ = "2.14.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/google_api_core.egg-info/PKG-INFO
new/google-api-core-2.14.0/google_api_core.egg-info/PKG-INFO
--- old/google-api-core-2.12.0/google_api_core.egg-info/PKG-INFO
2023-09-25 18:31:13.000000000 +0200
+++ new/google-api-core-2.14.0/google_api_core.egg-info/PKG-INFO
2023-11-10 00:16:17.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-api-core
-Version: 2.12.0
+Version: 2.14.0
Summary: Google API client core library
Home-page: https://github.com/googleapis/python-api-core
Author: Google LLC
@@ -20,10 +20,20 @@
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet
Requires-Python: >=3.7
+License-File: LICENSE
+Requires-Dist: googleapis-common-protos<2.0.dev0,>=1.56.2
+Requires-Dist:
protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5
+Requires-Dist: google-auth<3.0.dev0,>=2.14.1
+Requires-Dist: requests<3.0.0.dev0,>=2.18.0
Provides-Extra: grpc
+Requires-Dist: grpcio<2.0dev,>=1.33.2; extra == "grpc"
+Requires-Dist: grpcio<2.0dev,>=1.49.1; python_version >= "3.11" and extra ==
"grpc"
+Requires-Dist: grpcio-status<2.0.dev0,>=1.33.2; extra == "grpc"
+Requires-Dist: grpcio-status<2.0.dev0,>=1.49.1; python_version >= "3.11" and
extra == "grpc"
Provides-Extra: grpcgcp
+Requires-Dist: grpcio-gcp<1.0.dev0,>=0.2.2; extra == "grpcgcp"
Provides-Extra: grpcio-gcp
-License-File: LICENSE
+Requires-Dist: grpcio-gcp<1.0.dev0,>=0.2.2; extra == "grpcio-gcp"
Core Library for Google Client Libraries
========================================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/tests/unit/gapic/test_method.py
new/google-api-core-2.14.0/tests/unit/gapic/test_method.py
--- old/google-api-core-2.12.0/tests/unit/gapic/test_method.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/tests/unit/gapic/test_method.py 2023-11-10
00:14:15.000000000 +0100
@@ -201,3 +201,24 @@
assert result == 42
method.assert_called_once_with(timeout=22, metadata=mock.ANY)
+
+
+def test_wrap_method_with_call():
+ method = mock.Mock()
+ mock_call = mock.Mock()
+ method.with_call.return_value = 42, mock_call
+
+ wrapped_method = google.api_core.gapic_v1.method.wrap_method(method,
with_call=True)
+ result = wrapped_method()
+ assert len(result) == 2
+ assert result[0] == 42
+ assert result[1] == mock_call
+
+
+def test_wrap_method_with_call_not_supported():
+ """Raises an error if wrapped callable doesn't have with_call method."""
+ method = lambda: None # noqa: E731
+
+ with pytest.raises(ValueError) as exc_info:
+ google.api_core.gapic_v1.method.wrap_method(method, with_call=True)
+ assert "with_call=True is only supported for unary calls" in
str(exc_info.value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google-api-core-2.12.0/tests/unit/gapic/test_routing_header.py
new/google-api-core-2.14.0/tests/unit/gapic/test_routing_header.py
--- old/google-api-core-2.12.0/tests/unit/gapic/test_routing_header.py
2023-09-25 18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/tests/unit/gapic/test_routing_header.py
2023-11-10 00:14:15.000000000 +0100
@@ -70,3 +70,34 @@
params = [("name", "meep"), ("book.read", "1")]
metadata = routing_header.to_grpc_metadata(params)
assert metadata == (routing_header.ROUTING_METADATA_KEY,
"name=meep&book.read=1")
+
+
[email protected](
+ "key,value,expected",
+ [
+ ("book.read", "1", "book.read=1"),
+ ("name", "me/ep", "name=me/ep"),
+ ("\\", "=", "%5C=%3D"),
+ (b"hello", "world", "hello=world"),
+ ("âï¸", "âï¸", "%E2%9C%94%EF%B8%8F=%E2%9C%8C%EF%B8%8F"),
+ ],
+)
+def test__urlencode_param(key, value, expected):
+ result = routing_header._urlencode_param(key, value)
+ assert result == expected
+
+
+def test__urlencode_param_caching_performance():
+ import time
+
+ key = "key" * 100
+ value = "value" * 100
+ # time with empty cache
+ start_time = time.perf_counter()
+ routing_header._urlencode_param(key, value)
+ duration = time.perf_counter() - start_time
+ second_start_time = time.perf_counter()
+ routing_header._urlencode_param(key, value)
+ second_duration = time.perf_counter() - second_start_time
+ # second call should be approximately 10 times faster
+ assert second_duration < duration / 10
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/tests/unit/test_bidi.py
new/google-api-core-2.14.0/tests/unit/test_bidi.py
--- old/google-api-core-2.12.0/tests/unit/test_bidi.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/tests/unit/test_bidi.py 2023-11-10
00:14:15.000000000 +0100
@@ -804,6 +804,21 @@
while consumer.is_active:
pass
+ def test_rpc_callback_fires_when_consumer_start_fails(self):
+ expected_exception = exceptions.InvalidArgument(
+ "test", response=grpc.StatusCode.INVALID_ARGUMENT
+ )
+ callback = mock.Mock(spec=["__call__"])
+
+ rpc, _ = make_rpc()
+ bidi_rpc = bidi.BidiRpc(rpc)
+ bidi_rpc.add_done_callback(callback)
+ bidi_rpc._start_rpc.side_effect = expected_exception
+
+ consumer = bidi.BackgroundConsumer(bidi_rpc, on_response=None)
+ consumer.start()
+ assert callback.call_args.args[0] == grpc.StatusCode.INVALID_ARGUMENT
+
def test_consumer_expected_error(self, caplog):
caplog.set_level(logging.DEBUG)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google-api-core-2.12.0/tests/unit/test_retry.py
new/google-api-core-2.14.0/tests/unit/test_retry.py
--- old/google-api-core-2.12.0/tests/unit/test_retry.py 2023-09-25
18:29:07.000000000 +0200
+++ new/google-api-core-2.14.0/tests/unit/test_retry.py 2023-11-10
00:14:15.000000000 +0100
@@ -129,6 +129,26 @@
sleep.assert_not_called()
[email protected]("asyncio.sleep", autospec=True)
[email protected](
+ "google.api_core.datetime_helpers.utcnow",
+ return_value=datetime.datetime.min,
+ autospec=True,
+)
[email protected]
+async def test_retry_target_warning_for_retry(utcnow, sleep):
+ predicate = retry.if_exception_type(ValueError)
+ target = mock.AsyncMock(spec=["__call__"])
+
+ with pytest.warns(Warning) as exc_info:
+ # Note: predicate is just a filler and doesn't affect the test
+ retry.retry_target(target, predicate, range(10), None)
+
+ assert len(exc_info) == 2
+ assert str(exc_info[0].message) == retry._ASYNC_RETRY_WARNING
+ sleep.assert_not_called()
+
+
@mock.patch("time.sleep", autospec=True)
@mock.patch("google.api_core.datetime_helpers.utcnow", autospec=True)
def test_retry_target_deadline_exceeded(utcnow, sleep):