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/mount.pyi CHANGED
@@ -1,5 +1,6 @@
1
1
  import collections.abc
2
2
  import google.protobuf.message
3
+ import modal._load_context
3
4
  import modal._object
4
5
  import modal._resolver
5
6
  import modal._utils.blob_utils
@@ -154,7 +155,6 @@ class _Mount(modal._object._Object):
154
155
  _entries: typing.Optional[list[_MountEntry]]
155
156
  _deployment_name: typing.Optional[str]
156
157
  _namespace: typing.Optional[int]
157
- _environment_name: typing.Optional[str]
158
158
  _allow_overwrite: bool
159
159
  _content_checksum_sha256_hex: typing.Optional[str]
160
160
 
@@ -189,30 +189,6 @@ class _Mount(modal._object._Object):
189
189
  """Add a local directory to the `Mount` object."""
190
190
  ...
191
191
 
192
- @staticmethod
193
- def from_local_dir(
194
- local_path: typing.Union[str, pathlib.Path],
195
- *,
196
- remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None,
197
- condition: typing.Optional[collections.abc.Callable[[str], bool]] = None,
198
- recursive: bool = True,
199
- ) -> _Mount:
200
- """**Deprecated:** Use image.add_local_dir() instead
201
-
202
- Create a `Mount` from a local directory.
203
-
204
- **Usage**
205
-
206
- ```python notest
207
- assets = modal.Mount.from_local_dir(
208
- "~/assets",
209
- condition=lambda pth: not ".venv" in pth,
210
- remote_path="/assets",
211
- )
212
- ```
213
- """
214
- ...
215
-
216
192
  @staticmethod
217
193
  def _from_local_dir(
218
194
  local_path: typing.Union[str, pathlib.Path],
@@ -229,26 +205,6 @@ class _Mount(modal._object._Object):
229
205
  """Add a local file to the `Mount` object."""
230
206
  ...
231
207
 
232
- @staticmethod
233
- def from_local_file(
234
- local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
235
- ) -> _Mount:
236
- """**Deprecated**: Use image.add_local_file() instead
237
-
238
- Create a `Mount` mounting a single local file.
239
-
240
- **Usage**
241
-
242
- ```python notest
243
- # Mount the DBT profile in user's home directory into container.
244
- dbt_profiles = modal.Mount.from_local_file(
245
- local_path="~/profiles.yml",
246
- remote_path="/root/dbt_profile/profiles.yml",
247
- )
248
- ```
249
- """
250
- ...
251
-
252
208
  @staticmethod
253
209
  def _from_local_file(
254
210
  local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
@@ -260,38 +216,11 @@ class _Mount(modal._object._Object):
260
216
  entries: list[_MountEntry],
261
217
  ) -> collections.abc.AsyncGenerator[modal._utils.blob_utils.FileUploadSpec, None]: ...
262
218
  async def _load_mount(
263
- self: _Mount, resolver: modal._resolver.Resolver, existing_object_id: typing.Optional[str]
219
+ self: _Mount,
220
+ resolver: modal._resolver.Resolver,
221
+ load_context: modal._load_context.LoadContext,
222
+ existing_object_id: typing.Optional[str],
264
223
  ): ...
265
- @staticmethod
266
- def from_local_python_packages(
267
- *module_names: str,
268
- remote_dir: typing.Union[str, pathlib.PurePosixPath] = "/root",
269
- condition: typing.Optional[collections.abc.Callable[[str], bool]] = None,
270
- ignore: typing.Union[typing.Sequence[str], collections.abc.Callable[[pathlib.Path], bool], None] = None,
271
- ) -> _Mount:
272
- """**Deprecated**: Use image.add_local_python_source instead
273
-
274
- Returns a `modal.Mount` that makes local modules listed in `module_names` available inside the container.
275
- This works by mounting the local path of each module's package to a directory inside the container
276
- that's on `PYTHONPATH`.
277
-
278
- **Usage**
279
-
280
- ```python notest
281
- import modal
282
- import my_local_module
283
-
284
- app = modal.App()
285
-
286
- @app.function(mounts=[
287
- modal.Mount.from_local_python_packages("my_local_module", "my_other_module"),
288
- ])
289
- def f():
290
- my_local_module.do_stuff()
291
- ```
292
- """
293
- ...
294
-
295
224
  @staticmethod
296
225
  def _from_local_python_packages(
297
226
  *module_names: str,
@@ -300,17 +229,12 @@ class _Mount(modal._object._Object):
300
229
  ignore: typing.Union[typing.Sequence[str], collections.abc.Callable[[pathlib.Path], bool], None] = None,
301
230
  ) -> _Mount: ...
302
231
  @staticmethod
303
- def from_name(name: str, *, namespace=1, environment_name: typing.Optional[str] = None) -> _Mount:
304
- """mdmd:hidden"""
305
- ...
306
-
307
- @classmethod
308
- async def lookup(
309
- cls: type[_Mount],
232
+ def from_name(
310
233
  name: str,
234
+ *,
311
235
  namespace=1,
312
- client: typing.Optional[modal.client._Client] = None,
313
236
  environment_name: typing.Optional[str] = None,
237
+ client: typing.Optional[modal.client._Client] = None,
314
238
  ) -> _Mount:
315
239
  """mdmd:hidden"""
316
240
  ...
@@ -354,7 +278,6 @@ class Mount(modal.object.Object):
354
278
  _entries: typing.Optional[list[_MountEntry]]
355
279
  _deployment_name: typing.Optional[str]
356
280
  _namespace: typing.Optional[int]
357
- _environment_name: typing.Optional[str]
358
281
  _allow_overwrite: bool
359
282
  _content_checksum_sha256_hex: typing.Optional[str]
360
283
 
@@ -393,30 +316,6 @@ class Mount(modal.object.Object):
393
316
  """Add a local directory to the `Mount` object."""
394
317
  ...
395
318
 
396
- @staticmethod
397
- def from_local_dir(
398
- local_path: typing.Union[str, pathlib.Path],
399
- *,
400
- remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None,
401
- condition: typing.Optional[collections.abc.Callable[[str], bool]] = None,
402
- recursive: bool = True,
403
- ) -> Mount:
404
- """**Deprecated:** Use image.add_local_dir() instead
405
-
406
- Create a `Mount` from a local directory.
407
-
408
- **Usage**
409
-
410
- ```python notest
411
- assets = modal.Mount.from_local_dir(
412
- "~/assets",
413
- condition=lambda pth: not ".venv" in pth,
414
- remote_path="/assets",
415
- )
416
- ```
417
- """
418
- ...
419
-
420
319
  @staticmethod
421
320
  def _from_local_dir(
422
321
  local_path: typing.Union[str, pathlib.Path],
@@ -433,26 +332,6 @@ class Mount(modal.object.Object):
433
332
  """Add a local file to the `Mount` object."""
434
333
  ...
435
334
 
436
- @staticmethod
437
- def from_local_file(
438
- local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
439
- ) -> Mount:
440
- """**Deprecated**: Use image.add_local_file() instead
441
-
442
- Create a `Mount` mounting a single local file.
443
-
444
- **Usage**
445
-
446
- ```python notest
447
- # Mount the DBT profile in user's home directory into container.
448
- dbt_profiles = modal.Mount.from_local_file(
449
- local_path="~/profiles.yml",
450
- remote_path="/root/dbt_profile/profiles.yml",
451
- )
452
- ```
453
- """
454
- ...
455
-
456
335
  @staticmethod
457
336
  def _from_local_file(
458
337
  local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
@@ -471,41 +350,23 @@ class Mount(modal.object.Object):
471
350
  _get_files: ___get_files_spec
472
351
 
473
352
  class ___load_mount_spec(typing_extensions.Protocol[SUPERSELF]):
474
- def __call__(self, /, resolver: modal._resolver.Resolver, existing_object_id: typing.Optional[str]): ...
475
- async def aio(self, /, resolver: modal._resolver.Resolver, existing_object_id: typing.Optional[str]): ...
353
+ def __call__(
354
+ self,
355
+ /,
356
+ resolver: modal._resolver.Resolver,
357
+ load_context: modal._load_context.LoadContext,
358
+ existing_object_id: typing.Optional[str],
359
+ ): ...
360
+ async def aio(
361
+ self,
362
+ /,
363
+ resolver: modal._resolver.Resolver,
364
+ load_context: modal._load_context.LoadContext,
365
+ existing_object_id: typing.Optional[str],
366
+ ): ...
476
367
 
477
368
  _load_mount: ___load_mount_spec[typing_extensions.Self]
478
369
 
479
- @staticmethod
480
- def from_local_python_packages(
481
- *module_names: str,
482
- remote_dir: typing.Union[str, pathlib.PurePosixPath] = "/root",
483
- condition: typing.Optional[collections.abc.Callable[[str], bool]] = None,
484
- ignore: typing.Union[typing.Sequence[str], collections.abc.Callable[[pathlib.Path], bool], None] = None,
485
- ) -> Mount:
486
- """**Deprecated**: Use image.add_local_python_source instead
487
-
488
- Returns a `modal.Mount` that makes local modules listed in `module_names` available inside the container.
489
- This works by mounting the local path of each module's package to a directory inside the container
490
- that's on `PYTHONPATH`.
491
-
492
- **Usage**
493
-
494
- ```python notest
495
- import modal
496
- import my_local_module
497
-
498
- app = modal.App()
499
-
500
- @app.function(mounts=[
501
- modal.Mount.from_local_python_packages("my_local_module", "my_other_module"),
502
- ])
503
- def f():
504
- my_local_module.do_stuff()
505
- ```
506
- """
507
- ...
508
-
509
370
  @staticmethod
510
371
  def _from_local_python_packages(
511
372
  *module_names: str,
@@ -514,17 +375,12 @@ class Mount(modal.object.Object):
514
375
  ignore: typing.Union[typing.Sequence[str], collections.abc.Callable[[pathlib.Path], bool], None] = None,
515
376
  ) -> Mount: ...
516
377
  @staticmethod
517
- def from_name(name: str, *, namespace=1, environment_name: typing.Optional[str] = None) -> Mount:
518
- """mdmd:hidden"""
519
- ...
520
-
521
- @classmethod
522
- def lookup(
523
- cls: type[Mount],
378
+ def from_name(
524
379
  name: str,
380
+ *,
525
381
  namespace=1,
526
- client: typing.Optional[modal.client.Client] = None,
527
382
  environment_name: typing.Optional[str] = None,
383
+ client: typing.Optional[modal.client.Client] = None,
528
384
  ) -> Mount:
529
385
  """mdmd:hidden"""
530
386
  ...
@@ -568,17 +424,34 @@ async def _create_single_client_dependency_mount(
568
424
  uv_python_platform: str,
569
425
  check_if_exists: bool = True,
570
426
  allow_overwrite: bool = False,
427
+ dry_run: bool = False,
571
428
  ): ...
572
429
  async def _create_client_dependency_mounts(
573
- client=None, python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"], check_if_exists=True
430
+ client=None,
431
+ python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"],
432
+ builder_versions: list[str] = ["2025.06"],
433
+ check_if_exists=True,
434
+ dry_run=False,
574
435
  ): ...
575
436
 
576
437
  class __create_client_dependency_mounts_spec(typing_extensions.Protocol):
577
438
  def __call__(
578
- self, /, client=None, python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"], check_if_exists=True
439
+ self,
440
+ /,
441
+ client=None,
442
+ python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"],
443
+ builder_versions: list[str] = ["2025.06"],
444
+ check_if_exists=True,
445
+ dry_run=False,
579
446
  ): ...
580
447
  async def aio(
581
- self, /, client=None, python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"], check_if_exists=True
448
+ self,
449
+ /,
450
+ client=None,
451
+ python_versions: list[str] = ["3.9", "3.10", "3.11", "3.12", "3.13"],
452
+ builder_versions: list[str] = ["2025.06"],
453
+ check_if_exists=True,
454
+ dry_run=False,
582
455
  ): ...
583
456
 
584
457
  create_client_dependency_mounts: __create_client_dependency_mounts_spec
@@ -11,6 +11,7 @@ from synchronicity.async_wrap import asynccontextmanager
11
11
  import modal
12
12
  from modal_proto import api_pb2
13
13
 
14
+ from ._load_context import LoadContext
14
15
  from ._object import (
15
16
  EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
16
17
  _get_environment_name,
@@ -21,8 +22,7 @@ from ._object import (
21
22
  from ._resolver import Resolver
22
23
  from ._utils.async_utils import TaskContext, aclosing, async_map, sync_or_async_iter, synchronize_api
23
24
  from ._utils.blob_utils import LARGE_FILE_LIMIT, blob_iter, blob_upload_file
24
- from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
25
- from ._utils.grpc_utils import retry_transient_errors
25
+ from ._utils.deprecation import warn_if_passing_namespace
26
26
  from ._utils.hash_utils import get_sha256_hex
27
27
  from ._utils.name_utils import check_object_name
28
28
  from .client import _Client
@@ -55,6 +55,8 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
55
55
  By attaching this file system as a mount to one or more functions, they can
56
56
  share and persist data with each other.
57
57
 
58
+ **Note: `NetworkFileSystem` has been deprecated and will be removed.**
59
+
58
60
  **Usage**
59
61
 
60
62
  ```python
@@ -94,6 +96,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
94
96
  namespace=None, # mdmd:line-hidden
95
97
  environment_name: Optional[str] = None,
96
98
  create_if_missing: bool = False,
99
+ client: Optional[_Client] = None,
97
100
  ) -> "_NetworkFileSystem":
98
101
  """Reference a NetworkFileSystem by its name, creating if necessary.
99
102
 
@@ -112,15 +115,17 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
112
115
  check_object_name(name, "NetworkFileSystem")
113
116
  warn_if_passing_namespace(namespace, "modal.NetworkFileSystem.from_name")
114
117
 
115
- async def _load(self: _NetworkFileSystem, resolver: Resolver, existing_object_id: Optional[str]):
118
+ async def _load(
119
+ self: _NetworkFileSystem, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
120
+ ):
116
121
  req = api_pb2.SharedVolumeGetOrCreateRequest(
117
122
  deployment_name=name,
118
- environment_name=_get_environment_name(environment_name, resolver),
123
+ environment_name=load_context.environment_name,
119
124
  object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
120
125
  )
121
126
  try:
122
- response = await resolver.client.stub.SharedVolumeGetOrCreate(req)
123
- self._hydrate(response.shared_volume_id, resolver.client, None)
127
+ response = await load_context.client.stub.SharedVolumeGetOrCreate(req)
128
+ self._hydrate(response.shared_volume_id, load_context.client, None)
124
129
  except modal.exception.NotFoundError as exc:
125
130
  if exc.args[0] == "App has wrong entity vo":
126
131
  raise InvalidError(
@@ -128,7 +133,12 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
128
133
  )
129
134
  raise
130
135
 
131
- return _NetworkFileSystem._from_loader(_load, "NetworkFileSystem()", hydrate_lazily=True)
136
+ return _NetworkFileSystem._from_loader(
137
+ _load,
138
+ "NetworkFileSystem()",
139
+ hydrate_lazily=True,
140
+ load_context_overrides=LoadContext(environment_name=environment_name, client=client),
141
+ )
132
142
 
133
143
  @classmethod
134
144
  @asynccontextmanager
@@ -136,7 +146,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
136
146
  cls: type["_NetworkFileSystem"],
137
147
  client: Optional[_Client] = None,
138
148
  environment_name: Optional[str] = None,
139
- _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
149
+ _heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, # mdmd:line-hidden
140
150
  ) -> AsyncIterator["_NetworkFileSystem"]:
141
151
  """Creates a new ephemeral network filesystem within a context manager:
142
152
 
@@ -161,46 +171,13 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
161
171
  async with TaskContext() as tc:
162
172
  request = api_pb2.SharedVolumeHeartbeatRequest(shared_volume_id=response.shared_volume_id)
163
173
  tc.infinite_loop(lambda: client.stub.SharedVolumeHeartbeat(request), sleep=_heartbeat_sleep)
164
- yield cls._new_hydrated(response.shared_volume_id, client, None, is_another_app=True)
165
-
166
- @staticmethod
167
- async def lookup(
168
- name: str,
169
- namespace=None, # mdmd:line-hidden
170
- client: Optional[_Client] = None,
171
- environment_name: Optional[str] = None,
172
- create_if_missing: bool = False,
173
- ) -> "_NetworkFileSystem":
174
- """mdmd:hidden
175
- Lookup a named NetworkFileSystem.
176
-
177
- DEPRECATED: This method is deprecated in favor of `modal.NetworkFileSystem.from_name`.
178
-
179
- In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
180
- that will hydrate the local object with metadata from Modal servers.
181
-
182
- ```python notest
183
- nfs = modal.NetworkFileSystem.lookup("my-nfs")
184
- print(nfs.listdir("/"))
185
- ```
186
- """
187
- deprecation_warning(
188
- (2025, 1, 27),
189
- "`modal.NetworkFileSystem.lookup` is deprecated and will be removed in a future release."
190
- " It can be replaced with `modal.NetworkFileSystem.from_name`."
191
- "\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
192
- )
193
- warn_if_passing_namespace(namespace, "modal.NetworkFileSystem.lookup")
194
- obj = _NetworkFileSystem.from_name(
195
- name,
196
- environment_name=environment_name,
197
- create_if_missing=create_if_missing,
198
- )
199
- if client is None:
200
- client = await _Client.from_env()
201
- resolver = Resolver(client=client)
202
- await resolver.load(obj)
203
- return obj
174
+ yield cls._new_hydrated(
175
+ response.shared_volume_id,
176
+ client,
177
+ None,
178
+ is_another_app=True,
179
+ rep="modal.NetworkFileSystem.ephemeral()",
180
+ )
204
181
 
205
182
  @staticmethod
206
183
  async def create_deployed(
@@ -219,14 +196,14 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
219
196
  environment_name=_get_environment_name(environment_name),
220
197
  object_creation_type=api_pb2.OBJECT_CREATION_TYPE_CREATE_FAIL_IF_EXISTS,
221
198
  )
222
- resp = await retry_transient_errors(client.stub.SharedVolumeGetOrCreate, request)
199
+ resp = await client.stub.SharedVolumeGetOrCreate(request)
223
200
  return resp.shared_volume_id
224
201
 
225
202
  @staticmethod
226
203
  async def delete(name: str, client: Optional[_Client] = None, environment_name: Optional[str] = None):
227
204
  obj = await _NetworkFileSystem.from_name(name, environment_name=environment_name).hydrate(client)
228
205
  req = api_pb2.SharedVolumeDeleteRequest(shared_volume_id=obj.object_id)
229
- await retry_transient_errors(obj._client.stub.SharedVolumeDelete, req)
206
+ await obj._client.stub.SharedVolumeDelete(req)
230
207
 
231
208
  @live_method
232
209
  async def write_file(self, remote_path: str, fp: BinaryIO, progress_cb: Optional[Callable[..., Any]] = None) -> int:
@@ -266,7 +243,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
266
243
 
267
244
  t0 = time.monotonic()
268
245
  while time.monotonic() - t0 < NETWORK_FILE_SYSTEM_PUT_FILE_CLIENT_TIMEOUT:
269
- response = await retry_transient_errors(self._client.stub.SharedVolumePutFile, req)
246
+ response = await self._client.stub.SharedVolumePutFile(req)
270
247
  if response.exists:
271
248
  break
272
249
  else:
@@ -279,7 +256,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
279
256
  """Read a file from the network file system"""
280
257
  req = api_pb2.SharedVolumeGetFileRequest(shared_volume_id=self.object_id, path=path)
281
258
  try:
282
- response = await retry_transient_errors(self._client.stub.SharedVolumeGetFile, req)
259
+ response = await self._client.stub.SharedVolumeGetFile(req)
283
260
  except modal.exception.NotFoundError as exc:
284
261
  raise FileNotFoundError(exc.args[0])
285
262
 
@@ -364,7 +341,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
364
341
  """Remove a file in a network file system."""
365
342
  req = api_pb2.SharedVolumeRemoveFileRequest(shared_volume_id=self.object_id, path=path, recursive=recursive)
366
343
  try:
367
- await retry_transient_errors(self._client.stub.SharedVolumeRemoveFile, req)
344
+ await self._client.stub.SharedVolumeRemoveFile(req)
368
345
  except modal.exception.NotFoundError as exc:
369
346
  raise FileNotFoundError(exc.args[0])
370
347
 
@@ -19,6 +19,8 @@ class _NetworkFileSystem(modal._object._Object):
19
19
  By attaching this file system as a mount to one or more functions, they can
20
20
  share and persist data with each other.
21
21
 
22
+ **Note: `NetworkFileSystem` has been deprecated and will be removed.**
23
+
22
24
  **Usage**
23
25
 
24
26
  ```python
@@ -52,7 +54,12 @@ class _NetworkFileSystem(modal._object._Object):
52
54
  """
53
55
  @staticmethod
54
56
  def from_name(
55
- name: str, *, namespace=None, environment_name: typing.Optional[str] = None, create_if_missing: bool = False
57
+ name: str,
58
+ *,
59
+ namespace=None,
60
+ environment_name: typing.Optional[str] = None,
61
+ create_if_missing: bool = False,
62
+ client: typing.Optional[modal.client._Client] = None,
56
63
  ) -> _NetworkFileSystem:
57
64
  """Reference a NetworkFileSystem by its name, creating if necessary.
58
65
 
@@ -92,29 +99,6 @@ class _NetworkFileSystem(modal._object._Object):
92
99
  """
93
100
  ...
94
101
 
95
- @staticmethod
96
- async def lookup(
97
- name: str,
98
- namespace=None,
99
- client: typing.Optional[modal.client._Client] = None,
100
- environment_name: typing.Optional[str] = None,
101
- create_if_missing: bool = False,
102
- ) -> _NetworkFileSystem:
103
- """mdmd:hidden
104
- Lookup a named NetworkFileSystem.
105
-
106
- DEPRECATED: This method is deprecated in favor of `modal.NetworkFileSystem.from_name`.
107
-
108
- In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
109
- that will hydrate the local object with metadata from Modal servers.
110
-
111
- ```python notest
112
- nfs = modal.NetworkFileSystem.lookup("my-nfs")
113
- print(nfs.listdir("/"))
114
- ```
115
- """
116
- ...
117
-
118
102
  @staticmethod
119
103
  async def create_deployed(
120
104
  deployment_name: str,
@@ -192,6 +176,8 @@ class NetworkFileSystem(modal.object.Object):
192
176
  By attaching this file system as a mount to one or more functions, they can
193
177
  share and persist data with each other.
194
178
 
179
+ **Note: `NetworkFileSystem` has been deprecated and will be removed.**
180
+
195
181
  **Usage**
196
182
 
197
183
  ```python
@@ -229,7 +215,12 @@ class NetworkFileSystem(modal.object.Object):
229
215
 
230
216
  @staticmethod
231
217
  def from_name(
232
- name: str, *, namespace=None, environment_name: typing.Optional[str] = None, create_if_missing: bool = False
218
+ name: str,
219
+ *,
220
+ namespace=None,
221
+ environment_name: typing.Optional[str] = None,
222
+ create_if_missing: bool = False,
223
+ client: typing.Optional[modal.client.Client] = None,
233
224
  ) -> NetworkFileSystem:
234
225
  """Reference a NetworkFileSystem by its name, creating if necessary.
235
226
 
@@ -269,57 +260,6 @@ class NetworkFileSystem(modal.object.Object):
269
260
  """
270
261
  ...
271
262
 
272
- class __lookup_spec(typing_extensions.Protocol):
273
- def __call__(
274
- self,
275
- /,
276
- name: str,
277
- namespace=None,
278
- client: typing.Optional[modal.client.Client] = None,
279
- environment_name: typing.Optional[str] = None,
280
- create_if_missing: bool = False,
281
- ) -> NetworkFileSystem:
282
- """mdmd:hidden
283
- Lookup a named NetworkFileSystem.
284
-
285
- DEPRECATED: This method is deprecated in favor of `modal.NetworkFileSystem.from_name`.
286
-
287
- In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
288
- that will hydrate the local object with metadata from Modal servers.
289
-
290
- ```python notest
291
- nfs = modal.NetworkFileSystem.lookup("my-nfs")
292
- print(nfs.listdir("/"))
293
- ```
294
- """
295
- ...
296
-
297
- async def aio(
298
- self,
299
- /,
300
- name: str,
301
- namespace=None,
302
- client: typing.Optional[modal.client.Client] = None,
303
- environment_name: typing.Optional[str] = None,
304
- create_if_missing: bool = False,
305
- ) -> NetworkFileSystem:
306
- """mdmd:hidden
307
- Lookup a named NetworkFileSystem.
308
-
309
- DEPRECATED: This method is deprecated in favor of `modal.NetworkFileSystem.from_name`.
310
-
311
- In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
312
- that will hydrate the local object with metadata from Modal servers.
313
-
314
- ```python notest
315
- nfs = modal.NetworkFileSystem.lookup("my-nfs")
316
- print(nfs.listdir("/"))
317
- ```
318
- """
319
- ...
320
-
321
- lookup: __lookup_spec
322
-
323
263
  class __create_deployed_spec(typing_extensions.Protocol):
324
264
  def __call__(
325
265
  self,