![](https://seccdn.libravatar.org/avatar/e2145bc5cf53dda95c308a3c75e8fef3.jpg?s=120&d=mm&r=g)
Hello community, here is the log from the commit of package python-google-api-core for openSUSE:Factory checked in at 2019-07-04 15:43:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-api-core (Old) and /work/SRC/openSUSE:Factory/.python-google-api-core.new.4615 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-google-api-core" Thu Jul 4 15:43:02 2019 rev:9 rq:713078 version:1.13.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-api-core/python-google-api-core.changes 2019-05-16 22:11:14.610220864 +0200 +++ /work/SRC/openSUSE:Factory/.python-google-api-core.new.4615/python-google-api-core.changes 2019-07-04 15:43:02.814088156 +0200 @@ -1,0 +2,6 @@ +Tue Jul 2 14:51:05 UTC 2019 - Tomáš Chvátal <tchvatal@suse.com> + +- Update to 1.13.0: + * Various fixes for new updated dependencies + +------------------------------------------------------------------- Old: ---- google-api-core-1.11.0.tar.gz New: ---- google-api-core-1.13.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-api-core.spec ++++++ --- /var/tmp/diff_new_pack.jLWvg3/_old 2019-07-04 15:43:03.582089356 +0200 +++ /var/tmp/diff_new_pack.jLWvg3/_new 2019-07-04 15:43:03.586089362 +0200 @@ -18,12 +18,12 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-google-api-core -Version: 1.11.0 +Version: 1.13.0 Release: 0 Summary: Google API client core library License: Apache-2.0 Group: Development/Languages/Python -Url: https://github.com/GoogleCloudPlatform/google-cloud-python +URL: https://github.com/GoogleCloudPlatform/google-cloud-python Source: https://files.pythonhosted.org/packages/source/g/google-api-core/google-api-core-%{version}.tar.gz BuildRequires: %{python_module google-auth >= 0.4.0} BuildRequires: %{python_module googleapis-common-protos >= 1.5.3} @@ -40,25 +40,24 @@ BuildRequires: python-rpm-macros BuildRequires: python2-enum34 BuildRequires: python2-futures >= 3.2.0 -%ifpython2 -BuildRequires: python2-enum34 -BuildRequires: python2-futures -%endif Requires: python-google-auth >= 0.4.0 Requires: python-googleapis-common-protos >= 1.5.3 +Requires: python-grpcio >= 1.8.2 Requires: python-protobuf >= 3.0.0 Requires: python-pytz Requires: python-requests >= 2.18.0 Requires: python-setuptools >= 34.0.0 Requires: python-six >= 1.10.0 +Suggests: python-grpcio-gcp >= 0.2.2 +BuildArch: noarch +%ifpython2 +BuildRequires: python2-enum34 +BuildRequires: python2-futures +%endif %ifpython2 Requires: python-enum34 Requires: python-futures >= 3.2.0 %endif -Requires: python-grpcio >= 1.8.2 -Suggests: python-grpcio-gcp >= 0.2.2 -BuildArch: noarch - %python_subpackages %description @@ -75,7 +74,7 @@ %python_expand %fdupes %{buildroot}%{$python_sitelib} %check -%python_exec -m pytest +%pytest %files %{python_files} %license LICENSE ++++++ google-api-core-1.11.0.tar.gz -> google-api-core-1.13.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/.coveragerc new/google-api-core-1.13.0/.coveragerc --- old/google-api-core-1.11.0/.coveragerc 2018-09-13 21:58:16.000000000 +0200 +++ new/google-api-core-1.13.0/.coveragerc 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/.flake8 new/google-api-core-1.13.0/.flake8 --- old/google-api-core-1.11.0/.flake8 2018-12-03 18:45:52.000000000 +0100 +++ new/google-api-core-1.13.0/.flake8 1970-01-01 01:00:00.000000000 +0100 @@ -1,11 +0,0 @@ -[flake8] -import-order-style=google -# Note: this forces all google imports to be in the third group. See -# https://github.com/PyCQA/flake8-import-order/issues/111 -application-import-names=google -ignore = E203, E266, E501, W503 -exclude = - __pycache__, - .git, - *.pyc, - conf.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/CHANGELOG.md new/google-api-core-1.13.0/CHANGELOG.md --- old/google-api-core-1.11.0/CHANGELOG.md 2019-05-15 19:57:02.000000000 +0200 +++ new/google-api-core-1.13.0/CHANGELOG.md 1970-01-01 01:00:00.000000000 +0100 @@ -1,281 +0,0 @@ -# Changelog - -[PyPI History][1] - -[1]: https://pypi.org/project/google-api-core/#history - -## 1.11.0 - -05-15-2019 10:29 PDT - -### New Features - -- Refactor 'client_info' support. ([#7849](https://github.com/googleapis/google-cloud-python/pull/7849)) - -## 1.10.0 - -04-29-2019 10:12 PDT - -### Implementation Changes - -- Append leading zeros for nanosecond precision DateTimes - ([#7663](https://github.com/googleapis/google-cloud-python/pull/7663)) - -### New Features - -- Add `user_agent` property to `ClientInfo` - ([#7799](https://github.com/googleapis/google-cloud-python/pull/7799)) - -## 1.9.0 - -04-05-2019 10:38 PDT - - -### Implementation Changes -- Allow passing metadata as part of creating a bidi ([#7514](https://github.com/googleapis/google-cloud-python/pull/7514)) - -### Internal / Testing Changes -- Update setup.py -- API Core: specify a pytype output directory in setup.cfg. ([#7639](https://github.com/googleapis/google-cloud-python/pull/7639)) - -## 1.8.2 - -03-22-2019 16:27 PDT - - -### Implementation Changes -- Remove classifier for Python 3.4 for end-of-life. ([#7535](https://github.com/googleapis/google-cloud-python/pull/7535)) - -### Internal / Testing Changes -- When re-opening a `ResumableBidiRPC` set `_request_queue_generator` to `None`. ([#7548](https://github.com/googleapis/google-cloud-python/pull/7548)) - -## 1.8.1 - -03-12-2019 12:45 PDT - -### Implementation Changes -- Protect the creation of a background thread in BackgroundConsumer and wait on it starting. ([#7499](https://github.com/googleapis/google-cloud-python/pull/7499)) - -## 1.8.0 - -02-23-2019 15:46 PST - - -### New Features -- Add support to unwrap Anys into wrapped pb2 objects. ([#7430](https://github.com/googleapis/google-cloud-python/pull/7430)) -- Add `Operation.deserialize`. ([#7427](https://github.com/googleapis/google-cloud-python/pull/7427)) - -### Documentation -- Updated client library documentation URLs. ([#7307](https://github.com/googleapis/google-cloud-python/pull/7307)) - -### Internal / Testing Changes -- Fix new lint failure. ([#7382](https://github.com/googleapis/google-cloud-python/pull/7382)) - -## 1.7.0 - -12-17-2018 13:56 PST - -### New Features -- Support converting `DatetimeWithNanos` to / from `google.protobuf.timestamp_pb2.Timestamp`. ([#6919](https://github.com/googleapis/google-cloud-python/pull/6919)) - -### Documentation -- Document Python 2 deprecation. ([#6910](https://github.com/googleapis/google-cloud-python/pull/6910)) -- Add usage example for `google.api_core.iam.Polcy`. ([#6855](https://github.com/googleapis/google-cloud-python/pull/6855)) - -### Internal / Testing Changes -- Work around pytype big for `ABCMeta.register`. ([#6873](https://github.com/googleapis/google-cloud-python/pull/6873)) - -## 1.6.0 - -11-30-2018 12:45 PST - - -### Implementation Changes -- Import stdlib ABCs from 'collections.abc' rather than 'collections'. ([#6451](https://github.com/googleapis/google-cloud-python/pull/6451)) - -### New Features -- Move google.cloud.iam (core) to google.api_core.iam ([#6740](https://github.com/googleapis/google-cloud-python/pull/6740)) -- Add bidi support to api_core. ([#6191](https://github.com/googleapis/google-cloud-python/pull/6191)) - -### Documentation -- Fix typo ([#6532](https://github.com/googleapis/google-cloud-python/pull/6532)) - -### Internal / Testing Changes -- blacken api_core and core ([#6668](https://github.com/googleapis/google-cloud-python/pull/6668)) - -## 1.5.2 - -11-09-2018 14:22 PST - - -### Implementation Changes -- Retry transient errors in 'PollingFuture.result'. ([#6305](https://github.com/googleapis/google-cloud-python/pull/6305)) - -### Dependencies -- Remove hyphen from named extra in api_core. ([#6468](https://github.com/googleapis/google-cloud-python/pull/6468)) -- Bump minimum 'api_core' version for all GAPIC libs to 1.4.1. ([#6391](https://github.com/googleapis/google-cloud-python/pull/6391)) -- Avoid broken 'google-common-apis 1.5.4' release. ([#6355](https://github.com/googleapis/google-cloud-python/pull/6355)) - -## 1.5.1 - -10-29-2018 13:29 PDT - -### Implementation Changes -- Don't URL-encode slashes in gRPC request headers. ([#6310](https://github.com/googleapis/google-cloud-python/pull/6310)) - -### Internal / Testing Changes -- Back out changes from [#6267](https://github.com/googleapis/google-cloud-python/pull/6267) / `api_core-1.6.0a1` release. ([#6328](https://github.com/googleapis/google-cloud-python/pull/6328)) - -## 1.5.0 - -### New Features -- Add bidi, Bidirection Streaming, to api-core ([#6211](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6211)) - -### Internal / Testing Changes -- Use new Nox ([#6175](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6175)) - -## 1.4.1 - -### Dependencies -- Pin minimum protobuf dependency to 3.4.0. ([#6132](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6132)) - -### Internal / Testing Changes -- Add type-checking via pytype to api_core. ([#6116](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6116)) - -## 1.4.0 - -### Dependencies - -- Add support for gRPC connection management (available when using optional grpc_gcp dependency) ([#5553](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5553)) ([#5904](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5904)) -- Update classifiers to drop Python 3.4 and add Python 3.7 ([#5702](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5702)) - -## 1.3.0 - -### New Features - -- Add protobuf_helpers.field_mask to calculate a field mask from two messages (#5320) - -## 1.2.1 - -### Implementation Changes -- Make client_info work without gRPC installed. (#5075) -- Rename `x-goog-header-params` to `x-goog-request-params` (#5495) - -## 1.2.0 - -### Implementation Changes -- Add close method to grpc Channel (#5333) - -### Internal / Testing Changes -- Fix tests after grpcio update (#5333) -- Add Test runs for Python 3.7 and remove 3.4 (#5295) - -## 1.1.2 - -### Packaging -- Update setuptools before packaging (#5265) - -## 1.1.1 - -### Internal / Testing Changes -- Use `install_requires` for platform dependencies instead of `extras_require` (#4991) -- Update trove classifer to '5 - Production/Stable' - -## 1.1.0 - -### Interface additions - -- Add `datetime_helpers.DatetimeWithNanoSeconds` (#4979) - -### Implementation changes - -- Use a class to wrap grpc streaming errors instead of monkey-patching (#4995) - -## 1.0.0 - -This is the stable v1.0.0 release of google-api-core for Python. Releases after -this will not contain breaking changes. - -### Interface changes and additions - -- Made `api_core.page_iterator.PageIterator.item_to_value` public -- Added ability to specify retry for `Operation` and `polling.Future`. (#4922) - -## 0.1.4 - -### New Features - -- Add `ChannelStub` to `grpc_helpers` for testing gRPC-based clients. (#4705) - -### Notable Implementation Changes - -- Fix handling of gapic metadata when specified as `None`. (#4701) - -## 0.1.3 - -### Notable Implementation Changes - -- Apply scopes to explicitly provided credentials if needed (#4594). -- Removing `google.api_core.gapic_v1.method.METRICS_METADATA_KEY`. It - can be accessed via - `google.api_core.gapic_v1.client_info.METRICS_METADATA_KEY` (#4588). - -### Dependencies - -- Upgrading to latest `grpcio==1.8.2` (#4642). For details, see - related gRPC [bug](https://github.com/grpc/grpc/issues/9688) - and [fix](https://github.com/grpc/grpc/pull/13665). - -PyPI: https://pypi.org/project/google-api-core/0.1.3/ - -## 0.1.2 - -- Upgrading `concurrent.futures` backport from `>= 3.0.0` - to `>= 3.2.0` (#4521). -- Moved `datetime`-related helpers from `google.cloud.core` to - `google.api_core.datetime_helpers` (#4399). -- Added missing `client_info` to `gapic_v1/__init__.py`'s - `__all__` (#4567). -- Added helpers for routing headers to `gapic_v1` (#4336). - -PyPI: https://pypi.org/project/google-api-core/0.1.2/ - -## 0.1.1 - -### Dependencies - -- Upgrading `grpcio` dependency from `1.2.0, < 1.6dev` to `>= 1.7.0` (#4280) - -PyPI: https://pypi.org/project/google-api-core/0.1.1/ - -## 0.1.0 - -Initial release - -Prior to being separated, this package was developed in `google-cloud-core`, so -relevant changes from that package are included here. - -- Add google.api.core.gapic_v1.config (#4022) -- Add google.api.core.helpers.grpc_helpers (#4041) -- Add google.api.core.gapic_v1.method (#4057) -- Add wrap_with_paging (#4067) -- Add grpc_helpers.create_channel (#4069) -- Add DEFAULT sentinel for gapic_v1.method (#4079) -- Remove `googleapis-common-protos` from deps in non-`core` packages. (#4098) -- Add google.api.core.operations_v1 (#4081) -- Fix test assertion in test_wrap_method_with_overriding_retry_deadline (#4131) -- Add google.api.core.helpers.general_helpers.wraps (#4166) -- Update Docs with Python Setup Guide (#4187) -- Move modules in google.api.core.helpers up one level, delete google.api.core.helpers. (#4196) -- Clarify that PollingFuture timeout is in seconds. (#4201) -- Add api_core package (#4210) -- Replace usage of google.api.core with google.api_core (#4221) -- Add google.api_core.gapic_v2.client_info (#4225) -- Fix how api_core.operation populates exception errors (#4231) -- Fix bare except (#4250) -- Fix parsing of API errors with Unicode err message (#4251) -- Port gax proto helper methods (#4249) -- Remove gapic_v1.method.wrap_with_paging (#4257) -- Add final set of protobuf helpers to api_core (#4259) - -PyPI: https://pypi.org/project/google-api-core/0.1.0/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/PKG-INFO new/google-api-core-1.13.0/PKG-INFO --- old/google-api-core-1.11.0/PKG-INFO 2019-05-15 20:00:54.000000000 +0200 +++ new/google-api-core-1.13.0/PKG-INFO 2019-06-24 23:08:07.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-api-core -Version: 1.11.0 +Version: 1.13.0 Summary: Google API client core library Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python Author: Google LLC @@ -44,5 +44,5 @@ Classifier: Topic :: Internet Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* Provides-Extra: grpcio-gcp -Provides-Extra: grpc Provides-Extra: grpcgcp +Provides-Extra: grpc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google/api_core/bidi.py new/google-api-core-1.13.0/google/api_core/bidi.py --- old/google-api-core-1.11.0/google/api_core/bidi.py 2019-05-15 19:22:09.000000000 +0200 +++ new/google-api-core-1.13.0/google/api_core/bidi.py 2019-06-24 23:05:41.000000000 +0200 @@ -14,8 +14,11 @@ """Bi-directional streaming RPC helpers.""" +import collections +import datetime import logging import threading +import time from six.moves import queue @@ -134,6 +137,73 @@ yield item +class _Throttle(object): + """A context manager limiting the total entries in a sliding time window. + + If more than ``access_limit`` attempts are made to enter the context manager + instance in the last ``time window`` interval, the exceeding requests block + until enough time elapses. + + The context manager instances are thread-safe and can be shared between + multiple threads. If multiple requests are blocked and waiting to enter, + the exact order in which they are allowed to proceed is not determined. + + Example:: + + max_three_per_second = _Throttle( + access_limit=3, time_window=datetime.timedelta(seconds=1) + ) + + for i in range(5): + with max_three_per_second as time_waited: + print("{}: Waited {} seconds to enter".format(i, time_waited)) + + Args: + access_limit (int): the maximum number of entries allowed in the time window + time_window (datetime.timedelta): the width of the sliding time window + """ + + def __init__(self, access_limit, time_window): + if access_limit < 1: + raise ValueError("access_limit argument must be positive") + + if time_window <= datetime.timedelta(0): + raise ValueError("time_window argument must be a positive timedelta") + + self._time_window = time_window + self._access_limit = access_limit + self._past_entries = collections.deque(maxlen=access_limit) # least recent first + self._entry_lock = threading.Lock() + + def __enter__(self): + with self._entry_lock: + cutoff_time = datetime.datetime.now() - self._time_window + + # drop the entries that are too old, as they are no longer relevant + while self._past_entries and self._past_entries[0] < cutoff_time: + self._past_entries.popleft() + + if len(self._past_entries) < self._access_limit: + self._past_entries.append(datetime.datetime.now()) + return 0.0 # no waiting was needed + + to_wait = (self._past_entries[0] - cutoff_time).total_seconds() + time.sleep(to_wait) + + self._past_entries.append(datetime.datetime.now()) + return to_wait + + def __exit__(self, *_): + pass + + def __repr__(self): + return "{}(access_limit={}, time_window={})".format( + self.__class__.__name__, + self._access_limit, + repr(self._time_window), + ) + + class BidiRpc(object): """A helper for consuming a bi-directional streaming RPC. @@ -323,15 +393,31 @@ whenever an error is encountered on the stream. metadata Sequence[Tuple(str, str)]: RPC metadata to include in the request. + throttle_reopen (bool): If ``True``, throttling will be applied to + stream reopen calls. Defaults to ``False``. """ - def __init__(self, start_rpc, should_recover, initial_request=None, metadata=None): + def __init__( + self, + start_rpc, + should_recover, + initial_request=None, + metadata=None, + throttle_reopen=False, + ): super(ResumableBidiRpc, self).__init__(start_rpc, initial_request, metadata) self._should_recover = should_recover self._operational_lock = threading.RLock() self._finalized = False self._finalize_lock = threading.Lock() + if throttle_reopen: + self._reopen_throttle = _Throttle( + access_limit=5, time_window=datetime.timedelta(seconds=10), + ) + else: + self._reopen_throttle = None + def _finalize(self, result): with self._finalize_lock: if self._finalized: @@ -374,7 +460,11 @@ # retryable error. try: - self.open() + if self._reopen_throttle: + with self._reopen_throttle: + self.open() + else: + self.open() # If re-opening or re-calling the method fails for any reason, # consider it a terminal error and finalize the stream. except Exception as exc: @@ -573,7 +663,7 @@ thread = threading.Thread( name=_BIDIRECTIONAL_CONSUMER_NAME, target=self._thread_main, - args=(ready,) + args=(ready,), ) thread.daemon = True thread.start() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google/api_core/client_options.py new/google-api-core-1.13.0/google/api_core/client_options.py --- old/google-api-core-1.11.0/google/api_core/client_options.py 1970-01-01 01:00:00.000000000 +0100 +++ new/google-api-core-1.13.0/google/api_core/client_options.py 2019-06-24 23:05:41.000000000 +0200 @@ -0,0 +1,48 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Client options class. + +Client options provide a consistent interface for user options to be defined +across clients. +""" + + +class ClientOptions(object): + """Client Options used to set options on clients. + + Args: + api_endpoint (str): The desired API endpoint, e.g., compute.googleapis.com + """ + + def __init__(self, api_endpoint=None): + self.api_endpoint = api_endpoint + + +def from_dict(options): + """Construct a client options object from a dictionary. + + Args: + options (dict): A dictionary with client options. + """ + + client_options = ClientOptions() + + for key, value in options.items(): + if hasattr(client_options, key): + setattr(client_options, key, value) + else: + raise ValueError("ClientOptions does not accept an option '" + key + "'") + + return client_options diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google/api_core/general_helpers.py new/google-api-core-1.13.0/google/api_core/general_helpers.py --- old/google-api-core-1.11.0/google/api_core/general_helpers.py 2018-12-03 18:45:52.000000000 +0100 +++ new/google-api-core-1.13.0/google/api_core/general_helpers.py 2019-06-24 23:05:41.000000000 +0200 @@ -26,7 +26,8 @@ def wraps(wrapped): """A functools.wraps helper that handles partial objects on Python 2.""" - if isinstance(wrapped, functools.partial): + # https://github.com/google/pytype/issues/322 + if isinstance(wrapped, functools.partial): # pytype: disable=wrong-arg-types return six.wraps(wrapped, assigned=_PARTIAL_VALID_ASSIGNMENTS) else: return six.wraps(wrapped) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google/api_core/retry.py new/google-api-core-1.13.0/google/api_core/retry.py --- old/google-api-core-1.11.0/google/api_core/retry.py 2018-12-03 18:45:52.000000000 +0100 +++ new/google-api-core-1.13.0/google/api_core/retry.py 2019-06-24 23:05:41.000000000 +0200 @@ -98,7 +98,9 @@ # Pylint sees this as a constant, but it is also an alias that should be # considered a function. if_transient_error = if_exception_type( - (exceptions.InternalServerError, exceptions.TooManyRequests) + exceptions.InternalServerError, + exceptions.TooManyRequests, + exceptions.ServiceUnavailable, ) """A predicate that checks if an exception is a transient API error. @@ -107,6 +109,7 @@ - :class:`google.api_core.exceptions.InternalServerError` - HTTP 500, gRPC ``INTERNAL(13)`` and its subclasses. - :class:`google.api_core.exceptions.TooManyRequests` - HTTP 429 +- :class:`google.api_core.exceptions.ServiceUnavailable` - HTTP 503 - :class:`google.api_core.exceptions.ResourceExhausted` - gRPC ``RESOURCE_EXHAUSTED(8)`` """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google_api_core.egg-info/PKG-INFO new/google-api-core-1.13.0/google_api_core.egg-info/PKG-INFO --- old/google-api-core-1.11.0/google_api_core.egg-info/PKG-INFO 2019-05-15 20:00:54.000000000 +0200 +++ new/google-api-core-1.13.0/google_api_core.egg-info/PKG-INFO 2019-06-24 23:08:06.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-api-core -Version: 1.11.0 +Version: 1.13.0 Summary: Google API client core library Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python Author: Google LLC @@ -44,5 +44,5 @@ Classifier: Topic :: Internet Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* Provides-Extra: grpcio-gcp -Provides-Extra: grpc Provides-Extra: grpcgcp +Provides-Extra: grpc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google_api_core.egg-info/SOURCES.txt new/google-api-core-1.13.0/google_api_core.egg-info/SOURCES.txt --- old/google-api-core-1.11.0/google_api_core.egg-info/SOURCES.txt 2019-05-15 20:00:54.000000000 +0200 +++ new/google-api-core-1.13.0/google_api_core.egg-info/SOURCES.txt 2019-06-24 23:08:06.000000000 +0200 @@ -1,16 +1,13 @@ -.coveragerc -.flake8 -CHANGELOG.md LICENSE MANIFEST.in README.rst -noxfile.py setup.cfg setup.py google/__init__.py google/api_core/__init__.py google/api_core/bidi.py google/api_core/client_info.py +google/api_core/client_options.py google/api_core/datetime_helpers.py google/api_core/exceptions.py google/api_core/general_helpers.py @@ -45,6 +42,7 @@ tests/unit/__init__.py tests/unit/test_bidi.py tests/unit/test_client_info.py +tests/unit/test_client_options.py tests/unit/test_datetime_helpers.py tests/unit/test_exceptions.py tests/unit/test_general_helpers.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/google_api_core.egg-info/requires.txt new/google-api-core-1.13.0/google_api_core.egg-info/requires.txt --- old/google-api-core-1.11.0/google_api_core.egg-info/requires.txt 2019-05-15 20:00:54.000000000 +0200 +++ new/google-api-core-1.13.0/google_api_core.egg-info/requires.txt 2019-06-24 23:08:06.000000000 +0200 @@ -10,7 +10,7 @@ futures>=3.2.0 [grpc] -grpcio>=1.8.2 +grpcio<2.0dev,>=1.8.2 [grpcgcp] grpcio-gcp>=0.2.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/noxfile.py new/google-api-core-1.13.0/noxfile.py --- old/google-api-core-1.11.0/noxfile.py 2019-05-15 19:22:09.000000000 +0200 +++ new/google-api-core-1.13.0/noxfile.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,105 +0,0 @@ -# Copyright 2016 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -import os - -# https://github.com/google/importlab/issues/25 -import nox # pytype: disable=import-error - - -def default(session): - """Default unit test session. - - This is intended to be run **without** an interpreter set, so - that the current ``python`` (on the ``PATH``) or the version of - Python corresponding to the ``nox`` binary the ``PATH`` can - run the tests. - """ - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov", "grpcio >= 1.0.2") - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.api_core", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=97", - os.path.join("tests", "unit"), - *session.posargs - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7"]) -def unit_grpc_gcp(session): - """Run the unit test suite with grpcio-gcp installed.""" - - # Install grpcio-gcp - session.install("grpcio-gcp") - - default(session) - - -@nox.session(python="3.6") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", "flake8-import-order") - session.install(".") - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - - session.install("docutils", "Pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -# No 2.7 due to https://github.com/google/importlab/issues/26. -# No 3.7 because pytype supports up to 3.6 only. -@nox.session(python="3.6") -def pytype(session): - """Run type-checking.""" - session.install( - ".", "grpcio >= 1.8.2", "grpcio-gcp >= 0.2.2", "pytype >= 2019.3.21" - ) - session.run("pytype") - - -@nox.session(python="3.6") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") - session.run("coverage", "erase") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/setup.py new/google-api-core-1.13.0/setup.py --- old/google-api-core-1.11.0/setup.py 2019-05-15 19:57:02.000000000 +0200 +++ new/google-api-core-1.13.0/setup.py 2019-06-24 23:05:41.000000000 +0200 @@ -22,7 +22,7 @@ name = "google-api-core" description = "Google API client core library" -version = "1.11.0" +version = "1.13.0" # Should be one of: # 'Development Status :: 3 - Alpha' # 'Development Status :: 4 - Beta' @@ -39,7 +39,7 @@ 'futures >= 3.2.0; python_version < "3.2"', ] extras = { - "grpc": "grpcio >= 1.8.2", + "grpc": "grpcio >= 1.8.2, < 2.0dev", "grpcgcp": "grpcio-gcp >= 0.2.2", "grpcio-gcp": "grpcio-gcp >= 0.2.2", } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/tests/unit/test_bidi.py new/google-api-core-1.13.0/tests/unit/test_bidi.py --- old/google-api-core-1.11.0/tests/unit/test_bidi.py 2019-05-15 19:22:09.000000000 +0200 +++ new/google-api-core-1.13.0/tests/unit/test_bidi.py 2019-06-24 23:05:41.000000000 +0200 @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import datetime import logging import threading @@ -116,6 +117,87 @@ assert items == [] +class Test_Throttle(object): + def test_repr(self): + delta = datetime.timedelta(seconds=4.5) + instance = bidi._Throttle(access_limit=42, time_window=delta) + assert repr(instance) == \ + "_Throttle(access_limit=42, time_window={})".format(repr(delta)) + + def test_raises_error_on_invalid_init_arguments(self): + with pytest.raises(ValueError) as exc_info: + bidi._Throttle( + access_limit=10, time_window=datetime.timedelta(seconds=0.0) + ) + assert "time_window" in str(exc_info.value) + assert "must be a positive timedelta" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + bidi._Throttle( + access_limit=0, time_window=datetime.timedelta(seconds=10) + ) + assert "access_limit" in str(exc_info.value) + assert "must be positive" in str(exc_info.value) + + def test_does_not_delay_entry_attempts_under_threshold(self): + throttle = bidi._Throttle( + access_limit=3, time_window=datetime.timedelta(seconds=1) + ) + entries = [] + + for _ in range(3): + with throttle as time_waited: + entry_info = { + "entered_at": datetime.datetime.now(), + "reported_wait": time_waited, + } + entries.append(entry_info) + + # check the reported wait times ... + assert all(entry["reported_wait"] == 0.0 for entry in entries) + + # .. and the actual wait times + delta = entries[1]["entered_at"] - entries[0]["entered_at"] + assert delta.total_seconds() < 0.1 + delta = entries[2]["entered_at"] - entries[1]["entered_at"] + assert delta.total_seconds() < 0.1 + + def test_delays_entry_attempts_above_threshold(self): + throttle = bidi._Throttle( + access_limit=3, time_window=datetime.timedelta(seconds=1) + ) + entries = [] + + for _ in range(6): + with throttle as time_waited: + entry_info = { + "entered_at": datetime.datetime.now(), + "reported_wait": time_waited, + } + entries.append(entry_info) + + # For each group of 4 consecutive entries the time difference between + # the first and the last entry must have been greater than time_window, + # because a maximum of 3 are allowed in each time_window. + for i, entry in enumerate(entries[3:], start=3): + first_entry = entries[i - 3] + delta = entry["entered_at"] - first_entry["entered_at"] + assert delta.total_seconds() > 1.0 + + # check the reported wait times + # (NOTE: not using assert all(...), b/c the coverage check would complain) + for i, entry in enumerate(entries): + if i != 3: + assert entry["reported_wait"] == 0.0 + + # The delayed entry is expected to have been delayed for a significant + # chunk of the full second, and the actual and reported delay times + # should reflect that. + assert entries[3]["reported_wait"] > 0.7 + delta = entries[3]["entered_at"] - entries[2]["entered_at"] + assert delta.total_seconds() > 0.7 + + class _CallAndFuture(grpc.Call, grpc.Future): pass @@ -442,6 +524,22 @@ assert bidi_rpc.is_active is False callback.assert_called_once_with(error2) + def test_using_throttle_on_reopen_requests(self): + call = CallStub([]) + start_rpc = mock.create_autospec( + grpc.StreamStreamMultiCallable, instance=True, return_value=call + ) + should_recover = mock.Mock(spec=["__call__"], return_value=True) + bidi_rpc = bidi.ResumableBidiRpc( + start_rpc, should_recover, throttle_reopen=True + ) + + patcher = mock.patch.object(bidi_rpc._reopen_throttle.__class__, "__enter__") + with patcher as mock_enter: + bidi_rpc._reopen() + + mock_enter.assert_called_once() + def test_send_not_open(self): bidi_rpc = bidi.ResumableBidiRpc(None, lambda _: False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/tests/unit/test_client_options.py new/google-api-core-1.13.0/tests/unit/test_client_options.py --- old/google-api-core-1.11.0/tests/unit/test_client_options.py 1970-01-01 01:00:00.000000000 +0100 +++ new/google-api-core-1.13.0/tests/unit/test_client_options.py 2019-06-24 23:05:41.000000000 +0200 @@ -0,0 +1,36 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +from google.api_core import client_options + + +def test_constructor(): + options = client_options.ClientOptions(api_endpoint="foo.googleapis.com") + + assert options.api_endpoint == "foo.googleapis.com" + + +def test_from_dict(): + options = client_options.from_dict({"api_endpoint": "foo.googleapis.com"}) + + assert options.api_endpoint == "foo.googleapis.com" + + +def test_from_dict_bad_argument(): + with pytest.raises(ValueError): + client_options.from_dict( + {"api_endpoint": "foo.googleapis.com", "bad_arg": "1234"} + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/tests/unit/test_datetime_helpers.py new/google-api-core-1.13.0/tests/unit/test_datetime_helpers.py --- old/google-api-core-1.11.0/tests/unit/test_datetime_helpers.py 2019-05-15 19:25:15.000000000 +0200 +++ new/google-api-core-1.13.0/tests/unit/test_datetime_helpers.py 2019-06-24 23:05:41.000000000 +0200 @@ -270,6 +270,24 @@ assert stamp == expected @staticmethod + @pytest.mark.parametrize( + "fractional, nanos", + [ + ("12345678", 123456780), + ("1234567", 123456700), + ("123456", 123456000), + ("12345", 123450000), + ("1234", 123400000), + ("123", 123000000), + ("12", 120000000), + ("1", 100000000), + ], + ) + def test_from_rfc3339_test_nanoseconds(fractional, nanos): + value = "2009-12-17T12:44:32.{}Z".format(fractional) + assert datetime_helpers.DatetimeWithNanoseconds.from_rfc3339(value).nanosecond == nanos + + @staticmethod def test_timestamp_pb_wo_nanos_naive(): stamp = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, 123456) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-api-core-1.11.0/tests/unit/test_retry.py new/google-api-core-1.13.0/tests/unit/test_retry.py --- old/google-api-core-1.11.0/tests/unit/test_retry.py 2018-12-03 18:45:52.000000000 +0100 +++ new/google-api-core-1.13.0/tests/unit/test_retry.py 2019-06-24 23:05:41.000000000 +0200 @@ -41,6 +41,7 @@ def test_if_transient_error(): assert retry.if_transient_error(exceptions.InternalServerError("")) assert retry.if_transient_error(exceptions.TooManyRequests("")) + assert retry.if_transient_error(exceptions.ServiceUnavailable("")) assert not retry.if_transient_error(exceptions.InvalidArgument(""))