modal 0.66.38__py3-none-any.whl → 0.66.40__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.
modal/client.pyi CHANGED
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[typing.Tuple[str, str]],
34
- version: str = "0.66.38",
34
+ version: str = "0.66.40",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -90,7 +90,7 @@ class Client:
90
90
  server_url: str,
91
91
  client_type: int,
92
92
  credentials: typing.Optional[typing.Tuple[str, str]],
93
- version: str = "0.66.38",
93
+ version: str = "0.66.40",
94
94
  ): ...
95
95
  def is_closed(self) -> bool: ...
96
96
  @property
modal/functions.pyi CHANGED
@@ -450,11 +450,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
450
450
 
451
451
  _call_generator_nowait: ___call_generator_nowait_spec
452
452
 
453
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
453
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
454
454
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
455
455
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
456
456
 
457
- remote: __remote_spec[ReturnType, P]
457
+ remote: __remote_spec[P, ReturnType]
458
458
 
459
459
  class __remote_gen_spec(typing_extensions.Protocol):
460
460
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -466,17 +466,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
466
466
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
467
467
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
468
468
 
469
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
469
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
470
470
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
471
471
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
472
472
 
473
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
473
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
474
474
 
475
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
475
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
476
476
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
477
477
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
478
478
 
479
- spawn: __spawn_spec[ReturnType, P]
479
+ spawn: __spawn_spec[P, ReturnType]
480
480
 
481
481
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
482
482
 
modal/image.py CHANGED
@@ -344,7 +344,7 @@ class _Image(_Object, type_prefix="im"):
344
344
  "\n"
345
345
  "my_image = (\n"
346
346
  " Image.debian_slim()\n"
347
- ' .add_local_python_packages("mypak", copy=True)\n'
347
+ ' .add_local_file("data.json", copy=True)\n'
348
348
  ' .run_commands("python -m mypak") # this now works!\n'
349
349
  ")\n"
350
350
  )
@@ -601,12 +601,59 @@ class _Image(_Object, type_prefix="im"):
601
601
  context_mount=mount,
602
602
  )
603
603
 
604
+ def add_local_file(self, local_path: Union[str, Path], remote_path: str, *, copy: bool = False) -> "_Image":
605
+ """Adds a local file to the image at `remote_path` within the container
606
+
607
+ By default (`copy=False`), the files are added to containers on startup and are not built into the actual Image,
608
+ which speeds up deployment.
609
+
610
+ Set `copy=True` to copy the files into an Image layer at build time instead, similar to how
611
+ [`COPY`](https://docs.docker.com/engine/reference/builder/#copy) works in a `Dockerfile`.
612
+
613
+ copy=True can slow down iteration since it requires a rebuild of the Image and any subsequent
614
+ build steps whenever the included files change, but it is required if you want to run additional
615
+ build steps after this one.
616
+ """
617
+ if not PurePosixPath(remote_path).is_absolute():
618
+ # TODO(elias): implement relative to absolute resolution using image workdir metadata
619
+ # + make default remote_path="./"
620
+ # This requires deferring the Mount creation until after "self" (the base image) has been resolved
621
+ # so we know the workdir of the operation.
622
+ raise InvalidError("image.add_local_file() currently only supports absolute remote_path values")
623
+
624
+ if remote_path.endswith("/"):
625
+ remote_path = remote_path + Path(local_path).name
626
+
627
+ mount = _Mount.from_local_file(local_path, remote_path)
628
+ return self._add_mount_layer_or_copy(mount, copy=copy)
629
+
630
+ def add_local_dir(self, local_path: Union[str, Path], remote_path: str, *, copy: bool = False) -> "_Image":
631
+ """Adds a local directory's content to the image at `remote_path` within the container
632
+
633
+ By default (`copy=False`), the files are added to containers on startup and are not built into the actual Image,
634
+ which speeds up deployment.
635
+
636
+ Set `copy=True` to copy the files into an Image layer at build time instead, similar to how
637
+ [`COPY`](https://docs.docker.com/engine/reference/builder/#copy) works in a `Dockerfile`.
638
+
639
+ copy=True can slow down iteration since it requires a rebuild of the Image and any subsequent
640
+ build steps whenever the included files change, but it is required if you want to run additional
641
+ build steps after this one.
642
+ """
643
+ if not PurePosixPath(remote_path).is_absolute():
644
+ # TODO(elias): implement relative to absolute resolution using image workdir metadata
645
+ # + make default remote_path="./"
646
+ raise InvalidError("image.add_local_dir() currently only supports absolute remote_path values")
647
+ mount = _Mount.from_local_dir(local_path, remote_path=remote_path)
648
+ return self._add_mount_layer_or_copy(mount, copy=copy)
649
+
604
650
  def copy_local_file(self, local_path: Union[str, Path], remote_path: Union[str, Path] = "./") -> "_Image":
605
651
  """Copy a file into the image as a part of building it.
606
652
 
607
653
  This works in a similar way to [`COPY`](https://docs.docker.com/engine/reference/builder/#copy)
608
654
  works in a `Dockerfile`.
609
655
  """
656
+ # TODO(elias): add pending deprecation with suggestion to use add_* instead
610
657
  basename = str(Path(local_path).name)
611
658
  mount = _Mount.from_local_file(local_path, remote_path=f"/{basename}")
612
659
 
@@ -1637,7 +1684,7 @@ class _Image(_Object, type_prefix="im"):
1637
1684
  dockerfile_function=build_dockerfile,
1638
1685
  )
1639
1686
 
1640
- def workdir(self, path: str) -> "_Image":
1687
+ def workdir(self, path: Union[str, PurePosixPath]) -> "_Image":
1641
1688
  """Set the working directory for subsequent image build steps and function execution.
1642
1689
 
1643
1690
  **Example**
modal/image.pyi CHANGED
@@ -100,6 +100,12 @@ class _Image(modal.object._Object):
100
100
  _do_assert_no_mount_layers: bool = True,
101
101
  ) -> _Image: ...
102
102
  def copy_mount(self, mount: modal.mount._Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> _Image: ...
103
+ def add_local_file(
104
+ self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
105
+ ) -> _Image: ...
106
+ def add_local_dir(
107
+ self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
108
+ ) -> _Image: ...
103
109
  def copy_local_file(
104
110
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "./"
105
111
  ) -> _Image: ...
@@ -301,7 +307,7 @@ class _Image(modal.object._Object):
301
307
  kwargs: typing.Dict[str, typing.Any] = {},
302
308
  ) -> _Image: ...
303
309
  def env(self, vars: typing.Dict[str, str]) -> _Image: ...
304
- def workdir(self, path: str) -> _Image: ...
310
+ def workdir(self, path: typing.Union[str, pathlib.PurePosixPath]) -> _Image: ...
305
311
  def imports(self): ...
306
312
  def _logs(self) -> typing.AsyncGenerator[str, None]: ...
307
313
 
@@ -351,6 +357,12 @@ class Image(modal.object.Object):
351
357
  _do_assert_no_mount_layers: bool = True,
352
358
  ) -> Image: ...
353
359
  def copy_mount(self, mount: modal.mount.Mount, remote_path: typing.Union[str, pathlib.Path] = ".") -> Image: ...
360
+ def add_local_file(
361
+ self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
362
+ ) -> Image: ...
363
+ def add_local_dir(
364
+ self, local_path: typing.Union[str, pathlib.Path], remote_path: str, *, copy: bool = False
365
+ ) -> Image: ...
354
366
  def copy_local_file(
355
367
  self, local_path: typing.Union[str, pathlib.Path], remote_path: typing.Union[str, pathlib.Path] = "./"
356
368
  ) -> Image: ...
@@ -552,7 +564,7 @@ class Image(modal.object.Object):
552
564
  kwargs: typing.Dict[str, typing.Any] = {},
553
565
  ) -> Image: ...
554
566
  def env(self, vars: typing.Dict[str, str]) -> Image: ...
555
- def workdir(self, path: str) -> Image: ...
567
+ def workdir(self, path: typing.Union[str, pathlib.PurePosixPath]) -> Image: ...
556
568
  def imports(self): ...
557
569
 
558
570
  class ___logs_spec(typing_extensions.Protocol):
modal/mount.py CHANGED
@@ -377,7 +377,9 @@ class _Mount(_Object, type_prefix="mo"):
377
377
  )
378
378
 
379
379
  def add_local_file(
380
- self, local_path: Union[str, Path], remote_path: Union[str, PurePosixPath, None] = None
380
+ self,
381
+ local_path: Union[str, Path],
382
+ remote_path: Union[str, PurePosixPath, None] = None,
381
383
  ) -> "_Mount":
382
384
  """
383
385
  Add a local file to the `Mount` object.
@@ -622,12 +624,13 @@ class _Mount(_Object, type_prefix="mo"):
622
624
  client: Optional[_Client] = None,
623
625
  ) -> None:
624
626
  check_object_name(deployment_name, "Mount")
627
+ environment_name = _get_environment_name(environment_name, resolver=None)
625
628
  self._deployment_name = deployment_name
626
629
  self._namespace = namespace
627
630
  self._environment_name = environment_name
628
631
  if client is None:
629
632
  client = await _Client.from_env()
630
- resolver = Resolver(client=client)
633
+ resolver = Resolver(client=client, environment_name=environment_name)
631
634
  await resolver.load(self)
632
635
 
633
636
  def _get_metadata(self) -> api_pb2.MountHandleMetadata:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.66.38
3
+ Version: 0.66.40
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -19,7 +19,7 @@ modal/app.py,sha256=QEBK8qYSrux36oi3iS3msBQmcUOS1r4s2nengzzynjQ,44658
19
19
  modal/app.pyi,sha256=wHwBIDqkUb2CQzYVhxZafJ8xZ17TZ-8y-cRyOeZsEm0,25182
20
20
  modal/call_graph.py,sha256=l-Wi6vM8aosCdHTWegcCyGeVJGFdZ_fzlCmbRVPBXFI,2593
21
21
  modal/client.py,sha256=4SpWb4n0nolITR36kADZl1tYLOg6avukmzZU56UQjCo,16385
22
- modal/client.pyi,sha256=iQhwKwTaHQFIekaf_ZrlnzW0TyRikjW10HGufxHXRUU,7372
22
+ modal/client.pyi,sha256=nQYC7piOrDOz9bvrhctQ1zVwbBkLFvU8OrvJawoePVg,7372
23
23
  modal/cloud_bucket_mount.py,sha256=eWQhCtMIczpokjfTZEgNBCGO_s5ft46PqTSLfKBykq4,5748
24
24
  modal/cloud_bucket_mount.pyi,sha256=tTF7M4FR9bTA30cFkz8qq3ZTlFL19NHU_36e_5GgAGA,1424
25
25
  modal/cls.py,sha256=Ci7EtMrLm1LExfjZ9K2IXyj-SV9Syq8dAbZCEfddcmY,24234
@@ -34,13 +34,13 @@ modal/environments.pyi,sha256=oScvFAclF55-tL9UioLIL_SPBwgy_9O-BBvJ-PLbRgY,3542
34
34
  modal/exception.py,sha256=K-czk1oK8wFvK8snWrytXSByo2WNb9SJAlgBVPGWZBs,6417
35
35
  modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
36
  modal/functions.py,sha256=3iAonXDZ1OXgtUhL1LuTguNxlJi_PtGu-cBibd6Y464,71837
37
- modal/functions.pyi,sha256=opYVDolZweBVZSfgT4t7OyQj4vBJ82B72IRoS8ZpoYw,24939
37
+ modal/functions.pyi,sha256=cvEhksXdIvBkEj2U3TDeOGUYqKYCaAL8f2ryO_LUkl8,24939
38
38
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
- modal/image.py,sha256=E6UVnhOdfkMnajiSpIm0iUEyE04yclkv9Y0BO6Vplrg,76043
40
- modal/image.pyi,sha256=ZQpSN7XR16aug50sEcDE597CPssekeP1UZBtq0F1lRk,23847
39
+ modal/image.py,sha256=j-NH8pLWk4jd5UOGD4y6W7DHWoeb3rG_VR7zPLSqj-Q,78927
40
+ modal/image.pyi,sha256=QEjjnl4ZSmqt7toHww5ZbhL2Re5qaFGgH7qADcJS_vA,24493
41
41
  modal/io_streams.py,sha256=kZ5o-aK0lPg4-NezYxpCFmjS2Vf_TbWn49S7c2xUQ6U,14255
42
42
  modal/io_streams.pyi,sha256=pn6UnOjCUjQwukPYiHHdCv92CH9S9YRb_WekKGoPN94,4350
43
- modal/mount.py,sha256=kWEz3yFdoVa0XFp3SA9HfaH7kSO7K_mMNHnm_e3tbDo,27616
43
+ modal/mount.py,sha256=QZ4nabpbNU9tjLIPCq86rlHor9CXzADMkhJWBYfKKgg,27750
44
44
  modal/mount.pyi,sha256=nywUmeUELLY2OEnAc1NNBHmSxuEylTWBzkh6nuXkkuc,9965
45
45
  modal/network_file_system.py,sha256=P_LsILecyda1SRHU76Hk4Lq3M1HSx9shFJbaLThzw0U,14071
46
46
  modal/network_file_system.pyi,sha256=XLyUnDx55ExbJcF_xlKxRax_r06XTvSsQh-a-_EyCOU,7239
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
159
159
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  modal_version/__init__.py,sha256=UnAuHBPuPSstqgdCOx0SBVdfhpeJnMlY_oxEbu44Izg,470
161
161
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=Q70mLVGe_VS_Wtwjm-d4I4LQ-xoTvVWPpVCykcWgZqE,149
163
- modal-0.66.38.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.66.38.dist-info/METADATA,sha256=hxpCQwsIaYXC0rGhW5dR8OejvKiHdhKVqI4HnhE3kEY,2329
165
- modal-0.66.38.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.66.38.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.66.38.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.66.38.dist-info/RECORD,,
162
+ modal_version/_version_generated.py,sha256=ElOQmpS8QZM2SCf0Vwf4RdYuXXfYg6JuasM2nrHNEzg,149
163
+ modal-0.66.40.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
+ modal-0.66.40.dist-info/METADATA,sha256=XD-k92cMc0rKo8giwLXM7CayJ-ohVEcNFeAnJOHiRow,2329
165
+ modal-0.66.40.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
+ modal-0.66.40.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
+ modal-0.66.40.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
+ modal-0.66.40.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2024
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 38 # git: 0d5cad4
4
+ build_number = 40 # git: a9ea369