google-api-core 2.19.2__tar.gz → 2.20.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.
Files changed (116) hide show
  1. {google_api_core-2.19.2/google_api_core.egg-info → google_api_core-2.20.0}/PKG-INFO +1 -1
  2. google_api_core-2.19.2/google/api_core/rest_streaming.py → google_api_core-2.20.0/google/api_core/_rest_streaming_base.py +18 -32
  3. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/exceptions.py +51 -15
  4. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/method_async.py +5 -1
  5. google_api_core-2.20.0/google/api_core/rest_streaming.py +66 -0
  6. google_api_core-2.20.0/google/api_core/rest_streaming_async.py +83 -0
  7. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/version.py +1 -1
  8. {google_api_core-2.19.2 → google_api_core-2.20.0/google_api_core.egg-info}/PKG-INFO +1 -1
  9. {google_api_core-2.19.2 → google_api_core-2.20.0}/google_api_core.egg-info/SOURCES.txt +4 -0
  10. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/gapic/test_method_async.py +11 -0
  11. google_api_core-2.20.0/tests/asyncio/test_rest_streaming_async.py +378 -0
  12. google_api_core-2.20.0/tests/helpers.py +71 -0
  13. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_rest_streaming.py +7 -52
  14. {google_api_core-2.19.2 → google_api_core-2.20.0}/LICENSE +0 -0
  15. {google_api_core-2.19.2 → google_api_core-2.20.0}/MANIFEST.in +0 -0
  16. {google_api_core-2.19.2 → google_api_core-2.20.0}/README.rst +0 -0
  17. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/__init__.py +0 -0
  18. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/bidi.py +0 -0
  19. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/client_info.py +0 -0
  20. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/client_options.py +0 -0
  21. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/datetime_helpers.py +0 -0
  22. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/extended_operation.py +0 -0
  23. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/future/__init__.py +0 -0
  24. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/future/_helpers.py +0 -0
  25. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/future/async_future.py +0 -0
  26. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/future/base.py +0 -0
  27. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/future/polling.py +0 -0
  28. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/__init__.py +0 -0
  29. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/client_info.py +0 -0
  30. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/config.py +0 -0
  31. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/config_async.py +0 -0
  32. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/method.py +0 -0
  33. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/gapic_v1/routing_header.py +0 -0
  34. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/general_helpers.py +0 -0
  35. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/grpc_helpers.py +0 -0
  36. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/grpc_helpers_async.py +0 -0
  37. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/iam.py +0 -0
  38. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operation.py +0 -0
  39. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operation_async.py +0 -0
  40. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/__init__.py +0 -0
  41. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/abstract_operations_client.py +0 -0
  42. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/operations_async_client.py +0 -0
  43. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/operations_client.py +0 -0
  44. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/operations_client_config.py +0 -0
  45. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/pagers.py +0 -0
  46. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/transports/__init__.py +0 -0
  47. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/transports/base.py +0 -0
  48. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/operations_v1/transports/rest.py +0 -0
  49. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/page_iterator.py +0 -0
  50. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/page_iterator_async.py +0 -0
  51. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/path_template.py +0 -0
  52. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/protobuf_helpers.py +0 -0
  53. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/py.typed +0 -0
  54. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/rest_helpers.py +0 -0
  55. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/__init__.py +0 -0
  56. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/retry_base.py +0 -0
  57. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/retry_streaming.py +0 -0
  58. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/retry_streaming_async.py +0 -0
  59. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/retry_unary.py +0 -0
  60. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry/retry_unary_async.py +0 -0
  61. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/retry_async.py +0 -0
  62. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/timeout.py +0 -0
  63. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/universe.py +0 -0
  64. {google_api_core-2.19.2 → google_api_core-2.20.0}/google/api_core/version_header.py +0 -0
  65. {google_api_core-2.19.2 → google_api_core-2.20.0}/google_api_core.egg-info/dependency_links.txt +0 -0
  66. {google_api_core-2.19.2 → google_api_core-2.20.0}/google_api_core.egg-info/not-zip-safe +0 -0
  67. {google_api_core-2.19.2 → google_api_core-2.20.0}/google_api_core.egg-info/requires.txt +0 -0
  68. {google_api_core-2.19.2 → google_api_core-2.20.0}/google_api_core.egg-info/top_level.txt +0 -0
  69. {google_api_core-2.19.2 → google_api_core-2.20.0}/setup.cfg +0 -0
  70. {google_api_core-2.19.2 → google_api_core-2.20.0}/setup.py +0 -0
  71. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/__init__.py +0 -0
  72. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/__init__.py +0 -0
  73. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/future/__init__.py +0 -0
  74. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/future/test_async_future.py +0 -0
  75. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/gapic/test_config_async.py +0 -0
  76. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/operations_v1/__init__.py +0 -0
  77. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/operations_v1/test_operations_async_client.py +0 -0
  78. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/retry/__init__.py +0 -0
  79. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/retry/test_retry_streaming_async.py +0 -0
  80. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/retry/test_retry_unary_async.py +0 -0
  81. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/test_grpc_helpers_async.py +0 -0
  82. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/test_operation_async.py +0 -0
  83. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/asyncio/test_page_iterator_async.py +0 -0
  84. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/__init__.py +0 -0
  85. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/future/__init__.py +0 -0
  86. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/future/test__helpers.py +0 -0
  87. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/future/test_polling.py +0 -0
  88. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/gapic/test_client_info.py +0 -0
  89. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/gapic/test_config.py +0 -0
  90. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/gapic/test_method.py +0 -0
  91. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/gapic/test_routing_header.py +0 -0
  92. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/operations_v1/__init__.py +0 -0
  93. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/operations_v1/test_operations_client.py +0 -0
  94. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/operations_v1/test_operations_rest_client.py +0 -0
  95. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/retry/__init__.py +0 -0
  96. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/retry/test_retry_base.py +0 -0
  97. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/retry/test_retry_imports.py +0 -0
  98. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/retry/test_retry_streaming.py +0 -0
  99. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/retry/test_retry_unary.py +0 -0
  100. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_bidi.py +0 -0
  101. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_client_info.py +0 -0
  102. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_client_options.py +0 -0
  103. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_datetime_helpers.py +0 -0
  104. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_exceptions.py +0 -0
  105. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_extended_operation.py +0 -0
  106. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_grpc_helpers.py +0 -0
  107. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_iam.py +0 -0
  108. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_operation.py +0 -0
  109. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_packaging.py +0 -0
  110. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_page_iterator.py +0 -0
  111. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_path_template.py +0 -0
  112. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_protobuf_helpers.py +0 -0
  113. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_rest_helpers.py +0 -0
  114. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_timeout.py +0 -0
  115. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_universe.py +0 -0
  116. {google_api_core-2.19.2 → google_api_core-2.20.0}/tests/unit/test_version_header.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-api-core
3
- Version: 2.19.2
3
+ Version: 2.20.0
4
4
  Summary: Google API client core library
5
5
  Home-page: https://github.com/googleapis/python-api-core
6
6
  Author: Google LLC
@@ -1,4 +1,4 @@
1
- # Copyright 2021 Google LLC
1
+ # Copyright 2024 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -17,18 +17,17 @@
17
17
  from collections import deque
18
18
  import string
19
19
  from typing import Deque, Union
20
+ import types
20
21
 
21
22
  import proto
22
- import requests
23
23
  import google.protobuf.message
24
24
  from google.protobuf.json_format import Parse
25
25
 
26
26
 
27
- class ResponseIterator:
28
- """Iterator over REST API responses.
27
+ class BaseResponseIterator:
28
+ """Base Iterator over REST API responses. This class should not be used directly.
29
29
 
30
30
  Args:
31
- response (requests.Response): An API response object.
32
31
  response_message_cls (Union[proto.Message, google.protobuf.message.Message]): A response
33
32
  class expected to be returned from an API.
34
33
 
@@ -38,13 +37,9 @@ class ResponseIterator:
38
37
 
39
38
  def __init__(
40
39
  self,
41
- response: requests.Response,
42
40
  response_message_cls: Union[proto.Message, google.protobuf.message.Message],
43
41
  ):
44
- self._response = response
45
42
  self._response_message_cls = response_message_cls
46
- # Inner iterator over HTTP response's content.
47
- self._response_itr = self._response.iter_content(decode_unicode=True)
48
43
  # Contains a list of JSON responses ready to be sent to user.
49
44
  self._ready_objs: Deque[str] = deque()
50
45
  # Current JSON response being built.
@@ -57,9 +52,7 @@ class ResponseIterator:
57
52
  # Whether an escape symbol "\" was encountered.
58
53
  self._escape_next = False
59
54
 
60
- def cancel(self):
61
- """Cancel existing streaming operation."""
62
- self._response.close()
55
+ self._grab = types.MethodType(self._create_grab(), self)
63
56
 
64
57
  def _process_chunk(self, chunk: str):
65
58
  if self._level == 0:
@@ -104,29 +97,22 @@ class ResponseIterator:
104
97
  self._obj += char
105
98
  self._escape_next = not self._escape_next if char == "\\" else False
106
99
 
107
- def __next__(self):
108
- while not self._ready_objs:
109
- try:
110
- chunk = next(self._response_itr)
111
- self._process_chunk(chunk)
112
- except StopIteration as e:
113
- if self._level > 0:
114
- raise ValueError("Unfinished stream: %s" % self._obj)
115
- raise e
116
- return self._grab()
117
-
118
- def _grab(self):
119
- # Add extra quotes to make json.loads happy.
100
+ def _create_grab(self):
120
101
  if issubclass(self._response_message_cls, proto.Message):
121
- return self._response_message_cls.from_json(
122
- self._ready_objs.popleft(), ignore_unknown_fields=True
123
- )
102
+
103
+ def grab(this):
104
+ return this._response_message_cls.from_json(
105
+ this._ready_objs.popleft(), ignore_unknown_fields=True
106
+ )
107
+
108
+ return grab
124
109
  elif issubclass(self._response_message_cls, google.protobuf.message.Message):
125
- return Parse(self._ready_objs.popleft(), self._response_message_cls())
110
+
111
+ def grab(this):
112
+ return Parse(this._ready_objs.popleft(), this._response_message_cls())
113
+
114
+ return grab
126
115
  else:
127
116
  raise ValueError(
128
117
  "Response message class must be a subclass of proto.Message or google.protobuf.message.Message."
129
118
  )
130
-
131
- def __iter__(self):
132
- return self
@@ -22,7 +22,7 @@ from __future__ import absolute_import
22
22
  from __future__ import unicode_literals
23
23
 
24
24
  import http.client
25
- from typing import Dict
25
+ from typing import Optional, Dict
26
26
  from typing import Union
27
27
  import warnings
28
28
 
@@ -442,6 +442,12 @@ class DeadlineExceeded(GatewayTimeout):
442
442
  grpc_status_code = grpc.StatusCode.DEADLINE_EXCEEDED if grpc is not None else None
443
443
 
444
444
 
445
+ class AsyncRestUnsupportedParameterError(NotImplementedError):
446
+ """Raised when an unsupported parameter is configured against async rest transport."""
447
+
448
+ pass
449
+
450
+
445
451
  def exception_class_for_http_status(status_code):
446
452
  """Return the exception class for a specific HTTP status code.
447
453
 
@@ -476,22 +482,37 @@ def from_http_status(status_code, message, **kwargs):
476
482
  return error
477
483
 
478
484
 
479
- def from_http_response(response):
480
- """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`.
485
+ def _format_rest_error_message(error, method, url):
486
+ method = method.upper() if method else None
487
+ message = "{method} {url}: {error}".format(
488
+ method=method,
489
+ url=url,
490
+ error=error,
491
+ )
492
+ return message
493
+
494
+
495
+ # NOTE: We're moving away from `from_http_status` because it expects an aiohttp response compared
496
+ # to `format_http_response_error` which expects a more abstract response from google.auth and is
497
+ # compatible with both sync and async response types.
498
+ # TODO(https://github.com/googleapis/python-api-core/issues/691): Add type hint for response.
499
+ def format_http_response_error(
500
+ response, method: str, url: str, payload: Optional[Dict] = None
501
+ ):
502
+ """Create a :class:`GoogleAPICallError` from a google auth rest response.
481
503
 
482
504
  Args:
483
- response (requests.Response): The HTTP response.
505
+ response Union[google.auth.transport.Response, google.auth.aio.transport.Response]: The HTTP response.
506
+ method Optional(str): The HTTP request method.
507
+ url Optional(str): The HTTP request url.
508
+ payload Optional(dict): The HTTP response payload. If not passed in, it is read from response for a response type of google.auth.transport.Response.
484
509
 
485
510
  Returns:
486
511
  GoogleAPICallError: An instance of the appropriate subclass of
487
512
  :class:`GoogleAPICallError`, with the message and errors populated
488
513
  from the response.
489
514
  """
490
- try:
491
- payload = response.json()
492
- except ValueError:
493
- payload = {"error": {"message": response.text or "unknown error"}}
494
-
515
+ payload = {} if not payload else payload
495
516
  error_message = payload.get("error", {}).get("message", "unknown error")
496
517
  errors = payload.get("error", {}).get("errors", ())
497
518
  # In JSON, details are already formatted in developer-friendly way.
@@ -504,12 +525,7 @@ def from_http_response(response):
504
525
  )
505
526
  )
506
527
  error_info = error_info[0] if error_info else None
507
-
508
- message = "{method} {url}: {error}".format(
509
- method=response.request.method,
510
- url=response.request.url,
511
- error=error_message,
512
- )
528
+ message = _format_rest_error_message(error_message, method, url)
513
529
 
514
530
  exception = from_http_status(
515
531
  response.status_code,
@@ -522,6 +538,26 @@ def from_http_response(response):
522
538
  return exception
523
539
 
524
540
 
541
+ def from_http_response(response):
542
+ """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`.
543
+
544
+ Args:
545
+ response (requests.Response): The HTTP response.
546
+
547
+ Returns:
548
+ GoogleAPICallError: An instance of the appropriate subclass of
549
+ :class:`GoogleAPICallError`, with the message and errors populated
550
+ from the response.
551
+ """
552
+ try:
553
+ payload = response.json()
554
+ except ValueError:
555
+ payload = {"error": {"message": response.text or "unknown error"}}
556
+ return format_http_response_error(
557
+ response, response.request.method, response.request.url, payload
558
+ )
559
+
560
+
525
561
  def exception_class_for_grpc_status(status_code):
526
562
  """Return the exception class for a specific :class:`grpc.StatusCode`.
527
563
 
@@ -25,6 +25,8 @@ from google.api_core.gapic_v1.method import _GapicCallable
25
25
  from google.api_core.gapic_v1.method import DEFAULT # noqa: F401
26
26
  from google.api_core.gapic_v1.method import USE_DEFAULT_METADATA # noqa: F401
27
27
 
28
+ _DEFAULT_ASYNC_TRANSPORT_KIND = "grpc_asyncio"
29
+
28
30
 
29
31
  def wrap_method(
30
32
  func,
@@ -32,6 +34,7 @@ def wrap_method(
32
34
  default_timeout=None,
33
35
  default_compression=None,
34
36
  client_info=client_info.DEFAULT_CLIENT_INFO,
37
+ kind=_DEFAULT_ASYNC_TRANSPORT_KIND,
35
38
  ):
36
39
  """Wrap an async RPC method with common behavior.
37
40
 
@@ -40,7 +43,8 @@ def wrap_method(
40
43
  and ``compression`` arguments and applies the common error mapping,
41
44
  retry, timeout, metadata, and compression behavior to the low-level RPC method.
42
45
  """
43
- func = grpc_helpers_async.wrap_errors(func)
46
+ if kind == _DEFAULT_ASYNC_TRANSPORT_KIND:
47
+ func = grpc_helpers_async.wrap_errors(func)
44
48
 
45
49
  metadata = [client_info.to_grpc_metadata()] if client_info is not None else None
46
50
 
@@ -0,0 +1,66 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for server-side streaming in REST."""
16
+
17
+ from typing import Union
18
+
19
+ import proto
20
+ import requests
21
+ import google.protobuf.message
22
+ from google.api_core._rest_streaming_base import BaseResponseIterator
23
+
24
+
25
+ class ResponseIterator(BaseResponseIterator):
26
+ """Iterator over REST API responses.
27
+
28
+ Args:
29
+ response (requests.Response): An API response object.
30
+ response_message_cls (Union[proto.Message, google.protobuf.message.Message]): A response
31
+ class expected to be returned from an API.
32
+
33
+ Raises:
34
+ ValueError:
35
+ - If `response_message_cls` is not a subclass of `proto.Message` or `google.protobuf.message.Message`.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ response: requests.Response,
41
+ response_message_cls: Union[proto.Message, google.protobuf.message.Message],
42
+ ):
43
+ self._response = response
44
+ # Inner iterator over HTTP response's content.
45
+ self._response_itr = self._response.iter_content(decode_unicode=True)
46
+ super(ResponseIterator, self).__init__(
47
+ response_message_cls=response_message_cls
48
+ )
49
+
50
+ def cancel(self):
51
+ """Cancel existing streaming operation."""
52
+ self._response.close()
53
+
54
+ def __next__(self):
55
+ while not self._ready_objs:
56
+ try:
57
+ chunk = next(self._response_itr)
58
+ self._process_chunk(chunk)
59
+ except StopIteration as e:
60
+ if self._level > 0:
61
+ raise ValueError("Unfinished stream: %s" % self._obj)
62
+ raise e
63
+ return self._grab()
64
+
65
+ def __iter__(self):
66
+ return self
@@ -0,0 +1,83 @@
1
+ # Copyright 2024 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for asynchronous server-side streaming in REST."""
16
+
17
+ from typing import Union
18
+
19
+ import proto
20
+
21
+ try:
22
+ import google.auth.aio.transport
23
+ except ImportError as e: # pragma: NO COVER
24
+ raise ImportError(
25
+ "google-auth>=2.35.0 is required to use asynchronous rest streaming."
26
+ ) from e
27
+
28
+ import google.protobuf.message
29
+ from google.api_core._rest_streaming_base import BaseResponseIterator
30
+
31
+
32
+ class AsyncResponseIterator(BaseResponseIterator):
33
+ """Asynchronous Iterator over REST API responses.
34
+
35
+ Args:
36
+ response (google.auth.aio.transport.Response): An API response object.
37
+ response_message_cls (Union[proto.Message, google.protobuf.message.Message]): A response
38
+ class expected to be returned from an API.
39
+
40
+ Raises:
41
+ ValueError:
42
+ - If `response_message_cls` is not a subclass of `proto.Message` or `google.protobuf.message.Message`.
43
+ """
44
+
45
+ def __init__(
46
+ self,
47
+ response: google.auth.aio.transport.Response,
48
+ response_message_cls: Union[proto.Message, google.protobuf.message.Message],
49
+ ):
50
+ self._response = response
51
+ self._chunk_size = 1024
52
+ self._response_itr = self._response.content().__aiter__()
53
+ super(AsyncResponseIterator, self).__init__(
54
+ response_message_cls=response_message_cls
55
+ )
56
+
57
+ async def __aenter__(self):
58
+ return self
59
+
60
+ async def cancel(self):
61
+ """Cancel existing streaming operation."""
62
+ await self._response.close()
63
+
64
+ async def __anext__(self):
65
+ while not self._ready_objs:
66
+ try:
67
+ chunk = await self._response_itr.__anext__()
68
+ chunk = chunk.decode("utf-8")
69
+ self._process_chunk(chunk)
70
+ except StopAsyncIteration as e:
71
+ if self._level > 0:
72
+ raise ValueError("i Unfinished stream: %s" % self._obj)
73
+ raise e
74
+ except ValueError as e:
75
+ raise e
76
+ return self._grab()
77
+
78
+ def __aiter__(self):
79
+ return self
80
+
81
+ async def __aexit__(self, exc_type, exc, tb):
82
+ """Cancel existing async streaming operation."""
83
+ await self._response.close()
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "2.19.2"
15
+ __version__ = "2.20.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-api-core
3
- Version: 2.19.2
3
+ Version: 2.20.0
4
4
  Summary: Google API client core library
5
5
  Home-page: https://github.com/googleapis/python-api-core
6
6
  Author: Google LLC
@@ -4,6 +4,7 @@ README.rst
4
4
  setup.cfg
5
5
  setup.py
6
6
  google/api_core/__init__.py
7
+ google/api_core/_rest_streaming_base.py
7
8
  google/api_core/bidi.py
8
9
  google/api_core/client_info.py
9
10
  google/api_core/client_options.py
@@ -23,6 +24,7 @@ google/api_core/protobuf_helpers.py
23
24
  google/api_core/py.typed
24
25
  google/api_core/rest_helpers.py
25
26
  google/api_core/rest_streaming.py
27
+ google/api_core/rest_streaming_async.py
26
28
  google/api_core/retry_async.py
27
29
  google/api_core/timeout.py
28
30
  google/api_core/universe.py
@@ -62,10 +64,12 @@ google_api_core.egg-info/not-zip-safe
62
64
  google_api_core.egg-info/requires.txt
63
65
  google_api_core.egg-info/top_level.txt
64
66
  tests/__init__.py
67
+ tests/helpers.py
65
68
  tests/asyncio/__init__.py
66
69
  tests/asyncio/test_grpc_helpers_async.py
67
70
  tests/asyncio/test_operation_async.py
68
71
  tests/asyncio/test_page_iterator_async.py
72
+ tests/asyncio/test_rest_streaming_async.py
69
73
  tests/asyncio/future/__init__.py
70
74
  tests/asyncio/future/test_async_future.py
71
75
  tests/asyncio/gapic/test_config_async.py
@@ -252,3 +252,14 @@ async def test_wrap_method_with_overriding_timeout_as_a_number():
252
252
 
253
253
  assert result == 42
254
254
  method.assert_called_once_with(timeout=22, metadata=mock.ANY)
255
+
256
+
257
+ @pytest.mark.asyncio
258
+ async def test_wrap_method_without_wrap_errors():
259
+ fake_call = mock.AsyncMock()
260
+
261
+ wrapped_method = gapic_v1.method_async.wrap_method(fake_call, kind="rest")
262
+ with mock.patch("google.api_core.grpc_helpers_async.wrap_errors") as method:
263
+ await wrapped_method()
264
+
265
+ method.assert_not_called()