modal 1.0.6.dev58__py3-none-any.whl → 1.2.3.dev7__py3-none-any.whl

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.

Potentially problematic release.


This version of modal might be problematic. Click here for more details.

Files changed (147) hide show
  1. modal/__main__.py +3 -4
  2. modal/_billing.py +80 -0
  3. modal/_clustered_functions.py +7 -3
  4. modal/_clustered_functions.pyi +4 -2
  5. modal/_container_entrypoint.py +41 -49
  6. modal/_functions.py +424 -195
  7. modal/_grpc_client.py +171 -0
  8. modal/_load_context.py +105 -0
  9. modal/_object.py +68 -20
  10. modal/_output.py +58 -45
  11. modal/_partial_function.py +36 -11
  12. modal/_pty.py +7 -3
  13. modal/_resolver.py +21 -35
  14. modal/_runtime/asgi.py +4 -3
  15. modal/_runtime/container_io_manager.py +301 -186
  16. modal/_runtime/container_io_manager.pyi +70 -61
  17. modal/_runtime/execution_context.py +18 -2
  18. modal/_runtime/execution_context.pyi +4 -1
  19. modal/_runtime/gpu_memory_snapshot.py +170 -63
  20. modal/_runtime/user_code_imports.py +28 -58
  21. modal/_serialization.py +57 -1
  22. modal/_utils/async_utils.py +33 -12
  23. modal/_utils/auth_token_manager.py +2 -5
  24. modal/_utils/blob_utils.py +110 -53
  25. modal/_utils/function_utils.py +49 -42
  26. modal/_utils/grpc_utils.py +80 -50
  27. modal/_utils/mount_utils.py +26 -1
  28. modal/_utils/name_utils.py +17 -3
  29. modal/_utils/task_command_router_client.py +536 -0
  30. modal/_utils/time_utils.py +34 -6
  31. modal/app.py +219 -83
  32. modal/app.pyi +229 -56
  33. modal/billing.py +5 -0
  34. modal/{requirements → builder}/2025.06.txt +1 -0
  35. modal/{requirements → builder}/PREVIEW.txt +1 -0
  36. modal/cli/_download.py +19 -3
  37. modal/cli/_traceback.py +3 -2
  38. modal/cli/app.py +4 -4
  39. modal/cli/cluster.py +15 -7
  40. modal/cli/config.py +5 -3
  41. modal/cli/container.py +7 -6
  42. modal/cli/dict.py +22 -16
  43. modal/cli/entry_point.py +12 -5
  44. modal/cli/environment.py +5 -4
  45. modal/cli/import_refs.py +3 -3
  46. modal/cli/launch.py +102 -5
  47. modal/cli/network_file_system.py +9 -13
  48. modal/cli/profile.py +3 -2
  49. modal/cli/programs/launch_instance_ssh.py +94 -0
  50. modal/cli/programs/run_jupyter.py +1 -1
  51. modal/cli/programs/run_marimo.py +95 -0
  52. modal/cli/programs/vscode.py +1 -1
  53. modal/cli/queues.py +57 -26
  54. modal/cli/run.py +58 -16
  55. modal/cli/secret.py +48 -22
  56. modal/cli/utils.py +3 -4
  57. modal/cli/volume.py +28 -25
  58. modal/client.py +13 -116
  59. modal/client.pyi +9 -91
  60. modal/cloud_bucket_mount.py +5 -3
  61. modal/cloud_bucket_mount.pyi +5 -1
  62. modal/cls.py +130 -102
  63. modal/cls.pyi +45 -85
  64. modal/config.py +29 -10
  65. modal/container_process.py +291 -13
  66. modal/container_process.pyi +95 -32
  67. modal/dict.py +282 -63
  68. modal/dict.pyi +423 -73
  69. modal/environments.py +15 -27
  70. modal/environments.pyi +5 -15
  71. modal/exception.py +8 -0
  72. modal/experimental/__init__.py +143 -38
  73. modal/experimental/flash.py +247 -78
  74. modal/experimental/flash.pyi +137 -9
  75. modal/file_io.py +14 -28
  76. modal/file_io.pyi +2 -2
  77. modal/file_pattern_matcher.py +25 -16
  78. modal/functions.pyi +134 -61
  79. modal/image.py +255 -86
  80. modal/image.pyi +300 -62
  81. modal/io_streams.py +436 -126
  82. modal/io_streams.pyi +236 -171
  83. modal/mount.py +62 -157
  84. modal/mount.pyi +45 -172
  85. modal/network_file_system.py +30 -53
  86. modal/network_file_system.pyi +16 -76
  87. modal/object.pyi +42 -8
  88. modal/parallel_map.py +821 -113
  89. modal/parallel_map.pyi +134 -0
  90. modal/partial_function.pyi +4 -1
  91. modal/proxy.py +16 -7
  92. modal/proxy.pyi +10 -2
  93. modal/queue.py +263 -61
  94. modal/queue.pyi +409 -66
  95. modal/runner.py +112 -92
  96. modal/runner.pyi +45 -27
  97. modal/sandbox.py +451 -124
  98. modal/sandbox.pyi +513 -67
  99. modal/secret.py +291 -67
  100. modal/secret.pyi +425 -19
  101. modal/serving.py +7 -11
  102. modal/serving.pyi +7 -8
  103. modal/snapshot.py +11 -8
  104. modal/token_flow.py +4 -4
  105. modal/volume.py +344 -98
  106. modal/volume.pyi +464 -68
  107. {modal-1.0.6.dev58.dist-info → modal-1.2.3.dev7.dist-info}/METADATA +9 -8
  108. modal-1.2.3.dev7.dist-info/RECORD +195 -0
  109. modal_docs/mdmd/mdmd.py +11 -1
  110. modal_proto/api.proto +399 -67
  111. modal_proto/api_grpc.py +241 -1
  112. modal_proto/api_pb2.py +1395 -1000
  113. modal_proto/api_pb2.pyi +1239 -79
  114. modal_proto/api_pb2_grpc.py +499 -4
  115. modal_proto/api_pb2_grpc.pyi +162 -14
  116. modal_proto/modal_api_grpc.py +175 -160
  117. modal_proto/sandbox_router.proto +145 -0
  118. modal_proto/sandbox_router_grpc.py +105 -0
  119. modal_proto/sandbox_router_pb2.py +149 -0
  120. modal_proto/sandbox_router_pb2.pyi +333 -0
  121. modal_proto/sandbox_router_pb2_grpc.py +203 -0
  122. modal_proto/sandbox_router_pb2_grpc.pyi +75 -0
  123. modal_proto/task_command_router.proto +144 -0
  124. modal_proto/task_command_router_grpc.py +105 -0
  125. modal_proto/task_command_router_pb2.py +149 -0
  126. modal_proto/task_command_router_pb2.pyi +333 -0
  127. modal_proto/task_command_router_pb2_grpc.py +203 -0
  128. modal_proto/task_command_router_pb2_grpc.pyi +75 -0
  129. modal_version/__init__.py +1 -1
  130. modal-1.0.6.dev58.dist-info/RECORD +0 -183
  131. modal_proto/modal_options_grpc.py +0 -3
  132. modal_proto/options.proto +0 -19
  133. modal_proto/options_grpc.py +0 -3
  134. modal_proto/options_pb2.py +0 -35
  135. modal_proto/options_pb2.pyi +0 -20
  136. modal_proto/options_pb2_grpc.py +0 -4
  137. modal_proto/options_pb2_grpc.pyi +0 -7
  138. /modal/{requirements → builder}/2023.12.312.txt +0 -0
  139. /modal/{requirements → builder}/2023.12.txt +0 -0
  140. /modal/{requirements → builder}/2024.04.txt +0 -0
  141. /modal/{requirements → builder}/2024.10.txt +0 -0
  142. /modal/{requirements → builder}/README.md +0 -0
  143. /modal/{requirements → builder}/base-images.json +0 -0
  144. {modal-1.0.6.dev58.dist-info → modal-1.2.3.dev7.dist-info}/WHEEL +0 -0
  145. {modal-1.0.6.dev58.dist-info → modal-1.2.3.dev7.dist-info}/entry_points.txt +0 -0
  146. {modal-1.0.6.dev58.dist-info → modal-1.2.3.dev7.dist-info}/licenses/LICENSE +0 -0
  147. {modal-1.0.6.dev58.dist-info → modal-1.2.3.dev7.dist-info}/top_level.txt +0 -0
modal/queue.py CHANGED
@@ -3,22 +3,213 @@ import queue # The system library
3
3
  import time
4
4
  import warnings
5
5
  from collections.abc import AsyncGenerator, AsyncIterator
6
- from typing import Any, Optional
6
+ from dataclasses import dataclass
7
+ from datetime import datetime
8
+ from typing import Any, Optional, Union
7
9
 
10
+ from google.protobuf.message import Message
8
11
  from grpclib import GRPCError, Status
12
+ from synchronicity import classproperty
9
13
  from synchronicity.async_wrap import asynccontextmanager
10
14
 
11
15
  from modal_proto import api_pb2
12
16
 
13
- from ._object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _Object, live_method, live_method_gen
17
+ from ._load_context import LoadContext
18
+ from ._object import (
19
+ EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
20
+ _get_environment_name,
21
+ _Object,
22
+ live_method,
23
+ live_method_gen,
24
+ )
14
25
  from ._resolver import Resolver
15
26
  from ._serialization import deserialize, serialize
16
27
  from ._utils.async_utils import TaskContext, synchronize_api, warn_if_generator_is_not_consumed
17
28
  from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
18
- from ._utils.grpc_utils import retry_transient_errors
29
+ from ._utils.grpc_utils import Retry
19
30
  from ._utils.name_utils import check_object_name
31
+ from ._utils.time_utils import as_timestamp, timestamp_to_localized_dt
20
32
  from .client import _Client
21
- from .exception import InvalidError, RequestSizeError
33
+ from .exception import AlreadyExistsError, InvalidError, NotFoundError, RequestSizeError
34
+
35
+
36
+ @dataclass
37
+ class QueueInfo:
38
+ """Information about the Queue object."""
39
+
40
+ # This dataclass should be limited to information that is unchanging over the lifetime of the Queue,
41
+ # since it is transmitted from the server when the object is hydrated and could be stale when accessed.
42
+
43
+ name: Optional[str]
44
+ created_at: datetime
45
+ created_by: Optional[str]
46
+
47
+
48
+ class _QueueManager:
49
+ """Namespace with methods for managing named Queue objects."""
50
+
51
+ @staticmethod
52
+ async def create(
53
+ name: str, # Name to use for the new Queue
54
+ *,
55
+ allow_existing: bool = False, # If True, no-op when the Queue already exists
56
+ environment_name: Optional[str] = None, # Uses active environment if not specified
57
+ client: Optional[_Client] = None, # Optional client with Modal credentials
58
+ ) -> None:
59
+ """Create a new Queue object.
60
+
61
+ **Examples:**
62
+
63
+ ```python notest
64
+ modal.Queue.objects.create("my-queue")
65
+ ```
66
+
67
+ Queues will be created in the active environment, or another one can be specified:
68
+
69
+ ```python notest
70
+ modal.Queue.objects.create("my-queue", environment_name="dev")
71
+ ```
72
+
73
+ By default, an error will be raised if the Queue already exists, but passing
74
+ `allow_existing=True` will make the creation attempt a no-op in this case.
75
+
76
+ ```python notest
77
+ modal.Queue.objects.create("my-queue", allow_existing=True)
78
+ ```
79
+
80
+ Note that this method does not return a local instance of the Queue. You can use
81
+ `modal.Queue.from_name` to perform a lookup after creation.
82
+
83
+ Added in v1.1.2.
84
+
85
+ """
86
+ check_object_name(name, "Queue")
87
+ client = await _Client.from_env() if client is None else client
88
+ object_creation_type = (
89
+ api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING
90
+ if allow_existing
91
+ else api_pb2.OBJECT_CREATION_TYPE_CREATE_FAIL_IF_EXISTS
92
+ )
93
+ req = api_pb2.QueueGetOrCreateRequest(
94
+ deployment_name=name,
95
+ environment_name=_get_environment_name(environment_name),
96
+ object_creation_type=object_creation_type,
97
+ )
98
+ try:
99
+ await client.stub.QueueGetOrCreate(req)
100
+ except GRPCError as exc:
101
+ if exc.status == Status.ALREADY_EXISTS and not allow_existing:
102
+ raise AlreadyExistsError(exc.message)
103
+ else:
104
+ raise
105
+
106
+ @staticmethod
107
+ async def list(
108
+ *,
109
+ max_objects: Optional[int] = None, # Limit results to this size
110
+ created_before: Optional[Union[datetime, str]] = None, # Limit based on creation date
111
+ environment_name: str = "", # Uses active environment if not specified
112
+ client: Optional[_Client] = None, # Optional client with Modal credentials
113
+ ) -> list["_Queue"]:
114
+ """Return a list of hydrated Queue objects.
115
+
116
+ **Examples:**
117
+
118
+ ```python
119
+ queues = modal.Queue.objects.list()
120
+ print([q.name for q in queues])
121
+ ```
122
+
123
+ Queues will be retreived from the active environment, or another one can be specified:
124
+
125
+ ```python notest
126
+ dev_queues = modal.Queue.objects.list(environment_name="dev")
127
+ ```
128
+
129
+ By default, all named Queues are returned, newest to oldest. It's also possible to limit the
130
+ number of results and to filter by creation date:
131
+
132
+ ```python
133
+ queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
134
+ ```
135
+
136
+ Added in v1.1.2.
137
+
138
+ """
139
+ client = await _Client.from_env() if client is None else client
140
+ if max_objects is not None and max_objects < 0:
141
+ raise InvalidError("max_objects cannot be negative")
142
+
143
+ items: list[api_pb2.QueueListResponse.QueueInfo] = []
144
+
145
+ async def retrieve_page(created_before: float) -> bool:
146
+ max_page_size = 100 if max_objects is None else min(100, max_objects - len(items))
147
+ pagination = api_pb2.ListPagination(max_objects=max_page_size, created_before=created_before)
148
+ req = api_pb2.QueueListRequest(
149
+ environment_name=_get_environment_name(environment_name), pagination=pagination
150
+ )
151
+ resp = await client.stub.QueueList(req)
152
+ items.extend(resp.queues)
153
+ finished = (len(resp.queues) < max_page_size) or (max_objects is not None and len(items) >= max_objects)
154
+ return finished
155
+
156
+ finished = await retrieve_page(as_timestamp(created_before))
157
+ while True:
158
+ if finished:
159
+ break
160
+ finished = await retrieve_page(items[-1].metadata.creation_info.created_at)
161
+
162
+ queues = [
163
+ _Queue._new_hydrated(
164
+ item.queue_id,
165
+ client,
166
+ item.metadata,
167
+ is_another_app=True,
168
+ rep=_Queue._repr(item.name, environment_name),
169
+ )
170
+ for item in items
171
+ ]
172
+ return queues[:max_objects] if max_objects is not None else queues
173
+
174
+ @staticmethod
175
+ async def delete(
176
+ name: str, # Name of the Queue to delete
177
+ *,
178
+ allow_missing: bool = False, # If True, don't raise an error if the Queue doesn't exist
179
+ environment_name: Optional[str] = None, # Uses active environment if not specified
180
+ client: Optional[_Client] = None, # Optional client with Modal credentials
181
+ ):
182
+ """Delete a named Queue.
183
+
184
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
185
+ Deletion is irreversible and will affect any Apps currently using the Queue.
186
+
187
+ **Examples:**
188
+
189
+ ```python notest
190
+ await modal.Queue.objects.delete("my-queue")
191
+ ```
192
+
193
+ Queues will be deleted from the active environment, or another one can be specified:
194
+
195
+ ```python notest
196
+ await modal.Queue.objects.delete("my-queue", environment_name="dev")
197
+ ```
198
+
199
+ Added in v1.1.2.
200
+
201
+ """
202
+ try:
203
+ obj = await _Queue.from_name(name, environment_name=environment_name).hydrate(client)
204
+ except NotFoundError:
205
+ if not allow_missing:
206
+ raise
207
+ else:
208
+ req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
209
+ await obj._client.stub.QueueDelete(req)
210
+
211
+
212
+ QueueManager = synchronize_api(_QueueManager)
22
213
 
23
214
 
24
215
  class _Queue(_Object, type_prefix="qu"):
@@ -94,10 +285,30 @@ class _Queue(_Object, type_prefix="qu"):
94
285
  Partition keys must be non-empty and must not exceed 64 bytes.
95
286
  """
96
287
 
288
+ _metadata: Optional[api_pb2.QueueMetadata] = None
289
+
97
290
  def __init__(self):
98
291
  """mdmd:hidden"""
99
292
  raise RuntimeError("Queue() is not allowed. Please use `Queue.from_name(...)` or `Queue.ephemeral()` instead.")
100
293
 
294
+ @classproperty
295
+ def objects(cls) -> _QueueManager:
296
+ return _QueueManager
297
+
298
+ @property
299
+ def name(self) -> Optional[str]:
300
+ return self._name
301
+
302
+ def _hydrate_metadata(self, metadata: Optional[Message]):
303
+ if metadata:
304
+ assert isinstance(metadata, api_pb2.QueueMetadata)
305
+ self._metadata = metadata
306
+ self._name = metadata.name
307
+
308
+ def _get_metadata(self) -> api_pb2.QueueMetadata:
309
+ assert self._metadata
310
+ return self._metadata
311
+
101
312
  @staticmethod
102
313
  def validate_partition_key(partition: Optional[str]) -> bytes:
103
314
  if partition is not None:
@@ -115,7 +326,7 @@ class _Queue(_Object, type_prefix="qu"):
115
326
  cls: type["_Queue"],
116
327
  client: Optional[_Client] = None,
117
328
  environment_name: Optional[str] = None,
118
- _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
329
+ _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, # mdmd:line-hidden
119
330
  ) -> AsyncIterator["_Queue"]:
120
331
  """Creates a new ephemeral queue within a context manager:
121
332
 
@@ -142,7 +353,7 @@ class _Queue(_Object, type_prefix="qu"):
142
353
  async with TaskContext() as tc:
143
354
  request = api_pb2.QueueHeartbeatRequest(queue_id=response.queue_id)
144
355
  tc.infinite_loop(lambda: client.stub.QueueHeartbeat(request), sleep=_heartbeat_sleep)
145
- yield cls._new_hydrated(response.queue_id, client, None, is_another_app=True)
356
+ yield cls._new_hydrated(response.queue_id, client, response.metadata, is_another_app=True)
146
357
 
147
358
  @staticmethod
148
359
  def from_name(
@@ -151,6 +362,7 @@ class _Queue(_Object, type_prefix="qu"):
151
362
  namespace=None, # mdmd:line-hidden
152
363
  environment_name: Optional[str] = None,
153
364
  create_if_missing: bool = False,
365
+ client: Optional[_Client] = None,
154
366
  ) -> "_Queue":
155
367
  """Reference a named Queue, creating if necessary.
156
368
 
@@ -166,61 +378,52 @@ class _Queue(_Object, type_prefix="qu"):
166
378
  check_object_name(name, "Queue")
167
379
  warn_if_passing_namespace(namespace, "modal.Queue.from_name")
168
380
 
169
- async def _load(self: _Queue, resolver: Resolver, existing_object_id: Optional[str]):
381
+ async def _load(self: _Queue, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]):
170
382
  req = api_pb2.QueueGetOrCreateRequest(
171
383
  deployment_name=name,
172
- environment_name=_get_environment_name(environment_name, resolver),
384
+ environment_name=load_context.environment_name,
173
385
  object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
174
386
  )
175
- response = await resolver.client.stub.QueueGetOrCreate(req)
176
- self._hydrate(response.queue_id, resolver.client, None)
177
-
178
- return _Queue._from_loader(_load, "Queue()", is_another_app=True, hydrate_lazily=True)
387
+ response = await load_context.client.stub.QueueGetOrCreate(req)
388
+ self._hydrate(response.queue_id, load_context.client, response.metadata)
389
+
390
+ rep = _Queue._repr(name, environment_name)
391
+ return _Queue._from_loader(
392
+ _load,
393
+ rep,
394
+ is_another_app=True,
395
+ hydrate_lazily=True,
396
+ name=name,
397
+ load_context_overrides=LoadContext(environment_name=environment_name, client=client),
398
+ )
179
399
 
180
400
  @staticmethod
181
- async def lookup(
182
- name: str,
183
- namespace=None, # mdmd:line-hidden
184
- client: Optional[_Client] = None,
185
- environment_name: Optional[str] = None,
186
- create_if_missing: bool = False,
187
- ) -> "_Queue":
401
+ async def delete(name: str, *, client: Optional[_Client] = None, environment_name: Optional[str] = None):
188
402
  """mdmd:hidden
189
- Lookup a named Queue.
403
+ Delete a named Queue.
190
404
 
191
- DEPRECATED: This method is deprecated in favor of `modal.Queue.from_name`.
405
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
406
+ Deletion is irreversible and will affect any Apps currently using the Queue.
192
407
 
193
- In contrast to `modal.Queue.from_name`, this is an eager method
194
- that will hydrate the local object with metadata from Modal servers.
408
+ DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
195
409
 
196
- ```python notest
197
- q = modal.Queue.lookup("my-queue")
198
- q.put(123)
199
- ```
200
410
  """
201
411
  deprecation_warning(
202
- (2025, 1, 27),
203
- "`modal.Queue.lookup` is deprecated and will be removed in a future release."
204
- " It can be replaced with `modal.Queue.from_name`."
205
- "\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
206
- )
207
- warn_if_passing_namespace(namespace, "modal.Queue.lookup")
208
- obj = _Queue.from_name(
209
- name,
210
- environment_name=environment_name,
211
- create_if_missing=create_if_missing,
412
+ (2025, 8, 6),
413
+ "`modal.Queue.delete` is deprecated; we recommend using `modal.Queue.objects.delete` instead.",
212
414
  )
213
- if client is None:
214
- client = await _Client.from_env()
215
- resolver = Resolver(client=client)
216
- await resolver.load(obj)
217
- return obj
415
+ await _Queue.objects.delete(name, environment_name=environment_name, client=client)
218
416
 
219
- @staticmethod
220
- async def delete(name: str, *, client: Optional[_Client] = None, environment_name: Optional[str] = None):
221
- obj = await _Queue.from_name(name, environment_name=environment_name).hydrate(client)
222
- req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
223
- await retry_transient_errors(obj._client.stub.QueueDelete, req)
417
+ @live_method
418
+ async def info(self) -> QueueInfo:
419
+ """Return information about the Queue object."""
420
+ metadata = self._get_metadata()
421
+ creation_info = metadata.creation_info
422
+ return QueueInfo(
423
+ name=metadata.name or None,
424
+ created_at=timestamp_to_localized_dt(creation_info.created_at),
425
+ created_by=creation_info.created_by or None,
426
+ )
224
427
 
225
428
  async def _get_nonblocking(self, partition: Optional[str], n_values: int) -> list[Any]:
226
429
  request = api_pb2.QueueGetRequest(
@@ -230,7 +433,7 @@ class _Queue(_Object, type_prefix="qu"):
230
433
  n_values=n_values,
231
434
  )
232
435
 
233
- response = await retry_transient_errors(self._client.stub.QueueGet, request)
436
+ response = await self._client.stub.QueueGet(request)
234
437
  if response.values:
235
438
  return [deserialize(value, self._client) for value in response.values]
236
439
  else:
@@ -255,7 +458,7 @@ class _Queue(_Object, type_prefix="qu"):
255
458
  n_values=n_values,
256
459
  )
257
460
 
258
- response = await retry_transient_errors(self._client.stub.QueueGet, request)
461
+ response = await self._client.stub.QueueGet(request)
259
462
 
260
463
  if response.values:
261
464
  return [deserialize(value, self._client) for value in response.values]
@@ -275,7 +478,7 @@ class _Queue(_Object, type_prefix="qu"):
275
478
  partition_key=self.validate_partition_key(partition),
276
479
  all_partitions=all,
277
480
  )
278
- await retry_transient_errors(self._client.stub.QueueClear, request)
481
+ await self._client.stub.QueueClear(request)
279
482
 
280
483
  @live_method
281
484
  async def get(
@@ -384,14 +587,15 @@ class _Queue(_Object, type_prefix="qu"):
384
587
  partition_ttl_seconds=partition_ttl,
385
588
  )
386
589
  try:
387
- await retry_transient_errors(
388
- self._client.stub.QueuePut,
590
+ await self._client.stub.QueuePut(
389
591
  request,
390
592
  # A full queue will return this status.
391
- additional_status_codes=[Status.RESOURCE_EXHAUSTED],
392
- max_delay=30.0,
393
- max_retries=None,
394
- total_timeout=timeout,
593
+ retry=Retry(
594
+ additional_status_codes=[Status.RESOURCE_EXHAUSTED],
595
+ max_delay=30.0,
596
+ max_retries=None,
597
+ total_timeout=timeout,
598
+ ),
395
599
  )
396
600
  except GRPCError as exc:
397
601
  if exc.status == Status.RESOURCE_EXHAUSTED:
@@ -411,7 +615,7 @@ class _Queue(_Object, type_prefix="qu"):
411
615
  partition_ttl_seconds=partition_ttl,
412
616
  )
413
617
  try:
414
- await retry_transient_errors(self._client.stub.QueuePut, request)
618
+ await self._client.stub.QueuePut(request)
415
619
  except GRPCError as exc:
416
620
  if exc.status == Status.RESOURCE_EXHAUSTED:
417
621
  raise queue.Full(exc.message)
@@ -431,7 +635,7 @@ class _Queue(_Object, type_prefix="qu"):
431
635
  partition_key=self.validate_partition_key(partition),
432
636
  total=total,
433
637
  )
434
- response = await retry_transient_errors(self._client.stub.QueueLen, request)
638
+ response = await self._client.stub.QueueLen(request)
435
639
  return response.len
436
640
 
437
641
  @warn_if_generator_is_not_consumed()
@@ -457,9 +661,7 @@ class _Queue(_Object, type_prefix="qu"):
457
661
  item_poll_timeout=poll_duration,
458
662
  )
459
663
 
460
- response: api_pb2.QueueNextItemsResponse = await retry_transient_errors(
461
- self._client.stub.QueueNextItems, request
462
- )
664
+ response: api_pb2.QueueNextItemsResponse = await self._client.stub.QueueNextItems(request)
463
665
  if response.items:
464
666
  for item in response.items:
465
667
  yield deserialize(item.value, self._client)