google-api-core 2.32.0__tar.gz → 2.34.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {google_api_core-2.32.0 → google_api_core-2.34.0}/PKG-INFO +6 -9
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/__init__.py +1 -2
- google_api_core-2.34.0/google/api_core/_feature_gating_helpers.py +139 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/_python_package_support.py +4 -6
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/_python_version_support.py +3 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/bidi.py +1 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/bidi_async.py +1 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/client_logging.py +1 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/datetime_helpers.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/future/_helpers.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/future/async_future.py +2 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/future/polling.py +1 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/__init__.py +3 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/client_info.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/config.py +1 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/method.py +72 -11
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/method_async.py +5 -3
- google_api_core-2.34.0/google/api_core/gapic_v1/requests.py +100 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/grpc_helpers.py +16 -7
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/grpc_helpers_async.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operation.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operation_async.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/abstract_operations_base_client.py +2 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/abstract_operations_client.py +8 -7
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/operations_async_client.py +3 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/operations_client.py +4 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/operations_rest_client_async.py +5 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/pagers.py +1 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/pagers_async.py +2 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/transports/__init__.py +1 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/transports/base.py +7 -5
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/transports/rest.py +13 -9
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/transports/rest_asyncio.py +31 -15
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/path_template.py +2 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/protobuf_helpers.py +1 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/rest_helpers.py +68 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/rest_streaming.py +2 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/rest_streaming_async.py +1 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/__init__.py +19 -16
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/retry_base.py +2 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/retry_streaming.py +15 -14
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/retry_streaming_async.py +17 -17
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/retry_unary.py +10 -9
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry/retry_unary_async.py +12 -11
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/retry_async.py +10 -7
- google_api_core-2.34.0/google/api_core/universe.py +199 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/version.py +1 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google_api_core.egg-info/PKG-INFO +6 -9
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google_api_core.egg-info/SOURCES.txt +5 -0
- google_api_core-2.34.0/google_api_core.egg-info/requires.txt +17 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/pyproject.toml +5 -8
- {google_api_core-2.32.0 → google_api_core-2.34.0}/setup.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/gapic/test_config_async.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/gapic/test_method_async.py +8 -6
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/operations_v1/test_operations_async_client.py +3 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/retry/test_retry_streaming_async.py +3 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/retry/test_retry_unary_async.py +1 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/test_bidi_async.py +1 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/test_grpc_helpers_async.py +4 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/test_operation_async.py +3 -6
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/test_rest_streaming_async.py +5 -8
- google_api_core-2.34.0/tests/conftest.py +31 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/helpers.py +2 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/gapic/test_config.py +0 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/gapic/test_method.py +99 -3
- google_api_core-2.34.0/tests/unit/gapic/test_requests.py +152 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/operations_v1/test_operations_client.py +52 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/operations_v1/test_operations_rest_client.py +19 -10
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/retry/test_retry_base.py +6 -11
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/retry/test_retry_imports.py +5 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/retry/test_retry_streaming.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/retry/test_retry_unary.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_bidi.py +1 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_client_options.py +3 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_datetime_helpers.py +1 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_extended_operation.py +1 -3
- google_api_core-2.34.0/tests/unit/test_feature_gating_helpers.py +224 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_grpc_helpers.py +3 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_iam.py +3 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_operation.py +3 -6
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_path_template.py +2 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_protobuf_helpers.py +13 -12
- google_api_core-2.34.0/tests/unit/test_rest_helpers.py +278 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_rest_streaming.py +2 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_timeout.py +2 -1
- google_api_core-2.34.0/tests/unit/test_universe.py +261 -0
- google_api_core-2.32.0/google/api_core/universe.py +0 -82
- google_api_core-2.32.0/google_api_core.egg-info/requires.txt +0 -24
- google_api_core-2.32.0/tests/unit/test_rest_helpers.py +0 -94
- google_api_core-2.32.0/tests/unit/test_universe.py +0 -63
- {google_api_core-2.32.0 → google_api_core-2.34.0}/LICENSE +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/MANIFEST.in +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/README.rst +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/_rest_streaming_base.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/bidi_base.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/client_info.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/client_options.py +1 -1
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/exceptions.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/extended_operation.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/future/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/future/base.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/config_async.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/gapic_v1/routing_header.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/general_helpers.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/iam.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/__init__.py +3 -3
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/operations_client_config.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/operations_v1/pagers_base.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/page_iterator.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/page_iterator_async.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/py.typed +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/timeout.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/version_header.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google_api_core.egg-info/dependency_links.txt +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/google_api_core.egg-info/top_level.txt +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/setup.cfg +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/future/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/future/test_async_future.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/operations_v1/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/retry/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/asyncio/test_page_iterator_async.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/future/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/future/test__helpers.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/future/test_polling.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/gapic/test_client_info.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/gapic/test_routing_header.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/operations_v1/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/retry/__init__.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_client_info.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_client_logging.py +2 -2
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_exceptions.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_packaging.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_page_iterator.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_python_package_support.py +4 -4
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_python_version_support.py +0 -0
- {google_api_core-2.32.0 → google_api_core-2.34.0}/tests/unit/test_version_header.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: google-api-core
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.34.0
|
|
4
4
|
Summary: Google API client core library
|
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
|
6
6
|
License: Apache 2.0
|
|
@@ -22,21 +22,18 @@ Classifier: Topic :: Internet
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/x-rst
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: googleapis-common-protos<2.0.0,>=1.
|
|
26
|
-
Requires-Dist: protobuf<8.0.0,>=
|
|
27
|
-
Requires-Dist: proto-plus<2.0.0,>=1.
|
|
28
|
-
Requires-Dist: proto-plus<2.0.0,>=1.25.0; python_version >= "3.13"
|
|
25
|
+
Requires-Dist: googleapis-common-protos<2.0.0,>=1.69.2
|
|
26
|
+
Requires-Dist: protobuf<8.0.0,>=6.33.5
|
|
27
|
+
Requires-Dist: proto-plus<2.0.0,>=1.26.1
|
|
29
28
|
Requires-Dist: google-auth<3.0.0,>=2.14.1
|
|
30
29
|
Requires-Dist: requests<3.0.0,>=2.33.0
|
|
31
30
|
Provides-Extra: async-rest
|
|
32
31
|
Requires-Dist: google-auth[aiohttp]<3.0.0,>=2.14.1; extra == "async-rest"
|
|
33
32
|
Requires-Dist: aiohttp>=3.13.4; extra == "async-rest"
|
|
34
33
|
Provides-Extra: grpc
|
|
35
|
-
Requires-Dist: grpcio<2.0.0,>=1.
|
|
36
|
-
Requires-Dist: grpcio<2.0.0,>=1.49.1; python_version >= "3.11" and extra == "grpc"
|
|
34
|
+
Requires-Dist: grpcio<2.0.0,>=1.59.0; extra == "grpc"
|
|
37
35
|
Requires-Dist: grpcio<2.0.0,>=1.75.1; python_version >= "3.14" and extra == "grpc"
|
|
38
|
-
Requires-Dist: grpcio-status<2.0.0,>=1.
|
|
39
|
-
Requires-Dist: grpcio-status<2.0.0,>=1.49.1; python_version >= "3.11" and extra == "grpc"
|
|
36
|
+
Requires-Dist: grpcio-status<2.0.0,>=1.59.0; extra == "grpc"
|
|
40
37
|
Requires-Dist: grpcio-status<2.0.0,>=1.75.1; python_version >= "3.14" and extra == "grpc"
|
|
41
38
|
Dynamic: license-file
|
|
42
39
|
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
This package contains common code and utilities used by Google client libraries.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
from google.api_core import _python_package_support
|
|
21
|
-
from google.api_core import _python_version_support
|
|
20
|
+
from google.api_core import _python_package_support, _python_version_support
|
|
22
21
|
from google.api_core import version as api_core_version
|
|
23
22
|
|
|
24
23
|
__version__ = api_core_version.__version__
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2026 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
"""Observability environment variable and client options resolution helpers."""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
import warnings
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
# We import ClientOptions for type hinting
|
|
24
|
+
from google.api_core.client_options import ClientOptions
|
|
25
|
+
|
|
26
|
+
# Allowed truthy and falsy patterns for environment variables
|
|
27
|
+
_TRUTHY_VALUES = ("y", "yes", "t", "true", "on", "1")
|
|
28
|
+
_FALSY_VALUES = ("n", "no", "f", "false", "off", "0")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FeatureGatingError(ValueError):
|
|
32
|
+
"""Raised when feature gating resolution fails or is misconfigured."""
|
|
33
|
+
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _strtobool(val: str) -> bool | None:
|
|
38
|
+
"""Convert a string representation of truth to a boolean."""
|
|
39
|
+
clean_val = val.lower().strip()
|
|
40
|
+
if not clean_val:
|
|
41
|
+
return None
|
|
42
|
+
if clean_val in _TRUTHY_VALUES:
|
|
43
|
+
return True
|
|
44
|
+
if clean_val in _FALSY_VALUES:
|
|
45
|
+
return False
|
|
46
|
+
raise ValueError(f"Invalid truth value: {val!r}")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _get_env_bool(name: str) -> bool | None:
|
|
50
|
+
"""Retrieve the boolean value of an environment variable."""
|
|
51
|
+
val = os.getenv(name)
|
|
52
|
+
if val is None:
|
|
53
|
+
return None
|
|
54
|
+
try:
|
|
55
|
+
return _strtobool(val)
|
|
56
|
+
except ValueError as e:
|
|
57
|
+
warnings.warn(f"Ignored invalid value for {name}: {e}", RuntimeWarning)
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _has_feature_key(
|
|
62
|
+
*, configuration: ClientOptions | dict[str, Any] | None, feature_key: str
|
|
63
|
+
) -> bool:
|
|
64
|
+
"""Checks if a specific feature key is present and not None in configuration."""
|
|
65
|
+
if configuration is None:
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
if feature_key.startswith("__"):
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
if isinstance(configuration, dict):
|
|
72
|
+
return configuration.get(feature_key) is not None
|
|
73
|
+
|
|
74
|
+
return getattr(configuration, feature_key, None) is not None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def resolve_feature_flags(
|
|
78
|
+
*,
|
|
79
|
+
env_var: str,
|
|
80
|
+
feature_key: str,
|
|
81
|
+
configuration: ClientOptions | dict[str, Any] | None = None,
|
|
82
|
+
) -> bool:
|
|
83
|
+
"""Determines if a feature is enabled based on environment variables and configuration.
|
|
84
|
+
|
|
85
|
+
Behavior depends on whether the `env_var` name contains "EXPERIMENTAL":
|
|
86
|
+
|
|
87
|
+
- **Experimental Path** (env_var contains "EXPERIMENTAL"):
|
|
88
|
+
Strict control. Requires the environment variable to be explicitly 'true'.
|
|
89
|
+
If a programmatic feature key is passed but the environment variable is not 'true',
|
|
90
|
+
raises FeatureGatingError (Fail Fast).
|
|
91
|
+
|
|
92
|
+
- **GA Path** (env_var does not contain "EXPERIMENTAL"):
|
|
93
|
+
Standard precedence. Enabled if a programmatic feature key is passed,
|
|
94
|
+
otherwise falls back to the environment variable value.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
env_var: The name of the environment variable controlling this feature.
|
|
98
|
+
feature_key: The key in configuration/attributes for the programmatic configuration.
|
|
99
|
+
configuration: Optional. A dictionary or object containing client configuration.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
bool: True if the feature is resolved to enabled, False otherwise.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
FeatureGatingError: If a feature key is provided for an experimental feature without enabling the experimental environment variable.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
# Check for programmatic feature configuration
|
|
109
|
+
has_feature_key = _has_feature_key(
|
|
110
|
+
configuration=configuration, feature_key=feature_key
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Read environment variable
|
|
114
|
+
env_var_setting = _get_env_bool(env_var)
|
|
115
|
+
|
|
116
|
+
# EXPERIMENTAL PATH:
|
|
117
|
+
# Resolution Hierarchy:
|
|
118
|
+
# 1. EXPERIMENTAL Environment Variable
|
|
119
|
+
# 2. Fail Fast if Feature Key present but EXPERIMENTAL Environment Variable is not enabled
|
|
120
|
+
if "EXPERIMENTAL" in env_var:
|
|
121
|
+
# Fail Fast if feature key present but experimental environment variable is not enabled
|
|
122
|
+
if env_var_setting is not True and has_feature_key:
|
|
123
|
+
raise FeatureGatingError(
|
|
124
|
+
f"Experimental feature requires {env_var} to be set to 'true' to use programmatic configuration."
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return bool(env_var_setting)
|
|
128
|
+
|
|
129
|
+
# GENERAL AVAILABILITY PATH:
|
|
130
|
+
# Resolution Hierarchy:
|
|
131
|
+
# 1. Programmatic Configuration (Feature Key)
|
|
132
|
+
# 2. Environment Variable
|
|
133
|
+
|
|
134
|
+
# Check Programmatic Configuration
|
|
135
|
+
if has_feature_key:
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
# Check Environment Variable
|
|
139
|
+
return bool(env_var_setting)
|
{google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/_python_package_support.py
RENAMED
|
@@ -15,17 +15,15 @@
|
|
|
15
15
|
"""Code to check versions of dependencies used by Google Cloud Client Libraries."""
|
|
16
16
|
|
|
17
17
|
import warnings
|
|
18
|
-
from typing import Optional, Tuple
|
|
19
|
-
|
|
20
18
|
from collections import namedtuple
|
|
19
|
+
from importlib import metadata
|
|
20
|
+
from typing import Optional, Tuple
|
|
21
21
|
|
|
22
22
|
from ._python_version_support import (
|
|
23
23
|
_flatten_message,
|
|
24
24
|
_get_distribution_and_import_packages,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
from importlib import metadata
|
|
28
|
-
|
|
29
27
|
ParsedVersion = Tuple[int, ...]
|
|
30
28
|
|
|
31
29
|
# Here we list all the packages for which we want to issue warnings
|
|
@@ -37,7 +35,7 @@ DependencyConstraint = namedtuple(
|
|
|
37
35
|
_PACKAGE_DEPENDENCY_WARNINGS = [
|
|
38
36
|
DependencyConstraint(
|
|
39
37
|
"google.protobuf",
|
|
40
|
-
minimum_fully_supported_version="
|
|
38
|
+
minimum_fully_supported_version="6.33.5",
|
|
41
39
|
recommended_version="6.x",
|
|
42
40
|
)
|
|
43
41
|
]
|
|
@@ -52,7 +50,7 @@ UNKNOWN_VERSION_STRING = "--"
|
|
|
52
50
|
def parse_version_to_tuple(version_string: str) -> ParsedVersion:
|
|
53
51
|
"""Safely converts a semantic version string to a comparable tuple of integers.
|
|
54
52
|
|
|
55
|
-
Example: "
|
|
53
|
+
Example: "6.33.5" -> (6, 33, 5)
|
|
56
54
|
Ignores non-numeric parts and handles common version formats.
|
|
57
55
|
|
|
58
56
|
Args:
|
{google_api_core-2.32.0 → google_api_core-2.34.0}/google/api_core/_python_version_support.py
RENAMED
|
@@ -17,13 +17,12 @@
|
|
|
17
17
|
import datetime
|
|
18
18
|
import enum
|
|
19
19
|
import functools
|
|
20
|
-
from importlib import metadata
|
|
21
20
|
import logging
|
|
22
|
-
import warnings
|
|
23
21
|
import sys
|
|
24
22
|
import textwrap
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
import warnings
|
|
24
|
+
from importlib import metadata
|
|
25
|
+
from typing import Any, Dict, List, NamedTuple, Optional, Tuple
|
|
27
26
|
|
|
28
27
|
_LOGGER = logging.getLogger(__name__)
|
|
29
28
|
|
|
@@ -113,7 +113,7 @@ class _RequestQueueGenerator(object):
|
|
|
113
113
|
except queue_module.Empty:
|
|
114
114
|
if not self._is_active():
|
|
115
115
|
_LOGGER.debug(
|
|
116
|
-
"Empty queue and inactive call, exiting request
|
|
116
|
+
"Empty queue and inactive call, exiting request generator."
|
|
117
117
|
)
|
|
118
118
|
return
|
|
119
119
|
else:
|
|
@@ -18,14 +18,12 @@ import asyncio
|
|
|
18
18
|
import logging
|
|
19
19
|
from typing import Callable, Optional, Union
|
|
20
20
|
|
|
21
|
+
from google.protobuf.message import Message as ProtobufMessage
|
|
21
22
|
from grpc import aio
|
|
22
23
|
|
|
23
24
|
from google.api_core import exceptions
|
|
24
25
|
from google.api_core.bidi_base import BidiRpcBase
|
|
25
26
|
|
|
26
|
-
from google.protobuf.message import Message as ProtobufMessage
|
|
27
|
-
|
|
28
|
-
|
|
29
27
|
_LOGGER = logging.getLogger(__name__)
|
|
30
28
|
|
|
31
29
|
|
|
@@ -16,9 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import asyncio
|
|
18
18
|
|
|
19
|
-
from google.api_core import exceptions
|
|
20
|
-
from google.api_core import retry
|
|
21
|
-
from google.api_core import retry_async
|
|
19
|
+
from google.api_core import exceptions, retry, retry_async
|
|
22
20
|
from google.api_core.future import base
|
|
23
21
|
|
|
24
22
|
|
|
@@ -101,7 +99,7 @@ class AsyncFuture(base.Future):
|
|
|
101
99
|
await retry_(self._done_or_raise)()
|
|
102
100
|
except exceptions.RetryError:
|
|
103
101
|
raise asyncio.TimeoutError(
|
|
104
|
-
"Operation did not complete within the designated
|
|
102
|
+
"Operation did not complete within the designated timeout."
|
|
105
103
|
)
|
|
106
104
|
|
|
107
105
|
async def result(self, timeout=None):
|
|
@@ -19,8 +19,7 @@ import concurrent.futures
|
|
|
19
19
|
|
|
20
20
|
from google.api_core import exceptions
|
|
21
21
|
from google.api_core import retry as retries
|
|
22
|
-
from google.api_core.future import _helpers
|
|
23
|
-
from google.api_core.future import base
|
|
22
|
+
from google.api_core.future import _helpers, base
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class _OperationNotComplete(Exception):
|
|
@@ -25,9 +25,10 @@ _has_grpc = importlib.util.find_spec("grpc") is not None
|
|
|
25
25
|
# Older Python versions safely ignore this variable.
|
|
26
26
|
__lazy_modules__: Set[str] = {
|
|
27
27
|
"google.api_core.gapic_v1.client_info",
|
|
28
|
+
"google.api_core.gapic_v1.requests",
|
|
28
29
|
"google.api_core.gapic_v1.routing_header",
|
|
29
30
|
}
|
|
30
|
-
__all__ = ["client_info", "routing_header"]
|
|
31
|
+
__all__ = ["client_info", "requests", "routing_header"]
|
|
31
32
|
|
|
32
33
|
if _has_grpc:
|
|
33
34
|
__lazy_modules__.update(
|
|
@@ -41,6 +42,7 @@ if _has_grpc:
|
|
|
41
42
|
|
|
42
43
|
from google.api_core.gapic_v1 import ( # noqa: E402
|
|
43
44
|
client_info,
|
|
45
|
+
requests,
|
|
44
46
|
routing_header,
|
|
45
47
|
)
|
|
46
48
|
|
|
@@ -22,10 +22,7 @@ import collections
|
|
|
22
22
|
|
|
23
23
|
import grpc
|
|
24
24
|
|
|
25
|
-
from google.api_core import exceptions
|
|
26
|
-
from google.api_core import retry
|
|
27
|
-
from google.api_core import timeout
|
|
28
|
-
|
|
25
|
+
from google.api_core import exceptions, retry, timeout
|
|
29
26
|
|
|
30
27
|
_MILLIS_PER_SECOND = 1000.0
|
|
31
28
|
|
|
@@ -20,6 +20,7 @@ compression, pagination, and long-running operations to gRPC methods.
|
|
|
20
20
|
|
|
21
21
|
import enum
|
|
22
22
|
import functools
|
|
23
|
+
from typing import List, Tuple
|
|
23
24
|
|
|
24
25
|
from google.api_core import grpc_helpers
|
|
25
26
|
from google.api_core.gapic_v1 import client_info
|
|
@@ -57,6 +58,52 @@ def _apply_decorators(func, decorators):
|
|
|
57
58
|
return func
|
|
58
59
|
|
|
59
60
|
|
|
61
|
+
def _deduplicate_metadata_tokens(*headers: str | None) -> str:
|
|
62
|
+
"""
|
|
63
|
+
Given one or more metadata payload strings, create a combined
|
|
64
|
+
string with deduplicated tokens, while preserving token order.
|
|
65
|
+
|
|
66
|
+
Inputs are expected to contain a set of metadata tokens separated by spaces
|
|
67
|
+
Example: `gl-python/3.14.0 grpc/1.76.0 gax/2.29.0 gapic/3.8.0 pb/6.33.4`
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
*headers: one or more metadata payload strings
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
a single combined payload string
|
|
74
|
+
"""
|
|
75
|
+
# Split all non-empty headers into individual tokens
|
|
76
|
+
token_list = " ".join(filter(None, headers)).split()
|
|
77
|
+
# Deduplicate while preserving order
|
|
78
|
+
return " ".join(dict.fromkeys(token_list))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _extract_metrics_header(metadata) -> Tuple[str, List[Tuple[str, str]]]:
|
|
82
|
+
"""Extract x-google-api-client header from metadata list.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
metadata (Sequence[Tuple[str, str]]): The metadata to extract from.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
A tuple containing:
|
|
89
|
+
- a string representing the header value.
|
|
90
|
+
- A sequence of remaining metadata tuples.
|
|
91
|
+
"""
|
|
92
|
+
if not metadata:
|
|
93
|
+
return "", []
|
|
94
|
+
|
|
95
|
+
key_to_find = client_info.METRICS_METADATA_KEY
|
|
96
|
+
|
|
97
|
+
metric_str = _deduplicate_metadata_tokens(
|
|
98
|
+
" ".join([v for k, v in metadata if k == key_to_find])
|
|
99
|
+
)
|
|
100
|
+
if not metric_str:
|
|
101
|
+
return "", list(metadata)
|
|
102
|
+
|
|
103
|
+
arbitrary_metadata = [item for item in metadata if item[0] != key_to_find]
|
|
104
|
+
return metric_str, arbitrary_metadata
|
|
105
|
+
|
|
106
|
+
|
|
60
107
|
class _GapicCallable(object):
|
|
61
108
|
"""Callable that applies retry, timeout, and metadata logic.
|
|
62
109
|
|
|
@@ -90,7 +137,16 @@ class _GapicCallable(object):
|
|
|
90
137
|
self._retry = retry
|
|
91
138
|
self._timeout = timeout
|
|
92
139
|
self._compression = compression
|
|
93
|
-
|
|
140
|
+
# Pre-extract the x-goog-api-client header from the initialized metadata.
|
|
141
|
+
self._x_goog_api_client, remaining = _extract_metrics_header(metadata)
|
|
142
|
+
self._static_metadata = tuple(remaining)
|
|
143
|
+
if self._x_goog_api_client:
|
|
144
|
+
self._default_metadata = (
|
|
145
|
+
(client_info.METRICS_METADATA_KEY, self._x_goog_api_client),
|
|
146
|
+
*self._static_metadata,
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
self._default_metadata = self._static_metadata
|
|
94
150
|
|
|
95
151
|
def __call__(
|
|
96
152
|
self, *args, timeout=DEFAULT, retry=DEFAULT, compression=DEFAULT, **kwargs
|
|
@@ -112,16 +168,21 @@ class _GapicCallable(object):
|
|
|
112
168
|
# Apply all applicable decorators.
|
|
113
169
|
wrapped_func = _apply_decorators(self._target, [retry, timeout])
|
|
114
170
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
171
|
+
if user_metadata := kwargs.get("metadata"):
|
|
172
|
+
# Add the user agent metadata to the call.
|
|
173
|
+
final_metadata = list(self._static_metadata)
|
|
174
|
+
user_x_goog, remaining = _extract_metrics_header(user_metadata)
|
|
175
|
+
|
|
176
|
+
merged_header = _deduplicate_metadata_tokens(
|
|
177
|
+
self._x_goog_api_client, user_x_goog
|
|
178
|
+
)
|
|
179
|
+
if merged_header:
|
|
180
|
+
final_metadata.append((client_info.METRICS_METADATA_KEY, merged_header))
|
|
181
|
+
final_metadata.extend(remaining)
|
|
182
|
+
kwargs["metadata"] = final_metadata
|
|
183
|
+
elif self._default_metadata:
|
|
184
|
+
kwargs["metadata"] = self._default_metadata
|
|
185
|
+
|
|
125
186
|
if self._compression is not None:
|
|
126
187
|
kwargs["compression"] = compression
|
|
127
188
|
|
|
@@ -21,9 +21,11 @@ import functools
|
|
|
21
21
|
|
|
22
22
|
from google.api_core import grpc_helpers_async
|
|
23
23
|
from google.api_core.gapic_v1 import client_info
|
|
24
|
-
from google.api_core.gapic_v1.method import
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
from google.api_core.gapic_v1.method import ( # noqa: F401
|
|
25
|
+
DEFAULT,
|
|
26
|
+
USE_DEFAULT_METADATA,
|
|
27
|
+
_GapicCallable,
|
|
28
|
+
)
|
|
27
29
|
|
|
28
30
|
_DEFAULT_ASYNC_TRANSPORT_KIND = "grpc_asyncio"
|
|
29
31
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2026 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
"""Helpers for preparing and structuring API requests.
|
|
18
|
+
|
|
19
|
+
This module provides utilities to preprocess request parameters and objects
|
|
20
|
+
before invoking API methods, such as automatically generating request IDs
|
|
21
|
+
if they are not already set.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import uuid
|
|
25
|
+
from typing import TYPE_CHECKING, Union
|
|
26
|
+
|
|
27
|
+
import google.protobuf.message
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING: # pragma: NO COVER
|
|
30
|
+
import proto # type: ignore[import-untyped]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def setup_request_id(
|
|
34
|
+
request: Union[google.protobuf.message.Message, "proto.Message", dict, None],
|
|
35
|
+
field_name: str,
|
|
36
|
+
is_proto3_optional: bool,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Populate a UUID4 field in the request if it is not already set.
|
|
39
|
+
|
|
40
|
+
This helper is used to ensure request idempotency by automatically
|
|
41
|
+
generating a unique identifier (such as `request_id`) for requests
|
|
42
|
+
that support it. If a request is retried, the same identifier can be
|
|
43
|
+
sent on subsequent retries, allowing the server to recognize the retried
|
|
44
|
+
request and prevent duplicate processing (e.g., creating duplicate
|
|
45
|
+
resources).
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
request (Union[google.protobuf.message.Message, proto.Message, dict, None]): The
|
|
49
|
+
request object or dictionary.
|
|
50
|
+
field_name (str): The name of the field to populate (e.g., "request_id").
|
|
51
|
+
is_proto3_optional (bool): Whether the field supports explicit presence
|
|
52
|
+
(defined with `optional` in proto3 syntax). When True, empty strings ("")
|
|
53
|
+
are preserved as explicit user input per AIP-4235, and UUID auto-population
|
|
54
|
+
occurs only if the field is unset. When False, any empty or falsy value is
|
|
55
|
+
populated with a UUID.
|
|
56
|
+
"""
|
|
57
|
+
if request is None:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
# Evaluate whether the field is considered "unset" and needs auto-population.
|
|
61
|
+
#
|
|
62
|
+
# According to AIP-4235, optional request ID fields must be populated
|
|
63
|
+
# if and only if they have explicit presence (`is_proto3_optional=True`)
|
|
64
|
+
# and were not set by the user (i.e. unset). Explicitly provided empty
|
|
65
|
+
# strings ('') must be preserved when `is_proto3_optional=True`.
|
|
66
|
+
should_populate = False
|
|
67
|
+
if isinstance(request, dict):
|
|
68
|
+
if is_proto3_optional:
|
|
69
|
+
# Case 1a: Dictionary request with explicit presence (`is_proto3_optional=True`).
|
|
70
|
+
# Per AIP-4235, auto-populate only if the key is completely missing from
|
|
71
|
+
# the dictionary or its value is explicitly set to None.
|
|
72
|
+
# An explicit empty string ('') must NOT be overwritten.
|
|
73
|
+
should_populate = field_name not in request or request[field_name] is None
|
|
74
|
+
else:
|
|
75
|
+
# Case 1b: Dictionary request without explicit presence (`is_proto3_optional=False`).
|
|
76
|
+
# Auto-populate if the key is missing, None, or falsy (e.g., empty string '').
|
|
77
|
+
should_populate = not request.get(field_name)
|
|
78
|
+
else:
|
|
79
|
+
if is_proto3_optional:
|
|
80
|
+
# Case 2a: Proto request with explicit presence (`is_proto3_optional=True`)
|
|
81
|
+
# (proto-plus wrapper or pure protobuf message).
|
|
82
|
+
# Extract the protobuf from proto-plus if wrapped.
|
|
83
|
+
pure_pb: google.protobuf.message.Message = getattr(request, "_pb", request)
|
|
84
|
+
try:
|
|
85
|
+
should_populate = not pure_pb.HasField(field_name)
|
|
86
|
+
except (AttributeError, ValueError):
|
|
87
|
+
# Fall back if `HasField` fails or is unsupported.
|
|
88
|
+
should_populate = getattr(pure_pb, field_name, None) is None
|
|
89
|
+
else:
|
|
90
|
+
# Case 2b: Proto request without explicit presence (`is_proto3_optional=False`).
|
|
91
|
+
# Auto-populate if the field value is falsy (None or empty string '').
|
|
92
|
+
should_populate = not bool(getattr(request, field_name, False))
|
|
93
|
+
|
|
94
|
+
# If the field was found to be empty, set random id
|
|
95
|
+
if should_populate:
|
|
96
|
+
generated_id = str(uuid.uuid4())
|
|
97
|
+
if isinstance(request, dict):
|
|
98
|
+
request[field_name] = generated_id
|
|
99
|
+
else:
|
|
100
|
+
setattr(request, field_name, generated_id)
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""Helpers for :mod:`grpc`."""
|
|
16
|
+
|
|
16
17
|
import collections
|
|
17
18
|
import functools
|
|
18
|
-
from typing import Generic, Iterator, Optional, TypeVar
|
|
19
19
|
import warnings
|
|
20
|
+
from typing import Generic, Iterator, Optional, TypeVar
|
|
20
21
|
|
|
21
22
|
import google.auth
|
|
22
23
|
import google.auth.credentials
|
|
@@ -27,7 +28,6 @@ import grpc
|
|
|
27
28
|
|
|
28
29
|
from google.api_core import exceptions, general_helpers
|
|
29
30
|
|
|
30
|
-
|
|
31
31
|
# The list of gRPC Callable interfaces that return iterators.
|
|
32
32
|
_STREAM_WRAP_CLASSES = (grpc.UnaryStreamMultiCallable, grpc.StreamStreamMultiCallable)
|
|
33
33
|
|
|
@@ -254,11 +254,20 @@ def _create_composite_credentials(
|
|
|
254
254
|
request = google.auth.transport.requests.Request()
|
|
255
255
|
|
|
256
256
|
# Create the metadata plugin for inserting the authorization header.
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
257
|
+
try:
|
|
258
|
+
metadata_plugin = google.auth.transport.grpc.AuthMetadataPlugin(
|
|
259
|
+
credentials,
|
|
260
|
+
request,
|
|
261
|
+
default_host=default_host,
|
|
262
|
+
suppress_metrics_header=True,
|
|
263
|
+
)
|
|
264
|
+
except TypeError:
|
|
265
|
+
# Support older versions of google-auth that do not accept suppress_metrics_header
|
|
266
|
+
metadata_plugin = google.auth.transport.grpc.AuthMetadataPlugin(
|
|
267
|
+
credentials,
|
|
268
|
+
request,
|
|
269
|
+
default_host=default_host,
|
|
270
|
+
)
|
|
262
271
|
|
|
263
272
|
# Create a set of grpc.CallCredentials using the metadata plugin.
|
|
264
273
|
google_auth_credentials = grpc.metadata_call_credentials(metadata_plugin)
|
|
@@ -39,13 +39,13 @@ Or asynchronously using callbacks and :meth:`Operation.add_done_callback`:
|
|
|
39
39
|
import functools
|
|
40
40
|
import threading
|
|
41
41
|
|
|
42
|
-
from google.api_core import exceptions
|
|
43
|
-
from google.api_core import protobuf_helpers
|
|
44
|
-
from google.api_core.future import polling
|
|
45
42
|
from google.longrunning import operations_pb2
|
|
46
43
|
from google.protobuf import json_format
|
|
47
44
|
from google.rpc import code_pb2
|
|
48
45
|
|
|
46
|
+
from google.api_core import exceptions, protobuf_helpers
|
|
47
|
+
from google.api_core.future import polling
|
|
48
|
+
|
|
49
49
|
|
|
50
50
|
class Operation(polling.PollingFuture):
|
|
51
51
|
"""A Future for interacting with a Google API Long-Running Operation.
|