modal 1.0.3.dev10__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 (160) hide show
  1. modal/__init__.py +0 -2
  2. modal/__main__.py +3 -4
  3. modal/_billing.py +80 -0
  4. modal/_clustered_functions.py +7 -3
  5. modal/_clustered_functions.pyi +15 -3
  6. modal/_container_entrypoint.py +51 -69
  7. modal/_functions.py +508 -240
  8. modal/_grpc_client.py +171 -0
  9. modal/_load_context.py +105 -0
  10. modal/_object.py +81 -21
  11. modal/_output.py +58 -45
  12. modal/_partial_function.py +48 -73
  13. modal/_pty.py +7 -3
  14. modal/_resolver.py +26 -46
  15. modal/_runtime/asgi.py +4 -3
  16. modal/_runtime/container_io_manager.py +358 -220
  17. modal/_runtime/container_io_manager.pyi +296 -101
  18. modal/_runtime/execution_context.py +18 -2
  19. modal/_runtime/execution_context.pyi +64 -7
  20. modal/_runtime/gpu_memory_snapshot.py +262 -57
  21. modal/_runtime/user_code_imports.py +28 -58
  22. modal/_serialization.py +90 -6
  23. modal/_traceback.py +42 -1
  24. modal/_tunnel.pyi +380 -12
  25. modal/_utils/async_utils.py +84 -29
  26. modal/_utils/auth_token_manager.py +111 -0
  27. modal/_utils/blob_utils.py +181 -58
  28. modal/_utils/deprecation.py +19 -0
  29. modal/_utils/function_utils.py +91 -47
  30. modal/_utils/grpc_utils.py +89 -66
  31. modal/_utils/mount_utils.py +26 -1
  32. modal/_utils/name_utils.py +17 -3
  33. modal/_utils/task_command_router_client.py +536 -0
  34. modal/_utils/time_utils.py +34 -6
  35. modal/app.py +256 -88
  36. modal/app.pyi +909 -92
  37. modal/billing.py +5 -0
  38. modal/builder/2025.06.txt +18 -0
  39. modal/builder/PREVIEW.txt +18 -0
  40. modal/builder/base-images.json +58 -0
  41. modal/cli/_download.py +19 -3
  42. modal/cli/_traceback.py +3 -2
  43. modal/cli/app.py +4 -4
  44. modal/cli/cluster.py +15 -7
  45. modal/cli/config.py +5 -3
  46. modal/cli/container.py +7 -6
  47. modal/cli/dict.py +22 -16
  48. modal/cli/entry_point.py +12 -5
  49. modal/cli/environment.py +5 -4
  50. modal/cli/import_refs.py +3 -3
  51. modal/cli/launch.py +102 -5
  52. modal/cli/network_file_system.py +11 -12
  53. modal/cli/profile.py +3 -2
  54. modal/cli/programs/launch_instance_ssh.py +94 -0
  55. modal/cli/programs/run_jupyter.py +1 -1
  56. modal/cli/programs/run_marimo.py +95 -0
  57. modal/cli/programs/vscode.py +1 -1
  58. modal/cli/queues.py +57 -26
  59. modal/cli/run.py +91 -23
  60. modal/cli/secret.py +48 -22
  61. modal/cli/token.py +7 -8
  62. modal/cli/utils.py +4 -7
  63. modal/cli/volume.py +31 -25
  64. modal/client.py +15 -85
  65. modal/client.pyi +183 -62
  66. modal/cloud_bucket_mount.py +5 -3
  67. modal/cloud_bucket_mount.pyi +197 -5
  68. modal/cls.py +200 -126
  69. modal/cls.pyi +446 -68
  70. modal/config.py +29 -11
  71. modal/container_process.py +319 -19
  72. modal/container_process.pyi +190 -20
  73. modal/dict.py +290 -71
  74. modal/dict.pyi +835 -83
  75. modal/environments.py +15 -27
  76. modal/environments.pyi +46 -24
  77. modal/exception.py +14 -2
  78. modal/experimental/__init__.py +194 -40
  79. modal/experimental/flash.py +618 -0
  80. modal/experimental/flash.pyi +380 -0
  81. modal/experimental/ipython.py +11 -7
  82. modal/file_io.py +29 -36
  83. modal/file_io.pyi +251 -53
  84. modal/file_pattern_matcher.py +56 -16
  85. modal/functions.pyi +673 -92
  86. modal/gpu.py +1 -1
  87. modal/image.py +528 -176
  88. modal/image.pyi +1572 -145
  89. modal/io_streams.py +458 -128
  90. modal/io_streams.pyi +433 -52
  91. modal/mount.py +216 -151
  92. modal/mount.pyi +225 -78
  93. modal/network_file_system.py +45 -62
  94. modal/network_file_system.pyi +277 -56
  95. modal/object.pyi +93 -17
  96. modal/parallel_map.py +942 -129
  97. modal/parallel_map.pyi +294 -15
  98. modal/partial_function.py +0 -2
  99. modal/partial_function.pyi +234 -19
  100. modal/proxy.py +17 -8
  101. modal/proxy.pyi +36 -3
  102. modal/queue.py +270 -65
  103. modal/queue.pyi +817 -57
  104. modal/runner.py +115 -101
  105. modal/runner.pyi +205 -49
  106. modal/sandbox.py +512 -136
  107. modal/sandbox.pyi +845 -111
  108. modal/schedule.py +1 -1
  109. modal/secret.py +300 -70
  110. modal/secret.pyi +589 -34
  111. modal/serving.py +7 -11
  112. modal/serving.pyi +7 -8
  113. modal/snapshot.py +11 -8
  114. modal/snapshot.pyi +25 -4
  115. modal/token_flow.py +4 -4
  116. modal/token_flow.pyi +28 -8
  117. modal/volume.py +416 -158
  118. modal/volume.pyi +1117 -121
  119. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/METADATA +10 -9
  120. modal-1.2.3.dev7.dist-info/RECORD +195 -0
  121. modal_docs/mdmd/mdmd.py +17 -4
  122. modal_proto/api.proto +534 -79
  123. modal_proto/api_grpc.py +337 -1
  124. modal_proto/api_pb2.py +1522 -968
  125. modal_proto/api_pb2.pyi +1619 -134
  126. modal_proto/api_pb2_grpc.py +699 -4
  127. modal_proto/api_pb2_grpc.pyi +226 -14
  128. modal_proto/modal_api_grpc.py +175 -154
  129. modal_proto/sandbox_router.proto +145 -0
  130. modal_proto/sandbox_router_grpc.py +105 -0
  131. modal_proto/sandbox_router_pb2.py +149 -0
  132. modal_proto/sandbox_router_pb2.pyi +333 -0
  133. modal_proto/sandbox_router_pb2_grpc.py +203 -0
  134. modal_proto/sandbox_router_pb2_grpc.pyi +75 -0
  135. modal_proto/task_command_router.proto +144 -0
  136. modal_proto/task_command_router_grpc.py +105 -0
  137. modal_proto/task_command_router_pb2.py +149 -0
  138. modal_proto/task_command_router_pb2.pyi +333 -0
  139. modal_proto/task_command_router_pb2_grpc.py +203 -0
  140. modal_proto/task_command_router_pb2_grpc.pyi +75 -0
  141. modal_version/__init__.py +1 -1
  142. modal/requirements/PREVIEW.txt +0 -16
  143. modal/requirements/base-images.json +0 -26
  144. modal-1.0.3.dev10.dist-info/RECORD +0 -179
  145. modal_proto/modal_options_grpc.py +0 -3
  146. modal_proto/options.proto +0 -19
  147. modal_proto/options_grpc.py +0 -3
  148. modal_proto/options_pb2.py +0 -35
  149. modal_proto/options_pb2.pyi +0 -20
  150. modal_proto/options_pb2_grpc.py +0 -4
  151. modal_proto/options_pb2_grpc.pyi +0 -7
  152. /modal/{requirements → builder}/2023.12.312.txt +0 -0
  153. /modal/{requirements → builder}/2023.12.txt +0 -0
  154. /modal/{requirements → builder}/2024.04.txt +0 -0
  155. /modal/{requirements → builder}/2024.10.txt +0 -0
  156. /modal/{requirements → builder}/README.md +0 -0
  157. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/WHEEL +0 -0
  158. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/entry_points.txt +0 -0
  159. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/licenses/LICENSE +0 -0
  160. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/top_level.txt +0 -0
modal/queue.pyi CHANGED
@@ -1,13 +1,441 @@
1
1
  import collections.abc
2
+ import datetime
3
+ import google.protobuf.message
2
4
  import modal._object
3
5
  import modal.client
4
6
  import modal.object
7
+ import modal_proto.api_pb2
8
+ import synchronicity
5
9
  import synchronicity.combined_types
6
10
  import typing
7
11
  import typing_extensions
8
12
 
13
+ class QueueInfo:
14
+ """Information about the Queue object."""
15
+
16
+ name: typing.Optional[str]
17
+ created_at: datetime.datetime
18
+ created_by: typing.Optional[str]
19
+
20
+ def __init__(
21
+ self, name: typing.Optional[str], created_at: datetime.datetime, created_by: typing.Optional[str]
22
+ ) -> None:
23
+ """Initialize self. See help(type(self)) for accurate signature."""
24
+ ...
25
+
26
+ def __repr__(self):
27
+ """Return repr(self)."""
28
+ ...
29
+
30
+ def __eq__(self, other):
31
+ """Return self==value."""
32
+ ...
33
+
34
+ class _QueueManager:
35
+ """Namespace with methods for managing named Queue objects."""
36
+ @staticmethod
37
+ async def create(
38
+ name: str,
39
+ *,
40
+ allow_existing: bool = False,
41
+ environment_name: typing.Optional[str] = None,
42
+ client: typing.Optional[modal.client._Client] = None,
43
+ ) -> None:
44
+ """Create a new Queue object.
45
+
46
+ **Examples:**
47
+
48
+ ```python notest
49
+ modal.Queue.objects.create("my-queue")
50
+ ```
51
+
52
+ Queues will be created in the active environment, or another one can be specified:
53
+
54
+ ```python notest
55
+ modal.Queue.objects.create("my-queue", environment_name="dev")
56
+ ```
57
+
58
+ By default, an error will be raised if the Queue already exists, but passing
59
+ `allow_existing=True` will make the creation attempt a no-op in this case.
60
+
61
+ ```python notest
62
+ modal.Queue.objects.create("my-queue", allow_existing=True)
63
+ ```
64
+
65
+ Note that this method does not return a local instance of the Queue. You can use
66
+ `modal.Queue.from_name` to perform a lookup after creation.
67
+
68
+ Added in v1.1.2.
69
+ """
70
+ ...
71
+
72
+ @staticmethod
73
+ async def list(
74
+ *,
75
+ max_objects: typing.Optional[int] = None,
76
+ created_before: typing.Union[datetime.datetime, str, None] = None,
77
+ environment_name: str = "",
78
+ client: typing.Optional[modal.client._Client] = None,
79
+ ) -> list[_Queue]:
80
+ """Return a list of hydrated Queue objects.
81
+
82
+ **Examples:**
83
+
84
+ ```python
85
+ queues = modal.Queue.objects.list()
86
+ print([q.name for q in queues])
87
+ ```
88
+
89
+ Queues will be retreived from the active environment, or another one can be specified:
90
+
91
+ ```python notest
92
+ dev_queues = modal.Queue.objects.list(environment_name="dev")
93
+ ```
94
+
95
+ By default, all named Queues are returned, newest to oldest. It's also possible to limit the
96
+ number of results and to filter by creation date:
97
+
98
+ ```python
99
+ queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
100
+ ```
101
+
102
+ Added in v1.1.2.
103
+ """
104
+ ...
105
+
106
+ @staticmethod
107
+ async def delete(
108
+ name: str,
109
+ *,
110
+ allow_missing: bool = False,
111
+ environment_name: typing.Optional[str] = None,
112
+ client: typing.Optional[modal.client._Client] = None,
113
+ ):
114
+ """Delete a named Queue.
115
+
116
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
117
+ Deletion is irreversible and will affect any Apps currently using the Queue.
118
+
119
+ **Examples:**
120
+
121
+ ```python notest
122
+ await modal.Queue.objects.delete("my-queue")
123
+ ```
124
+
125
+ Queues will be deleted from the active environment, or another one can be specified:
126
+
127
+ ```python notest
128
+ await modal.Queue.objects.delete("my-queue", environment_name="dev")
129
+ ```
130
+
131
+ Added in v1.1.2.
132
+ """
133
+ ...
134
+
135
+ class QueueManager:
136
+ """Namespace with methods for managing named Queue objects."""
137
+ def __init__(self, /, *args, **kwargs):
138
+ """Initialize self. See help(type(self)) for accurate signature."""
139
+ ...
140
+
141
+ class __create_spec(typing_extensions.Protocol):
142
+ def __call__(
143
+ self,
144
+ /,
145
+ name: str,
146
+ *,
147
+ allow_existing: bool = False,
148
+ environment_name: typing.Optional[str] = None,
149
+ client: typing.Optional[modal.client.Client] = None,
150
+ ) -> None:
151
+ """Create a new Queue object.
152
+
153
+ **Examples:**
154
+
155
+ ```python notest
156
+ modal.Queue.objects.create("my-queue")
157
+ ```
158
+
159
+ Queues will be created in the active environment, or another one can be specified:
160
+
161
+ ```python notest
162
+ modal.Queue.objects.create("my-queue", environment_name="dev")
163
+ ```
164
+
165
+ By default, an error will be raised if the Queue already exists, but passing
166
+ `allow_existing=True` will make the creation attempt a no-op in this case.
167
+
168
+ ```python notest
169
+ modal.Queue.objects.create("my-queue", allow_existing=True)
170
+ ```
171
+
172
+ Note that this method does not return a local instance of the Queue. You can use
173
+ `modal.Queue.from_name` to perform a lookup after creation.
174
+
175
+ Added in v1.1.2.
176
+ """
177
+ ...
178
+
179
+ async def aio(
180
+ self,
181
+ /,
182
+ name: str,
183
+ *,
184
+ allow_existing: bool = False,
185
+ environment_name: typing.Optional[str] = None,
186
+ client: typing.Optional[modal.client.Client] = None,
187
+ ) -> None:
188
+ """Create a new Queue object.
189
+
190
+ **Examples:**
191
+
192
+ ```python notest
193
+ modal.Queue.objects.create("my-queue")
194
+ ```
195
+
196
+ Queues will be created in the active environment, or another one can be specified:
197
+
198
+ ```python notest
199
+ modal.Queue.objects.create("my-queue", environment_name="dev")
200
+ ```
201
+
202
+ By default, an error will be raised if the Queue already exists, but passing
203
+ `allow_existing=True` will make the creation attempt a no-op in this case.
204
+
205
+ ```python notest
206
+ modal.Queue.objects.create("my-queue", allow_existing=True)
207
+ ```
208
+
209
+ Note that this method does not return a local instance of the Queue. You can use
210
+ `modal.Queue.from_name` to perform a lookup after creation.
211
+
212
+ Added in v1.1.2.
213
+ """
214
+ ...
215
+
216
+ create: __create_spec
217
+
218
+ class __list_spec(typing_extensions.Protocol):
219
+ def __call__(
220
+ self,
221
+ /,
222
+ *,
223
+ max_objects: typing.Optional[int] = None,
224
+ created_before: typing.Union[datetime.datetime, str, None] = None,
225
+ environment_name: str = "",
226
+ client: typing.Optional[modal.client.Client] = None,
227
+ ) -> list[Queue]:
228
+ """Return a list of hydrated Queue objects.
229
+
230
+ **Examples:**
231
+
232
+ ```python
233
+ queues = modal.Queue.objects.list()
234
+ print([q.name for q in queues])
235
+ ```
236
+
237
+ Queues will be retreived from the active environment, or another one can be specified:
238
+
239
+ ```python notest
240
+ dev_queues = modal.Queue.objects.list(environment_name="dev")
241
+ ```
242
+
243
+ By default, all named Queues are returned, newest to oldest. It's also possible to limit the
244
+ number of results and to filter by creation date:
245
+
246
+ ```python
247
+ queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
248
+ ```
249
+
250
+ Added in v1.1.2.
251
+ """
252
+ ...
253
+
254
+ async def aio(
255
+ self,
256
+ /,
257
+ *,
258
+ max_objects: typing.Optional[int] = None,
259
+ created_before: typing.Union[datetime.datetime, str, None] = None,
260
+ environment_name: str = "",
261
+ client: typing.Optional[modal.client.Client] = None,
262
+ ) -> list[Queue]:
263
+ """Return a list of hydrated Queue objects.
264
+
265
+ **Examples:**
266
+
267
+ ```python
268
+ queues = modal.Queue.objects.list()
269
+ print([q.name for q in queues])
270
+ ```
271
+
272
+ Queues will be retreived from the active environment, or another one can be specified:
273
+
274
+ ```python notest
275
+ dev_queues = modal.Queue.objects.list(environment_name="dev")
276
+ ```
277
+
278
+ By default, all named Queues are returned, newest to oldest. It's also possible to limit the
279
+ number of results and to filter by creation date:
280
+
281
+ ```python
282
+ queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
283
+ ```
284
+
285
+ Added in v1.1.2.
286
+ """
287
+ ...
288
+
289
+ list: __list_spec
290
+
291
+ class __delete_spec(typing_extensions.Protocol):
292
+ def __call__(
293
+ self,
294
+ /,
295
+ name: str,
296
+ *,
297
+ allow_missing: bool = False,
298
+ environment_name: typing.Optional[str] = None,
299
+ client: typing.Optional[modal.client.Client] = None,
300
+ ):
301
+ """Delete a named Queue.
302
+
303
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
304
+ Deletion is irreversible and will affect any Apps currently using the Queue.
305
+
306
+ **Examples:**
307
+
308
+ ```python notest
309
+ await modal.Queue.objects.delete("my-queue")
310
+ ```
311
+
312
+ Queues will be deleted from the active environment, or another one can be specified:
313
+
314
+ ```python notest
315
+ await modal.Queue.objects.delete("my-queue", environment_name="dev")
316
+ ```
317
+
318
+ Added in v1.1.2.
319
+ """
320
+ ...
321
+
322
+ async def aio(
323
+ self,
324
+ /,
325
+ name: str,
326
+ *,
327
+ allow_missing: bool = False,
328
+ environment_name: typing.Optional[str] = None,
329
+ client: typing.Optional[modal.client.Client] = None,
330
+ ):
331
+ """Delete a named Queue.
332
+
333
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
334
+ Deletion is irreversible and will affect any Apps currently using the Queue.
335
+
336
+ **Examples:**
337
+
338
+ ```python notest
339
+ await modal.Queue.objects.delete("my-queue")
340
+ ```
341
+
342
+ Queues will be deleted from the active environment, or another one can be specified:
343
+
344
+ ```python notest
345
+ await modal.Queue.objects.delete("my-queue", environment_name="dev")
346
+ ```
347
+
348
+ Added in v1.1.2.
349
+ """
350
+ ...
351
+
352
+ delete: __delete_spec
353
+
9
354
  class _Queue(modal._object._Object):
10
- def __init__(self): ...
355
+ """Distributed, FIFO queue for data flow in Modal apps.
356
+
357
+ The queue can contain any object serializable by `cloudpickle`, including Modal objects.
358
+
359
+ By default, the `Queue` object acts as a single FIFO queue which supports puts and gets (blocking and non-blocking).
360
+
361
+ **Usage**
362
+
363
+ ```python
364
+ from modal import Queue
365
+
366
+ # Create an ephemeral queue which is anonymous and garbage collected
367
+ with Queue.ephemeral() as my_queue:
368
+ # Putting values
369
+ my_queue.put("some value")
370
+ my_queue.put(123)
371
+
372
+ # Getting values
373
+ assert my_queue.get() == "some value"
374
+ assert my_queue.get() == 123
375
+
376
+ # Using partitions
377
+ my_queue.put(0)
378
+ my_queue.put(1, partition="foo")
379
+ my_queue.put(2, partition="bar")
380
+
381
+ # Default and "foo" partition are ignored by the get operation.
382
+ assert my_queue.get(partition="bar") == 2
383
+
384
+ # Set custom 10s expiration time on "foo" partition.
385
+ my_queue.put(3, partition="foo", partition_ttl=10)
386
+
387
+ # (beta feature) Iterate through items in place (read immutably)
388
+ my_queue.put(1)
389
+ assert [v for v in my_queue.iterate()] == [0, 1]
390
+
391
+ # You can also create persistent queues that can be used across apps
392
+ queue = Queue.from_name("my-persisted-queue", create_if_missing=True)
393
+ queue.put(42)
394
+ assert queue.get() == 42
395
+ ```
396
+
397
+ For more examples, see the [guide](https://modal.com/docs/guide/dicts-and-queues#modal-queues).
398
+
399
+ **Queue partitions (beta)**
400
+
401
+ Specifying partition keys gives access to other independent FIFO partitions within the same `Queue` object.
402
+ Across any two partitions, puts and gets are completely independent.
403
+ For example, a put in one partition does not affect a get in any other partition.
404
+
405
+ When no partition key is specified (by default), puts and gets will operate on a default partition.
406
+ This default partition is also isolated from all other partitions.
407
+ Please see the Usage section below for an example using partitions.
408
+
409
+ **Lifetime of a queue and its partitions**
410
+
411
+ By default, each partition is cleared 24 hours after the last `put` operation.
412
+ A lower TTL can be specified by the `partition_ttl` argument in the `put` or `put_many` methods.
413
+ Each partition's expiry is handled independently.
414
+
415
+ As such, `Queue`s are best used for communication between active functions and not relied on for persistent storage.
416
+
417
+ On app completion or after stopping an app any associated `Queue` objects are cleaned up.
418
+ All its partitions will be cleared.
419
+
420
+ **Limits**
421
+
422
+ A single `Queue` can contain up to 100,000 partitions, each with up to 5,000 items. Each item can be up to 1 MiB.
423
+
424
+ Partition keys must be non-empty and must not exceed 64 bytes.
425
+ """
426
+
427
+ _metadata: typing.Optional[modal_proto.api_pb2.QueueMetadata]
428
+
429
+ def __init__(self):
430
+ """mdmd:hidden"""
431
+ ...
432
+
433
+ @synchronicity.classproperty
434
+ def objects(cls) -> _QueueManager: ...
435
+ @property
436
+ def name(self) -> typing.Optional[str]: ...
437
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
438
+ def _get_metadata(self) -> modal_proto.api_pb2.QueueMetadata: ...
11
439
  @staticmethod
12
440
  def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
13
441
  @classmethod
@@ -16,34 +444,89 @@ class _Queue(modal._object._Object):
16
444
  client: typing.Optional[modal.client._Client] = None,
17
445
  environment_name: typing.Optional[str] = None,
18
446
  _heartbeat_sleep: float = 300,
19
- ) -> typing.AsyncContextManager[_Queue]: ...
447
+ ) -> typing.AsyncContextManager[_Queue]:
448
+ """Creates a new ephemeral queue within a context manager:
449
+
450
+ Usage:
451
+ ```python
452
+ from modal import Queue
453
+
454
+ with Queue.ephemeral() as q:
455
+ q.put(123)
456
+ ```
457
+
458
+ ```python notest
459
+ async with Queue.ephemeral() as q:
460
+ await q.put.aio(123)
461
+ ```
462
+ """
463
+ ...
464
+
20
465
  @staticmethod
21
466
  def from_name(
22
- name: str, *, namespace=1, environment_name: typing.Optional[str] = None, create_if_missing: bool = False
23
- ) -> _Queue: ...
24
- @staticmethod
25
- async def lookup(
26
467
  name: str,
27
- namespace=1,
28
- client: typing.Optional[modal.client._Client] = None,
468
+ *,
469
+ namespace=None,
29
470
  environment_name: typing.Optional[str] = None,
30
471
  create_if_missing: bool = False,
31
- ) -> _Queue: ...
472
+ client: typing.Optional[modal.client._Client] = None,
473
+ ) -> _Queue:
474
+ """Reference a named Queue, creating if necessary.
475
+
476
+ This is a lazy method the defers hydrating the local
477
+ object with metadata from Modal servers until the first
478
+ time it is actually used.
479
+
480
+ ```python
481
+ q = modal.Queue.from_name("my-queue", create_if_missing=True)
482
+ q.put(123)
483
+ ```
484
+ """
485
+ ...
486
+
32
487
  @staticmethod
33
488
  async def delete(
34
489
  name: str,
35
490
  *,
36
491
  client: typing.Optional[modal.client._Client] = None,
37
492
  environment_name: typing.Optional[str] = None,
38
- ): ...
493
+ ):
494
+ """mdmd:hidden
495
+ Delete a named Queue.
496
+
497
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
498
+ Deletion is irreversible and will affect any Apps currently using the Queue.
499
+
500
+ DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
501
+ """
502
+ ...
503
+
504
+ async def info(self) -> QueueInfo:
505
+ """Return information about the Queue object."""
506
+ ...
507
+
39
508
  async def _get_nonblocking(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
40
509
  async def _get_blocking(
41
510
  self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
42
511
  ) -> list[typing.Any]: ...
43
- async def clear(self, *, partition: typing.Optional[str] = None, all: bool = False) -> None: ...
512
+ async def clear(self, *, partition: typing.Optional[str] = None, all: bool = False) -> None:
513
+ """Clear the contents of a single partition or all partitions."""
514
+ ...
515
+
44
516
  async def get(
45
517
  self, block: bool = True, timeout: typing.Optional[float] = None, *, partition: typing.Optional[str] = None
46
- ) -> typing.Optional[typing.Any]: ...
518
+ ) -> typing.Optional[typing.Any]:
519
+ """Remove and return the next object in the queue.
520
+
521
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
522
+ an object, or until `timeout` if specified. Raises a native `queue.Empty` exception
523
+ if the `timeout` is reached.
524
+
525
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
526
+ ignored in this case.
527
+ """
528
+ ...
529
+
47
530
  async def get_many(
48
531
  self,
49
532
  n_values: int,
@@ -51,7 +534,20 @@ class _Queue(modal._object._Object):
51
534
  timeout: typing.Optional[float] = None,
52
535
  *,
53
536
  partition: typing.Optional[str] = None,
54
- ) -> list[typing.Any]: ...
537
+ ) -> list[typing.Any]:
538
+ """Remove and return up to `n_values` objects from the queue.
539
+
540
+ If there are fewer than `n_values` items in the queue, return all of them.
541
+
542
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
543
+ at least 1 object to be present, or until `timeout` if specified. Raises the stdlib's `queue.Empty`
544
+ exception if the `timeout` is reached.
545
+
546
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
547
+ ignored in this case.
548
+ """
549
+ ...
550
+
55
551
  async def put(
56
552
  self,
57
553
  v: typing.Any,
@@ -60,7 +556,18 @@ class _Queue(modal._object._Object):
60
556
  *,
61
557
  partition: typing.Optional[str] = None,
62
558
  partition_ttl: int = 86400,
63
- ) -> None: ...
559
+ ) -> None:
560
+ """Add an object to the end of the queue.
561
+
562
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
563
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
564
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
565
+
566
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
567
+ ignored in this case.
568
+ """
569
+ ...
570
+
64
571
  async def put_many(
65
572
  self,
66
573
  vs: list[typing.Any],
@@ -69,7 +576,18 @@ class _Queue(modal._object._Object):
69
576
  *,
70
577
  partition: typing.Optional[str] = None,
71
578
  partition_ttl: int = 86400,
72
- ) -> None: ...
579
+ ) -> None:
580
+ """Add several objects to the end of the queue.
581
+
582
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
583
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
584
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
585
+
586
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
587
+ ignored in this case.
588
+ """
589
+ ...
590
+
73
591
  async def _put_many_blocking(
74
592
  self,
75
593
  partition: typing.Optional[str],
@@ -80,15 +598,106 @@ class _Queue(modal._object._Object):
80
598
  async def _put_many_nonblocking(
81
599
  self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]
82
600
  ): ...
83
- async def len(self, *, partition: typing.Optional[str] = None, total: bool = False) -> int: ...
601
+ async def len(self, *, partition: typing.Optional[str] = None, total: bool = False) -> int:
602
+ """Return the number of objects in the queue partition."""
603
+ ...
604
+
84
605
  def iterate(
85
606
  self, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
86
- ) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
607
+ ) -> collections.abc.AsyncGenerator[typing.Any, None]:
608
+ """(Beta feature) Iterate through items in the queue without mutation.
609
+
610
+ Specify `item_poll_timeout` to control how long the iterator should wait for the next time before giving up.
611
+ """
612
+ ...
87
613
 
88
614
  SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
89
615
 
90
616
  class Queue(modal.object.Object):
91
- def __init__(self): ...
617
+ """Distributed, FIFO queue for data flow in Modal apps.
618
+
619
+ The queue can contain any object serializable by `cloudpickle`, including Modal objects.
620
+
621
+ By default, the `Queue` object acts as a single FIFO queue which supports puts and gets (blocking and non-blocking).
622
+
623
+ **Usage**
624
+
625
+ ```python
626
+ from modal import Queue
627
+
628
+ # Create an ephemeral queue which is anonymous and garbage collected
629
+ with Queue.ephemeral() as my_queue:
630
+ # Putting values
631
+ my_queue.put("some value")
632
+ my_queue.put(123)
633
+
634
+ # Getting values
635
+ assert my_queue.get() == "some value"
636
+ assert my_queue.get() == 123
637
+
638
+ # Using partitions
639
+ my_queue.put(0)
640
+ my_queue.put(1, partition="foo")
641
+ my_queue.put(2, partition="bar")
642
+
643
+ # Default and "foo" partition are ignored by the get operation.
644
+ assert my_queue.get(partition="bar") == 2
645
+
646
+ # Set custom 10s expiration time on "foo" partition.
647
+ my_queue.put(3, partition="foo", partition_ttl=10)
648
+
649
+ # (beta feature) Iterate through items in place (read immutably)
650
+ my_queue.put(1)
651
+ assert [v for v in my_queue.iterate()] == [0, 1]
652
+
653
+ # You can also create persistent queues that can be used across apps
654
+ queue = Queue.from_name("my-persisted-queue", create_if_missing=True)
655
+ queue.put(42)
656
+ assert queue.get() == 42
657
+ ```
658
+
659
+ For more examples, see the [guide](https://modal.com/docs/guide/dicts-and-queues#modal-queues).
660
+
661
+ **Queue partitions (beta)**
662
+
663
+ Specifying partition keys gives access to other independent FIFO partitions within the same `Queue` object.
664
+ Across any two partitions, puts and gets are completely independent.
665
+ For example, a put in one partition does not affect a get in any other partition.
666
+
667
+ When no partition key is specified (by default), puts and gets will operate on a default partition.
668
+ This default partition is also isolated from all other partitions.
669
+ Please see the Usage section below for an example using partitions.
670
+
671
+ **Lifetime of a queue and its partitions**
672
+
673
+ By default, each partition is cleared 24 hours after the last `put` operation.
674
+ A lower TTL can be specified by the `partition_ttl` argument in the `put` or `put_many` methods.
675
+ Each partition's expiry is handled independently.
676
+
677
+ As such, `Queue`s are best used for communication between active functions and not relied on for persistent storage.
678
+
679
+ On app completion or after stopping an app any associated `Queue` objects are cleaned up.
680
+ All its partitions will be cleared.
681
+
682
+ **Limits**
683
+
684
+ A single `Queue` can contain up to 100,000 partitions, each with up to 5,000 items. Each item can be up to 1 MiB.
685
+
686
+ Partition keys must be non-empty and must not exceed 64 bytes.
687
+ """
688
+
689
+ _metadata: typing.Optional[modal_proto.api_pb2.QueueMetadata]
690
+
691
+ def __init__(self):
692
+ """mdmd:hidden"""
693
+ ...
694
+
695
+ @synchronicity.classproperty
696
+ def objects(cls) -> QueueManager: ...
697
+ @property
698
+ def name(self) -> typing.Optional[str]: ...
699
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
700
+ def _get_metadata(self) -> modal_proto.api_pb2.QueueMetadata: ...
92
701
  @staticmethod
93
702
  def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
94
703
  @classmethod
@@ -97,33 +706,45 @@ class Queue(modal.object.Object):
97
706
  client: typing.Optional[modal.client.Client] = None,
98
707
  environment_name: typing.Optional[str] = None,
99
708
  _heartbeat_sleep: float = 300,
100
- ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Queue]: ...
709
+ ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Queue]:
710
+ """Creates a new ephemeral queue within a context manager:
711
+
712
+ Usage:
713
+ ```python
714
+ from modal import Queue
715
+
716
+ with Queue.ephemeral() as q:
717
+ q.put(123)
718
+ ```
719
+
720
+ ```python notest
721
+ async with Queue.ephemeral() as q:
722
+ await q.put.aio(123)
723
+ ```
724
+ """
725
+ ...
726
+
101
727
  @staticmethod
102
728
  def from_name(
103
- name: str, *, namespace=1, environment_name: typing.Optional[str] = None, create_if_missing: bool = False
104
- ) -> Queue: ...
729
+ name: str,
730
+ *,
731
+ namespace=None,
732
+ environment_name: typing.Optional[str] = None,
733
+ create_if_missing: bool = False,
734
+ client: typing.Optional[modal.client.Client] = None,
735
+ ) -> Queue:
736
+ """Reference a named Queue, creating if necessary.
105
737
 
106
- class __lookup_spec(typing_extensions.Protocol):
107
- def __call__(
108
- self,
109
- /,
110
- name: str,
111
- namespace=1,
112
- client: typing.Optional[modal.client.Client] = None,
113
- environment_name: typing.Optional[str] = None,
114
- create_if_missing: bool = False,
115
- ) -> Queue: ...
116
- async def aio(
117
- self,
118
- /,
119
- name: str,
120
- namespace=1,
121
- client: typing.Optional[modal.client.Client] = None,
122
- environment_name: typing.Optional[str] = None,
123
- create_if_missing: bool = False,
124
- ) -> Queue: ...
738
+ This is a lazy method the defers hydrating the local
739
+ object with metadata from Modal servers until the first
740
+ time it is actually used.
125
741
 
126
- lookup: __lookup_spec
742
+ ```python
743
+ q = modal.Queue.from_name("my-queue", create_if_missing=True)
744
+ q.put(123)
745
+ ```
746
+ """
747
+ ...
127
748
 
128
749
  class __delete_spec(typing_extensions.Protocol):
129
750
  def __call__(
@@ -133,7 +754,17 @@ class Queue(modal.object.Object):
133
754
  *,
134
755
  client: typing.Optional[modal.client.Client] = None,
135
756
  environment_name: typing.Optional[str] = None,
136
- ): ...
757
+ ):
758
+ """mdmd:hidden
759
+ Delete a named Queue.
760
+
761
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
762
+ Deletion is irreversible and will affect any Apps currently using the Queue.
763
+
764
+ DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
765
+ """
766
+ ...
767
+
137
768
  async def aio(
138
769
  self,
139
770
  /,
@@ -141,10 +772,30 @@ class Queue(modal.object.Object):
141
772
  *,
142
773
  client: typing.Optional[modal.client.Client] = None,
143
774
  environment_name: typing.Optional[str] = None,
144
- ): ...
775
+ ):
776
+ """mdmd:hidden
777
+ Delete a named Queue.
778
+
779
+ Warning: This deletes an *entire Queue*, not just a specific entry or partition.
780
+ Deletion is irreversible and will affect any Apps currently using the Queue.
781
+
782
+ DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
783
+ """
784
+ ...
145
785
 
146
786
  delete: __delete_spec
147
787
 
788
+ class __info_spec(typing_extensions.Protocol[SUPERSELF]):
789
+ def __call__(self, /) -> QueueInfo:
790
+ """Return information about the Queue object."""
791
+ ...
792
+
793
+ async def aio(self, /) -> QueueInfo:
794
+ """Return information about the Queue object."""
795
+ ...
796
+
797
+ info: __info_spec[typing_extensions.Self]
798
+
148
799
  class ___get_nonblocking_spec(typing_extensions.Protocol[SUPERSELF]):
149
800
  def __call__(self, /, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
150
801
  async def aio(self, /, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
@@ -162,8 +813,13 @@ class Queue(modal.object.Object):
162
813
  _get_blocking: ___get_blocking_spec[typing_extensions.Self]
163
814
 
164
815
  class __clear_spec(typing_extensions.Protocol[SUPERSELF]):
165
- def __call__(self, /, *, partition: typing.Optional[str] = None, all: bool = False) -> None: ...
166
- async def aio(self, /, *, partition: typing.Optional[str] = None, all: bool = False) -> None: ...
816
+ def __call__(self, /, *, partition: typing.Optional[str] = None, all: bool = False) -> None:
817
+ """Clear the contents of a single partition or all partitions."""
818
+ ...
819
+
820
+ async def aio(self, /, *, partition: typing.Optional[str] = None, all: bool = False) -> None:
821
+ """Clear the contents of a single partition or all partitions."""
822
+ ...
167
823
 
168
824
  clear: __clear_spec[typing_extensions.Self]
169
825
 
@@ -175,7 +831,18 @@ class Queue(modal.object.Object):
175
831
  timeout: typing.Optional[float] = None,
176
832
  *,
177
833
  partition: typing.Optional[str] = None,
178
- ) -> typing.Optional[typing.Any]: ...
834
+ ) -> typing.Optional[typing.Any]:
835
+ """Remove and return the next object in the queue.
836
+
837
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
838
+ an object, or until `timeout` if specified. Raises a native `queue.Empty` exception
839
+ if the `timeout` is reached.
840
+
841
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
842
+ ignored in this case.
843
+ """
844
+ ...
845
+
179
846
  async def aio(
180
847
  self,
181
848
  /,
@@ -183,7 +850,17 @@ class Queue(modal.object.Object):
183
850
  timeout: typing.Optional[float] = None,
184
851
  *,
185
852
  partition: typing.Optional[str] = None,
186
- ) -> typing.Optional[typing.Any]: ...
853
+ ) -> typing.Optional[typing.Any]:
854
+ """Remove and return the next object in the queue.
855
+
856
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
857
+ an object, or until `timeout` if specified. Raises a native `queue.Empty` exception
858
+ if the `timeout` is reached.
859
+
860
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
861
+ ignored in this case.
862
+ """
863
+ ...
187
864
 
188
865
  get: __get_spec[typing_extensions.Self]
189
866
 
@@ -196,7 +873,20 @@ class Queue(modal.object.Object):
196
873
  timeout: typing.Optional[float] = None,
197
874
  *,
198
875
  partition: typing.Optional[str] = None,
199
- ) -> list[typing.Any]: ...
876
+ ) -> list[typing.Any]:
877
+ """Remove and return up to `n_values` objects from the queue.
878
+
879
+ If there are fewer than `n_values` items in the queue, return all of them.
880
+
881
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
882
+ at least 1 object to be present, or until `timeout` if specified. Raises the stdlib's `queue.Empty`
883
+ exception if the `timeout` is reached.
884
+
885
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
886
+ ignored in this case.
887
+ """
888
+ ...
889
+
200
890
  async def aio(
201
891
  self,
202
892
  /,
@@ -205,7 +895,19 @@ class Queue(modal.object.Object):
205
895
  timeout: typing.Optional[float] = None,
206
896
  *,
207
897
  partition: typing.Optional[str] = None,
208
- ) -> list[typing.Any]: ...
898
+ ) -> list[typing.Any]:
899
+ """Remove and return up to `n_values` objects from the queue.
900
+
901
+ If there are fewer than `n_values` items in the queue, return all of them.
902
+
903
+ If `block` is `True` (the default) and the queue is empty, `get` will wait indefinitely for
904
+ at least 1 object to be present, or until `timeout` if specified. Raises the stdlib's `queue.Empty`
905
+ exception if the `timeout` is reached.
906
+
907
+ If `block` is `False`, `get` returns `None` immediately if the queue is empty. The `timeout` is
908
+ ignored in this case.
909
+ """
910
+ ...
209
911
 
210
912
  get_many: __get_many_spec[typing_extensions.Self]
211
913
 
@@ -219,7 +921,18 @@ class Queue(modal.object.Object):
219
921
  *,
220
922
  partition: typing.Optional[str] = None,
221
923
  partition_ttl: int = 86400,
222
- ) -> None: ...
924
+ ) -> None:
925
+ """Add an object to the end of the queue.
926
+
927
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
928
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
929
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
930
+
931
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
932
+ ignored in this case.
933
+ """
934
+ ...
935
+
223
936
  async def aio(
224
937
  self,
225
938
  /,
@@ -229,7 +942,17 @@ class Queue(modal.object.Object):
229
942
  *,
230
943
  partition: typing.Optional[str] = None,
231
944
  partition_ttl: int = 86400,
232
- ) -> None: ...
945
+ ) -> None:
946
+ """Add an object to the end of the queue.
947
+
948
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
949
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
950
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
951
+
952
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
953
+ ignored in this case.
954
+ """
955
+ ...
233
956
 
234
957
  put: __put_spec[typing_extensions.Self]
235
958
 
@@ -243,7 +966,18 @@ class Queue(modal.object.Object):
243
966
  *,
244
967
  partition: typing.Optional[str] = None,
245
968
  partition_ttl: int = 86400,
246
- ) -> None: ...
969
+ ) -> None:
970
+ """Add several objects to the end of the queue.
971
+
972
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
973
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
974
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
975
+
976
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
977
+ ignored in this case.
978
+ """
979
+ ...
980
+
247
981
  async def aio(
248
982
  self,
249
983
  /,
@@ -253,7 +987,17 @@ class Queue(modal.object.Object):
253
987
  *,
254
988
  partition: typing.Optional[str] = None,
255
989
  partition_ttl: int = 86400,
256
- ) -> None: ...
990
+ ) -> None:
991
+ """Add several objects to the end of the queue.
992
+
993
+ If `block` is `True` and the queue is full, this method will retry indefinitely or
994
+ until `timeout` if specified. Raises the stdlib's `queue.Full` exception if the `timeout` is reached.
995
+ If blocking it is not recommended to omit the `timeout`, as the operation could wait indefinitely.
996
+
997
+ If `block` is `False`, this method raises `queue.Full` immediately if the queue is full. The `timeout` is
998
+ ignored in this case.
999
+ """
1000
+ ...
257
1001
 
258
1002
  put_many: __put_many_spec[typing_extensions.Self]
259
1003
 
@@ -284,17 +1028,33 @@ class Queue(modal.object.Object):
284
1028
  _put_many_nonblocking: ___put_many_nonblocking_spec[typing_extensions.Self]
285
1029
 
286
1030
  class __len_spec(typing_extensions.Protocol[SUPERSELF]):
287
- def __call__(self, /, *, partition: typing.Optional[str] = None, total: bool = False) -> int: ...
288
- async def aio(self, /, *, partition: typing.Optional[str] = None, total: bool = False) -> int: ...
1031
+ def __call__(self, /, *, partition: typing.Optional[str] = None, total: bool = False) -> int:
1032
+ """Return the number of objects in the queue partition."""
1033
+ ...
1034
+
1035
+ async def aio(self, /, *, partition: typing.Optional[str] = None, total: bool = False) -> int:
1036
+ """Return the number of objects in the queue partition."""
1037
+ ...
289
1038
 
290
1039
  len: __len_spec[typing_extensions.Self]
291
1040
 
292
1041
  class __iterate_spec(typing_extensions.Protocol[SUPERSELF]):
293
1042
  def __call__(
294
1043
  self, /, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
295
- ) -> typing.Generator[typing.Any, None, None]: ...
1044
+ ) -> typing.Generator[typing.Any, None, None]:
1045
+ """(Beta feature) Iterate through items in the queue without mutation.
1046
+
1047
+ Specify `item_poll_timeout` to control how long the iterator should wait for the next time before giving up.
1048
+ """
1049
+ ...
1050
+
296
1051
  def aio(
297
1052
  self, /, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
298
- ) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
1053
+ ) -> collections.abc.AsyncGenerator[typing.Any, None]:
1054
+ """(Beta feature) Iterate through items in the queue without mutation.
1055
+
1056
+ Specify `item_poll_timeout` to control how long the iterator should wait for the next time before giving up.
1057
+ """
1058
+ ...
299
1059
 
300
1060
  iterate: __iterate_spec[typing_extensions.Self]