modAL 1.6.3.dev7__py3-none-any.whl → 1.6.3.dev8__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/_image.py CHANGED
@@ -349,6 +349,13 @@ def _get_image_builder_version(server_version: ImageBuilderVersion) -> ImageBuil
349
349
  return version
350
350
 
351
351
 
352
+ async def _resolve_image_builder_version(load_context: LoadContext) -> ImageBuilderVersion:
353
+ environment = await _get_environment_cached(load_context.environment_name or "", load_context.client)
354
+ # A bit hacky,but assume that the environment provides a valid builder version
355
+ image_builder_version = cast(ImageBuilderVersion, environment._settings.image_builder_version)
356
+ return _get_image_builder_version(image_builder_version)
357
+
358
+
352
359
  def _create_context_mount(
353
360
  docker_commands: Sequence[str],
354
361
  ignore_fn: Callable[[Path], bool],
@@ -663,10 +670,7 @@ class _Image(_Object, type_prefix="im"):
663
670
 
664
671
  async def _load(self: _Image, resolver: Resolver, load_context: LoadContext, existing_object_id: str | None):
665
672
  assert load_context.app_id # type narrowing
666
- environment = await _get_environment_cached(load_context.environment_name or "", load_context.client)
667
- # A bit hacky,but assume that the environment provides a valid builder version
668
- image_builder_version = cast(ImageBuilderVersion, environment._settings.image_builder_version)
669
- builder_version = _get_image_builder_version(image_builder_version)
673
+ builder_version = await _resolve_image_builder_version(load_context)
670
674
 
671
675
  context_mount = context_mount_function(builder_version) if context_mount_function else None
672
676
  if context_mount:
@@ -2289,12 +2293,48 @@ class _Image(_Object, type_prefix="im"):
2289
2293
  context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, add_python)}
2290
2294
  return DockerfileSpec(commands=commands, context_files=context_files)
2291
2295
 
2292
- return _Image._from_args(
2296
+ single_layer_image = _Image._from_args(
2293
2297
  dockerfile_function=build_dockerfile,
2294
2298
  context_mount_function=context_mount_function,
2295
2299
  force_build=force_build,
2296
2300
  **kwargs,
2297
2301
  )
2302
+ if not add_python:
2303
+ return single_layer_image
2304
+
2305
+ # Builder versions after 2025.06 put the registry image and the standalone Python in separate layers.
2306
+ registry_image = _Image._from_args(
2307
+ dockerfile_function=lambda version: DockerfileSpec(commands=[f"FROM {tag}"], context_files={}),
2308
+ image_registry_config=kwargs.get("image_registry_config"),
2309
+ force_build=force_build,
2310
+ )
2311
+
2312
+ def build_python_dockerfile(version: ImageBuilderVersion) -> DockerfileSpec:
2313
+ commands = _Image._registry_setup_commands("base", version, setup_dockerfile_commands, add_python)
2314
+ return DockerfileSpec(commands=commands, context_files={})
2315
+
2316
+ split_image = _Image._from_args(
2317
+ base_images={"base": registry_image},
2318
+ dockerfile_function=build_python_dockerfile,
2319
+ context_mount_function=context_mount_function,
2320
+ force_build=force_build,
2321
+ **kwargs,
2322
+ )
2323
+
2324
+ async def _load(self: _Image, resolver: Resolver, load_context: LoadContext, existing_object_id: str | None):
2325
+ builder_version = await _resolve_image_builder_version(load_context)
2326
+ # Validate before the registry base image of split_image is built.
2327
+ _validate_python_version(
2328
+ add_python, builder_version, allow_micro_granularity=False, allow_free_threading=True
2329
+ )
2330
+ image = split_image if builder_version > "2025.06" else single_layer_image
2331
+ await resolver.load(image, load_context)
2332
+ self._hydrate_from_other(image)
2333
+ self._serve_mounts = image._serve_mounts
2334
+
2335
+ obj = _Image._from_loader(_load, f"Image.from_registry({tag!r})", load_context_overrides=LoadContext.empty())
2336
+ obj.force_build = force_build
2337
+ return obj
2298
2338
 
2299
2339
  @staticmethod
2300
2340
  def from_gcp_artifact_registry(
modal/client.pyi CHANGED
@@ -80,7 +80,7 @@ class _Client:
80
80
  server_url: str,
81
81
  client_type: int,
82
82
  credentials: typing.Optional[tuple[str, str]],
83
- version: str = "1.6.3.dev7",
83
+ version: str = "1.6.3.dev8",
84
84
  *,
85
85
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
86
86
  ):
@@ -290,7 +290,7 @@ class Client:
290
290
  server_url: str,
291
291
  client_type: int,
292
292
  credentials: typing.Optional[tuple[str, str]],
293
- version: str = "1.6.3.dev7",
293
+ version: str = "1.6.3.dev8",
294
294
  *,
295
295
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
296
296
  ):
modal/functions.pyi CHANGED
@@ -619,7 +619,7 @@ class Function(
619
619
 
620
620
  _call_generator: ___call_generator_spec
621
621
 
622
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
622
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
623
623
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
624
624
  """Calls the function remotely, executing it with the given arguments and returning the execution's result.
625
625
 
@@ -644,7 +644,7 @@ class Function(
644
644
  """
645
645
  ...
646
646
 
647
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
647
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
648
648
 
649
649
  class __remote_gen_spec(typing_extensions.Protocol):
650
650
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -694,7 +694,7 @@ class Function(
694
694
  """
695
695
  ...
696
696
 
697
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
697
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
698
698
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
699
699
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
700
700
 
@@ -727,7 +727,7 @@ class Function(
727
727
  """
728
728
  ...
729
729
 
730
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
730
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
731
731
 
732
732
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
733
733
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -735,7 +735,7 @@ class Function(
735
735
 
736
736
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
737
737
 
738
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
738
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
739
739
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
740
740
  """Calls the function with the given arguments, without waiting for the results.
741
741
 
@@ -768,7 +768,7 @@ class Function(
768
768
  """
769
769
  ...
770
770
 
771
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
771
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
772
772
 
773
773
  @property
774
774
  def _raw_f_(self) -> collections.abc.Callable[..., typing.Any]: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.6.3.dev7
3
+ Version: 1.6.3.dev8
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -8,7 +8,7 @@ modal/_environments.py,sha256=O7YagqEUhmxEG5Q10Ch6FDSIsAKFbKXULLaeRw0uCio,27602
8
8
  modal/_function_variants.py,sha256=xF34OxGaZbmxe0chAJCQb9Uyc8TP78VG8MO55deBWLs,24398
9
9
  modal/_functions.py,sha256=-yGdaDkb2IPKDu4TWl93HpiWEU2Qv3bBGrSklEjiE3I,118392
10
10
  modal/_grpc_client.py,sha256=ajCxTqhDk-rpWuYmUScRXwYMPVmvujo8ckvvv4l0czk,7088
11
- modal/_image.py,sha256=RrTSL4WBuaCpZwvimgK8jvQWzwIvBOd2crKM_QYonOM,133085
11
+ modal/_image.py,sha256=5Eud1WuM3O36Ddob_gSnoYLwXyhBWKmdAhCurWcFAsQ,135068
12
12
  modal/_ipython.py,sha256=Bu9fc3hm3xt2O47qLe_d-Mu2jS81LwMsmXNJ1sawBA0,575
13
13
  modal/_load_context.py,sha256=wrDqD3KehhFepp0vBhyz_PoLWoRVD0gZHP8dlLHCTiw,4818
14
14
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
@@ -39,7 +39,7 @@ modal/billing.py,sha256=E1-P_P8bJFLp-bTaggYd4BaaViImPB5UdtXiY8VeAZQ,390
39
39
  modal/billing.pyi,sha256=4m7VLYNS8IiJ2I3CJx0awvrOM6BILWRVLfdeqtAYr8M,7189
40
40
  modal/call_graph.py,sha256=XGALIDn1bLchWo_goyX23bcPjzCZcfqKUo8INIfDapo,1775
41
41
  modal/client.py,sha256=cstrL0wpXCZmcvRs7Sy3QRw9Vz8zkZy8NNk0tPe38sk,22852
42
- modal/client.pyi,sha256=Rezm_F0bqn00RhEQ0cCYxSqFdofGx4A61ZDQIBpDpFk,23488
42
+ modal/client.pyi,sha256=BKx9TW_udi_V9KQk-F6qBf5SHPVXvvSoZfwqfUyy52c,23488
43
43
  modal/cloud_bucket_mount.py,sha256=ZOg69dhIFcJcwim4JP-6s1tqwOYAfgS9806jRpspifw,7511
44
44
  modal/cloud_bucket_mount.pyi,sha256=HoPe_NG5jYdVfmTNY-ZJ3-C8Eo_FzJovl9orJRjkGbE,10252
45
45
  modal/cls.py,sha256=JfDAUMrkhasm26lK7kDUNarXZA_7AvZrymf7XNSGTDM,41777
@@ -56,7 +56,7 @@ modal/environments.pyi,sha256=drmg6yVLjpPhGJ4byOrdBEp2KRLburPrKT-FYtgNPoM,23628
56
56
  modal/exception.py,sha256=L-dUKust6feZzn5qhTVusSAr0IBa4Wa3qIA225IT_lY,12334
57
57
  modal/file_pattern_matcher.py,sha256=CpaNNj7oBlOSewX-AAUZCF8KDxH0_DmgwzfpVGbPYJ4,8138
58
58
  modal/functions.py,sha256=-5aogviGxcNXX4qZ34GSBMKnLqH-WH0eb4cGbHpCYYw,382
59
- modal/functions.pyi,sha256=lnDLXYKS86J57g0gmNOWeY70KIyIho945CDSkPDN5lU,62671
59
+ modal/functions.pyi,sha256=33XS_ROlsagDDnVDCMIWUsuddB_CxhM4Di32gf_ZLx4,62671
60
60
  modal/image.py,sha256=c0lUSAoU-Ip3g5DGZ0uhdCzoWSQWh1g0i-7Rxo-Sz-I,160
61
61
  modal/image.pyi,sha256=L53g84DVKa94LvqSqqYZLpG2o9-vxcC5vp5pXKQB3f0,61210
62
62
  modal/io_streams.py,sha256=iWwhGCcTwhNtIo2t2f-qVV3FBEK1DIi40Tm_Ai01eYA,32992
@@ -210,7 +210,7 @@ modal/sandbox/_task_command_router_client.py,sha256=ta_I2EsVruEkRE9YCaCHns4oCb_h
210
210
  modal/sandbox/sandbox.py,sha256=4ekghND9qUGf5wtIQH4mVa6PHGjHgY0UN5RKryOM05k,683
211
211
  modal/sandbox/sandbox.pyi,sha256=iWxqScPKLa6oo9vJGukv2XhuCOK0E-bj52trqetBBh8,138895
212
212
  modal/skills/modal/SKILL.md,sha256=Bm-0BPTYppJoeQzA-N-Re8L6-nKnV6gspJXMl4cD0P0,5490
213
- modal-1.6.3.dev7.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
213
+ modal-1.6.3.dev8.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
214
214
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
215
215
  modal_docs/gen_cli_docs.py,sha256=9-b8vl2EsLWD9zJqpCK8IUi5h44Bjn3i3rSdedZV4bA,6415
216
216
  modal_docs/gen_cli_docs_main.py,sha256=UPGr7O1DYTIRLwfINe2rbdh89J3cPVTU1OWL-SjxnOQ,198
@@ -223,8 +223,8 @@ modal_docs/mdmd/signatures.py,sha256=OASroKle763Kfumn4Ek4PABJXEGP56JMCTug44QoBx4
223
223
  modal_docs/mdmd/types.py,sha256=tv7fvziPr-MeDzOp4e2pK5h3d1DXTUOO74rPqDoBn6g,736
224
224
  modal_proto/__init__.py,sha256=Hkou4lcD5tArEkW_9v9KZhLY7fl0fA9-O28beKU55pg,396
225
225
  modal_proto/api_grpc.py,sha256=cXcllVdAI4xWfDPPaOnTWjwOytwSY2Yd3utdDd57zOs,211812
226
- modal_proto/api_pb2.py,sha256=f9A55U6BHkr5PY0l_79R0OxlTw8vTjbZ-3Hqqn4W1lI,616666
227
- modal_proto/api_pb2.pyi,sha256=Oa_A9yHHUfNTUA1Tse-1BQyIALxXrXpDOeDPG8bpqIY,857038
226
+ modal_proto/api_pb2.py,sha256=8RY58w7Eco4oq7L6pDASw0G8Kbpnoxzi9Iwu8dFKkhs,616956
227
+ modal_proto/api_pb2.pyi,sha256=elfFllZVhKGtMyMJ7mgYrTcChgfVbxTJApmZzYa5Uvk,858709
228
228
  modal_proto/api_pb2_grpc.py,sha256=-_Me41rc31QYu7mdtlEQvbSdbkZOCl8KTCdcf5QFgiI,453303
229
229
  modal_proto/api_pb2_grpc.pyi,sha256=VEa9TK3W4kQyYgUzdgY1liQwMDlrZ-TmyZv3WABiQnE,106540
230
230
  modal_proto/modal_api_grpc.py,sha256=_U4ZIvJFiBtb_C6RQwHGNulDTA2Eo0us9BzJGYM_FL8,33302
@@ -234,10 +234,10 @@ modal_proto/task_command_router_pb2.py,sha256=ysC0d8p3YxwyOpP3B-qDlvE81Yo4ntQiwi
234
234
  modal_proto/task_command_router_pb2.pyi,sha256=FDcd5t3ZCmQHUjefOzg07iglrgKYcBrzFvdKIWsEMHI,50628
235
235
  modal_proto/task_command_router_pb2_grpc.py,sha256=8iGUGwEVbqOsZWPJ7OsQ9OKUGaSCf9Dr2tvb04Ww6d4,44620
236
236
  modal_proto/task_command_router_pb2_grpc.pyi,sha256=26Fq9RQo09B9KLHsgdpRuw-I6Z4-2jrXLQkuDzB-moI,15097
237
- modal_version/__init__.py,sha256=_NyIMw3R_WktxIyqvxZFAsrP4rSI-AsLzcRB4crWyC4,120
237
+ modal_version/__init__.py,sha256=BEzViUd-D7xWY_kpSFaB_DnZ9UsYAwubPlgIOhPvp_U,120
238
238
  modal_version/__main__.py,sha256=nLUbubxKx7GXNzJIkTB7M7_u8080LyLM0IS0rzFkC_c,119
239
- modal-1.6.3.dev7.dist-info/METADATA,sha256=YcuXMLRCPRbuK-tN6nj38HqhWH0YinACJZOjRI5NjbI,2577
240
- modal-1.6.3.dev7.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
241
- modal-1.6.3.dev7.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
242
- modal-1.6.3.dev7.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
243
- modal-1.6.3.dev7.dist-info/RECORD,,
239
+ modal-1.6.3.dev8.dist-info/METADATA,sha256=d_uDAgCIZd0Rp0ryre8NuG7uTb2RHW8EVzYhlrqV72s,2577
240
+ modal-1.6.3.dev8.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
241
+ modal-1.6.3.dev8.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
242
+ modal-1.6.3.dev8.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
243
+ modal-1.6.3.dev8.dist-info/RECORD,,