modAL 1.2.7.dev11__tar.gz → 1.2.7.dev13__tar.gz
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-1.2.7.dev11 → modal-1.2.7.dev13}/PKG-INFO +5 -5
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/README.md +1 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/__init__.py +2 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_functions.py +12 -6
- modal-1.2.7.dev13/modal/_ipython.py +21 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_object.py +16 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/container_io_manager.pyi +42 -44
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_serialization.py +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/async_utils.py +310 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/grpc_testing.py +6 -3
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/rand_pb_testing.py +8 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/cloudpickle.py +144 -48
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/app.py +5 -4
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/app.pyi +11 -11
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2025.06.txt +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/PREVIEW.txt +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/base-images.json +4 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/run.py +14 -4
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/client.py +3 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/client.pyi +88 -48
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cls.py +1 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cls.pyi +6 -8
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/config.py +1 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/container_process.pyi +6 -8
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/dict.py +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/dict.pyi +84 -57
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/exception.py +4 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/flash.pyi +28 -30
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_io.pyi +105 -62
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/functions.pyi +56 -80
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/image.py +12 -7
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/image.pyi +20 -21
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/io_streams.pyi +4 -6
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/mount.py +1 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/mount.pyi +8 -10
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/network_file_system.pyi +60 -37
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/object.pyi +91 -26
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/parallel_map.pyi +6 -8
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/partial_function.pyi +0 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/queue.py +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/queue.pyi +76 -50
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/sandbox.py +3 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/sandbox.pyi +52 -54
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/secret.py +2 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/secret.pyi +7 -9
- modal-1.2.7.dev13/modal/snapshot.py +56 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/snapshot.pyi +18 -10
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/token_flow.pyi +4 -6
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/volume.py +15 -5
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/volume.pyi +95 -68
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/PKG-INFO +5 -5
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/requires.txt +2 -2
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_version/__init__.py +1 -1
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/pyproject.toml +5 -3
- modal-1.2.7.dev11/modal/_ipython.py +0 -11
- modal-1.2.7.dev11/modal/snapshot.py +0 -45
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/LICENSE +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/__main__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_billing.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_clustered_functions.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_grpc_client.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_load_context.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_location.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_output.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_partial_function.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_pty.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_resolver.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_resources.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_traceback.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_tunnel.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_tunnel.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_type_manager.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/logger.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/_watcher.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/billing.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/builder/README.md +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/call_graph.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/_download.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/_traceback.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/app.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/cluster.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/config.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/container.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/dict.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/entry_point.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/environment.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/import_refs.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/launch.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/profile.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/queues.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/secret.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/shell.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/token.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/utils.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cli/volume.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/container_process.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/environments.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/environments.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/flash.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/experimental/ipython.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_io.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/functions.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/gpu.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/io_streams.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/network_file_system.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/object.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/output.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/parallel_map.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/partial_function.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/proxy.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/proxy.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/py.typed +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/retries.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/runner.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/runner.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/running_app.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/schedule.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/scheduler_placement.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/serving.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/serving.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/stream_type.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal/token_flow.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/__init__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api.proto +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/py.typed +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/modal_version/__main__.py +0 -0
- {modal-1.2.7.dev11 → modal-1.2.7.dev13}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modal
|
|
3
|
-
Version: 1.2.7.
|
|
3
|
+
Version: 1.2.7.dev13
|
|
4
4
|
Summary: Python client library for Modal
|
|
5
5
|
Author-email: Modal Labs <support@modal.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -13,17 +13,17 @@ Classifier: Topic :: System :: Distributed Computing
|
|
|
13
13
|
Classifier: Operating System :: OS Independent
|
|
14
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Requires-Python: <3.
|
|
16
|
+
Requires-Python: <3.15,>=3.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Requires-Dist: aiohttp
|
|
20
20
|
Requires-Dist: cbor2
|
|
21
21
|
Requires-Dist: certifi
|
|
22
22
|
Requires-Dist: click~=8.1
|
|
23
|
-
Requires-Dist: grpclib<0.4.
|
|
23
|
+
Requires-Dist: grpclib<0.4.10,>=0.4.7
|
|
24
24
|
Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
|
|
25
25
|
Requires-Dist: rich>=12.0.0
|
|
26
|
-
Requires-Dist: synchronicity~=0.
|
|
26
|
+
Requires-Dist: synchronicity~=0.11.1
|
|
27
27
|
Requires-Dist: toml
|
|
28
28
|
Requires-Dist: typer>=0.9
|
|
29
29
|
Requires-Dist: types-certifi
|
|
@@ -51,7 +51,7 @@ a [user guide](https://modal.com/docs/guide), and the detailed
|
|
|
51
51
|
|
|
52
52
|
## Installation
|
|
53
53
|
|
|
54
|
-
**This library requires Python 3.10 – 3.
|
|
54
|
+
**This library requires Python 3.10 – 3.14.**
|
|
55
55
|
|
|
56
56
|
Install the package with `uv` or `pip`:
|
|
57
57
|
|
|
@@ -3,8 +3,8 @@ import sys
|
|
|
3
3
|
|
|
4
4
|
if sys.version_info[:2] < (3, 10):
|
|
5
5
|
raise RuntimeError("This version of Modal requires at least Python 3.10")
|
|
6
|
-
if sys.version_info[:2] >= (3,
|
|
7
|
-
raise RuntimeError("This version of Modal does not support Python 3.
|
|
6
|
+
if sys.version_info[:2] >= (3, 15):
|
|
7
|
+
raise RuntimeError("This version of Modal does not support Python 3.15+")
|
|
8
8
|
|
|
9
9
|
from modal_version import __version__
|
|
10
10
|
|
|
@@ -38,6 +38,7 @@ from ._utils.async_utils import (
|
|
|
38
38
|
aclosing,
|
|
39
39
|
async_merge,
|
|
40
40
|
callable_to_agen,
|
|
41
|
+
deprecate_aio_usage,
|
|
41
42
|
synchronizer,
|
|
42
43
|
warn_if_generator_is_not_consumed,
|
|
43
44
|
)
|
|
@@ -96,6 +97,7 @@ from .volume import _Volume
|
|
|
96
97
|
if TYPE_CHECKING:
|
|
97
98
|
import modal.app
|
|
98
99
|
import modal.cls
|
|
100
|
+
import modal.functions
|
|
99
101
|
|
|
100
102
|
MAX_INTERNAL_FAILURE_COUNT = 8
|
|
101
103
|
TERMINAL_STATUSES = (
|
|
@@ -2025,8 +2027,11 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2025
2027
|
assert self._client and self._client.stub
|
|
2026
2028
|
await self._client.stub.FunctionCallCancel(request)
|
|
2027
2029
|
|
|
2028
|
-
@
|
|
2029
|
-
|
|
2030
|
+
@deprecate_aio_usage((2025, 11, 14), "FunctionCall.from_id")
|
|
2031
|
+
@classmethod
|
|
2032
|
+
def from_id(
|
|
2033
|
+
cls, function_call_id: str, client: Optional["modal.client.Client"] = None
|
|
2034
|
+
) -> "modal.functions.FunctionCall[Any]":
|
|
2030
2035
|
"""Instantiate a FunctionCall object from an existing ID.
|
|
2031
2036
|
|
|
2032
2037
|
Examples:
|
|
@@ -2037,7 +2042,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2037
2042
|
fc_id = fc.object_id
|
|
2038
2043
|
|
|
2039
2044
|
# Later, use the ID to re-instantiate the FunctionCall object
|
|
2040
|
-
fc =
|
|
2045
|
+
fc = FunctionCall.from_id(fc_id)
|
|
2041
2046
|
result = fc.get()
|
|
2042
2047
|
```
|
|
2043
2048
|
|
|
@@ -2045,6 +2050,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2045
2050
|
if you no longer have access to the original object returned from `Function.spawn`.
|
|
2046
2051
|
|
|
2047
2052
|
"""
|
|
2053
|
+
_client = typing.cast(_Client, synchronizer._translate_in(client))
|
|
2048
2054
|
|
|
2049
2055
|
async def _load(
|
|
2050
2056
|
self: _FunctionCall, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
|
|
@@ -2053,10 +2059,10 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2053
2059
|
self._hydrate(function_call_id, load_context.client, None)
|
|
2054
2060
|
|
|
2055
2061
|
rep = f"FunctionCall.from_id({function_call_id!r})"
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
_load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
|
|
2062
|
+
impl_instance = _FunctionCall._from_loader(
|
|
2063
|
+
_load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=_client)
|
|
2059
2064
|
)
|
|
2065
|
+
return typing.cast("modal.functions.FunctionCall[Any]", synchronizer._translate_out(impl_instance))
|
|
2060
2066
|
|
|
2061
2067
|
@staticmethod
|
|
2062
2068
|
async def gather(*function_calls: "_FunctionCall[T]") -> typing.Sequence[T]:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright Modal Labs 2022
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def is_interactive_ipython():
|
|
6
|
+
"""
|
|
7
|
+
Detect if we're running in an interactive IPython session.
|
|
8
|
+
|
|
9
|
+
Returns True for IPython shells (including Jupyter notebooks), False otherwise.
|
|
10
|
+
"""
|
|
11
|
+
try:
|
|
12
|
+
# Check if IPython is available and get the current instance
|
|
13
|
+
ipython = sys.modules.get("IPython")
|
|
14
|
+
if ipython is None:
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
# Try to get the active IPython instance
|
|
18
|
+
shell = ipython.get_ipython()
|
|
19
|
+
return shell is not None
|
|
20
|
+
except Exception:
|
|
21
|
+
return False
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
|
+
import contextlib
|
|
2
3
|
import typing
|
|
3
4
|
import uuid
|
|
4
5
|
from collections.abc import Awaitable, Hashable, Sequence
|
|
@@ -350,3 +351,18 @@ def live_method_gen(method):
|
|
|
350
351
|
yield item
|
|
351
352
|
|
|
352
353
|
return wrapped
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def live_method_contextmanager(method):
|
|
357
|
+
# make sure a wrapped function returning an async context manager
|
|
358
|
+
# will not require both an `await func.aio()` and `async with`
|
|
359
|
+
# which would have been the case if it was wrapped in live_method
|
|
360
|
+
|
|
361
|
+
@wraps(method)
|
|
362
|
+
@contextlib.asynccontextmanager
|
|
363
|
+
async def wrapped(self, *args, **kwargs):
|
|
364
|
+
await self.hydrate()
|
|
365
|
+
async with method(self, *args, **kwargs) as ctx:
|
|
366
|
+
yield ctx
|
|
367
|
+
|
|
368
|
+
return wrapped
|
|
@@ -252,8 +252,6 @@ class _ContainerIOManager:
|
|
|
252
252
|
@classmethod
|
|
253
253
|
def stop_fetching_inputs(cls): ...
|
|
254
254
|
|
|
255
|
-
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
|
256
|
-
|
|
257
255
|
class ContainerIOManager:
|
|
258
256
|
"""Synchronizes all RPC calls and network operations for a running container.
|
|
259
257
|
|
|
@@ -298,47 +296,47 @@ class ContainerIOManager:
|
|
|
298
296
|
"""Only used for tests."""
|
|
299
297
|
...
|
|
300
298
|
|
|
301
|
-
class __hello_spec(typing_extensions.Protocol
|
|
299
|
+
class __hello_spec(typing_extensions.Protocol):
|
|
302
300
|
def __call__(self, /): ...
|
|
303
301
|
async def aio(self, /): ...
|
|
304
302
|
|
|
305
|
-
hello: __hello_spec
|
|
303
|
+
hello: __hello_spec
|
|
306
304
|
|
|
307
|
-
class ___run_heartbeat_loop_spec(typing_extensions.Protocol
|
|
305
|
+
class ___run_heartbeat_loop_spec(typing_extensions.Protocol):
|
|
308
306
|
def __call__(self, /): ...
|
|
309
307
|
async def aio(self, /): ...
|
|
310
308
|
|
|
311
|
-
_run_heartbeat_loop: ___run_heartbeat_loop_spec
|
|
309
|
+
_run_heartbeat_loop: ___run_heartbeat_loop_spec
|
|
312
310
|
|
|
313
|
-
class ___heartbeat_handle_cancellations_spec(typing_extensions.Protocol
|
|
311
|
+
class ___heartbeat_handle_cancellations_spec(typing_extensions.Protocol):
|
|
314
312
|
def __call__(self, /) -> bool: ...
|
|
315
313
|
async def aio(self, /) -> bool: ...
|
|
316
314
|
|
|
317
|
-
_heartbeat_handle_cancellations: ___heartbeat_handle_cancellations_spec
|
|
315
|
+
_heartbeat_handle_cancellations: ___heartbeat_handle_cancellations_spec
|
|
318
316
|
|
|
319
|
-
class __heartbeats_spec(typing_extensions.Protocol
|
|
317
|
+
class __heartbeats_spec(typing_extensions.Protocol):
|
|
320
318
|
def __call__(
|
|
321
319
|
self, /, wait_for_mem_snap: bool
|
|
322
320
|
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
|
323
321
|
def aio(self, /, wait_for_mem_snap: bool) -> typing.AsyncContextManager[None]: ...
|
|
324
322
|
|
|
325
|
-
heartbeats: __heartbeats_spec
|
|
323
|
+
heartbeats: __heartbeats_spec
|
|
326
324
|
|
|
327
325
|
def stop_heartbeat(self): ...
|
|
328
326
|
|
|
329
|
-
class __dynamic_concurrency_manager_spec(typing_extensions.Protocol
|
|
327
|
+
class __dynamic_concurrency_manager_spec(typing_extensions.Protocol):
|
|
330
328
|
def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]: ...
|
|
331
329
|
def aio(self, /) -> typing.AsyncContextManager[None]: ...
|
|
332
330
|
|
|
333
|
-
dynamic_concurrency_manager: __dynamic_concurrency_manager_spec
|
|
331
|
+
dynamic_concurrency_manager: __dynamic_concurrency_manager_spec
|
|
334
332
|
|
|
335
|
-
class ___dynamic_concurrency_loop_spec(typing_extensions.Protocol
|
|
333
|
+
class ___dynamic_concurrency_loop_spec(typing_extensions.Protocol):
|
|
336
334
|
def __call__(self, /): ...
|
|
337
335
|
async def aio(self, /): ...
|
|
338
336
|
|
|
339
|
-
_dynamic_concurrency_loop: ___dynamic_concurrency_loop_spec
|
|
337
|
+
_dynamic_concurrency_loop: ___dynamic_concurrency_loop_spec
|
|
340
338
|
|
|
341
|
-
class __get_data_in_spec(typing_extensions.Protocol
|
|
339
|
+
class __get_data_in_spec(typing_extensions.Protocol):
|
|
342
340
|
def __call__(
|
|
343
341
|
self, /, function_call_id: str, attempt_token: typing.Optional[str]
|
|
344
342
|
) -> typing.Iterator[typing.Any]:
|
|
@@ -351,9 +349,9 @@ class ContainerIOManager:
|
|
|
351
349
|
"""Read from the `data_in` stream of a function call."""
|
|
352
350
|
...
|
|
353
351
|
|
|
354
|
-
get_data_in: __get_data_in_spec
|
|
352
|
+
get_data_in: __get_data_in_spec
|
|
355
353
|
|
|
356
|
-
class __put_data_out_spec(typing_extensions.Protocol
|
|
354
|
+
class __put_data_out_spec(typing_extensions.Protocol):
|
|
357
355
|
def __call__(
|
|
358
356
|
self,
|
|
359
357
|
/,
|
|
@@ -388,9 +386,9 @@ class ContainerIOManager:
|
|
|
388
386
|
"""
|
|
389
387
|
...
|
|
390
388
|
|
|
391
|
-
put_data_out: __put_data_out_spec
|
|
389
|
+
put_data_out: __put_data_out_spec
|
|
392
390
|
|
|
393
|
-
class __generator_output_sender_spec(typing_extensions.Protocol
|
|
391
|
+
class __generator_output_sender_spec(typing_extensions.Protocol):
|
|
394
392
|
def __call__(
|
|
395
393
|
self, /, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.queues.Queue
|
|
396
394
|
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
|
@@ -403,9 +401,9 @@ class ContainerIOManager:
|
|
|
403
401
|
"""Runs background task that feeds generator outputs into a function call's `data_out` stream."""
|
|
404
402
|
...
|
|
405
403
|
|
|
406
|
-
generator_output_sender: __generator_output_sender_spec
|
|
404
|
+
generator_output_sender: __generator_output_sender_spec
|
|
407
405
|
|
|
408
|
-
class ___queue_create_spec(typing_extensions.Protocol
|
|
406
|
+
class ___queue_create_spec(typing_extensions.Protocol):
|
|
409
407
|
def __call__(self, /, size: int) -> asyncio.queues.Queue:
|
|
410
408
|
"""Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
|
|
411
409
|
...
|
|
@@ -414,9 +412,9 @@ class ContainerIOManager:
|
|
|
414
412
|
"""Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
|
|
415
413
|
...
|
|
416
414
|
|
|
417
|
-
_queue_create: ___queue_create_spec
|
|
415
|
+
_queue_create: ___queue_create_spec
|
|
418
416
|
|
|
419
|
-
class ___queue_put_spec(typing_extensions.Protocol
|
|
417
|
+
class ___queue_put_spec(typing_extensions.Protocol):
|
|
420
418
|
def __call__(self, /, queue: asyncio.queues.Queue, value: typing.Any) -> None:
|
|
421
419
|
"""Put a value onto a queue, using the synchronicity event loop."""
|
|
422
420
|
...
|
|
@@ -425,12 +423,12 @@ class ContainerIOManager:
|
|
|
425
423
|
"""Put a value onto a queue, using the synchronicity event loop."""
|
|
426
424
|
...
|
|
427
425
|
|
|
428
|
-
_queue_put: ___queue_put_spec
|
|
426
|
+
_queue_put: ___queue_put_spec
|
|
429
427
|
|
|
430
428
|
def get_average_call_time(self) -> float: ...
|
|
431
429
|
def get_max_inputs_to_fetch(self): ...
|
|
432
430
|
|
|
433
|
-
class ___generate_inputs_spec(typing_extensions.Protocol
|
|
431
|
+
class ___generate_inputs_spec(typing_extensions.Protocol):
|
|
434
432
|
def __call__(
|
|
435
433
|
self, /, batch_max_size: int, batch_wait_ms: int
|
|
436
434
|
) -> typing.Iterator[list[tuple[str, int, str, str, modal_proto.api_pb2.FunctionInput]]]: ...
|
|
@@ -438,9 +436,9 @@ class ContainerIOManager:
|
|
|
438
436
|
self, /, batch_max_size: int, batch_wait_ms: int
|
|
439
437
|
) -> collections.abc.AsyncIterator[list[tuple[str, int, str, str, modal_proto.api_pb2.FunctionInput]]]: ...
|
|
440
438
|
|
|
441
|
-
_generate_inputs: ___generate_inputs_spec
|
|
439
|
+
_generate_inputs: ___generate_inputs_spec
|
|
442
440
|
|
|
443
|
-
class __run_inputs_outputs_spec(typing_extensions.Protocol
|
|
441
|
+
class __run_inputs_outputs_spec(typing_extensions.Protocol):
|
|
444
442
|
def __call__(
|
|
445
443
|
self,
|
|
446
444
|
/,
|
|
@@ -456,9 +454,9 @@ class ContainerIOManager:
|
|
|
456
454
|
batch_wait_ms: int = 0,
|
|
457
455
|
) -> collections.abc.AsyncIterator[IOContext]: ...
|
|
458
456
|
|
|
459
|
-
run_inputs_outputs: __run_inputs_outputs_spec
|
|
457
|
+
run_inputs_outputs: __run_inputs_outputs_spec
|
|
460
458
|
|
|
461
|
-
class ___send_outputs_spec(typing_extensions.Protocol
|
|
459
|
+
class ___send_outputs_spec(typing_extensions.Protocol):
|
|
462
460
|
def __call__(self, /, started_at: float, outputs: list[modal_proto.api_pb2.FunctionPutOutputsItem]) -> None:
|
|
463
461
|
"""Send pre-built output items with retry and chunking."""
|
|
464
462
|
...
|
|
@@ -467,9 +465,9 @@ class ContainerIOManager:
|
|
|
467
465
|
"""Send pre-built output items with retry and chunking."""
|
|
468
466
|
...
|
|
469
467
|
|
|
470
|
-
_send_outputs: ___send_outputs_spec
|
|
468
|
+
_send_outputs: ___send_outputs_spec
|
|
471
469
|
|
|
472
|
-
class __handle_user_exception_spec(typing_extensions.Protocol
|
|
470
|
+
class __handle_user_exception_spec(typing_extensions.Protocol):
|
|
473
471
|
def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
|
474
472
|
"""Sets the task as failed in a way where it's not retried.
|
|
475
473
|
|
|
@@ -486,9 +484,9 @@ class ContainerIOManager:
|
|
|
486
484
|
"""
|
|
487
485
|
...
|
|
488
486
|
|
|
489
|
-
handle_user_exception: __handle_user_exception_spec
|
|
487
|
+
handle_user_exception: __handle_user_exception_spec
|
|
490
488
|
|
|
491
|
-
class __handle_input_exception_spec(typing_extensions.Protocol
|
|
489
|
+
class __handle_input_exception_spec(typing_extensions.Protocol):
|
|
492
490
|
def __call__(
|
|
493
491
|
self, /, io_context: IOContext, started_at: float
|
|
494
492
|
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
|
@@ -499,23 +497,23 @@ class ContainerIOManager:
|
|
|
499
497
|
"""Handle an exception while processing a function input."""
|
|
500
498
|
...
|
|
501
499
|
|
|
502
|
-
handle_input_exception: __handle_input_exception_spec
|
|
500
|
+
handle_input_exception: __handle_input_exception_spec
|
|
503
501
|
|
|
504
502
|
def exit_context(self, started_at, input_ids: list[str]): ...
|
|
505
503
|
|
|
506
|
-
class __push_outputs_spec(typing_extensions.Protocol
|
|
504
|
+
class __push_outputs_spec(typing_extensions.Protocol):
|
|
507
505
|
def __call__(self, /, io_context: IOContext, started_at: float, output_data: list[typing.Any]) -> None: ...
|
|
508
506
|
async def aio(self, /, io_context: IOContext, started_at: float, output_data: list[typing.Any]) -> None: ...
|
|
509
507
|
|
|
510
|
-
push_outputs: __push_outputs_spec
|
|
508
|
+
push_outputs: __push_outputs_spec
|
|
511
509
|
|
|
512
|
-
class __memory_restore_spec(typing_extensions.Protocol
|
|
510
|
+
class __memory_restore_spec(typing_extensions.Protocol):
|
|
513
511
|
def __call__(self, /) -> None: ...
|
|
514
512
|
async def aio(self, /) -> None: ...
|
|
515
513
|
|
|
516
|
-
memory_restore: __memory_restore_spec
|
|
514
|
+
memory_restore: __memory_restore_spec
|
|
517
515
|
|
|
518
|
-
class __memory_snapshot_spec(typing_extensions.Protocol
|
|
516
|
+
class __memory_snapshot_spec(typing_extensions.Protocol):
|
|
519
517
|
def __call__(self, /) -> None:
|
|
520
518
|
"""Message server indicating that function is ready to be checkpointed."""
|
|
521
519
|
...
|
|
@@ -524,9 +522,9 @@ class ContainerIOManager:
|
|
|
524
522
|
"""Message server indicating that function is ready to be checkpointed."""
|
|
525
523
|
...
|
|
526
524
|
|
|
527
|
-
memory_snapshot: __memory_snapshot_spec
|
|
525
|
+
memory_snapshot: __memory_snapshot_spec
|
|
528
526
|
|
|
529
|
-
class __volume_commit_spec(typing_extensions.Protocol
|
|
527
|
+
class __volume_commit_spec(typing_extensions.Protocol):
|
|
530
528
|
def __call__(self, /, volume_ids: list[str]) -> None:
|
|
531
529
|
"""Perform volume commit for given `volume_ids`.
|
|
532
530
|
Only used on container exit to persist uncommitted changes on behalf of user.
|
|
@@ -539,13 +537,13 @@ class ContainerIOManager:
|
|
|
539
537
|
"""
|
|
540
538
|
...
|
|
541
539
|
|
|
542
|
-
volume_commit: __volume_commit_spec
|
|
540
|
+
volume_commit: __volume_commit_spec
|
|
543
541
|
|
|
544
|
-
class __interact_spec(typing_extensions.Protocol
|
|
542
|
+
class __interact_spec(typing_extensions.Protocol):
|
|
545
543
|
def __call__(self, /, from_breakpoint: bool = False): ...
|
|
546
544
|
async def aio(self, /, from_breakpoint: bool = False): ...
|
|
547
545
|
|
|
548
|
-
interact: __interact_spec
|
|
546
|
+
interact: __interact_spec
|
|
549
547
|
|
|
550
548
|
@property
|
|
551
549
|
def target_concurrency(self) -> int: ...
|
|
@@ -420,7 +420,8 @@ def check_valid_cls_constructor_arg(key, obj):
|
|
|
420
420
|
try:
|
|
421
421
|
ClsConstructorPickler(buf).dump(obj)
|
|
422
422
|
return True
|
|
423
|
-
except (AttributeError, ValueError):
|
|
423
|
+
except (AttributeError, ValueError, pickle.PicklingError):
|
|
424
|
+
# Python 3.14+ now raises an PicklingError for certain types of `dump` failures
|
|
424
425
|
raise ValueError(
|
|
425
426
|
f"Only pickle-able types are allowed in remote class constructors: argument {key} of type {type(obj)}."
|
|
426
427
|
)
|