google-cloud-pubsub 2.31.0__tar.gz → 2.32.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 (124) hide show
  1. {google_cloud_pubsub-2.31.0/google_cloud_pubsub.egg-info → google_cloud_pubsub-2.32.0}/PKG-INFO +4 -2
  2. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/open_telemetry/subscribe_opentelemetry.py +9 -1
  3. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_sequencer/base.py +2 -2
  4. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/requests.py +2 -0
  5. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py +101 -28
  6. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/message.py +30 -0
  7. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/scheduler.py +21 -2
  8. {google_cloud_pubsub-2.31.0/google/pubsub_v1 → google_cloud_pubsub-2.32.0/google/pubsub}/gapic_version.py +1 -1
  9. {google_cloud_pubsub-2.31.0/google/pubsub → google_cloud_pubsub-2.32.0/google/pubsub_v1}/gapic_version.py +1 -1
  10. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/client.py +1 -1
  11. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/client.py +1 -1
  12. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/client.py +1 -1
  13. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/types/pubsub.py +33 -25
  14. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0/google_cloud_pubsub.egg-info}/PKG-INFO +4 -2
  15. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google_cloud_pubsub.egg-info/requires.txt +6 -1
  16. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/scripts/fixup_pubsub_v1_keywords.py +1 -1
  17. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/setup.py +3 -1
  18. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/test_publisher_client.py +25 -20
  19. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_message.py +21 -3
  20. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py +22 -12
  21. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/LICENSE +0 -0
  22. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/MANIFEST.in +0 -0
  23. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/README.rst +0 -0
  24. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub/__init__.py +0 -0
  25. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/__init__.py +0 -0
  26. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/exceptions.py +0 -0
  27. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/futures.py +0 -0
  28. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/open_telemetry/__init__.py +0 -0
  29. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/open_telemetry/context_propagation.py +0 -0
  30. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/open_telemetry/publish_message_wrapper.py +0 -0
  31. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/proto/pubsub.proto +0 -0
  32. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/proto/schema.proto +0 -0
  33. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/__init__.py +0 -0
  34. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_batch/__init__.py +0 -0
  35. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_batch/base.py +0 -0
  36. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_batch/thread.py +0 -0
  37. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_sequencer/__init__.py +0 -0
  38. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_sequencer/ordered_sequencer.py +0 -0
  39. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/_sequencer/unordered_sequencer.py +0 -0
  40. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/client.py +0 -0
  41. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/exceptions.py +0 -0
  42. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/flow_controller.py +0 -0
  43. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/publisher/futures.py +0 -0
  44. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/__init__.py +0 -0
  45. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/__init__.py +0 -0
  46. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py +0 -0
  47. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py +0 -0
  48. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py +0 -0
  49. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/histogram.py +0 -0
  50. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/leaser.py +0 -0
  51. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/_protocol/messages_on_hold.py +0 -0
  52. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/client.py +0 -0
  53. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/exceptions.py +0 -0
  54. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/subscriber/futures.py +0 -0
  55. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/cloud/pubsub_v1/types.py +0 -0
  56. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub/__init__.py +0 -0
  57. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub/py.typed +0 -0
  58. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/__init__.py +0 -0
  59. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/gapic_metadata.json +0 -0
  60. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/py.typed +0 -0
  61. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/__init__.py +0 -0
  62. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/__init__.py +0 -0
  63. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/async_client.py +0 -0
  64. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/pagers.py +0 -0
  65. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/__init__.py +0 -0
  66. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/base.py +0 -0
  67. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/grpc.py +0 -0
  68. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/grpc_asyncio.py +0 -0
  69. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/rest.py +0 -0
  70. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/publisher/transports/rest_base.py +0 -0
  71. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/__init__.py +0 -0
  72. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/async_client.py +0 -0
  73. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/pagers.py +0 -0
  74. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/__init__.py +0 -0
  75. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/base.py +0 -0
  76. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/grpc.py +0 -0
  77. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/grpc_asyncio.py +0 -0
  78. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/rest.py +0 -0
  79. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/schema_service/transports/rest_base.py +0 -0
  80. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/__init__.py +0 -0
  81. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/async_client.py +0 -0
  82. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/pagers.py +0 -0
  83. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/__init__.py +0 -0
  84. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/base.py +0 -0
  85. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/grpc.py +0 -0
  86. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/grpc_asyncio.py +0 -0
  87. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/rest.py +0 -0
  88. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/services/subscriber/transports/rest_base.py +0 -0
  89. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/types/__init__.py +0 -0
  90. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google/pubsub_v1/types/schema.py +0 -0
  91. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google_cloud_pubsub.egg-info/SOURCES.txt +0 -0
  92. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google_cloud_pubsub.egg-info/dependency_links.txt +0 -0
  93. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google_cloud_pubsub.egg-info/not-zip-safe +0 -0
  94. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/google_cloud_pubsub.egg-info/top_level.txt +0 -0
  95. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/setup.cfg +0 -0
  96. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/__init__.py +0 -0
  97. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/system.py +0 -0
  98. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/__init__.py +0 -0
  99. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/gapic/__init__.py +0 -0
  100. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/gapic/pubsub_v1/__init__.py +0 -0
  101. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/gapic/pubsub_v1/test_publisher.py +0 -0
  102. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/gapic/pubsub_v1/test_schema_service.py +0 -0
  103. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/gapic/pubsub_v1/test_subscriber.py +0 -0
  104. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/conftest.py +0 -0
  105. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/batch/test_base.py +0 -0
  106. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/batch/test_thread.py +0 -0
  107. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/sequencer/test_ordered_sequencer.py +0 -0
  108. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/sequencer/test_unordered_sequencer.py +0 -0
  109. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/test_flow_controller.py +0 -0
  110. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/test_futures_publisher.py +0 -0
  111. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/publisher/test_publish_message_wrapper.py +0 -0
  112. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_dispatcher.py +0 -0
  113. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_futures_subscriber.py +0 -0
  114. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_heartbeater.py +0 -0
  115. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_helper_threads.py +0 -0
  116. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_histogram.py +0 -0
  117. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_leaser.py +0 -0
  118. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_messages_on_hold.py +0 -0
  119. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_scheduler.py +0 -0
  120. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_subscribe_opentelemetry.py +0 -0
  121. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py +0 -0
  122. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/pubsub_v1/test_futures.py +0 -0
  123. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/test_packaging.py +0 -0
  124. {google_cloud_pubsub-2.31.0 → google_cloud_pubsub-2.32.0}/tests/unit/test_pubsub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-pubsub
3
- Version: 2.31.0
3
+ Version: 2.32.0
4
4
  Summary: Google Cloud Pub/Sub API client library
5
5
  Home-page: https://github.com/googleapis/python-pubsub
6
6
  Author: Google LLC
@@ -19,11 +19,13 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Operating System :: OS Independent
23
24
  Classifier: Topic :: Internet
24
25
  Requires-Python: >=3.7
25
26
  License-File: LICENSE
26
- Requires-Dist: grpcio<2.0.0,>=1.51.3
27
+ Requires-Dist: grpcio<2.0.0,>=1.51.3; python_version < "3.14"
28
+ Requires-Dist: grpcio<2.0.0,>=1.75.1; python_version >= "3.14"
27
29
  Requires-Dist: google-auth<3.0.0,>=2.14.1
28
30
  Requires-Dist: google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0,>=1.34.0
29
31
  Requires-Dist: proto-plus<2.0.0,>=1.22.0
@@ -160,7 +160,7 @@ class SubscribeOpenTelemetry:
160
160
  assert self._scheduler_span is not None
161
161
  self._scheduler_span.end()
162
162
 
163
- def start_process_span(self) -> None:
163
+ def start_process_span(self) -> trace.Span:
164
164
  assert self._subscribe_span is not None
165
165
  tracer = trace.get_tracer(_OPEN_TELEMETRY_TRACER_NAME)
166
166
  publish_create_span_link: Optional[trace.Link] = None
@@ -186,6 +186,7 @@ class SubscribeOpenTelemetry:
186
186
  end_on_exit=False,
187
187
  ) as process_span:
188
188
  self._process_span = process_span
189
+ return process_span
189
190
 
190
191
  def end_process_span(self) -> None:
191
192
  assert self._process_span is not None
@@ -200,6 +201,13 @@ class SubscribeOpenTelemetry:
200
201
  },
201
202
  )
202
203
 
204
+ def __enter__(self) -> trace.Span:
205
+ return self.start_process_span()
206
+
207
+ def __exit__(self, exc_type, exc_val, traceback):
208
+ if self._process_span:
209
+ self.end_process_span()
210
+
203
211
 
204
212
  def start_modack_span(
205
213
  subscribe_span_links: List[trace.Link],
@@ -53,8 +53,8 @@ class Sequencer(metaclass=abc.ABCMeta):
53
53
  def publish(
54
54
  self,
55
55
  message: gapic_types.PubsubMessage,
56
- retry: "OptionalRetry" = gapic_v1.method.DEFAULT,
57
- timeout: gapic_types.TimeoutType = gapic_v1.method.DEFAULT,
56
+ retry: "OptionalRetry" = gapic_v1.method.DEFAULT, # type: ignore
57
+ timeout: gapic_types.TimeoutType = gapic_v1.method.DEFAULT, # type: ignore
58
58
  ) -> "futures.Future": # pragma: NO COVER
59
59
  """Publish message for this ordering key.
60
60
 
@@ -32,6 +32,7 @@ class AckRequest(NamedTuple):
32
32
  ordering_key: Optional[str]
33
33
  future: Optional["futures.Future"]
34
34
  opentelemetry_data: Optional[SubscribeOpenTelemetry] = None
35
+ message_id: Optional[str] = None
35
36
 
36
37
 
37
38
  class DropRequest(NamedTuple):
@@ -52,6 +53,7 @@ class ModAckRequest(NamedTuple):
52
53
  seconds: float
53
54
  future: Optional["futures.Future"]
54
55
  opentelemetry_data: Optional[SubscribeOpenTelemetry] = None
56
+ message_id: Optional[str] = None
55
57
 
56
58
 
57
59
  class NackRequest(NamedTuple):
@@ -21,7 +21,16 @@ import itertools
21
21
  import logging
22
22
  import threading
23
23
  import typing
24
- from typing import Any, Dict, Callable, Iterable, List, Optional, Set, Tuple
24
+ from typing import (
25
+ Any,
26
+ Dict,
27
+ Callable,
28
+ Iterable,
29
+ List,
30
+ Optional,
31
+ Set,
32
+ Tuple,
33
+ )
25
34
  import uuid
26
35
 
27
36
  from opentelemetry import trace
@@ -60,6 +69,12 @@ if typing.TYPE_CHECKING: # pragma: NO COVER
60
69
 
61
70
 
62
71
  _LOGGER = logging.getLogger(__name__)
72
+ _SLOW_ACK_LOGGER = logging.getLogger("slow-ack")
73
+ _STREAMS_LOGGER = logging.getLogger("subscriber-streams")
74
+ _FLOW_CONTROL_LOGGER = logging.getLogger("subscriber-flow-control")
75
+ _CALLBACK_DELIVERY_LOGGER = logging.getLogger("callback-delivery")
76
+ _CALLBACK_EXCEPTION_LOGGER = logging.getLogger("callback-exceptions")
77
+ _EXPIRY_LOGGER = logging.getLogger("expiry")
63
78
  _REGULAR_SHUTDOWN_THREAD_NAME = "Thread-RegularStreamShutdown"
64
79
  _RPC_ERROR_THREAD_NAME = "Thread-OnRpcTerminated"
65
80
  _RETRYABLE_STREAM_ERRORS = (
@@ -145,18 +160,34 @@ def _wrap_callback_errors(
145
160
  callback: The user callback.
146
161
  message: The Pub/Sub message.
147
162
  """
163
+ _CALLBACK_DELIVERY_LOGGER.debug(
164
+ "Message (id=%s, ack_id=%s, ordering_key=%s, exactly_once=%s) received by subscriber callback",
165
+ message.message_id,
166
+ message.ack_id,
167
+ message.ordering_key,
168
+ message.exactly_once_enabled,
169
+ )
170
+
148
171
  try:
149
172
  if message.opentelemetry_data:
150
173
  message.opentelemetry_data.end_subscribe_concurrency_control_span()
151
- message.opentelemetry_data.start_process_span()
152
- callback(message)
174
+ with message.opentelemetry_data:
175
+ callback(message)
176
+ else:
177
+ callback(message)
153
178
  except BaseException as exc:
154
179
  # Note: the likelihood of this failing is extremely low. This just adds
155
180
  # a message to a queue, so if this doesn't work the world is in an
156
181
  # unrecoverable state and this thread should just bail.
157
- _LOGGER.exception(
158
- "Top-level exception occurred in callback while processing a message"
182
+
183
+ _CALLBACK_EXCEPTION_LOGGER.exception(
184
+ "Message (id=%s, ack_id=%s, ordering_key=%s, exactly_once=%s)'s callback threw exception, nacking message.",
185
+ message.message_id,
186
+ message.ack_id,
187
+ message.ordering_key,
188
+ message.exactly_once_enabled,
159
189
  )
190
+
160
191
  message.nack()
161
192
  on_callback_error(exc)
162
193
 
@@ -197,6 +228,9 @@ def _process_requests(
197
228
  error_status: Optional["status_pb2.Status"],
198
229
  ack_reqs_dict: Dict[str, requests.AckRequest],
199
230
  errors_dict: Optional[Dict[str, str]],
231
+ ack_histogram: Optional[histogram.Histogram] = None,
232
+ # TODO - Change this param to a Union of Literals when we drop p3.7 support
233
+ req_type: str = "ack",
200
234
  ):
201
235
  """Process requests when exactly-once delivery is enabled by referring to
202
236
  error_status and errors_dict.
@@ -207,28 +241,40 @@ def _process_requests(
207
241
  """
208
242
  requests_completed = []
209
243
  requests_to_retry = []
210
- for ack_id in ack_reqs_dict:
244
+ for ack_id, ack_request in ack_reqs_dict.items():
245
+ # Debug logging: slow acks
246
+ if (
247
+ req_type == "ack"
248
+ and ack_histogram
249
+ and ack_request.time_to_ack > ack_histogram.percentile(percent=99)
250
+ ):
251
+ _SLOW_ACK_LOGGER.debug(
252
+ "Message (id=%s, ack_id=%s) ack duration of %s s is higher than the p99 ack duration",
253
+ ack_request.message_id,
254
+ ack_request.ack_id,
255
+ )
256
+
211
257
  # Handle special errors returned for ack/modack RPCs via the ErrorInfo
212
258
  # sidecar metadata when exactly-once delivery is enabled.
213
259
  if errors_dict and ack_id in errors_dict:
214
260
  exactly_once_error = errors_dict[ack_id]
215
261
  if exactly_once_error.startswith("TRANSIENT_"):
216
- requests_to_retry.append(ack_reqs_dict[ack_id])
262
+ requests_to_retry.append(ack_request)
217
263
  else:
218
264
  if exactly_once_error == "PERMANENT_FAILURE_INVALID_ACK_ID":
219
265
  exc = AcknowledgeError(AcknowledgeStatus.INVALID_ACK_ID, info=None)
220
266
  else:
221
267
  exc = AcknowledgeError(AcknowledgeStatus.OTHER, exactly_once_error)
222
- future = ack_reqs_dict[ack_id].future
268
+ future = ack_request.future
223
269
  if future is not None:
224
270
  future.set_exception(exc)
225
- requests_completed.append(ack_reqs_dict[ack_id])
271
+ requests_completed.append(ack_request)
226
272
  # Temporary GRPC errors are retried
227
273
  elif (
228
274
  error_status
229
275
  and error_status.code in _EXACTLY_ONCE_DELIVERY_TEMPORARY_RETRY_ERRORS
230
276
  ):
231
- requests_to_retry.append(ack_reqs_dict[ack_id])
277
+ requests_to_retry.append(ack_request)
232
278
  # Other GRPC errors are NOT retried
233
279
  elif error_status:
234
280
  if error_status.code == code_pb2.PERMISSION_DENIED:
@@ -237,20 +283,20 @@ def _process_requests(
237
283
  exc = AcknowledgeError(AcknowledgeStatus.FAILED_PRECONDITION, info=None)
238
284
  else:
239
285
  exc = AcknowledgeError(AcknowledgeStatus.OTHER, str(error_status))
240
- future = ack_reqs_dict[ack_id].future
286
+ future = ack_request.future
241
287
  if future is not None:
242
288
  future.set_exception(exc)
243
- requests_completed.append(ack_reqs_dict[ack_id])
289
+ requests_completed.append(ack_request)
244
290
  # Since no error occurred, requests with futures are completed successfully.
245
- elif ack_reqs_dict[ack_id].future:
246
- future = ack_reqs_dict[ack_id].future
291
+ elif ack_request.future:
292
+ future = ack_request.future
247
293
  # success
248
294
  assert future is not None
249
295
  future.set_result(AcknowledgeStatus.SUCCESS)
250
- requests_completed.append(ack_reqs_dict[ack_id])
296
+ requests_completed.append(ack_request)
251
297
  # All other requests are considered completed.
252
298
  else:
253
- requests_completed.append(ack_reqs_dict[ack_id])
299
+ requests_completed.append(ack_request)
254
300
 
255
301
  return requests_completed, requests_to_retry
256
302
 
@@ -412,7 +458,7 @@ class StreamingPullManager(object):
412
458
  return self._dispatcher
413
459
 
414
460
  @property
415
- def leaser(self) -> Optional[leaser.Leaser]:
461
+ def leaser(self) -> Optional["leaser.Leaser"]:
416
462
  """The leaser helper."""
417
463
  return self._leaser
418
464
 
@@ -558,8 +604,10 @@ class StreamingPullManager(object):
558
604
  with self._pause_resume_lock:
559
605
  if self.load >= _MAX_LOAD:
560
606
  if self._consumer is not None and not self._consumer.is_paused:
561
- _LOGGER.debug(
562
- "Message backlog over load at %.2f, pausing.", self.load
607
+ _FLOW_CONTROL_LOGGER.debug(
608
+ "Message backlog over load at %.2f (threshold %.2f), initiating client-side flow control",
609
+ self.load,
610
+ _RESUME_THRESHOLD,
563
611
  )
564
612
  self._consumer.pause()
565
613
 
@@ -586,10 +634,18 @@ class StreamingPullManager(object):
586
634
  self._maybe_release_messages()
587
635
 
588
636
  if self.load < _RESUME_THRESHOLD:
589
- _LOGGER.debug("Current load is %.2f, resuming consumer.", self.load)
637
+ _FLOW_CONTROL_LOGGER.debug(
638
+ "Current load is %.2f (threshold %.2f), suspending client-side flow control.",
639
+ self.load,
640
+ _RESUME_THRESHOLD,
641
+ )
590
642
  self._consumer.resume()
591
643
  else:
592
- _LOGGER.debug("Did not resume, current load is %.2f.", self.load)
644
+ _FLOW_CONTROL_LOGGER.debug(
645
+ "Current load is %.2f (threshold %.2f), retaining client-side flow control.",
646
+ self.load,
647
+ _RESUME_THRESHOLD,
648
+ )
593
649
 
594
650
  def _maybe_release_messages(self) -> None:
595
651
  """Release (some of) the held messages if the current load allows for it.
@@ -700,7 +756,7 @@ class StreamingPullManager(object):
700
756
 
701
757
  if self._exactly_once_delivery_enabled():
702
758
  requests_completed, requests_to_retry = _process_requests(
703
- error_status, ack_reqs_dict, ack_errors_dict
759
+ error_status, ack_reqs_dict, ack_errors_dict, self.ack_histogram, "ack"
704
760
  )
705
761
  else:
706
762
  requests_completed = []
@@ -794,7 +850,11 @@ class StreamingPullManager(object):
794
850
 
795
851
  if self._exactly_once_delivery_enabled():
796
852
  requests_completed, requests_to_retry = _process_requests(
797
- error_status, ack_reqs_dict, modack_errors_dict
853
+ error_status,
854
+ ack_reqs_dict,
855
+ modack_errors_dict,
856
+ self.ack_histogram,
857
+ "modack",
798
858
  )
799
859
  else:
800
860
  requests_completed = []
@@ -1237,6 +1297,11 @@ class StreamingPullManager(object):
1237
1297
  receipt_modack=True,
1238
1298
  )
1239
1299
 
1300
+ if len(expired_ack_ids):
1301
+ _EXPIRY_LOGGER.debug(
1302
+ "ack ids %s were dropped as they have already expired.", expired_ack_ids
1303
+ )
1304
+
1240
1305
  with self._pause_resume_lock:
1241
1306
  if self._scheduler is None or self._leaser is None:
1242
1307
  _LOGGER.debug(
@@ -1279,7 +1344,7 @@ class StreamingPullManager(object):
1279
1344
  Called whenever `self.consumer` receives a non-retryable exception.
1280
1345
  We close the manager on such non-retryable cases.
1281
1346
  """
1282
- _LOGGER.exception(
1347
+ _LOGGER.info(
1283
1348
  "Streaming pull terminating after receiving non-recoverable error: %s",
1284
1349
  exception,
1285
1350
  )
@@ -1302,9 +1367,13 @@ class StreamingPullManager(object):
1302
1367
  # If this is in the list of idempotent exceptions, then we want to
1303
1368
  # recover.
1304
1369
  if isinstance(exception, _RETRYABLE_STREAM_ERRORS):
1305
- _LOGGER.debug("Observed recoverable stream error %s", exception)
1370
+ _STREAMS_LOGGER.debug(
1371
+ "Observed recoverable stream error %s, reopening stream", exception
1372
+ )
1306
1373
  return True
1307
- _LOGGER.debug("Observed non-recoverable stream error %s", exception)
1374
+ _STREAMS_LOGGER.debug(
1375
+ "Observed non-recoverable stream error %s, shutting down stream", exception
1376
+ )
1308
1377
  return False
1309
1378
 
1310
1379
  def _should_terminate(self, exception: BaseException) -> bool:
@@ -1324,9 +1393,13 @@ class StreamingPullManager(object):
1324
1393
  is_api_error = isinstance(exception, exceptions.GoogleAPICallError)
1325
1394
  # Terminate any non-API errors, or non-retryable errors (permission denied, unauthorized, etc.)
1326
1395
  if not is_api_error or isinstance(exception, _TERMINATING_STREAM_ERRORS):
1327
- _LOGGER.error("Observed terminating stream error %s", exception)
1396
+ _STREAMS_LOGGER.debug(
1397
+ "Observed terminating stream error %s, shutting down stream", exception
1398
+ )
1328
1399
  return True
1329
- _LOGGER.debug("Observed non-terminating stream error %s", exception)
1400
+ _STREAMS_LOGGER.debug(
1401
+ "Observed non-terminating stream error %s, attempting to reopen", exception
1402
+ )
1330
1403
  return False
1331
1404
 
1332
1405
  def _on_rpc_done(self, future: Any) -> None:
@@ -16,6 +16,7 @@ from __future__ import absolute_import
16
16
 
17
17
  import datetime as dt
18
18
  import json
19
+ import logging
19
20
  import math
20
21
  import time
21
22
  import typing
@@ -43,6 +44,8 @@ Message {{
43
44
  attributes: {}
44
45
  }}"""
45
46
 
47
+ _ACK_NACK_LOGGER = logging.getLogger("ack-nack")
48
+
46
49
  _SUCCESS_FUTURE = futures.Future()
47
50
  _SUCCESS_FUTURE.set_result(AcknowledgeStatus.SUCCESS)
48
51
 
@@ -274,6 +277,7 @@ class Message(object):
274
277
  time_to_ack = math.ceil(time.time() - self._received_timestamp)
275
278
  self._request_queue.put(
276
279
  requests.AckRequest(
280
+ message_id=self.message_id,
277
281
  ack_id=self._ack_id,
278
282
  byte_size=self.size,
279
283
  time_to_ack=time_to_ack,
@@ -282,6 +286,12 @@ class Message(object):
282
286
  opentelemetry_data=self.opentelemetry_data,
283
287
  )
284
288
  )
289
+ _ACK_NACK_LOGGER.debug(
290
+ "Called ack for message (id=%s, ack_id=%s, ordering_key=%s)",
291
+ self.message_id,
292
+ self.ack_id,
293
+ self.ordering_key,
294
+ )
285
295
 
286
296
  def ack_with_response(self) -> "futures.Future":
287
297
  """Acknowledge the given message.
@@ -322,6 +332,12 @@ class Message(object):
322
332
  pubsub_v1.subscriber.exceptions.AcknowledgeError exception
323
333
  will be thrown.
324
334
  """
335
+ _ACK_NACK_LOGGER.debug(
336
+ "Called ack for message (id=%s, ack_id=%s, ordering_key=%s, exactly_once=True)",
337
+ self.message_id,
338
+ self.ack_id,
339
+ self.ordering_key,
340
+ )
325
341
  if self.opentelemetry_data:
326
342
  self.opentelemetry_data.add_process_span_event("ack called")
327
343
  self.opentelemetry_data.end_process_span()
@@ -335,6 +351,7 @@ class Message(object):
335
351
  time_to_ack = math.ceil(time.time() - self._received_timestamp)
336
352
  self._request_queue.put(
337
353
  requests.AckRequest(
354
+ message_id=self.message_id,
338
355
  ack_id=self._ack_id,
339
356
  byte_size=self.size,
340
357
  time_to_ack=time_to_ack,
@@ -382,6 +399,7 @@ class Message(object):
382
399
  """
383
400
  self._request_queue.put(
384
401
  requests.ModAckRequest(
402
+ message_id=self.message_id,
385
403
  ack_id=self._ack_id,
386
404
  seconds=seconds,
387
405
  future=None,
@@ -445,6 +463,7 @@ class Message(object):
445
463
 
446
464
  self._request_queue.put(
447
465
  requests.ModAckRequest(
466
+ message_id=self.message_id,
448
467
  ack_id=self._ack_id,
449
468
  seconds=seconds,
450
469
  future=req_future,
@@ -461,6 +480,13 @@ class Message(object):
461
480
  may take place immediately or after a delay, and may arrive at this subscriber
462
481
  or another.
463
482
  """
483
+ _ACK_NACK_LOGGER.debug(
484
+ "Called nack for message (id=%s, ack_id=%s, ordering_key=%s, exactly_once=%s)",
485
+ self.message_id,
486
+ self.ack_id,
487
+ self.ordering_key,
488
+ self._exactly_once_delivery_enabled_func(),
489
+ )
464
490
  if self.opentelemetry_data:
465
491
  self.opentelemetry_data.add_process_span_event("nack called")
466
492
  self.opentelemetry_data.end_process_span()
@@ -530,3 +556,7 @@ class Message(object):
530
556
  )
531
557
 
532
558
  return future
559
+
560
+ @property
561
+ def exactly_once_enabled(self):
562
+ return self._exactly_once_delivery_enabled_func()
@@ -21,6 +21,7 @@ each message.
21
21
  import abc
22
22
  import concurrent.futures
23
23
  import queue
24
+ import sys
24
25
  import typing
25
26
  from typing import Callable, List, Optional
26
27
  import warnings
@@ -37,7 +38,7 @@ class Scheduler(metaclass=abc.ABCMeta):
37
38
 
38
39
  @property
39
40
  @abc.abstractmethod
40
- def queue(self) -> queue.Queue: # pragma: NO COVER
41
+ def queue(self) -> "queue.Queue": # pragma: NO COVER
41
42
  """Queue: A concurrency-safe queue specific to the underlying
42
43
  concurrency implementation.
43
44
 
@@ -162,7 +163,25 @@ class ThreadScheduler(Scheduler):
162
163
  work_item = self._executor._work_queue.get(block=False)
163
164
  if work_item is None: # Exceutor in shutdown mode.
164
165
  continue
165
- dropped_messages.append(work_item.args[0]) # type: ignore[index]
166
+
167
+ dropped_message = None
168
+ if sys.version_info < (3, 14):
169
+ # For Python < 3.14, work_item.args is a tuple of positional arguments.
170
+ # The message is expected to be the first argument.
171
+ if hasattr(work_item, "args") and work_item.args:
172
+ dropped_message = work_item.args[0] # type: ignore[index]
173
+ else:
174
+ # For Python >= 3.14, work_item.task is (fn, args, kwargs).
175
+ # The message is expected to be the first item in the args tuple (task[1]).
176
+ if (
177
+ hasattr(work_item, "task")
178
+ and len(work_item.task) == 3
179
+ and work_item.task[1]
180
+ ):
181
+ dropped_message = work_item.task[1][0]
182
+
183
+ if dropped_message is not None:
184
+ dropped_messages.append(dropped_message)
166
185
  except queue.Empty:
167
186
  pass
168
187
 
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "2.31.0" # {x-release-please-version}
16
+ __version__ = "2.32.0" # {x-release-please-version}
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "2.31.0" # {x-release-please-version}
16
+ __version__ = "2.32.0" # {x-release-please-version}
@@ -725,7 +725,7 @@ class PublisherClient(metaclass=PublisherClientMeta):
725
725
 
726
726
  emulator_host = os.environ.get("PUBSUB_EMULATOR_HOST")
727
727
  if emulator_host:
728
- if issubclass(transport_init, type(self)._transport_registry["grpc"]):
728
+ if issubclass(transport_init, type(self)._transport_registry["grpc"]): # type: ignore
729
729
  channel = grpc.insecure_channel(target=emulator_host)
730
730
  else:
731
731
  channel = grpc.aio.insecure_channel(target=emulator_host)
@@ -677,7 +677,7 @@ class SchemaServiceClient(metaclass=SchemaServiceClientMeta):
677
677
 
678
678
  emulator_host = os.environ.get("PUBSUB_EMULATOR_HOST")
679
679
  if emulator_host:
680
- if issubclass(transport_init, type(self)._transport_registry["grpc"]):
680
+ if issubclass(transport_init, type(self)._transport_registry["grpc"]): # type: ignore
681
681
  channel = grpc.insecure_channel(target=emulator_host)
682
682
  else:
683
683
  channel = grpc.aio.insecure_channel(target=emulator_host)
@@ -729,7 +729,7 @@ class SubscriberClient(metaclass=SubscriberClientMeta):
729
729
 
730
730
  emulator_host = os.environ.get("PUBSUB_EMULATOR_HOST")
731
731
  if emulator_host:
732
- if issubclass(transport_init, type(self)._transport_registry["grpc"]):
732
+ if issubclass(transport_init, type(self)._transport_registry["grpc"]): # type: ignore
733
733
  channel = grpc.insecure_channel(target=emulator_host)
734
734
  else:
735
735
  channel = grpc.aio.insecure_channel(target=emulator_host)
@@ -241,13 +241,13 @@ class IngestionDataSourceSettings(proto.Message):
241
241
  Permission denied encountered while consuming data from
242
242
  Kinesis. This can happen if:
243
243
 
244
- - The provided ``aws_role_arn`` does not exist or does not
245
- have the appropriate permissions attached.
246
- - The provided ``aws_role_arn`` is not set up properly for
247
- Identity Federation using ``gcp_service_account``.
248
- - The Pub/Sub SA is not granted the
249
- ``iam.serviceAccounts.getOpenIdToken`` permission on
250
- ``gcp_service_account``.
244
+ - The provided ``aws_role_arn`` does not exist or does not
245
+ have the appropriate permissions attached.
246
+ - The provided ``aws_role_arn`` is not set up properly for
247
+ Identity Federation using ``gcp_service_account``.
248
+ - The Pub/Sub SA is not granted the
249
+ ``iam.serviceAccounts.getOpenIdToken`` permission on
250
+ ``gcp_service_account``.
251
251
  PUBLISH_PERMISSION_DENIED (3):
252
252
  Permission denied encountered while publishing to the topic.
253
253
  This can happen if the Pub/Sub SA has not been granted the
@@ -347,9 +347,9 @@ class IngestionDataSourceSettings(proto.Message):
347
347
  granted the `appropriate
348
348
  permissions <https://cloud.google.com/storage/docs/access-control/iam-permissions>`__:
349
349
 
350
- - storage.objects.list: to list the objects in a bucket.
351
- - storage.objects.get: to read the objects in a bucket.
352
- - storage.buckets.get: to verify the bucket exists.
350
+ - storage.objects.list: to list the objects in a bucket.
351
+ - storage.objects.get: to read the objects in a bucket.
352
+ - storage.buckets.get: to verify the bucket exists.
353
353
  PUBLISH_PERMISSION_DENIED (3):
354
354
  Permission denied encountered while publishing to the topic.
355
355
  This can happen if the Pub/Sub SA has not been granted the
@@ -1991,11 +1991,11 @@ class Subscription(proto.Message):
1991
1991
  for the delivery of a message with a given value of
1992
1992
  ``message_id`` on this subscription:
1993
1993
 
1994
- - The message sent to a subscriber is guaranteed not to be
1995
- resent before the message's acknowledgment deadline
1996
- expires.
1997
- - An acknowledged message will not be resent to a
1998
- subscriber.
1994
+ - The message sent to a subscriber is guaranteed not to be
1995
+ resent before the message's acknowledgment deadline
1996
+ expires.
1997
+ - An acknowledged message will not be resent to a
1998
+ subscriber.
1999
1999
 
2000
2000
  Note that subscribers may still receive multiple copies of a
2001
2001
  message when ``enable_exactly_once_delivery`` is true if the
@@ -2309,10 +2309,10 @@ class PushConfig(proto.Message):
2309
2309
  The only supported values for the ``x-goog-version``
2310
2310
  attribute are:
2311
2311
 
2312
- - ``v1beta1``: uses the push format defined in the v1beta1
2313
- Pub/Sub API.
2314
- - ``v1`` or ``v1beta2``: uses the push format defined in
2315
- the v1 Pub/Sub API.
2312
+ - ``v1beta1``: uses the push format defined in the v1beta1
2313
+ Pub/Sub API.
2314
+ - ``v1`` or ``v1beta2``: uses the push format defined in the
2315
+ v1 Pub/Sub API.
2316
2316
 
2317
2317
  For example: ``attributes { "x-goog-version": "v1" }``
2318
2318
  oidc_token (google.pubsub_v1.types.PushConfig.OidcToken):
@@ -2478,12 +2478,11 @@ class BigQueryConfig(proto.Message):
2478
2478
  Cannot write to the BigQuery table because of permission
2479
2479
  denied errors. This can happen if
2480
2480
 
2481
- - Pub/Sub SA has not been granted the `appropriate BigQuery
2482
- IAM
2483
- permissions <https://cloud.google.com/pubsub/docs/create-subscription#assign_bigquery_service_account>`__
2484
- - bigquery.googleapis.com API is not enabled for the
2485
- project
2486
- (`instructions <https://cloud.google.com/service-usage/docs/enable-disable>`__)
2481
+ - Pub/Sub SA has not been granted the `appropriate BigQuery
2482
+ IAM
2483
+ permissions <https://cloud.google.com/pubsub/docs/create-subscription#assign_bigquery_service_account>`__
2484
+ - bigquery.googleapis.com API is not enabled for the project
2485
+ (`instructions <https://cloud.google.com/service-usage/docs/enable-disable>`__)
2487
2486
  NOT_FOUND (3):
2488
2487
  Cannot write to the BigQuery table because it
2489
2488
  does not exist.
@@ -3111,6 +3110,11 @@ class StreamingPullRequest(proto.Message):
3111
3110
  only be set on the initial StreamingPullRequest. If it is
3112
3111
  set on a subsequent request, the stream will be aborted with
3113
3112
  status ``INVALID_ARGUMENT``.
3113
+ protocol_version (int):
3114
+ Optional. The protocol version used by the client. This
3115
+ property can only be set on the initial
3116
+ StreamingPullRequest. If it is set on a subsequent request,
3117
+ the stream will be aborted with status ``INVALID_ARGUMENT``.
3114
3118
  """
3115
3119
 
3116
3120
  subscription: str = proto.Field(
@@ -3145,6 +3149,10 @@ class StreamingPullRequest(proto.Message):
3145
3149
  proto.INT64,
3146
3150
  number=8,
3147
3151
  )
3152
+ protocol_version: int = proto.Field(
3153
+ proto.INT64,
3154
+ number=10,
3155
+ )
3148
3156
 
3149
3157
 
3150
3158
  class StreamingPullResponse(proto.Message):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-cloud-pubsub
3
- Version: 2.31.0
3
+ Version: 2.32.0
4
4
  Summary: Google Cloud Pub/Sub API client library
5
5
  Home-page: https://github.com/googleapis/python-pubsub
6
6
  Author: Google LLC
@@ -19,11 +19,13 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Operating System :: OS Independent
23
24
  Classifier: Topic :: Internet
24
25
  Requires-Python: >=3.7
25
26
  License-File: LICENSE
26
- Requires-Dist: grpcio<2.0.0,>=1.51.3
27
+ Requires-Dist: grpcio<2.0.0,>=1.51.3; python_version < "3.14"
28
+ Requires-Dist: grpcio<2.0.0,>=1.75.1; python_version >= "3.14"
27
29
  Requires-Dist: google-auth<3.0.0,>=2.14.1
28
30
  Requires-Dist: google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0,>=1.34.0
29
31
  Requires-Dist: proto-plus<2.0.0,>=1.22.0