modal 0.71.13__py3-none-any.whl → 0.72.1__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.
@@ -1,7 +1,8 @@
1
1
  # Copyright Modal Labs 2024
2
2
  import re
3
3
  import shlex
4
- from typing import Sequence
4
+ from pathlib import Path
5
+ from typing import Optional, Sequence
5
6
 
6
7
  from ..exception import InvalidError
7
8
 
@@ -62,3 +63,36 @@ def extract_copy_command_patterns(dockerfile_lines: Sequence[str]) -> list[str]:
62
63
  current_command = ""
63
64
 
64
65
  return list(copy_source_patterns)
66
+
67
+
68
+ def find_dockerignore_file(context_directory: Path, dockerfile_path: Optional[Path] = None) -> Optional[Path]:
69
+ """
70
+ Find dockerignore file relative to current context directory
71
+ and if dockerfile path is provided, check if specific <dockerfile_name>.dockerignore
72
+ file exists in the same directory as <dockerfile_name>
73
+ Finds the most specific dockerignore file that exists.
74
+ """
75
+
76
+ def valid_dockerignore_file(fp):
77
+ # fp has to exist
78
+ if not fp.exists():
79
+ return False
80
+ # fp has to be subpath to current working directory
81
+ if not fp.is_relative_to(context_directory):
82
+ return False
83
+
84
+ return True
85
+
86
+ generic_name = ".dockerignore"
87
+ possible_locations = []
88
+ if dockerfile_path:
89
+ specific_name = f"{dockerfile_path.name}.dockerignore"
90
+ # 1. check if specific <dockerfile_name>.dockerignore file exists in the same directory as <dockerfile_name>
91
+ possible_locations.append(dockerfile_path.parent / specific_name)
92
+ # 2. check if generic .dockerignore file exists in the same directory as <dockerfile_name>
93
+ possible_locations.append(dockerfile_path.parent / generic_name)
94
+
95
+ # 3. check if generic .dockerignore file exists in current working directory
96
+ possible_locations.append(context_directory / generic_name)
97
+
98
+ return next((e for e in possible_locations if valid_dockerignore_file(e)), None)
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.71.13"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.1"
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.71.13"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.72.1"
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[P_INNER, ReturnType_INNER]):
465
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_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[P, ReturnType]
469
+ remote: __remote_spec[ReturnType, P]
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[P_INNER, ReturnType_INNER]):
482
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_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[P, ReturnType]
486
+ _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
487
487
 
488
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
488
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_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[P, ReturnType]
492
+ spawn: __spawn_spec[ReturnType, P]
493
493
 
494
494
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
495
495
 
modal/image.py CHANGED
@@ -33,6 +33,7 @@ from ._utils.blob_utils import MAX_OBJECT_SIZE_BYTES
33
33
  from ._utils.deprecation import deprecation_error, deprecation_warning
34
34
  from ._utils.docker_utils import (
35
35
  extract_copy_command_patterns,
36
+ find_dockerignore_file,
36
37
  )
37
38
  from ._utils.function_utils import FunctionInfo
38
39
  from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES, retry_transient_errors
@@ -71,6 +72,17 @@ LOCAL_REQUIREMENTS_DIR = Path(__file__).parent / "requirements"
71
72
  CONTAINER_REQUIREMENTS_PATH = "/modal_requirements.txt"
72
73
 
73
74
 
75
+ class _AutoDockerIgnoreSentinel:
76
+ def __repr__(self) -> str:
77
+ return f"{__name__}.AUTO_DOCKERIGNORE"
78
+
79
+ def __call__(self, _: Path) -> bool:
80
+ raise NotImplementedError("This is only a placeholder. Do not call")
81
+
82
+
83
+ AUTO_DOCKERIGNORE = _AutoDockerIgnoreSentinel()
84
+
85
+
74
86
  def _validate_python_version(
75
87
  python_version: Optional[str], builder_version: ImageBuilderVersion, allow_micro_granularity: bool = True
76
88
  ) -> str:
@@ -266,6 +278,47 @@ def _create_context_mount(
266
278
  return _Mount._add_local_dir(Path("./"), PurePosixPath("/"), ignore=ignore_with_include)
267
279
 
268
280
 
281
+ def _create_context_mount_function(
282
+ ignore: Union[Sequence[str], Callable[[Path], bool]],
283
+ dockerfile_cmds: list[str] = [],
284
+ dockerfile_path: Optional[Path] = None,
285
+ context_mount: Optional[_Mount] = None,
286
+ ):
287
+ if dockerfile_path and dockerfile_cmds:
288
+ raise InvalidError("Cannot provide both dockerfile and docker commands")
289
+
290
+ if context_mount:
291
+ if ignore is not AUTO_DOCKERIGNORE:
292
+ raise InvalidError("Cannot set both `context_mount` and `ignore`")
293
+
294
+ def identity_context_mount_fn() -> Optional[_Mount]:
295
+ return context_mount
296
+
297
+ return identity_context_mount_fn
298
+ elif ignore is AUTO_DOCKERIGNORE:
299
+
300
+ def auto_created_context_mount_fn() -> Optional[_Mount]:
301
+ context_dir = Path.cwd()
302
+ dockerignore_file = find_dockerignore_file(context_dir, dockerfile_path)
303
+ ignore_fn = (
304
+ FilePatternMatcher(*dockerignore_file.read_text("utf8").splitlines())
305
+ if dockerignore_file
306
+ else _ignore_fn(())
307
+ )
308
+
309
+ cmds = dockerfile_path.read_text("utf8").splitlines() if dockerfile_path else dockerfile_cmds
310
+ return _create_context_mount(cmds, ignore_fn=ignore_fn, context_dir=context_dir)
311
+
312
+ return auto_created_context_mount_fn
313
+
314
+ def auto_created_context_mount_fn() -> Optional[_Mount]:
315
+ # use COPY commands and ignore patterns to construct implicit context mount
316
+ cmds = dockerfile_path.read_text("utf8").splitlines() if dockerfile_path else dockerfile_cmds
317
+ return _create_context_mount(cmds, ignore_fn=_ignore_fn(ignore), context_dir=Path.cwd())
318
+
319
+ return auto_created_context_mount_fn
320
+
321
+
269
322
  class _ImageRegistryConfig:
270
323
  """mdmd:hidden"""
271
324
 
@@ -1221,7 +1274,7 @@ class _Image(_Object, type_prefix="im"):
1221
1274
  # modal.Mount with local files to supply as build context for COPY commands
1222
1275
  context_mount: Optional[_Mount] = None,
1223
1276
  force_build: bool = False, # Ignore cached builds, similar to 'docker build --no-cache'
1224
- ignore: Union[Sequence[str], Callable[[Path], bool]] = (),
1277
+ ignore: Union[Sequence[str], Callable[[Path], bool]] = AUTO_DOCKERIGNORE,
1225
1278
  ) -> "_Image":
1226
1279
  """
1227
1280
  Extend an image with arbitrary Dockerfile-like commands.
@@ -1232,6 +1285,11 @@ class _Image(_Object, type_prefix="im"):
1232
1285
  from pathlib import Path
1233
1286
  from modal import FilePatternMatcher
1234
1287
 
1288
+ # By default a .dockerignore file is used if present in the current working directory
1289
+ image = modal.Image.debian_slim().dockerfile_commands(
1290
+ ["COPY data /data"],
1291
+ )
1292
+
1235
1293
  image = modal.Image.debian_slim().dockerfile_commands(
1236
1294
  ["COPY data /data"],
1237
1295
  ignore=["*.venv"],
@@ -1264,22 +1322,6 @@ class _Image(_Object, type_prefix="im"):
1264
1322
  if not cmds:
1265
1323
  return self
1266
1324
 
1267
- if context_mount:
1268
- if ignore:
1269
- raise InvalidError("Cannot set both `context_mount` and `ignore`")
1270
-
1271
- def identity_context_mount_fn() -> Optional[_Mount]:
1272
- return context_mount
1273
-
1274
- context_mount_function = identity_context_mount_fn
1275
- else:
1276
-
1277
- def auto_created_context_mount_fn() -> Optional[_Mount]:
1278
- # use COPY commands and ignore patterns to construct implicit context mount
1279
- return _create_context_mount(cmds, ignore_fn=_ignore_fn(ignore), context_dir=Path.cwd())
1280
-
1281
- context_mount_function = auto_created_context_mount_fn
1282
-
1283
1325
  def build_dockerfile(version: ImageBuilderVersion) -> DockerfileSpec:
1284
1326
  return DockerfileSpec(commands=["FROM base", *cmds], context_files=context_files)
1285
1327
 
@@ -1288,7 +1330,9 @@ class _Image(_Object, type_prefix="im"):
1288
1330
  dockerfile_function=build_dockerfile,
1289
1331
  secrets=secrets,
1290
1332
  gpu_config=parse_gpu_config(gpu),
1291
- context_mount_function=context_mount_function,
1333
+ context_mount_function=_create_context_mount_function(
1334
+ ignore=ignore, dockerfile_cmds=cmds, context_mount=context_mount
1335
+ ),
1292
1336
  force_build=self.force_build or force_build,
1293
1337
  )
1294
1338
 
@@ -1653,7 +1697,7 @@ class _Image(_Object, type_prefix="im"):
1653
1697
  secrets: Sequence[_Secret] = [],
1654
1698
  gpu: GPU_T = None,
1655
1699
  add_python: Optional[str] = None,
1656
- ignore: Union[Sequence[str], Callable[[Path], bool]] = (),
1700
+ ignore: Union[Sequence[str], Callable[[Path], bool]] = AUTO_DOCKERIGNORE,
1657
1701
  ) -> "_Image":
1658
1702
  """Build a Modal image from a local Dockerfile.
1659
1703
 
@@ -1666,6 +1710,12 @@ class _Image(_Object, type_prefix="im"):
1666
1710
  from pathlib import Path
1667
1711
  from modal import FilePatternMatcher
1668
1712
 
1713
+ # By default a .dockerignore file is used if present in the current working directory
1714
+ image = modal.Image.from_dockerfile(
1715
+ "./Dockerfile",
1716
+ add_python="3.12",
1717
+ )
1718
+
1669
1719
  image = modal.Image.from_dockerfile(
1670
1720
  "./Dockerfile",
1671
1721
  add_python="3.12",
@@ -1700,22 +1750,6 @@ class _Image(_Object, type_prefix="im"):
1700
1750
  ```
1701
1751
  """
1702
1752
 
1703
- if context_mount:
1704
- if ignore:
1705
- raise InvalidError("Cannot set both `context_mount` and `ignore`")
1706
-
1707
- def identity_context_mount_fn() -> Optional[_Mount]:
1708
- return context_mount
1709
-
1710
- context_mount_function = identity_context_mount_fn
1711
- else:
1712
-
1713
- def auto_created_context_mount_fn() -> Optional[_Mount]:
1714
- lines = Path(path).read_text("utf8").splitlines()
1715
- return _create_context_mount(lines, ignore_fn=_ignore_fn(ignore), context_dir=Path.cwd())
1716
-
1717
- context_mount_function = auto_created_context_mount_fn
1718
-
1719
1753
  # --- Build the base dockerfile
1720
1754
 
1721
1755
  def build_dockerfile_base(version: ImageBuilderVersion) -> DockerfileSpec:
@@ -1726,7 +1760,9 @@ class _Image(_Object, type_prefix="im"):
1726
1760
  gpu_config = parse_gpu_config(gpu)
1727
1761
  base_image = _Image._from_args(
1728
1762
  dockerfile_function=build_dockerfile_base,
1729
- context_mount_function=context_mount_function,
1763
+ context_mount_function=_create_context_mount_function(
1764
+ ignore=ignore, dockerfile_path=Path(path), context_mount=context_mount
1765
+ ),
1730
1766
  gpu_config=gpu_config,
1731
1767
  secrets=secrets,
1732
1768
  )
modal/image.pyi CHANGED
@@ -16,6 +16,12 @@ import typing_extensions
16
16
 
17
17
  ImageBuilderVersion = typing.Literal["2023.12", "2024.04", "2024.10"]
18
18
 
19
+ class _AutoDockerIgnoreSentinel:
20
+ def __repr__(self) -> str: ...
21
+ def __call__(self, _: pathlib.Path) -> bool: ...
22
+
23
+ AUTO_DOCKERIGNORE: _AutoDockerIgnoreSentinel
24
+
19
25
  def _validate_python_version(
20
26
  python_version: typing.Optional[str],
21
27
  builder_version: typing.Literal["2023.12", "2024.04", "2024.10"],
@@ -49,6 +55,12 @@ def _create_context_mount(
49
55
  ignore_fn: typing.Callable[[pathlib.Path], bool],
50
56
  context_dir: pathlib.Path,
51
57
  ) -> typing.Optional[modal.mount._Mount]: ...
58
+ def _create_context_mount_function(
59
+ ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]],
60
+ dockerfile_cmds: list[str] = [],
61
+ dockerfile_path: typing.Optional[pathlib.Path] = None,
62
+ context_mount: typing.Optional[modal.mount._Mount] = None,
63
+ ): ...
52
64
 
53
65
  class _ImageRegistryConfig:
54
66
  def __init__(self, registry_auth_type: int = 0, secret: typing.Optional[modal.secret._Secret] = None): ...
@@ -202,7 +214,9 @@ class _Image(modal.object._Object):
202
214
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
203
215
  context_mount: typing.Optional[modal.mount._Mount] = None,
204
216
  force_build: bool = False,
205
- ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = (),
217
+ ignore: typing.Union[
218
+ collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]
219
+ ] = modal.image.AUTO_DOCKERIGNORE,
206
220
  ) -> _Image: ...
207
221
  def entrypoint(self, entrypoint_commands: list[str]) -> _Image: ...
208
222
  def shell(self, shell_commands: list[str]) -> _Image: ...
@@ -288,7 +302,9 @@ class _Image(modal.object._Object):
288
302
  secrets: collections.abc.Sequence[modal.secret._Secret] = [],
289
303
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
290
304
  add_python: typing.Optional[str] = None,
291
- ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = (),
305
+ ignore: typing.Union[
306
+ collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]
307
+ ] = modal.image.AUTO_DOCKERIGNORE,
292
308
  ) -> _Image: ...
293
309
  @staticmethod
294
310
  def debian_slim(python_version: typing.Optional[str] = None, force_build: bool = False) -> _Image: ...
@@ -470,7 +486,9 @@ class Image(modal.object.Object):
470
486
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
471
487
  context_mount: typing.Optional[modal.mount.Mount] = None,
472
488
  force_build: bool = False,
473
- ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = (),
489
+ ignore: typing.Union[
490
+ collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]
491
+ ] = modal.image.AUTO_DOCKERIGNORE,
474
492
  ) -> Image: ...
475
493
  def entrypoint(self, entrypoint_commands: list[str]) -> Image: ...
476
494
  def shell(self, shell_commands: list[str]) -> Image: ...
@@ -556,7 +574,9 @@ class Image(modal.object.Object):
556
574
  secrets: collections.abc.Sequence[modal.secret.Secret] = [],
557
575
  gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
558
576
  add_python: typing.Optional[str] = None,
559
- ignore: typing.Union[collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]] = (),
577
+ ignore: typing.Union[
578
+ collections.abc.Sequence[str], typing.Callable[[pathlib.Path], bool]
579
+ ] = modal.image.AUTO_DOCKERIGNORE,
560
580
  ) -> Image: ...
561
581
  @staticmethod
562
582
  def debian_slim(python_version: typing.Optional[str] = None, force_build: bool = False) -> Image: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.71.13
3
+ Version: 0.72.1
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=vEE0cK5QPF6_cdW5AJvcuWxz5KmeprHwBEtlDkVRHgE,45582
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=8J3-EAE51lpcCOdLSSKFWuC3NhItuXhgxIv5NXpy4_0,7280
22
+ modal/client.pyi,sha256=D39rHvd8qZ1Qmr_iaXMNRhehsLW3OUI95XzZ-m0ymoI,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,10 +37,10 @@ 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=LiSDgH-X7jcZ56pAoLMwo3x9Dzdp_3Sd7W5MVAJPoCg,25407
40
+ modal/functions.pyi,sha256=3ESJ61f8oEDycDmrpnuNB2vjFKuLBG_aqyliXPTdY7M,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
42
- modal/image.py,sha256=l1qJRQwkeD1Fq5KWY80ZwNyxpcEJwA92fbrAizBRtdk,87985
43
- modal/image.pyi,sha256=Pa1_LVr3FyNsnu_MhBO08fBgCeLazTEe25phYdu0bzE,25365
42
+ modal/image.py,sha256=BAalPHfJn3TM5RW63AK-TRQjq82K2KLgzXXxWwfYbxI,89366
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
46
  modal/mount.py,sha256=wOr-2vmKImsE3lHBII8hL2gYy5ng46R58QwId4JultQ,29313
@@ -88,7 +88,7 @@ modal/_utils/async_utils.py,sha256=9ubwMkwiDB4gzOYG2jL9j7Fs-5dxHjcifZe3r7JRg-k,2
88
88
  modal/_utils/blob_utils.py,sha256=N66LtZI8PpCkZ7maA7GLW5CAmYUoNJdG-GjaAUR4_NQ,14509
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
- modal/_utils/docker_utils.py,sha256=FLz1q0YicL6i_Iq-4inkgDVFfEINVG6YPT2s_P6ly0o,2264
91
+ modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
92
92
  modal/_utils/function_utils.py,sha256=q68HhFH16MwhHRnGD8jvIgqDjduRQVp3a_qMWXPyrgU,25518
93
93
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
94
94
  modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
@@ -163,12 +163,12 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
163
163
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
164
164
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
165
165
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
- modal_version/__init__.py,sha256=BEBWj9tcbFUwzEjUrqly601rauw5cYsHdcmJHs3iu0s,470
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=cnSvdhptI6bv1AtiTbV-_FVYatlo2RYUt2MB2J1rdVs,149
169
- modal-0.71.13.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
- modal-0.71.13.dist-info/METADATA,sha256=iN3iHC6_4sMlOR9fHSl0HGvlELImU8UanLI2qt3DMpE,2329
171
- modal-0.71.13.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
- modal-0.71.13.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
- modal-0.71.13.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
- modal-0.71.13.dist-info/RECORD,,
168
+ modal_version/_version_generated.py,sha256=hf7Ku1iuUEFstHQ5CvUppu-0HDHbb019aO6skc5WUOg,148
169
+ modal-0.72.1.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
170
+ modal-0.72.1.dist-info/METADATA,sha256=mAHgUFrVfbTrzQ8TDRQTUaIuJmzAaDV_LvrLoenWDIw,2328
171
+ modal-0.72.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
172
+ modal-0.72.1.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
173
+ modal-0.72.1.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
174
+ modal-0.72.1.dist-info/RECORD,,
modal_version/__init__.py CHANGED
@@ -7,7 +7,7 @@ from ._version_generated import build_number
7
7
  major_number = 0
8
8
 
9
9
  # Bump this manually on breaking changes, then reset the number in _version_generated.py
10
- minor_number = 71
10
+ minor_number = 72
11
11
 
12
12
  # Right now, automatically increment the patch number in CI
13
13
  __version__ = f"{major_number}.{minor_number}.{max(build_number, 0)}"
@@ -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 = 13 # git: 1c4cfc0
4
+ build_number = 1 # git: d3ea87d