modal 0.72.2__py3-none-any.whl → 0.72.4__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.
@@ -326,11 +326,11 @@ class FunctionInfo:
326
326
  # make sure the function's own entrypoint is included:
327
327
  if self._type == FunctionInfoType.PACKAGE:
328
328
  if config.get("automount"):
329
- return [_Mount.from_local_python_packages(self.module_name)]
329
+ return [_Mount._from_local_python_packages(self.module_name)]
330
330
  elif not self.is_serialized():
331
331
  # mount only relevant file and __init__.py:s
332
332
  return [
333
- _Mount.from_local_dir(
333
+ _Mount._from_local_dir(
334
334
  self._base_dir,
335
335
  remote_path=self._remote_dir,
336
336
  recursive=True,
@@ -341,7 +341,7 @@ class FunctionInfo:
341
341
  remote_path = ROOT_DIR / Path(self._file).name
342
342
  if not _is_modal_path(remote_path):
343
343
  return [
344
- _Mount.from_local_file(
344
+ _Mount._from_local_file(
345
345
  self._file,
346
346
  remote_path=remote_path,
347
347
  )
modal/app.py CHANGED
@@ -200,10 +200,9 @@ class _App:
200
200
 
201
201
  ```python notest
202
202
  image = modal.Image.debian_slim().pip_install(...)
203
- mount = modal.Mount.from_local_dir("./config")
204
203
  secret = modal.Secret.from_name("my-secret")
205
204
  volume = modal.Volume.from_name("my-data")
206
- app = modal.App(image=image, mounts=[mount], secrets=[secret], volumes={"/mnt/data": volume})
205
+ app = modal.App(image=image, secrets=[secret], volumes={"/mnt/data": volume})
207
206
  ```
208
207
  """
209
208
  if name is not None and not isinstance(name, str):
modal/cli/launch.py CHANGED
@@ -55,7 +55,7 @@ def jupyter(
55
55
  timeout: int = 3600,
56
56
  image: str = "ubuntu:22.04",
57
57
  add_python: Optional[str] = "3.11",
58
- mount: Optional[str] = None, # Create a `modal.Mount` from a local directory.
58
+ mount: Optional[str] = None, # Adds a local directory to the jupyter container
59
59
  volume: Optional[str] = None, # Attach a persisted `modal.Volume` by name (creating if missing).
60
60
  detach: bool = False, # Run the app in "detached" mode to persist after local client disconnects
61
61
  ):
@@ -10,25 +10,20 @@ import time
10
10
  import webbrowser
11
11
  from typing import Any
12
12
 
13
- from modal import App, Image, Mount, Queue, Secret, Volume, forward
13
+ from modal import App, Image, Queue, Secret, Volume, forward
14
14
 
15
15
  # Passed by `modal launch` locally via CLI, plumbed to remote runner through secrets.
16
16
  args: dict[str, Any] = json.loads(os.environ.get("MODAL_LAUNCH_ARGS", "{}"))
17
17
 
18
-
19
18
  app = App()
20
- app.image = Image.from_registry(args.get("image"), add_python=args.get("add_python")).pip_install("jupyterlab")
21
19
 
20
+ image = Image.from_registry(args.get("image"), add_python=args.get("add_python")).pip_install("jupyterlab")
22
21
 
23
- mount = (
24
- Mount.from_local_dir(
22
+ if args.get("mount"):
23
+ image = image.add_local_dir(
25
24
  args.get("mount"),
26
25
  remote_path="/root/lab/mount",
27
26
  )
28
- if args.get("mount")
29
- else None
30
- )
31
- mounts = [mount] if mount else []
32
27
 
33
28
  volume = (
34
29
  Volume.from_name(
@@ -55,12 +50,12 @@ def wait_for_port(url: str, q: Queue):
55
50
 
56
51
 
57
52
  @app.function(
53
+ image=image,
58
54
  cpu=args.get("cpu"),
59
55
  memory=args.get("memory"),
60
56
  gpu=args.get("gpu"),
61
57
  timeout=args.get("timeout"),
62
58
  secrets=[Secret.from_dict({"MODAL_LAUNCH_ARGS": json.dumps(args)})],
63
- mounts=mounts,
64
59
  volumes=volumes,
65
60
  concurrency_limit=1 if volume else None,
66
61
  )
@@ -10,7 +10,7 @@ import time
10
10
  import webbrowser
11
11
  from typing import Any
12
12
 
13
- from modal import App, Image, Mount, Queue, Secret, Volume, forward
13
+ from modal import App, Image, Queue, Secret, Volume, forward
14
14
 
15
15
  # Passed by `modal launch` locally via CLI, plumbed to remote runner through secrets.
16
16
  args: dict[str, Any] = json.loads(os.environ.get("MODAL_LAUNCH_ARGS", "{}"))
@@ -23,7 +23,7 @@ FIXUD_INSTALLER = "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fi
23
23
 
24
24
 
25
25
  app = App()
26
- app.image = (
26
+ image = (
27
27
  Image.from_registry(args.get("image"), add_python="3.11")
28
28
  .apt_install("curl", "dumb-init", "git", "git-lfs")
29
29
  .run_commands(
@@ -44,16 +44,11 @@ app.image = (
44
44
  .env({"ENTRYPOINTD": ""})
45
45
  )
46
46
 
47
-
48
- mount = (
49
- Mount.from_local_dir(
47
+ if args.get("mount"):
48
+ image = image.add_local_dir(
50
49
  args.get("mount"),
51
50
  remote_path="/home/coder/mount",
52
51
  )
53
- if args.get("mount")
54
- else None
55
- )
56
- mounts = [mount] if mount else []
57
52
 
58
53
  volume = (
59
54
  Volume.from_name(
@@ -80,12 +75,12 @@ def wait_for_port(data: tuple[str, str], q: Queue):
80
75
 
81
76
 
82
77
  @app.function(
78
+ image=image,
83
79
  cpu=args.get("cpu"),
84
80
  memory=args.get("memory"),
85
81
  gpu=args.get("gpu"),
86
82
  timeout=args.get("timeout"),
87
83
  secrets=[Secret.from_dict({"MODAL_LAUNCH_ARGS": json.dumps(args)})],
88
- mounts=mounts,
89
84
  volumes=volumes,
90
85
  concurrency_limit=1 if volume else None,
91
86
  )
modal/client.pyi CHANGED
@@ -26,7 +26,7 @@ class _Client:
26
26
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
27
27
 
28
28
  def __init__(
29
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.2"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.4"
30
30
  ): ...
31
31
  def is_closed(self) -> bool: ...
32
32
  @property
@@ -81,7 +81,7 @@ class Client:
81
81
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
82
82
 
83
83
  def __init__(
84
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.2"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.4"
85
85
  ): ...
86
86
  def is_closed(self) -> bool: ...
87
87
  @property
modal/functions.pyi CHANGED
@@ -462,11 +462,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
462
462
 
463
463
  _call_generator_nowait: ___call_generator_nowait_spec
464
464
 
465
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
465
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
466
466
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
467
467
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
468
468
 
469
- remote: __remote_spec[ReturnType, P]
469
+ remote: __remote_spec[P, ReturnType]
470
470
 
471
471
  class __remote_gen_spec(typing_extensions.Protocol):
472
472
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -479,17 +479,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
479
479
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
480
480
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
481
481
 
482
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
482
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
483
483
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
484
484
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
485
485
 
486
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
486
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
487
487
 
488
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
488
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
489
489
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
490
490
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
491
491
 
492
- spawn: __spawn_spec[ReturnType, P]
492
+ spawn: __spawn_spec[P, ReturnType]
493
493
 
494
494
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
495
495
 
modal/image.py CHANGED
@@ -707,7 +707,7 @@ class _Image(_Object, type_prefix="im"):
707
707
  if remote_path.endswith("/"):
708
708
  remote_path = remote_path + Path(local_path).name
709
709
 
710
- mount = _Mount.from_local_file(local_path, remote_path)
710
+ mount = _Mount._from_local_file(local_path, remote_path)
711
711
  return self._add_mount_layer_or_copy(mount, copy=copy)
712
712
 
713
713
  def add_local_dir(
@@ -795,7 +795,7 @@ class _Image(_Object, type_prefix="im"):
795
795
  return _Image._from_args(
796
796
  base_images={"base": self},
797
797
  dockerfile_function=build_dockerfile,
798
- context_mount_function=lambda: _Mount.from_local_file(local_path, remote_path=f"/{basename}"),
798
+ context_mount_function=lambda: _Mount._from_local_file(local_path, remote_path=f"/{basename}"),
799
799
  )
800
800
 
801
801
  def add_local_python_source(
@@ -833,7 +833,7 @@ class _Image(_Object, type_prefix="im"):
833
833
  )
834
834
  ```
835
835
  """
836
- mount = _Mount.from_local_python_packages(*modules, ignore=ignore)
836
+ mount = _Mount._from_local_python_packages(*modules, ignore=ignore)
837
837
  return self._add_mount_layer_or_copy(mount, copy=copy)
838
838
 
839
839
  def copy_local_dir(
modal/mount.py CHANGED
@@ -23,7 +23,7 @@ from modal_version import __version__
23
23
  from ._resolver import Resolver
24
24
  from ._utils.async_utils import aclosing, async_map, synchronize_api
25
25
  from ._utils.blob_utils import FileUploadSpec, blob_upload_file, get_file_upload_spec_from_path
26
- from ._utils.deprecation import renamed_parameter
26
+ from ._utils.deprecation import deprecation_warning, renamed_parameter
27
27
  from ._utils.grpc_utils import retry_transient_errors
28
28
  from ._utils.name_utils import check_object_name
29
29
  from ._utils.package_utils import get_module_mount_info
@@ -48,6 +48,11 @@ PYTHON_STANDALONE_VERSIONS: dict[str, tuple[str, str]] = {
48
48
  "3.13": ("20241008", "3.13.0"),
49
49
  }
50
50
 
51
+ MOUNT_DEPRECATION_MESSAGE_PATTERN = """modal.Mount usage will soon be deprecated.
52
+
53
+ Use {replacement} instead, which is functionally and performance-wise equivalent.
54
+ """
55
+
51
56
 
52
57
  def client_mount_name() -> str:
53
58
  """Get the deployed name of the client package mount."""
@@ -401,6 +406,23 @@ class _Mount(_Object, type_prefix="mo"):
401
406
  )
402
407
  ```
403
408
  """
409
+ deprecation_warning(
410
+ (2024, 1, 8), MOUNT_DEPRECATION_MESSAGE_PATTERN.format(replacement="image.add_local_dir"), pending=True
411
+ )
412
+ return _Mount._from_local_dir(local_path, remote_path=remote_path, condition=condition, recursive=recursive)
413
+
414
+ @staticmethod
415
+ def _from_local_dir(
416
+ local_path: Union[str, Path],
417
+ *,
418
+ # Where the directory is placed within in the mount
419
+ remote_path: Union[str, PurePosixPath, None] = None,
420
+ # Predicate filter function for file selection, which should accept a filepath and return `True` for inclusion.
421
+ # Defaults to including all files.
422
+ condition: Optional[Callable[[str], bool]] = None,
423
+ # add files from subdirectories as well
424
+ recursive: bool = True,
425
+ ) -> "_Mount":
404
426
  return _Mount._new().add_local_dir(
405
427
  local_path, remote_path=remote_path, condition=condition, recursive=recursive
406
428
  )
@@ -439,6 +461,13 @@ class _Mount(_Object, type_prefix="mo"):
439
461
  )
440
462
  ```
441
463
  """
464
+ deprecation_warning(
465
+ (2024, 1, 8), MOUNT_DEPRECATION_MESSAGE_PATTERN.format(replacement="image.add_local_file"), pending=True
466
+ )
467
+ return _Mount._from_local_file(local_path, remote_path)
468
+
469
+ @staticmethod
470
+ def _from_local_file(local_path: Union[str, Path], remote_path: Union[str, PurePosixPath, None] = None) -> "_Mount":
442
471
  return _Mount._new().add_local_file(local_path, remote_path=remote_path)
443
472
 
444
473
  @staticmethod
@@ -601,7 +630,24 @@ class _Mount(_Object, type_prefix="mo"):
601
630
  my_local_module.do_stuff()
602
631
  ```
603
632
  """
633
+ deprecation_warning(
634
+ (2024, 1, 8),
635
+ MOUNT_DEPRECATION_MESSAGE_PATTERN.format(replacement="image.add_local_python_source"),
636
+ pending=True,
637
+ )
638
+ return _Mount._from_local_python_packages(
639
+ *module_names, remote_dir=remote_dir, condition=condition, ignore=ignore
640
+ )
604
641
 
642
+ @staticmethod
643
+ def _from_local_python_packages(
644
+ *module_names: str,
645
+ remote_dir: Union[str, PurePosixPath] = ROOT_DIR.as_posix(),
646
+ # Predicate filter function for file selection, which should accept a filepath and return `True` for inclusion.
647
+ # Defaults to including all files.
648
+ condition: Optional[Callable[[str], bool]] = None,
649
+ ignore: Optional[Union[Sequence[str], Callable[[Path], bool]]] = None,
650
+ ) -> "_Mount":
605
651
  # Don't re-run inside container.
606
652
 
607
653
  if condition is not None:
@@ -786,7 +832,7 @@ def get_auto_mounts() -> list[_Mount]:
786
832
 
787
833
  try:
788
834
  # at this point we don't know if the sys.modules module should be mounted or not
789
- potential_mount = _Mount.from_local_python_packages(module_name)
835
+ potential_mount = _Mount._from_local_python_packages(module_name)
790
836
  mount_paths = potential_mount._top_level_paths()
791
837
  except ModuleNotMountable:
792
838
  # this typically happens if the module is a built-in, has binary components or doesn't exist
modal/mount.pyi CHANGED
@@ -113,6 +113,14 @@ class _Mount(modal.object._Object):
113
113
  condition: typing.Optional[typing.Callable[[str], bool]] = None,
114
114
  recursive: bool = True,
115
115
  ) -> _Mount: ...
116
+ @staticmethod
117
+ def _from_local_dir(
118
+ local_path: typing.Union[str, pathlib.Path],
119
+ *,
120
+ remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None,
121
+ condition: typing.Optional[typing.Callable[[str], bool]] = None,
122
+ recursive: bool = True,
123
+ ) -> _Mount: ...
116
124
  def add_local_file(
117
125
  self,
118
126
  local_path: typing.Union[str, pathlib.Path],
@@ -123,6 +131,10 @@ class _Mount(modal.object._Object):
123
131
  local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
124
132
  ) -> _Mount: ...
125
133
  @staticmethod
134
+ def _from_local_file(
135
+ local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
136
+ ) -> _Mount: ...
137
+ @staticmethod
126
138
  def _description(entries: list[_MountEntry]) -> str: ...
127
139
  @staticmethod
128
140
  def _get_files(
@@ -139,6 +151,13 @@ class _Mount(modal.object._Object):
139
151
  ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool], None] = None,
140
152
  ) -> _Mount: ...
141
153
  @staticmethod
154
+ def _from_local_python_packages(
155
+ *module_names: str,
156
+ remote_dir: typing.Union[str, pathlib.PurePosixPath] = "/root",
157
+ condition: typing.Optional[typing.Callable[[str], bool]] = None,
158
+ ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool], None] = None,
159
+ ) -> _Mount: ...
160
+ @staticmethod
142
161
  def from_name(name: str, namespace=1, environment_name: typing.Optional[str] = None) -> _Mount: ...
143
162
  @classmethod
144
163
  async def lookup(
@@ -195,6 +214,14 @@ class Mount(modal.object.Object):
195
214
  condition: typing.Optional[typing.Callable[[str], bool]] = None,
196
215
  recursive: bool = True,
197
216
  ) -> Mount: ...
217
+ @staticmethod
218
+ def _from_local_dir(
219
+ local_path: typing.Union[str, pathlib.Path],
220
+ *,
221
+ remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None,
222
+ condition: typing.Optional[typing.Callable[[str], bool]] = None,
223
+ recursive: bool = True,
224
+ ) -> Mount: ...
198
225
  def add_local_file(
199
226
  self,
200
227
  local_path: typing.Union[str, pathlib.Path],
@@ -205,6 +232,10 @@ class Mount(modal.object.Object):
205
232
  local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
206
233
  ) -> Mount: ...
207
234
  @staticmethod
235
+ def _from_local_file(
236
+ local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.PurePosixPath, None] = None
237
+ ) -> Mount: ...
238
+ @staticmethod
208
239
  def _description(entries: list[_MountEntry]) -> str: ...
209
240
 
210
241
  class ___get_files_spec(typing_extensions.Protocol):
@@ -231,6 +262,13 @@ class Mount(modal.object.Object):
231
262
  ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool], None] = None,
232
263
  ) -> Mount: ...
233
264
  @staticmethod
265
+ def _from_local_python_packages(
266
+ *module_names: str,
267
+ remote_dir: typing.Union[str, pathlib.PurePosixPath] = "/root",
268
+ condition: typing.Optional[typing.Callable[[str], bool]] = None,
269
+ ignore: typing.Union[typing.Sequence[str], typing.Callable[[pathlib.Path], bool], None] = None,
270
+ ) -> Mount: ...
271
+ @staticmethod
234
272
  def from_name(name: str, namespace=1, environment_name: typing.Optional[str] = None) -> Mount: ...
235
273
  @classmethod
236
274
  def lookup(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.72.2
3
+ Version: 0.72.4
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -15,11 +15,11 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
15
15
  modal/_tunnel.py,sha256=o-jJhS4vQ6-XswDhHcJWGMZZmD03SC0e9i8fEu1JTjo,6310
16
16
  modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
17
17
  modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
18
- modal/app.py,sha256=vEE0cK5QPF6_cdW5AJvcuWxz5KmeprHwBEtlDkVRHgE,45582
18
+ modal/app.py,sha256=1h8v96KuIg_SAdWDK9gNWVOYYFciBIerhldRPjvDgxs,45511
19
19
  modal/app.pyi,sha256=Gx7gxjfQ70sxhbwfpx1VjvzEON-ZEMTJ_Vy8qt0oQvo,25302
20
20
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
21
21
  modal/client.py,sha256=JAnd4-GCN093BwkvOFAK5a6iy5ycxofjpUncMxlrIMw,15253
22
- modal/client.pyi,sha256=rOlKRk1iCM3hIsk99foS4WdAwfKabZBNrLnovewTEFs,7278
22
+ modal/client.pyi,sha256=m8LzW64Ywdd96wK4kywyhj6vPrPCR-JrddgqlGvckRQ,7278
23
23
  modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
24
24
  modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
25
25
  modal/cls.py,sha256=3hjb0JcoPjxKZNeK22f5rR43bZRBjoRI7_EMZXY7YrE,31172
@@ -37,14 +37,14 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
37
37
  modal/file_io.pyi,sha256=NrIoB0YjIqZ8MDMe826xAnybT0ww_kxQM3iPLo82REU,8898
38
38
  modal/file_pattern_matcher.py,sha256=uksEpQG4LSNdW57NQVqP9oOWPpD2-c9QVaAN_dmzKIQ,6415
39
39
  modal/functions.py,sha256=3uJPbrEAWhpFfLfUnoRjGmvEUC-_wVh-8yNJBx8eVeM,68249
40
- modal/functions.pyi,sha256=3ESJ61f8oEDycDmrpnuNB2vjFKuLBG_aqyliXPTdY7M,25407
40
+ modal/functions.pyi,sha256=LiSDgH-X7jcZ56pAoLMwo3x9Dzdp_3Sd7W5MVAJPoCg,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
42
- modal/image.py,sha256=Np2nccyZjqbez5PSpVSSQzgKN77MuTuwIQQZ4AQfQa4,89799
42
+ modal/image.py,sha256=_ALAfk8YEiWnv_pHSnixBPoR88RGSDstsAUvlJa1nKc,89802
43
43
  modal/image.pyi,sha256=NfZyLkl4rmxpc5fokaO4mmEeGFOwGn0AndV1vKwBdbs,26027
44
44
  modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
45
45
  modal/io_streams.pyi,sha256=bCCVSxkMcosYd8O3PQDDwJw7TQ8JEcnYonLJ5t27TQs,4804
46
- modal/mount.py,sha256=wOr-2vmKImsE3lHBII8hL2gYy5ng46R58QwId4JultQ,29313
47
- modal/mount.pyi,sha256=FiNV1wIKFvd0ZMZ0tm1mz6ZSA5Hjsge-kFSA5tPWfcI,10503
46
+ modal/mount.py,sha256=nGimxizRzCpyZu9cpTdKQRgU9uqMnl3xBrTRR_rD6fE,31480
47
+ modal/mount.pyi,sha256=mcKMYwt8dX3oO8OzzKqCdh7K2EhMhWIHEPoJwzi1rl8,12194
48
48
  modal/network_file_system.py,sha256=INj1TfN_Fsmabmlte7anvey1epodjbMmjBW_TIJSST4,14406
49
49
  modal/network_file_system.pyi,sha256=61M-sdWrtaRjmuNVsvusI6kf1Qw-jUOVXvEAeOkM8Aw,7751
50
50
  modal/object.py,sha256=HZs3N59C6JxlMuPQWJYvrWV1FEEkH9txUovVDorVUbs,9763
@@ -89,7 +89,7 @@ modal/_utils/blob_utils.py,sha256=N66LtZI8PpCkZ7maA7GLW5CAmYUoNJdG-GjaAUR4_NQ,14
89
89
  modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
90
90
  modal/_utils/deprecation.py,sha256=dycySRBxyZf3ITzEqPNM6MxXTk9-0VVLA8oCPQ5j_Os,3426
91
91
  modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
92
- modal/_utils/function_utils.py,sha256=q68HhFH16MwhHRnGD8jvIgqDjduRQVp3a_qMWXPyrgU,25518
92
+ modal/_utils/function_utils.py,sha256=VFz3RdQc0yOKRmw5u5gkZCRzkJNqm9WoQAKg9CeUnJo,25521
93
93
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
94
94
  modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
95
95
  modal/_utils/hash_utils.py,sha256=zg3J6OGxTFGSFri1qQ12giDz90lWk8bzaxCTUCRtiX4,3034
@@ -115,7 +115,7 @@ modal/cli/dict.py,sha256=HaEcjfll7i3Uj3Fg56aj4407if5UljsYfr6fIq-D2W8,4589
115
115
  modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
116
116
  modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
117
117
  modal/cli/import_refs.py,sha256=wnqE5AMeyAN3IZmQvJCp54KRnJh8Nq_5fMqB6u6GEL8,9147
118
- modal/cli/launch.py,sha256=44oOlGB0KYDBMfuIlkhW2uzjkWbHhDRR64UOEnGwsJ4,2989
118
+ modal/cli/launch.py,sha256=t1XsExzTWip4n9Cqa-Jhzj65P6bVHO0je2d76JQRi_w,2990
119
119
  modal/cli/network_file_system.py,sha256=o6VLTgN4xn5XUiNPBfxYec-5uWCgYrDmfFFLM1ZW_eE,8180
120
120
  modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
121
121
  modal/cli/queues.py,sha256=MIh2OsliNE2QeL1erubfsRsNuG4fxqcqWA2vgIfQ4Mg,4494
@@ -125,8 +125,8 @@ modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
125
125
  modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
126
126
  modal/cli/volume.py,sha256=Jrm-1R9u92JbbUM62bkB9RzAM_jO8wi7T2-i6Cb2XG0,10568
127
127
  modal/cli/programs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
128
- modal/cli/programs/run_jupyter.py,sha256=RRr07CqZrStMbLdBM3PpzU6KM8t9FtLbdIPthg2-Mpw,2755
129
- modal/cli/programs/vscode.py,sha256=m80wuQyTALTc7y-kAVqmMjtrcb6muCtpuhxsJm4Va2Y,3453
128
+ modal/cli/programs/run_jupyter.py,sha256=KNaxG4LixbBJdLOzwKZB5IMA6tO1CSjHMKY6SpaIXd0,2685
129
+ modal/cli/programs/vscode.py,sha256=0k65NdAvRL3WGtngEYt-3w_kn9x2y3PqzA-dqdaVHtw,3383
130
130
  modal/extensions/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
131
131
  modal/extensions/ipython.py,sha256=Xvzy-A7cvwMSDa9p4c4CEMLOX2_Xsg9DkM1J9uyu7jc,983
132
132
  modal/requirements/2023.12.312.txt,sha256=zWWUVgVQ92GXBKNYYr2-5vn9rlnXcmkqlwlX5u1eTYw,400
@@ -146,7 +146,7 @@ modal_global_objects/images/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
146
146
  modal_global_objects/images/base_images.py,sha256=tFc7tzQRJHtq23kURd6DTrnnO4Yp5ujr34WdJOM5ubI,775
147
147
  modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
148
148
  modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
149
- modal_global_objects/mounts/python_standalone.py,sha256=SL_riIxpd8mP4i4CLDCWiFFNj0Ltknm9c_UIGfX5d60,1836
149
+ modal_global_objects/mounts/python_standalone.py,sha256=pEML5GaV2_0ahci_1vpfc_FnySpsfi2fhYmFF5I7IiQ,1837
150
150
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
151
151
  modal_proto/api.proto,sha256=1hO6_dn7DwgFra9TQSAXBt1NV4ETiiURPHe09bodinc,80368
152
152
  modal_proto/api_grpc.py,sha256=VakjV_Ge3fgZDRJN6EeG2yY_LMkZvn6yVXr5SnFKIDA,103542
@@ -165,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
165
165
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
166
  modal_version/__init__.py,sha256=kGya2ZlItX2zB7oHORs-wvP4PG8lg_mtbi1QIK3G6SQ,470
167
167
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
168
- modal_version/_version_generated.py,sha256=rRmweluGooHhgGfqaFtJmtdG0NIoYaqz450u2-_vYec,148
169
- modal-0.72.2.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
- modal-0.72.2.dist-info/METADATA,sha256=0mGM7aP6YvrTTKTPBqlZGCw_3KOk8sVtb_prOJW-pqs,2328
171
- modal-0.72.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
- modal-0.72.2.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
- modal-0.72.2.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
- modal-0.72.2.dist-info/RECORD,,
168
+ modal_version/_version_generated.py,sha256=f4e7qyTZCPpyCUarmH2KNELfulika6S1oKpZUAreFj4,148
169
+ modal-0.72.4.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
+ modal-0.72.4.dist-info/METADATA,sha256=DiP1je0a_ziUpy36xipRnOuhvD31C733phKRFsZbD3I,2328
171
+ modal-0.72.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
+ modal-0.72.4.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
+ modal-0.72.4.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
+ modal-0.72.4.dist-info/RECORD,,
@@ -34,7 +34,7 @@ def publish_python_standalone_mount(client, version: str) -> None:
34
34
  urllib.request.urlretrieve(url, f"{d}/cpython.tar.gz")
35
35
  shutil.unpack_archive(f"{d}/cpython.tar.gz", d)
36
36
  print(f"🌐 Downloaded and unpacked archive to {d}.")
37
- python_mount = Mount.from_local_dir(f"{d}/python")
37
+ python_mount = Mount._from_local_dir(f"{d}/python")
38
38
  python_mount._deploy(
39
39
  mount_name,
40
40
  api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 2 # git: a32d5c8
4
+ build_number = 4 # git: 83650fa
File without changes