modal 1.1.1.dev41__py3-none-any.whl → 1.1.2__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 (68) hide show
  1. modal/__main__.py +1 -2
  2. modal/_container_entrypoint.py +18 -7
  3. modal/_functions.py +135 -13
  4. modal/_object.py +13 -2
  5. modal/_partial_function.py +8 -8
  6. modal/_runtime/asgi.py +3 -2
  7. modal/_runtime/container_io_manager.py +20 -14
  8. modal/_runtime/container_io_manager.pyi +38 -13
  9. modal/_runtime/execution_context.py +18 -2
  10. modal/_runtime/execution_context.pyi +4 -1
  11. modal/_runtime/gpu_memory_snapshot.py +158 -54
  12. modal/_utils/blob_utils.py +83 -24
  13. modal/_utils/function_utils.py +4 -3
  14. modal/_utils/time_utils.py +28 -4
  15. modal/app.py +8 -4
  16. modal/app.pyi +8 -8
  17. modal/cli/dict.py +14 -11
  18. modal/cli/entry_point.py +9 -3
  19. modal/cli/launch.py +102 -4
  20. modal/cli/profile.py +1 -0
  21. modal/cli/programs/launch_instance_ssh.py +94 -0
  22. modal/cli/programs/run_marimo.py +95 -0
  23. modal/cli/queues.py +49 -19
  24. modal/cli/secret.py +45 -18
  25. modal/cli/volume.py +14 -16
  26. modal/client.pyi +2 -10
  27. modal/cls.py +12 -2
  28. modal/cls.pyi +9 -1
  29. modal/config.py +7 -7
  30. modal/dict.py +206 -12
  31. modal/dict.pyi +358 -4
  32. modal/experimental/__init__.py +130 -0
  33. modal/file_io.py +1 -1
  34. modal/file_io.pyi +2 -2
  35. modal/file_pattern_matcher.py +25 -16
  36. modal/functions.pyi +111 -11
  37. modal/image.py +9 -3
  38. modal/image.pyi +7 -7
  39. modal/mount.py +20 -13
  40. modal/mount.pyi +16 -3
  41. modal/network_file_system.py +8 -2
  42. modal/object.pyi +3 -0
  43. modal/parallel_map.py +346 -101
  44. modal/parallel_map.pyi +108 -0
  45. modal/proxy.py +2 -1
  46. modal/queue.py +199 -9
  47. modal/queue.pyi +357 -3
  48. modal/sandbox.py +6 -5
  49. modal/sandbox.pyi +17 -14
  50. modal/secret.py +196 -3
  51. modal/secret.pyi +372 -0
  52. modal/volume.py +239 -23
  53. modal/volume.pyi +405 -10
  54. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/METADATA +2 -2
  55. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/RECORD +68 -66
  56. modal_docs/mdmd/mdmd.py +11 -1
  57. modal_proto/api.proto +37 -10
  58. modal_proto/api_grpc.py +32 -0
  59. modal_proto/api_pb2.py +627 -597
  60. modal_proto/api_pb2.pyi +107 -19
  61. modal_proto/api_pb2_grpc.py +67 -2
  62. modal_proto/api_pb2_grpc.pyi +24 -8
  63. modal_proto/modal_api_grpc.py +2 -0
  64. modal_version/__init__.py +1 -1
  65. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/WHEEL +0 -0
  66. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/entry_points.txt +0 -0
  67. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/licenses/LICENSE +0 -0
  68. {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/top_level.txt +0 -0
modal/volume.pyi CHANGED
@@ -10,6 +10,7 @@ import modal.client
10
10
  import modal.object
11
11
  import modal_proto.api_pb2
12
12
  import pathlib
13
+ import synchronicity
13
14
  import synchronicity.combined_types
14
15
  import typing
15
16
  import typing_extensions
@@ -79,6 +80,329 @@ class VolumeInfo:
79
80
  """Return self==value."""
80
81
  ...
81
82
 
83
+ class _VolumeManager:
84
+ """Namespace with methods for managing named Volume objects."""
85
+ @staticmethod
86
+ async def create(
87
+ name: str,
88
+ *,
89
+ version: typing.Optional[int] = None,
90
+ allow_existing: bool = False,
91
+ environment_name: typing.Optional[str] = None,
92
+ client: typing.Optional[modal.client._Client] = None,
93
+ ) -> None:
94
+ """Create a new Volume object.
95
+
96
+ **Examples:**
97
+
98
+ ```python notest
99
+ modal.Volume.objects.create("my-volume")
100
+ ```
101
+
102
+ Volumes will be created in the active environment, or another one can be specified:
103
+
104
+ ```python notest
105
+ modal.Volume.objects.create("my-volume", environment_name="dev")
106
+ ```
107
+
108
+ By default, an error will be raised if the Volume already exists, but passing
109
+ `allow_existing=True` will make the creation attempt a no-op in this case.
110
+
111
+ ```python notest
112
+ modal.Volume.objects.create("my-volume", allow_existing=True)
113
+ ```
114
+
115
+ Note that this method does not return a local instance of the Volume. You can use
116
+ `modal.Volume.from_name` to perform a lookup after creation.
117
+
118
+ Added in v1.1.2.
119
+ """
120
+ ...
121
+
122
+ @staticmethod
123
+ async def list(
124
+ *,
125
+ max_objects: typing.Optional[int] = None,
126
+ created_before: typing.Union[datetime.datetime, str, None] = None,
127
+ environment_name: str = "",
128
+ client: typing.Optional[modal.client._Client] = None,
129
+ ) -> list[_Volume]:
130
+ """Return a list of hydrated Volume objects.
131
+
132
+ **Examples:**
133
+
134
+ ```python
135
+ volumes = modal.Volume.objects.list()
136
+ print([v.name for v in volumes])
137
+ ```
138
+
139
+ Volumes will be retreived from the active environment, or another one can be specified:
140
+
141
+ ```python notest
142
+ dev_volumes = modal.Volume.objects.list(environment_name="dev")
143
+ ```
144
+
145
+ By default, all named Volumes are returned, newest to oldest. It's also possible to limit the
146
+ number of results and to filter by creation date:
147
+
148
+ ```python
149
+ volumes = modal.Volume.objects.list(max_objects=10, created_before="2025-01-01")
150
+ ```
151
+
152
+ Added in v1.1.2.
153
+ """
154
+ ...
155
+
156
+ @staticmethod
157
+ async def delete(
158
+ name: str,
159
+ *,
160
+ allow_missing: bool = False,
161
+ environment_name: typing.Optional[str] = None,
162
+ client: typing.Optional[modal.client._Client] = None,
163
+ ):
164
+ """Delete a named Volume.
165
+
166
+ Warning: This deletes an *entire Volume*, not just a specific file.
167
+ Deletion is irreversible and will affect any Apps currently using the Volume.
168
+
169
+ **Examples:**
170
+
171
+ ```python notest
172
+ await modal.Volume.objects.delete("my-volume")
173
+ ```
174
+
175
+ Volumes will be deleted from the active environment, or another one can be specified:
176
+
177
+ ```python notest
178
+ await modal.Volume.objects.delete("my-volume", environment_name="dev")
179
+ ```
180
+
181
+ Added in v1.1.2.
182
+ """
183
+ ...
184
+
185
+ class VolumeManager:
186
+ """Namespace with methods for managing named Volume objects."""
187
+ def __init__(self, /, *args, **kwargs):
188
+ """Initialize self. See help(type(self)) for accurate signature."""
189
+ ...
190
+
191
+ class __create_spec(typing_extensions.Protocol):
192
+ def __call__(
193
+ self,
194
+ /,
195
+ name: str,
196
+ *,
197
+ version: typing.Optional[int] = None,
198
+ allow_existing: bool = False,
199
+ environment_name: typing.Optional[str] = None,
200
+ client: typing.Optional[modal.client.Client] = None,
201
+ ) -> None:
202
+ """Create a new Volume object.
203
+
204
+ **Examples:**
205
+
206
+ ```python notest
207
+ modal.Volume.objects.create("my-volume")
208
+ ```
209
+
210
+ Volumes will be created in the active environment, or another one can be specified:
211
+
212
+ ```python notest
213
+ modal.Volume.objects.create("my-volume", environment_name="dev")
214
+ ```
215
+
216
+ By default, an error will be raised if the Volume already exists, but passing
217
+ `allow_existing=True` will make the creation attempt a no-op in this case.
218
+
219
+ ```python notest
220
+ modal.Volume.objects.create("my-volume", allow_existing=True)
221
+ ```
222
+
223
+ Note that this method does not return a local instance of the Volume. You can use
224
+ `modal.Volume.from_name` to perform a lookup after creation.
225
+
226
+ Added in v1.1.2.
227
+ """
228
+ ...
229
+
230
+ async def aio(
231
+ self,
232
+ /,
233
+ name: str,
234
+ *,
235
+ version: typing.Optional[int] = None,
236
+ allow_existing: bool = False,
237
+ environment_name: typing.Optional[str] = None,
238
+ client: typing.Optional[modal.client.Client] = None,
239
+ ) -> None:
240
+ """Create a new Volume object.
241
+
242
+ **Examples:**
243
+
244
+ ```python notest
245
+ modal.Volume.objects.create("my-volume")
246
+ ```
247
+
248
+ Volumes will be created in the active environment, or another one can be specified:
249
+
250
+ ```python notest
251
+ modal.Volume.objects.create("my-volume", environment_name="dev")
252
+ ```
253
+
254
+ By default, an error will be raised if the Volume already exists, but passing
255
+ `allow_existing=True` will make the creation attempt a no-op in this case.
256
+
257
+ ```python notest
258
+ modal.Volume.objects.create("my-volume", allow_existing=True)
259
+ ```
260
+
261
+ Note that this method does not return a local instance of the Volume. You can use
262
+ `modal.Volume.from_name` to perform a lookup after creation.
263
+
264
+ Added in v1.1.2.
265
+ """
266
+ ...
267
+
268
+ create: __create_spec
269
+
270
+ class __list_spec(typing_extensions.Protocol):
271
+ def __call__(
272
+ self,
273
+ /,
274
+ *,
275
+ max_objects: typing.Optional[int] = None,
276
+ created_before: typing.Union[datetime.datetime, str, None] = None,
277
+ environment_name: str = "",
278
+ client: typing.Optional[modal.client.Client] = None,
279
+ ) -> list[Volume]:
280
+ """Return a list of hydrated Volume objects.
281
+
282
+ **Examples:**
283
+
284
+ ```python
285
+ volumes = modal.Volume.objects.list()
286
+ print([v.name for v in volumes])
287
+ ```
288
+
289
+ Volumes will be retreived from the active environment, or another one can be specified:
290
+
291
+ ```python notest
292
+ dev_volumes = modal.Volume.objects.list(environment_name="dev")
293
+ ```
294
+
295
+ By default, all named Volumes are returned, newest to oldest. It's also possible to limit the
296
+ number of results and to filter by creation date:
297
+
298
+ ```python
299
+ volumes = modal.Volume.objects.list(max_objects=10, created_before="2025-01-01")
300
+ ```
301
+
302
+ Added in v1.1.2.
303
+ """
304
+ ...
305
+
306
+ async def aio(
307
+ self,
308
+ /,
309
+ *,
310
+ max_objects: typing.Optional[int] = None,
311
+ created_before: typing.Union[datetime.datetime, str, None] = None,
312
+ environment_name: str = "",
313
+ client: typing.Optional[modal.client.Client] = None,
314
+ ) -> list[Volume]:
315
+ """Return a list of hydrated Volume objects.
316
+
317
+ **Examples:**
318
+
319
+ ```python
320
+ volumes = modal.Volume.objects.list()
321
+ print([v.name for v in volumes])
322
+ ```
323
+
324
+ Volumes will be retreived from the active environment, or another one can be specified:
325
+
326
+ ```python notest
327
+ dev_volumes = modal.Volume.objects.list(environment_name="dev")
328
+ ```
329
+
330
+ By default, all named Volumes are returned, newest to oldest. It's also possible to limit the
331
+ number of results and to filter by creation date:
332
+
333
+ ```python
334
+ volumes = modal.Volume.objects.list(max_objects=10, created_before="2025-01-01")
335
+ ```
336
+
337
+ Added in v1.1.2.
338
+ """
339
+ ...
340
+
341
+ list: __list_spec
342
+
343
+ class __delete_spec(typing_extensions.Protocol):
344
+ def __call__(
345
+ self,
346
+ /,
347
+ name: str,
348
+ *,
349
+ allow_missing: bool = False,
350
+ environment_name: typing.Optional[str] = None,
351
+ client: typing.Optional[modal.client.Client] = None,
352
+ ):
353
+ """Delete a named Volume.
354
+
355
+ Warning: This deletes an *entire Volume*, not just a specific file.
356
+ Deletion is irreversible and will affect any Apps currently using the Volume.
357
+
358
+ **Examples:**
359
+
360
+ ```python notest
361
+ await modal.Volume.objects.delete("my-volume")
362
+ ```
363
+
364
+ Volumes will be deleted from the active environment, or another one can be specified:
365
+
366
+ ```python notest
367
+ await modal.Volume.objects.delete("my-volume", environment_name="dev")
368
+ ```
369
+
370
+ Added in v1.1.2.
371
+ """
372
+ ...
373
+
374
+ async def aio(
375
+ self,
376
+ /,
377
+ name: str,
378
+ *,
379
+ allow_missing: bool = False,
380
+ environment_name: typing.Optional[str] = None,
381
+ client: typing.Optional[modal.client.Client] = None,
382
+ ):
383
+ """Delete a named Volume.
384
+
385
+ Warning: This deletes an *entire Volume*, not just a specific file.
386
+ Deletion is irreversible and will affect any Apps currently using the Volume.
387
+
388
+ **Examples:**
389
+
390
+ ```python notest
391
+ await modal.Volume.objects.delete("my-volume")
392
+ ```
393
+
394
+ Volumes will be deleted from the active environment, or another one can be specified:
395
+
396
+ ```python notest
397
+ await modal.Volume.objects.delete("my-volume", environment_name="dev")
398
+ ```
399
+
400
+ Added in v1.1.2.
401
+ """
402
+ ...
403
+
404
+ delete: __delete_spec
405
+
82
406
  class _Volume(modal._object._Object):
83
407
  """A writeable volume that can be used to share files between one or more Modal functions.
84
408
 
@@ -125,6 +449,10 @@ class _Volume(modal._object._Object):
125
449
  _metadata: typing.Optional[modal_proto.api_pb2.VolumeMetadata]
126
450
  _read_only: bool
127
451
 
452
+ @synchronicity.classproperty
453
+ def objects(cls) -> _VolumeManager: ...
454
+ @property
455
+ def name(self) -> typing.Optional[str]: ...
128
456
  def read_only(self) -> _Volume:
129
457
  """Configure Volume to mount as read-only.
130
458
 
@@ -148,8 +476,6 @@ class _Volume(modal._object._Object):
148
476
  """
149
477
  ...
150
478
 
151
- @property
152
- def name(self) -> typing.Optional[str]: ...
153
479
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
154
480
  def _get_metadata(self) -> typing.Optional[google.protobuf.message.Message]: ...
155
481
  async def _get_lock(self): ...
@@ -242,13 +568,24 @@ class _Volume(modal._object._Object):
242
568
  """mdmd:hidden"""
243
569
  ...
244
570
 
571
+ @staticmethod
572
+ async def _create_deployed(
573
+ deployment_name: str,
574
+ namespace=None,
575
+ client: typing.Optional[modal.client._Client] = None,
576
+ environment_name: typing.Optional[str] = None,
577
+ version: typing.Optional[int] = None,
578
+ ) -> str:
579
+ """mdmd:hidden"""
580
+ ...
581
+
245
582
  async def info(self) -> VolumeInfo:
246
583
  """Return information about the Volume object."""
247
584
  ...
248
585
 
249
586
  async def _do_reload(self, lock=True): ...
250
587
  async def commit(self):
251
- """Commit changes to the volume.
588
+ """Commit changes to a mounted volume.
252
589
 
253
590
  If successful, the changes made are now persisted in durable storage and available to other containers accessing
254
591
  the volume.
@@ -367,7 +704,17 @@ class _Volume(modal._object._Object):
367
704
  @staticmethod
368
705
  async def delete(
369
706
  name: str, client: typing.Optional[modal.client._Client] = None, environment_name: typing.Optional[str] = None
370
- ): ...
707
+ ):
708
+ """mdmd:hidden
709
+ Delete a named Volume.
710
+
711
+ Warning: This deletes an *entire Volume*, not just a specific file.
712
+ Deletion is irreversible and will affect any Apps currently using the Volume.
713
+
714
+ DEPRECATED: This method is deprecated; we recommend using `modal.Volume.objects.delete` instead.
715
+ """
716
+ ...
717
+
371
718
  @staticmethod
372
719
  async def rename(
373
720
  old_name: str,
@@ -429,6 +776,10 @@ class Volume(modal.object.Object):
429
776
  """mdmd:hidden"""
430
777
  ...
431
778
 
779
+ @synchronicity.classproperty
780
+ def objects(cls) -> VolumeManager: ...
781
+ @property
782
+ def name(self) -> typing.Optional[str]: ...
432
783
  def read_only(self) -> Volume:
433
784
  """Configure Volume to mount as read-only.
434
785
 
@@ -452,8 +803,6 @@ class Volume(modal.object.Object):
452
803
  """
453
804
  ...
454
805
 
455
- @property
456
- def name(self) -> typing.Optional[str]: ...
457
806
  def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
458
807
  def _get_metadata(self) -> typing.Optional[google.protobuf.message.Message]: ...
459
808
 
@@ -597,6 +946,33 @@ class Volume(modal.object.Object):
597
946
 
598
947
  create_deployed: __create_deployed_spec
599
948
 
949
+ class ___create_deployed_spec(typing_extensions.Protocol):
950
+ def __call__(
951
+ self,
952
+ /,
953
+ deployment_name: str,
954
+ namespace=None,
955
+ client: typing.Optional[modal.client.Client] = None,
956
+ environment_name: typing.Optional[str] = None,
957
+ version: typing.Optional[int] = None,
958
+ ) -> str:
959
+ """mdmd:hidden"""
960
+ ...
961
+
962
+ async def aio(
963
+ self,
964
+ /,
965
+ deployment_name: str,
966
+ namespace=None,
967
+ client: typing.Optional[modal.client.Client] = None,
968
+ environment_name: typing.Optional[str] = None,
969
+ version: typing.Optional[int] = None,
970
+ ) -> str:
971
+ """mdmd:hidden"""
972
+ ...
973
+
974
+ _create_deployed: ___create_deployed_spec
975
+
600
976
  class __info_spec(typing_extensions.Protocol[SUPERSELF]):
601
977
  def __call__(self, /) -> VolumeInfo:
602
978
  """Return information about the Volume object."""
@@ -616,7 +992,7 @@ class Volume(modal.object.Object):
616
992
 
617
993
  class __commit_spec(typing_extensions.Protocol[SUPERSELF]):
618
994
  def __call__(self, /):
619
- """Commit changes to the volume.
995
+ """Commit changes to a mounted volume.
620
996
 
621
997
  If successful, the changes made are now persisted in durable storage and available to other containers accessing
622
998
  the volume.
@@ -624,7 +1000,7 @@ class Volume(modal.object.Object):
624
1000
  ...
625
1001
 
626
1002
  async def aio(self, /):
627
- """Commit changes to the volume.
1003
+ """Commit changes to a mounted volume.
628
1004
 
629
1005
  If successful, the changes made are now persisted in durable storage and available to other containers accessing
630
1006
  the volume.
@@ -886,14 +1262,33 @@ class Volume(modal.object.Object):
886
1262
  name: str,
887
1263
  client: typing.Optional[modal.client.Client] = None,
888
1264
  environment_name: typing.Optional[str] = None,
889
- ): ...
1265
+ ):
1266
+ """mdmd:hidden
1267
+ Delete a named Volume.
1268
+
1269
+ Warning: This deletes an *entire Volume*, not just a specific file.
1270
+ Deletion is irreversible and will affect any Apps currently using the Volume.
1271
+
1272
+ DEPRECATED: This method is deprecated; we recommend using `modal.Volume.objects.delete` instead.
1273
+ """
1274
+ ...
1275
+
890
1276
  async def aio(
891
1277
  self,
892
1278
  /,
893
1279
  name: str,
894
1280
  client: typing.Optional[modal.client.Client] = None,
895
1281
  environment_name: typing.Optional[str] = None,
896
- ): ...
1282
+ ):
1283
+ """mdmd:hidden
1284
+ Delete a named Volume.
1285
+
1286
+ Warning: This deletes an *entire Volume*, not just a specific file.
1287
+ Deletion is irreversible and will affect any Apps currently using the Volume.
1288
+
1289
+ DEPRECATED: This method is deprecated; we recommend using `modal.Volume.objects.delete` instead.
1290
+ """
1291
+ ...
897
1292
 
898
1293
  delete: __delete_spec
899
1294
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.1.dev41
3
+ Version: 1.1.2
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -22,7 +22,7 @@ Requires-Dist: click~=8.1
22
22
  Requires-Dist: grpclib<0.4.9,>=0.4.7
23
23
  Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
24
24
  Requires-Dist: rich>=12.0.0
25
- Requires-Dist: synchronicity~=0.10.1
25
+ Requires-Dist: synchronicity~=0.10.2
26
26
  Requires-Dist: toml
27
27
  Requires-Dist: typer>=0.9
28
28
  Requires-Dist: types-certifi