modAL 1.6.3.dev6__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 +62 -23
- modal/client.pyi +2 -2
- modal/functions.pyi +6 -6
- modal/image.pyi +4 -1
- modal/mount.py +35 -13
- modal/mount.pyi +10 -8
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/METADATA +1 -1
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/RECORD +15 -15
- modal_proto/api_pb2.py +1376 -1376
- modal_proto/api_pb2.pyi +20 -5
- modal_version/__init__.py +1 -1
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/WHEEL +0 -0
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/entry_points.txt +0 -0
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/licenses/LICENSE +0 -0
- {modal-1.6.3.dev6.dist-info → modal-1.6.3.dev8.dist-info}/top_level.txt +0 -0
modal/_image.py
CHANGED
|
@@ -57,7 +57,7 @@ from .exception import (
|
|
|
57
57
|
VersionError,
|
|
58
58
|
)
|
|
59
59
|
from .file_pattern_matcher import NON_PYTHON_FILES, FilePatternMatcher, _ignore_fn
|
|
60
|
-
from .mount import _Mount, python_standalone_mount_name
|
|
60
|
+
from .mount import PYTHON_STANDALONE_VERSIONS, _Mount, python_standalone_mount_name
|
|
61
61
|
from .network_file_system import _NetworkFileSystem
|
|
62
62
|
from .output import OutputManager
|
|
63
63
|
from .secret import _Secret
|
|
@@ -70,6 +70,7 @@ if typing.TYPE_CHECKING:
|
|
|
70
70
|
|
|
71
71
|
# This is used for both type checking and runtime validation
|
|
72
72
|
ImageBuilderVersion = Literal["2023.12", "2024.04", "2024.10", "2025.06", "PREVIEW"]
|
|
73
|
+
LATEST_IMAGE_BUILDER_VERSION: ImageBuilderVersion = "2025.06"
|
|
73
74
|
|
|
74
75
|
# Note: we also define supported Python versions via logic at the top of the package __init__.py
|
|
75
76
|
# so that we fail fast / clearly in unsupported containers. Additionally, we enumerate the supported
|
|
@@ -348,6 +349,13 @@ def _get_image_builder_version(server_version: ImageBuilderVersion) -> ImageBuil
|
|
|
348
349
|
return version
|
|
349
350
|
|
|
350
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
|
+
|
|
351
359
|
def _create_context_mount(
|
|
352
360
|
docker_commands: Sequence[str],
|
|
353
361
|
ignore_fn: Callable[[Path], bool],
|
|
@@ -402,7 +410,7 @@ def _create_context_mount_function(
|
|
|
402
410
|
|
|
403
411
|
if ignore is AUTO_DOCKERIGNORE:
|
|
404
412
|
|
|
405
|
-
def auto_created_context_mount_fn() -> _Mount | None:
|
|
413
|
+
def auto_created_context_mount_fn(builder_version: ImageBuilderVersion) -> _Mount | None:
|
|
406
414
|
nonlocal context_dir
|
|
407
415
|
context_dir = Path.cwd() if context_dir is None else Path(context_dir).absolute()
|
|
408
416
|
dockerignore_file = find_dockerignore_file(context_dir, dockerfile_path)
|
|
@@ -419,7 +427,7 @@ def _create_context_mount_function(
|
|
|
419
427
|
|
|
420
428
|
else:
|
|
421
429
|
|
|
422
|
-
def auto_created_context_mount_fn() -> _Mount | None:
|
|
430
|
+
def auto_created_context_mount_fn(builder_version: ImageBuilderVersion) -> _Mount | None:
|
|
423
431
|
# use COPY commands and ignore patterns to construct implicit context mount
|
|
424
432
|
nonlocal context_dir
|
|
425
433
|
context_dir = Path.cwd() if context_dir is None else Path(context_dir).absolute()
|
|
@@ -622,7 +630,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
622
630
|
build_function: "modal._functions._Function | None" = None,
|
|
623
631
|
build_function_input: api_pb2.FunctionInput | None = None,
|
|
624
632
|
image_registry_config: _ImageRegistryConfig | None = None,
|
|
625
|
-
context_mount_function: Callable[[], _Mount | None] | None = None,
|
|
633
|
+
context_mount_function: Callable[[ImageBuilderVersion], _Mount | None] | None = None,
|
|
626
634
|
force_build: bool = False,
|
|
627
635
|
build_args: dict[str, str] = {},
|
|
628
636
|
validated_volumes: Sequence[tuple[str, _Volume]] | None = None,
|
|
@@ -661,7 +669,10 @@ class _Image(_Object, type_prefix="im"):
|
|
|
661
669
|
return deps
|
|
662
670
|
|
|
663
671
|
async def _load(self: _Image, resolver: Resolver, load_context: LoadContext, existing_object_id: str | None):
|
|
664
|
-
|
|
672
|
+
assert load_context.app_id # type narrowing
|
|
673
|
+
builder_version = await _resolve_image_builder_version(load_context)
|
|
674
|
+
|
|
675
|
+
context_mount = context_mount_function(builder_version) if context_mount_function else None
|
|
665
676
|
if context_mount:
|
|
666
677
|
await resolver.load(context_mount, load_context)
|
|
667
678
|
|
|
@@ -670,12 +681,6 @@ class _Image(_Object, type_prefix="im"):
|
|
|
670
681
|
# base images can't have
|
|
671
682
|
image._assert_no_mount_layers()
|
|
672
683
|
|
|
673
|
-
assert load_context.app_id # type narrowing
|
|
674
|
-
environment = await _get_environment_cached(load_context.environment_name or "", load_context.client)
|
|
675
|
-
# A bit hacky,but assume that the environment provides a valid builder version
|
|
676
|
-
image_builder_version = cast(ImageBuilderVersion, environment._settings.image_builder_version)
|
|
677
|
-
builder_version = _get_image_builder_version(image_builder_version)
|
|
678
|
-
|
|
679
684
|
if dockerfile_function is None:
|
|
680
685
|
dockerfile = DockerfileSpec(commands=[], context_files={})
|
|
681
686
|
else:
|
|
@@ -847,7 +852,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
847
852
|
return _Image._from_args(
|
|
848
853
|
base_images={"base": self},
|
|
849
854
|
dockerfile_function=build_dockerfile,
|
|
850
|
-
context_mount_function=lambda: mount,
|
|
855
|
+
context_mount_function=lambda builder_version: mount,
|
|
851
856
|
)
|
|
852
857
|
|
|
853
858
|
@_requires_image_instance
|
|
@@ -2191,12 +2196,9 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2191
2196
|
"COPY /python/. /usr/local",
|
|
2192
2197
|
"ENV TERMINFO_DIRS=/etc/terminfo:/lib/terminfo:/usr/share/terminfo:/usr/lib/terminfo",
|
|
2193
2198
|
]
|
|
2194
|
-
|
|
2195
|
-
if
|
|
2196
|
-
|
|
2197
|
-
if int(python_minor) < 13:
|
|
2198
|
-
# Previous versions did not include the `python` binary, but later ones do.
|
|
2199
|
-
# (The important factor is not the Python version itself, but the standalone dist version.)
|
|
2199
|
+
release, _ = PYTHON_STANDALONE_VERSIONS[builder_version][add_python]
|
|
2200
|
+
if release < "20241008":
|
|
2201
|
+
# Older standalone releases do not include the `python` binary.
|
|
2200
2202
|
# We insert the command in the list at the position it was previously always added
|
|
2201
2203
|
# for backwards compatibility with existing images.
|
|
2202
2204
|
add_python_commands.insert(1, "RUN ln -s /usr/local/bin/python3 /usr/local/bin/python")
|
|
@@ -2271,10 +2273,10 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2271
2273
|
```
|
|
2272
2274
|
"""
|
|
2273
2275
|
|
|
2274
|
-
def context_mount_function() -> _Mount | None:
|
|
2276
|
+
def context_mount_function(builder_version: ImageBuilderVersion) -> _Mount | None:
|
|
2275
2277
|
return (
|
|
2276
2278
|
_Mount.from_name(
|
|
2277
|
-
python_standalone_mount_name(add_python),
|
|
2279
|
+
python_standalone_mount_name(add_python, builder_version),
|
|
2278
2280
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL,
|
|
2279
2281
|
)
|
|
2280
2282
|
if add_python
|
|
@@ -2291,12 +2293,48 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2291
2293
|
context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, add_python)}
|
|
2292
2294
|
return DockerfileSpec(commands=commands, context_files=context_files)
|
|
2293
2295
|
|
|
2294
|
-
|
|
2296
|
+
single_layer_image = _Image._from_args(
|
|
2295
2297
|
dockerfile_function=build_dockerfile,
|
|
2296
2298
|
context_mount_function=context_mount_function,
|
|
2297
2299
|
force_build=force_build,
|
|
2298
2300
|
**kwargs,
|
|
2299
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
|
|
2300
2338
|
|
|
2301
2339
|
@staticmethod
|
|
2302
2340
|
def from_gcp_artifact_registry(
|
|
@@ -2516,16 +2554,17 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2516
2554
|
gpu_config=gpu_config,
|
|
2517
2555
|
secrets=secrets,
|
|
2518
2556
|
build_args=build_args,
|
|
2557
|
+
force_build=force_build,
|
|
2519
2558
|
)
|
|
2520
2559
|
|
|
2521
2560
|
# --- Now add in the modal dependencies, and, optionally a Python distribution
|
|
2522
2561
|
# This happening in two steps is probably a vestigial consequence of previous limitations,
|
|
2523
2562
|
# but it will be difficult to merge them without forcing rebuilds of images.
|
|
2524
2563
|
|
|
2525
|
-
def add_python_mount():
|
|
2564
|
+
def add_python_mount(builder_version: ImageBuilderVersion) -> _Mount | None:
|
|
2526
2565
|
return (
|
|
2527
2566
|
_Mount.from_name(
|
|
2528
|
-
python_standalone_mount_name(add_python),
|
|
2567
|
+
python_standalone_mount_name(add_python, builder_version),
|
|
2529
2568
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_GLOBAL,
|
|
2530
2569
|
)
|
|
2531
2570
|
if add_python
|
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.
|
|
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.
|
|
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[
|
|
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.
|
|
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[
|
|
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.
|
|
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[
|
|
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.
|
|
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]: ...
|
modal/image.pyi
CHANGED
|
@@ -74,7 +74,10 @@ class Image(modal.object.Object):
|
|
|
74
74
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
|
75
75
|
image_registry_config: typing.Optional[modal._image._ImageRegistryConfig] = None,
|
|
76
76
|
context_mount_function: typing.Optional[
|
|
77
|
-
collections.abc.Callable[
|
|
77
|
+
collections.abc.Callable[
|
|
78
|
+
[typing.Literal["2023.12", "2024.04", "2024.10", "2025.06", "PREVIEW"]],
|
|
79
|
+
typing.Optional[modal.mount.Mount],
|
|
80
|
+
]
|
|
78
81
|
] = None,
|
|
79
82
|
force_build: bool = False,
|
|
80
83
|
build_args: dict[str, str] = {},
|
modal/mount.py
CHANGED
|
@@ -39,11 +39,11 @@ from .file_pattern_matcher import FilePatternMatcher
|
|
|
39
39
|
ROOT_DIR: PurePosixPath = PurePosixPath("/root")
|
|
40
40
|
MOUNT_PUT_FILE_CLIENT_TIMEOUT = 10 * 60 # 10 min max for transferring files
|
|
41
41
|
|
|
42
|
-
# Supported releases and versions for python-build-standalone.
|
|
42
|
+
# Supported releases and versions for python-build-standalone, keyed by image builder version.
|
|
43
43
|
#
|
|
44
|
-
#
|
|
45
|
-
# that rely on `add_python()` in their constructor.
|
|
46
|
-
|
|
44
|
+
# Changing the versions for a builder version triggers a rebuild for all images on that builder
|
|
45
|
+
# version that rely on `add_python()` in their constructor, so only "PREVIEW" should be updated.
|
|
46
|
+
_PYTHON_STANDALONE_VERSIONS_2025_06: dict[str, tuple[str, str]] = {
|
|
47
47
|
"3.10": ("20230826", "3.10.13"),
|
|
48
48
|
"3.11": ("20230826", "3.11.5"),
|
|
49
49
|
"3.12": ("20240107", "3.12.1"),
|
|
@@ -53,6 +53,22 @@ PYTHON_STANDALONE_VERSIONS: dict[str, tuple[str, str]] = {
|
|
|
53
53
|
"3.15": ("20261009", "3.15.0"),
|
|
54
54
|
"3.15t": ("20261009", "3.15.0t"),
|
|
55
55
|
}
|
|
56
|
+
PYTHON_STANDALONE_VERSIONS: dict[str, dict[str, tuple[str, str]]] = {
|
|
57
|
+
"PREVIEW": {
|
|
58
|
+
"3.10": ("20261009", "3.10.22"),
|
|
59
|
+
"3.11": ("20261021", "3.11.17"),
|
|
60
|
+
"3.12": ("20261021", "3.12.15"),
|
|
61
|
+
"3.13": ("20261021", "3.13.17"),
|
|
62
|
+
"3.14": ("20261021", "3.14.9"),
|
|
63
|
+
"3.14t": ("20261021", "3.14.9t"),
|
|
64
|
+
"3.15": ("20261021", "3.15.1"),
|
|
65
|
+
"3.15t": ("20261021", "3.15.1t"),
|
|
66
|
+
},
|
|
67
|
+
"2025.06": _PYTHON_STANDALONE_VERSIONS_2025_06,
|
|
68
|
+
"2024.10": _PYTHON_STANDALONE_VERSIONS_2025_06,
|
|
69
|
+
"2024.04": _PYTHON_STANDALONE_VERSIONS_2025_06,
|
|
70
|
+
"2023.12": _PYTHON_STANDALONE_VERSIONS_2025_06,
|
|
71
|
+
}
|
|
56
72
|
|
|
57
73
|
MOUNT_DEPRECATION_MESSAGE_PATTERN = """modal.Mount usage will soon be deprecated.
|
|
58
74
|
|
|
@@ -72,20 +88,20 @@ def client_mount_name() -> str:
|
|
|
72
88
|
return f"modal-client-mount-{version}"
|
|
73
89
|
|
|
74
90
|
|
|
75
|
-
def python_standalone_mount_name(version: str) -> str:
|
|
91
|
+
def python_standalone_mount_name(version: str, builder_version: str) -> str:
|
|
76
92
|
"""Get the deployed name of the python-build-standalone mount."""
|
|
77
93
|
if "-" in version: # default to glibc
|
|
78
94
|
version, libc = version.split("-")
|
|
79
95
|
else:
|
|
80
96
|
libc = "gnu"
|
|
81
|
-
|
|
97
|
+
standalone_versions = PYTHON_STANDALONE_VERSIONS[builder_version]
|
|
98
|
+
if version not in standalone_versions:
|
|
82
99
|
raise modal.exception.InvalidError(
|
|
83
|
-
f"Unsupported standalone python version: {version!r}, supported values are "
|
|
84
|
-
f"{list(PYTHON_STANDALONE_VERSIONS)}"
|
|
100
|
+
f"Unsupported standalone python version: {version!r}, supported values are {list(standalone_versions)}"
|
|
85
101
|
)
|
|
86
102
|
if libc != "gnu":
|
|
87
103
|
raise modal.exception.InvalidError(f"Unsupported libc identifier: {libc}")
|
|
88
|
-
release, full_version =
|
|
104
|
+
release, full_version = standalone_versions[version]
|
|
89
105
|
return f"python-build-standalone.{release}.{full_version}-{libc}"
|
|
90
106
|
|
|
91
107
|
|
|
@@ -950,19 +966,25 @@ async def _create_single_client_dependency_mount(
|
|
|
950
966
|
|
|
951
967
|
async def _create_client_dependency_mounts(
|
|
952
968
|
client=None,
|
|
953
|
-
python_versions: list[str] =
|
|
954
|
-
builder_versions: list[str] =
|
|
969
|
+
python_versions: list[str] | None = None,
|
|
970
|
+
builder_versions: list[str] | None = None, # Pass "PREVIEW" during testing
|
|
955
971
|
check_if_exists=True,
|
|
956
972
|
dry_run=False,
|
|
957
973
|
):
|
|
974
|
+
from ._image import LATEST_IMAGE_BUILDER_VERSION, SUPPORTED_PYTHON_SERIES
|
|
975
|
+
|
|
958
976
|
arch = "x86_64"
|
|
959
977
|
platform_tags = [
|
|
960
978
|
("manylinux_2_17", f"{arch}-manylinux_2_17"), # glibc >= 2.17
|
|
961
979
|
("musllinux_1_2", f"{arch}-unknown-linux-musl"), # musl >= 1.2
|
|
962
980
|
]
|
|
963
981
|
coros = []
|
|
964
|
-
for
|
|
965
|
-
|
|
982
|
+
for builder_version in builder_versions or [LATEST_IMAGE_BUILDER_VERSION]:
|
|
983
|
+
if python_versions is None:
|
|
984
|
+
builder_python_versions = SUPPORTED_PYTHON_SERIES[builder_version]
|
|
985
|
+
else:
|
|
986
|
+
builder_python_versions = python_versions
|
|
987
|
+
for python_version in builder_python_versions:
|
|
966
988
|
for platform, uv_python_platform in platform_tags:
|
|
967
989
|
coros.append(
|
|
968
990
|
_create_single_client_dependency_mount(
|
modal/mount.pyi
CHANGED
|
@@ -16,7 +16,7 @@ def client_mount_name() -> str:
|
|
|
16
16
|
"""Get the deployed name of the client package mount."""
|
|
17
17
|
...
|
|
18
18
|
|
|
19
|
-
def python_standalone_mount_name(version: str) -> str:
|
|
19
|
+
def python_standalone_mount_name(version: str, builder_version: str) -> str:
|
|
20
20
|
"""Get the deployed name of the python-build-standalone mount."""
|
|
21
21
|
...
|
|
22
22
|
|
|
@@ -444,8 +444,8 @@ async def _create_single_client_dependency_mount(
|
|
|
444
444
|
): ...
|
|
445
445
|
async def _create_client_dependency_mounts(
|
|
446
446
|
client=None,
|
|
447
|
-
python_versions: list[str] =
|
|
448
|
-
builder_versions: list[str] =
|
|
447
|
+
python_versions: typing.Optional[list[str]] = None,
|
|
448
|
+
builder_versions: typing.Optional[list[str]] = None,
|
|
449
449
|
check_if_exists=True,
|
|
450
450
|
dry_run=False,
|
|
451
451
|
): ...
|
|
@@ -455,8 +455,8 @@ class __create_client_dependency_mounts_spec(typing_extensions.Protocol):
|
|
|
455
455
|
self,
|
|
456
456
|
/,
|
|
457
457
|
client=None,
|
|
458
|
-
python_versions: list[str] =
|
|
459
|
-
builder_versions: list[str] =
|
|
458
|
+
python_versions: typing.Optional[list[str]] = None,
|
|
459
|
+
builder_versions: typing.Optional[list[str]] = None,
|
|
460
460
|
check_if_exists=True,
|
|
461
461
|
dry_run=False,
|
|
462
462
|
): ...
|
|
@@ -464,8 +464,8 @@ class __create_client_dependency_mounts_spec(typing_extensions.Protocol):
|
|
|
464
464
|
self,
|
|
465
465
|
/,
|
|
466
466
|
client=None,
|
|
467
|
-
python_versions: list[str] =
|
|
468
|
-
builder_versions: list[str] =
|
|
467
|
+
python_versions: typing.Optional[list[str]] = None,
|
|
468
|
+
builder_versions: typing.Optional[list[str]] = None,
|
|
469
469
|
check_if_exists=True,
|
|
470
470
|
dry_run=False,
|
|
471
471
|
): ...
|
|
@@ -474,4 +474,6 @@ create_client_dependency_mounts: __create_client_dependency_mounts_spec
|
|
|
474
474
|
|
|
475
475
|
ROOT_DIR: pathlib.PurePosixPath
|
|
476
476
|
|
|
477
|
-
|
|
477
|
+
_PYTHON_STANDALONE_VERSIONS_2025_06: dict[str, tuple[str, str]]
|
|
478
|
+
|
|
479
|
+
PYTHON_STANDALONE_VERSIONS: dict[str, dict[str, tuple[str, str]]]
|
|
@@ -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=
|
|
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=
|
|
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,13 +56,13 @@ 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=
|
|
59
|
+
modal/functions.pyi,sha256=33XS_ROlsagDDnVDCMIWUsuddB_CxhM4Di32gf_ZLx4,62671
|
|
60
60
|
modal/image.py,sha256=c0lUSAoU-Ip3g5DGZ0uhdCzoWSQWh1g0i-7Rxo-Sz-I,160
|
|
61
|
-
modal/image.pyi,sha256=
|
|
61
|
+
modal/image.pyi,sha256=L53g84DVKa94LvqSqqYZLpG2o9-vxcC5vp5pXKQB3f0,61210
|
|
62
62
|
modal/io_streams.py,sha256=iWwhGCcTwhNtIo2t2f-qVV3FBEK1DIi40Tm_Ai01eYA,32992
|
|
63
63
|
modal/io_streams.pyi,sha256=ciTHe1pyl6Wii7QEI5cPRmnHBLOw3sOh_AnWsQlpzTw,26345
|
|
64
|
-
modal/mount.py,sha256=
|
|
65
|
-
modal/mount.pyi,sha256=
|
|
64
|
+
modal/mount.py,sha256=Wmt6F0aUqTZHQycu_Rs-qrHlngdtNnSgLGLVv4ex4mY,38767
|
|
65
|
+
modal/mount.pyi,sha256=RjYRGZzFe0RYpnZT6aXkZRsIsFyPAa9F-3gz9uXkRfA,16639
|
|
66
66
|
modal/network_file_system.py,sha256=2uNLvtvN-WnDJlriKqQE5e4Eh10dJHFGGIEQH7xlaKc,14617
|
|
67
67
|
modal/network_file_system.pyi,sha256=Z1BFJJSd99g1IKZXydikE6fuYWu0vQ2uBsApG9WX4H8,18037
|
|
68
68
|
modal/object.py,sha256=bTeskuY8JFrESjU4_UL_nTwYlBQdOLmVaOX3X6EMxsg,164
|
|
@@ -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.
|
|
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=
|
|
227
|
-
modal_proto/api_pb2.pyi,sha256=
|
|
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=
|
|
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.
|
|
240
|
-
modal-1.6.3.
|
|
241
|
-
modal-1.6.3.
|
|
242
|
-
modal-1.6.3.
|
|
243
|
-
modal-1.6.3.
|
|
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,,
|