google-api-core 2.38.0__tar.gz → 2.40.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 (145) hide show
  1. {google_api_core-2.38.0/google_api_core.egg-info → google_api_core-2.40.0}/PKG-INFO +2 -1
  2. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/_python_package_support.py +1 -1
  3. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/exceptions.py +35 -0
  4. google_api_core-2.40.0/google/api_core/resumable_transfer/__init__.py +49 -0
  5. google_api_core-2.40.0/google/api_core/resumable_transfer/common.py +191 -0
  6. google_api_core-2.40.0/google/api_core/resumable_transfer/upload.py +1092 -0
  7. google_api_core-2.40.0/google/api_core/resumable_transfer/upload_async.py +1143 -0
  8. google_api_core-2.40.0/google/api_core/resumable_transfer/upload_state.py +339 -0
  9. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/version.py +1 -1
  10. {google_api_core-2.38.0 → google_api_core-2.40.0/google_api_core.egg-info}/PKG-INFO +2 -1
  11. {google_api_core-2.38.0 → google_api_core-2.40.0}/google_api_core.egg-info/SOURCES.txt +8 -0
  12. {google_api_core-2.38.0 → google_api_core-2.40.0}/pyproject.toml +1 -0
  13. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/test_grpc_helpers_async.py +1 -1
  14. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/test_rest_streaming_async.py +1 -1
  15. google_api_core-2.40.0/tests/asyncio/test_resumable_transfer_async.py +2294 -0
  16. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/helpers.py +1 -1
  17. google_api_core-2.40.0/tests/unit/test_resumable_transfer.py +2003 -0
  18. google_api_core-2.40.0/tests/unit/test_resumable_transfer_scenarios.py +862 -0
  19. {google_api_core-2.38.0 → google_api_core-2.40.0}/LICENSE +0 -0
  20. {google_api_core-2.38.0 → google_api_core-2.40.0}/MANIFEST.in +0 -0
  21. {google_api_core-2.38.0 → google_api_core-2.40.0}/README.rst +0 -0
  22. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/__init__.py +0 -0
  23. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/_feature_gating_helpers.py +0 -0
  24. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/_observability.py +0 -0
  25. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/_python_version_support.py +0 -0
  26. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/_rest_streaming_base.py +0 -0
  27. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/bidi.py +0 -0
  28. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/bidi_async.py +0 -0
  29. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/bidi_base.py +0 -0
  30. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/client_info.py +0 -0
  31. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/client_logging.py +0 -0
  32. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/client_options.py +0 -0
  33. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/datetime_helpers.py +0 -0
  34. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/extended_operation.py +0 -0
  35. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/future/__init__.py +0 -0
  36. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/future/_helpers.py +0 -0
  37. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/future/async_future.py +0 -0
  38. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/future/base.py +0 -0
  39. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/future/polling.py +0 -0
  40. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/__init__.py +0 -0
  41. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/client_info.py +0 -0
  42. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/config.py +0 -0
  43. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/config_async.py +0 -0
  44. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/method.py +0 -0
  45. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/method_async.py +0 -0
  46. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/requests.py +0 -0
  47. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/gapic_v1/routing_header.py +0 -0
  48. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/general_helpers.py +0 -0
  49. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/grpc_helpers.py +0 -0
  50. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/grpc_helpers_async.py +0 -0
  51. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/iam.py +0 -0
  52. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operation.py +0 -0
  53. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operation_async.py +0 -0
  54. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/__init__.py +0 -0
  55. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/abstract_operations_base_client.py +0 -0
  56. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/abstract_operations_client.py +0 -0
  57. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/operations_async_client.py +0 -0
  58. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/operations_client.py +0 -0
  59. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/operations_client_config.py +0 -0
  60. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/operations_rest_client_async.py +0 -0
  61. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/pagers.py +0 -0
  62. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/pagers_async.py +0 -0
  63. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/pagers_base.py +0 -0
  64. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/transports/__init__.py +0 -0
  65. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/transports/base.py +0 -0
  66. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/transports/rest.py +0 -0
  67. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/operations_v1/transports/rest_asyncio.py +0 -0
  68. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/page_iterator.py +0 -0
  69. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/page_iterator_async.py +0 -0
  70. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/path_template.py +0 -0
  71. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/protobuf_helpers.py +0 -0
  72. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/py.typed +0 -0
  73. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/rest_helpers.py +0 -0
  74. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/rest_streaming.py +0 -0
  75. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/rest_streaming_async.py +0 -0
  76. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/__init__.py +0 -0
  77. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/retry_base.py +0 -0
  78. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/retry_streaming.py +0 -0
  79. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/retry_streaming_async.py +0 -0
  80. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/retry_unary.py +0 -0
  81. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry/retry_unary_async.py +0 -0
  82. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/retry_async.py +0 -0
  83. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/timeout.py +0 -0
  84. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/universe.py +0 -0
  85. {google_api_core-2.38.0 → google_api_core-2.40.0}/google/api_core/version_header.py +0 -0
  86. {google_api_core-2.38.0 → google_api_core-2.40.0}/google_api_core.egg-info/dependency_links.txt +0 -0
  87. {google_api_core-2.38.0 → google_api_core-2.40.0}/google_api_core.egg-info/requires.txt +0 -0
  88. {google_api_core-2.38.0 → google_api_core-2.40.0}/google_api_core.egg-info/top_level.txt +0 -0
  89. {google_api_core-2.38.0 → google_api_core-2.40.0}/setup.cfg +0 -0
  90. {google_api_core-2.38.0 → google_api_core-2.40.0}/setup.py +0 -0
  91. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/__init__.py +0 -0
  92. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/__init__.py +0 -0
  93. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/future/__init__.py +0 -0
  94. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/future/test_async_future.py +0 -0
  95. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/gapic/test_config_async.py +0 -0
  96. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/gapic/test_method_async.py +0 -0
  97. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/operations_v1/__init__.py +0 -0
  98. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/operations_v1/test_operations_async_client.py +0 -0
  99. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/retry/__init__.py +0 -0
  100. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/retry/test_retry_streaming_async.py +0 -0
  101. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/retry/test_retry_unary_async.py +0 -0
  102. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/test_bidi_async.py +0 -0
  103. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/test_operation_async.py +0 -0
  104. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/asyncio/test_page_iterator_async.py +0 -0
  105. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/conftest.py +0 -0
  106. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/__init__.py +0 -0
  107. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/future/__init__.py +0 -0
  108. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/future/test__helpers.py +0 -0
  109. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/future/test_polling.py +0 -0
  110. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/gapic/test_client_info.py +0 -0
  111. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/gapic/test_config.py +0 -0
  112. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/gapic/test_method.py +0 -0
  113. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/gapic/test_requests.py +0 -0
  114. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/gapic/test_routing_header.py +0 -0
  115. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/operations_v1/__init__.py +0 -0
  116. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/operations_v1/test_operations_client.py +0 -0
  117. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/operations_v1/test_operations_rest_client.py +0 -0
  118. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/retry/__init__.py +0 -0
  119. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/retry/test_retry_base.py +0 -0
  120. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/retry/test_retry_imports.py +0 -0
  121. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/retry/test_retry_streaming.py +0 -0
  122. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/retry/test_retry_unary.py +0 -0
  123. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_bidi.py +0 -0
  124. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_client_info.py +0 -0
  125. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_client_logging.py +0 -0
  126. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_client_options.py +0 -0
  127. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_datetime_helpers.py +0 -0
  128. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_exceptions.py +0 -0
  129. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_extended_operation.py +0 -0
  130. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_feature_gating_helpers.py +0 -0
  131. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_grpc_helpers.py +0 -0
  132. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_iam.py +0 -0
  133. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_observability.py +0 -0
  134. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_operation.py +0 -0
  135. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_packaging.py +0 -0
  136. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_page_iterator.py +0 -0
  137. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_path_template.py +0 -0
  138. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_protobuf_helpers.py +0 -0
  139. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_python_package_support.py +0 -0
  140. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_python_version_support.py +0 -0
  141. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_rest_helpers.py +0 -0
  142. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_rest_streaming.py +0 -0
  143. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_timeout.py +0 -0
  144. {google_api_core-2.38.0 → google_api_core-2.40.0}/tests/unit/test_universe.py +0 -0
  145. {google_api_core-2.38.0 → google_api_core-2.40.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.38.0
3
+ Version: 2.40.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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: 3.15
20
21
  Classifier: Operating System :: OS Independent
21
22
  Classifier: Topic :: Internet
22
23
  Requires-Python: >=3.10
@@ -42,7 +42,7 @@ DependencyConstraint = namedtuple(
42
42
  PQC_GRPC_WARNING_TEMPLATE = (
43
43
  "Package {consumer_package} depends on {dependency_package}, currently installed at version {version_used_string}. "
44
44
  "grpcio < 1.83.0 does not support Post-Quantum Cryptography (PQC). "
45
- "Support for non-PQC environments is deprecated. In October 2026, "
45
+ "Support for non-PQC environments is deprecated. In April 2027, "
46
46
  "Google Cloud Python packages will raise their minimum requirements "
47
47
  "(including google-api-core, grpcio, and grpcio-status) to enforce grpcio >= 1.83.0. "
48
48
  "For more details on Google Cloud's post-quantum security migration, visit: "
@@ -446,6 +446,41 @@ class AsyncRestUnsupportedParameterError(NotImplementedError):
446
446
  pass
447
447
 
448
448
 
449
+ class ResumableTransferError(GoogleAPICallError):
450
+ """Base class for resumable transfer errors."""
451
+
452
+ upload_url: Optional[str] = None
453
+ chunk_size: Optional[int] = None
454
+
455
+ def __init__(
456
+ self,
457
+ message: str,
458
+ *args,
459
+ upload_url: Optional[str] = None,
460
+ chunk_size: Optional[int] = None,
461
+ **kwargs,
462
+ ) -> None:
463
+ super().__init__(message, *args, **kwargs)
464
+ self.upload_url = upload_url
465
+ self.chunk_size = chunk_size
466
+
467
+
468
+ class TransferStalledError(ResumableTransferError):
469
+ """Raised when upload throughput stays below minimum rate past stall timeout."""
470
+
471
+
472
+ class UnseekableStreamError(ResumableTransferError):
473
+ """Raised when server recovery requires rewinding a non-seekable stream."""
474
+
475
+
476
+ class UploadCancelledError(ResumableTransferError):
477
+ """Raised when the upload is cancelled by the client or server."""
478
+
479
+
480
+ class MissingStatusHeaderError(ResumableTransferError):
481
+ """Raised when server response lacks the required X-Goog-Upload-Status header."""
482
+
483
+
449
484
  def exception_class_for_http_status(status_code):
450
485
  """Return the exception class for a specific HTTP status code.
451
486
 
@@ -0,0 +1,49 @@
1
+ # Copyright 2026 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
+ """Resumable transfer library for Google APIs."""
16
+
17
+ from google.api_core.exceptions import (
18
+ MissingStatusHeaderError,
19
+ ResumableTransferError,
20
+ TransferStalledError,
21
+ UnseekableStreamError,
22
+ UploadCancelledError,
23
+ )
24
+ from google.api_core.resumable_transfer.common import (
25
+ DEFAULT_CHUNK_SIZE,
26
+ ProgressState,
27
+ ResumableUploadConfig,
28
+ UploadProgress,
29
+ )
30
+ from google.api_core.resumable_transfer.upload import ResumableUploadSession
31
+ from google.api_core.resumable_transfer.upload_async import (
32
+ AsyncResumableUploadSession,
33
+ AsyncUploadOperation,
34
+ )
35
+
36
+ __all__ = [
37
+ "DEFAULT_CHUNK_SIZE",
38
+ "MissingStatusHeaderError",
39
+ "ProgressState",
40
+ "ResumableTransferError",
41
+ "TransferStalledError",
42
+ "UnseekableStreamError",
43
+ "UploadCancelledError",
44
+ "UploadProgress",
45
+ "ResumableUploadConfig",
46
+ "ResumableUploadSession",
47
+ "AsyncResumableUploadSession",
48
+ "AsyncUploadOperation",
49
+ ]
@@ -0,0 +1,191 @@
1
+ # Copyright 2026 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
+ """Common constants, headers, and shared configuration for Resumable Upload protocol."""
16
+
17
+ import dataclasses
18
+ import datetime
19
+ import enum
20
+ from typing import Any, Mapping, Optional, Sequence, Tuple, Union
21
+
22
+ import google.protobuf.message
23
+ import proto
24
+ from google.protobuf import json_format
25
+
26
+ from google.api_core import exceptions
27
+
28
+ # Default chunk size: 10 MiB
29
+ DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024
30
+
31
+ # Default timeout in seconds for the initial start request
32
+ DEFAULT_START_TIMEOUT = 60.0
33
+
34
+ # Protocol Headers
35
+ HEADER_PROTOCOL = "X-Goog-Upload-Protocol"
36
+ HEADER_COMMAND = "X-Goog-Upload-Command"
37
+ HEADER_STATUS = "X-Goog-Upload-Status"
38
+ HEADER_URL = "X-Goog-Upload-URL"
39
+ HEADER_OFFSET = "X-Goog-Upload-Offset"
40
+ HEADER_SIZE_RECEIVED = "X-Goog-Upload-Size-Received"
41
+ HEADER_CONTENT_TYPE = "X-Goog-Upload-Header-Content-Type"
42
+ HEADER_CONTENT_LENGTH = "X-Goog-Upload-Header-Content-Length"
43
+ HEADER_CHUNK_GRANULARITY = "X-Goog-Upload-Chunk-Granularity"
44
+
45
+ PROTOCOL_RESUMABLE = "resumable"
46
+
47
+
48
+ class _Command(str, enum.Enum):
49
+ """Protocol commands."""
50
+
51
+ START = "start"
52
+ UPLOAD = "upload"
53
+ FINALIZE = "finalize"
54
+ QUERY = "query"
55
+ CANCEL = "cancel"
56
+
57
+
58
+ class _Status(str, enum.Enum):
59
+ """Server upload status values."""
60
+
61
+ ACTIVE = "active"
62
+ FINAL = "final"
63
+ CANCELLED = "cancelled"
64
+
65
+
66
+ class ProgressState(str, enum.Enum):
67
+ """Progress notification state values."""
68
+
69
+ STARTED = "started"
70
+ UPLOADING = "uploading"
71
+ RECOVERING = "recovering"
72
+ OFFSET_RECEIVED = "offset received"
73
+ FINALIZED = "finalized"
74
+
75
+
76
+ @dataclasses.dataclass(frozen=True)
77
+ class UploadProgress:
78
+ """Upload progress notification payload.
79
+
80
+ Attributes:
81
+ upload_url: The unique session URL for this upload.
82
+ chunk_size: The actual negotiated chunk size.
83
+ bytes_uploaded: The total confirmed bytes committed so far.
84
+ total_bytes: The total size of the stream in bytes, if known.
85
+ state: The current progress state.
86
+ """
87
+
88
+ upload_url: str
89
+ chunk_size: int
90
+ bytes_uploaded: int
91
+ total_bytes: Optional[int]
92
+ state: ProgressState
93
+
94
+
95
+ # HTTP status codes indicating transient retryable errors (Category 1)
96
+ RETRYABLE_STATUS_CODES = (408, 429, 500, 502, 503, 504)
97
+
98
+ # HTTP status codes indicating state consistency errors requiring recovery (Category 2)
99
+ RECOVERABLE_STATUS_CODES = (400, 412, 416)
100
+
101
+ # Exception types indicating unrecoverable terminal conditions (Category 3)
102
+ TERMINAL_ERRORS = (
103
+ exceptions.DeadlineExceeded,
104
+ exceptions.TransferStalledError,
105
+ exceptions.UploadCancelledError,
106
+ exceptions.UnseekableStreamError,
107
+ )
108
+
109
+
110
+ @dataclasses.dataclass
111
+ class ResumableUploadConfig:
112
+ """Configuration options for a resumable upload.
113
+
114
+ Attributes:
115
+ chunk_size: Size in bytes for each uploaded data chunk. Defaults to 10 MiB.
116
+ stall_minimum_rate: Minimum transfer rate in bytes per second. Defaults to 64 KiB/s.
117
+ stall_timeout: Stall duration threshold in seconds. Defaults to 120s.
118
+ headers: Additional HTTP headers dispatched exclusively with start request.
119
+ deadline: Optional overall wall-clock deadline for the entire upload process.
120
+ When set, each HTTP request timeout is trimmed to the remaining time before
121
+ the deadline, and DeadlineExceeded is raised immediately when the deadline
122
+ elapses (even on healthy streams). Timezone-aware datetimes (e.g.,
123
+ ``datetime.now(timezone.utc) + timedelta(...)``) are recommended;
124
+ timezone-naive datetimes are assumed to be in local system time. When
125
+ None (default), transfer duration is governed by stall control
126
+ (stall_minimum_rate and stall_timeout), allowing healthy streams
127
+ transferring above the minimum rate to continue indefinitely.
128
+ """
129
+
130
+ chunk_size: int = DEFAULT_CHUNK_SIZE
131
+ stall_minimum_rate: int = 64 * 1024
132
+ stall_timeout: float = 120.0
133
+ headers: Optional[Union[Mapping[str, str], Sequence[Tuple[str, str]]]] = None
134
+ deadline: Optional[datetime.datetime] = None
135
+
136
+ def __post_init__(self) -> None:
137
+ if self.deadline is not None:
138
+ self.deadline = self.deadline.astimezone(datetime.timezone.utc)
139
+
140
+ @property
141
+ def start_headers(self) -> Optional[Sequence[Tuple[str, str]]]:
142
+ """Returns normalized additional headers for the start request."""
143
+ if self.headers is None:
144
+ return None
145
+ if isinstance(self.headers, Mapping):
146
+ return list(self.headers.items())
147
+ return list(self.headers)
148
+
149
+
150
+ def _format_response_payload(
151
+ response: Union[Any, bytes],
152
+ response_type: Optional[Any],
153
+ ) -> Any:
154
+ """Formats raw response or bytes into protobuf or proto-plus message type if configured.
155
+
156
+ Args:
157
+ response: Raw HTTP response object or response body bytes.
158
+ response_type: Deserializer callable, proto.Message class, or
159
+ google.protobuf.message.Message class or instance.
160
+
161
+ Returns:
162
+ Deserialized protobuf message, or raw response bytes if
163
+ ``response_type`` is ``None``.
164
+ """
165
+ content: bytes
166
+ if isinstance(response, bytes):
167
+ content = response
168
+ elif hasattr(response, "content"):
169
+ content = response.content
170
+ else:
171
+ content = bytes(response)
172
+
173
+ if response_type is None:
174
+ return content
175
+
176
+ from_json_fn = getattr(response_type, "from_json", None)
177
+ if callable(from_json_fn):
178
+ if isinstance(response_type, type) and issubclass(response_type, proto.Message):
179
+ return from_json_fn(content, ignore_unknown_fields=True)
180
+ return from_json_fn(content)
181
+ if isinstance(response_type, type) and issubclass(
182
+ response_type, google.protobuf.message.Message
183
+ ):
184
+ instance = response_type()
185
+ return json_format.Parse(content, instance, ignore_unknown_fields=True)
186
+ if isinstance(response_type, google.protobuf.message.Message):
187
+ return json_format.Parse(content, response_type, ignore_unknown_fields=True)
188
+ if callable(response_type):
189
+ return response_type(content)
190
+
191
+ return content