Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3c7e43e

Browse filesBrowse files
partheaohmayrgcf-owl-bot[bot]
authored
feat: implement OperationsRestAsyncTransport to support long running operations (#700)
* feat: Add OperationsRestAsyncTransport to support long running operations * update TODO comment * update TODO comment * address feedback * address feedback * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix mypy and lint issues * minor fix * add no cover * fix no cover tag * link coverage issue * silence coverage issue * fix statement name error * address PR feedback * address PR feedback * address PR comments --------- Co-authored-by: ohmayr <omairnaveed@ymail.com> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 84bf637 commit 3c7e43e
Copy full SHA for 3c7e43e

File tree

Expand file treeCollapse file tree

8 files changed

+657
-65
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+657
-65
lines changed

‎google/api_core/client_info.py

Copy file name to clipboardExpand all lines: google/api_core/client_info.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class ClientInfo(object):
5757
user_agent (Optional[str]): Prefix to the user agent header. This is
5858
used to supply information such as application name or partner tool.
5959
Recommended format: ``application-or-tool-ID/major.minor.version``.
60-
rest_version (Optional[str]): The requests library version.
60+
rest_version (Optional[str]): A string with labeled versions of the
61+
dependencies used for REST transport.
6162
"""
6263

6364
def __init__(

‎google/api_core/gapic_v1/client_info.py

Copy file name to clipboardExpand all lines: google/api_core/gapic_v1/client_info.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class ClientInfo(client_info.ClientInfo):
4545
user_agent (Optional[str]): Prefix to the user agent header. This is
4646
used to supply information such as application name or partner tool.
4747
Recommended format: ``application-or-tool-ID/major.minor.version``.
48+
rest_version (Optional[str]): A string with labeled versions of the
49+
dependencies used for REST transport.
4850
"""
4951

5052
def to_grpc_metadata(self):

‎google/api_core/operations_v1/__init__.py

Copy file name to clipboardExpand all lines: google/api_core/operations_v1/__init__.py
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,14 @@
2525
"AbstractOperationsClient",
2626
"OperationsAsyncClient",
2727
"OperationsClient",
28-
"OperationsRestTransport",
28+
"OperationsRestTransport"
2929
]
30+
31+
try:
32+
from google.api_core.operations_v1.transports.rest_asyncio import OperationsRestAsyncTransport # noqa: F401
33+
__all__.append("OperationsRestAsyncTransport")
34+
except ImportError:
35+
# This import requires the `async_rest` extra.
36+
# Don't raise an exception if `OperationsRestAsyncTransport` cannot be imported
37+
# as other transports are still available.
38+
pass

‎google/api_core/operations_v1/transports/__init__.py

Copy file name to clipboardExpand all lines: google/api_core/operations_v1/transports/__init__.py
+17-7Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,26 @@
1414
# limitations under the License.
1515
#
1616
from collections import OrderedDict
17+
from typing import cast, Dict, Tuple
1718

1819
from .base import OperationsTransport
1920
from .rest import OperationsRestTransport
2021

21-
2222
# Compile a registry of transports.
23-
_transport_registry = OrderedDict()
24-
_transport_registry["rest"] = OperationsRestTransport
23+
_transport_registry: Dict[str, OperationsTransport] = OrderedDict()
24+
_transport_registry["rest"] = cast(OperationsTransport, OperationsRestTransport)
25+
26+
__all__: Tuple[str, ...] = ("OperationsTransport", "OperationsRestTransport")
27+
28+
try:
29+
from .rest_asyncio import OperationsRestAsyncTransport
2530

26-
__all__ = (
27-
"OperationsTransport",
28-
"OperationsRestTransport",
29-
)
31+
__all__ += ("OperationsRestAsyncTransport",)
32+
_transport_registry["rest_asyncio"] = cast(
33+
OperationsTransport, OperationsRestAsyncTransport
34+
)
35+
except ImportError:
36+
# This import requires the `async_rest` extra.
37+
# Don't raise an exception if `OperationsRestAsyncTransport` cannot be imported
38+
# as other transports are still available.
39+
pass

‎google/api_core/operations_v1/transports/base.py

Copy file name to clipboardExpand all lines: google/api_core/operations_v1/transports/base.py
+52-2Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# limitations under the License.
1515
#
1616
import abc
17+
import re
1718
from typing import Awaitable, Callable, Optional, Sequence, Union
1819

1920
import google.api_core # type: ignore
@@ -25,10 +26,13 @@
2526
from google.auth import credentials as ga_credentials # type: ignore
2627
from google.longrunning import operations_pb2
2728
from google.oauth2 import service_account # type: ignore
28-
from google.protobuf import empty_pb2 # type: ignore
29+
import google.protobuf
30+
from google.protobuf import empty_pb2, json_format # type: ignore
2931
from grpc import Compression
3032

3133

34+
PROTOBUF_VERSION = google.protobuf.__version__
35+
3236
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
3337
gapic_version=version.__version__,
3438
)
@@ -45,12 +49,14 @@ def __init__(
4549
self,
4650
*,
4751
host: str = DEFAULT_HOST,
52+
# TODO(https://github.com/googleapis/python-api-core/issues/709): update type hint for credentials to include `google.auth.aio.Credentials`.
4853
credentials: Optional[ga_credentials.Credentials] = None,
4954
credentials_file: Optional[str] = None,
5055
scopes: Optional[Sequence[str]] = None,
5156
quota_project_id: Optional[str] = None,
5257
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
5358
always_use_jwt_access: Optional[bool] = False,
59+
url_scheme="https",
5460
**kwargs,
5561
) -> None:
5662
"""Instantiate the transport.
@@ -76,10 +82,23 @@ def __init__(
7682
your own client library.
7783
always_use_jwt_access (Optional[bool]): Whether self signed JWT should
7884
be used for service account credentials.
85+
url_scheme: the protocol scheme for the API endpoint. Normally
86+
"https", but for testing or local servers,
87+
"http" can be specified.
7988
"""
89+
maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
90+
if maybe_url_match is None:
91+
raise ValueError(
92+
f"Unexpected hostname structure: {host}"
93+
) # pragma: NO COVER
94+
95+
url_match_items = maybe_url_match.groupdict()
96+
97+
host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
98+
8099
# Save the hostname. Default to port 443 (HTTPS) if none is specified.
81100
if ":" not in host:
82-
host += ":443"
101+
host += ":443" # pragma: NO COVER
83102
self._host = host
84103

85104
scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES}
@@ -189,6 +208,37 @@ def close(self):
189208
"""
190209
raise NotImplementedError()
191210

211+
def _convert_protobuf_message_to_dict(
212+
self, message: google.protobuf.message.Message
213+
):
214+
r"""Converts protobuf message to a dictionary.
215+
216+
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
217+
218+
Args:
219+
message(google.protobuf.message.Message): The protocol buffers message
220+
instance to serialize.
221+
222+
Returns:
223+
A dict representation of the protocol buffer message.
224+
"""
225+
# TODO(https://github.com/googleapis/python-api-core/issues/643): For backwards compatibility
226+
# with protobuf 3.x 4.x, Remove once support for protobuf 3.x and 4.x is dropped.
227+
if PROTOBUF_VERSION[0:2] in ["3.", "4."]:
228+
result = json_format.MessageToDict(
229+
message,
230+
preserving_proto_field_name=True,
231+
including_default_value_fields=True, # type: ignore # backward compatibility
232+
)
233+
else:
234+
result = json_format.MessageToDict(
235+
message,
236+
preserving_proto_field_name=True,
237+
always_print_fields_with_no_presence=True,
238+
)
239+
240+
return result
241+
192242
@property
193243
def list_operations(
194244
self,

‎google/api_core/operations_v1/transports/rest.py

Copy file name to clipboardExpand all lines: google/api_core/operations_v1/transports/rest.py
+6-44Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# limitations under the License.
1515
#
1616

17-
import re
1817
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
1918

2019
from requests import __version__ as requests_version
@@ -41,7 +40,7 @@
4140
DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
4241
gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
4342
grpc_version=None,
44-
rest_version=requests_version,
43+
rest_version=f"requests@{requests_version}",
4544
)
4645

4746

@@ -123,16 +122,6 @@ def __init__(
123122
# TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
124123
# TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the
125124
# credentials object
126-
maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
127-
if maybe_url_match is None:
128-
raise ValueError(
129-
f"Unexpected hostname structure: {host}"
130-
) # pragma: NO COVER
131-
132-
url_match_items = maybe_url_match.groupdict()
133-
134-
host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
135-
136125
super().__init__(
137126
host=host,
138127
credentials=credentials,
@@ -144,6 +133,7 @@ def __init__(
144133
)
145134
if client_cert_source_for_mtls:
146135
self._session.configure_mtls_channel(client_cert_source_for_mtls)
136+
# TODO(https://github.com/googleapis/python-api-core/issues/720): Add wrap logic directly to the property methods for callables.
147137
self._prep_wrapped_messages(client_info)
148138
self._http_options = http_options or {}
149139
self._path_prefix = path_prefix
@@ -206,6 +196,7 @@ def _list_operations(
206196
# Send the request
207197
headers = dict(metadata)
208198
headers["Content-Type"] = "application/json"
199+
# TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name.
209200
response = getattr(self._session, method)(
210201
"{host}{uri}".format(host=self._host, uri=uri),
211202
timeout=timeout,
@@ -282,6 +273,7 @@ def _get_operation(
282273
# Send the request
283274
headers = dict(metadata)
284275
headers["Content-Type"] = "application/json"
276+
# TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name.
285277
response = getattr(self._session, method)(
286278
"{host}{uri}".format(host=self._host, uri=uri),
287279
timeout=timeout,
@@ -351,6 +343,7 @@ def _delete_operation(
351343
# Send the request
352344
headers = dict(metadata)
353345
headers["Content-Type"] = "application/json"
346+
# TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name.
354347
response = getattr(self._session, method)(
355348
"{host}{uri}".format(host=self._host, uri=uri),
356349
timeout=timeout,
@@ -426,6 +419,7 @@ def _cancel_operation(
426419
# Send the request
427420
headers = dict(metadata)
428421
headers["Content-Type"] = "application/json"
422+
# TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name.
429423
response = getattr(self._session, method)(
430424
"{host}{uri}".format(host=self._host, uri=uri),
431425
timeout=timeout,
@@ -441,38 +435,6 @@ def _cancel_operation(
441435

442436
return empty_pb2.Empty()
443437

444-
def _convert_protobuf_message_to_dict(
445-
self, message: google.protobuf.message.Message
446-
):
447-
r"""Converts protobuf message to a dictionary.
448-
449-
When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
450-
451-
Args:
452-
message(google.protobuf.message.Message): The protocol buffers message
453-
instance to serialize.
454-
455-
Returns:
456-
A dict representation of the protocol buffer message.
457-
"""
458-
# For backwards compatibility with protobuf 3.x 4.x
459-
# Remove once support for protobuf 3.x and 4.x is dropped
460-
# https://github.com/googleapis/python-api-core/issues/643
461-
if PROTOBUF_VERSION[0:2] in ["3.", "4."]:
462-
result = json_format.MessageToDict(
463-
message,
464-
preserving_proto_field_name=True,
465-
including_default_value_fields=True, # type: ignore # backward compatibility
466-
)
467-
else:
468-
result = json_format.MessageToDict(
469-
message,
470-
preserving_proto_field_name=True,
471-
always_print_fields_with_no_presence=True,
472-
)
473-
474-
return result
475-
476438
@property
477439
def list_operations(
478440
self,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.