modal 1.1.5.dev35__tar.gz → 1.3.1.dev20__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.1.5.dev35 → modal-1.3.1.dev20}/PKG-INFO +11 -9
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/README.md +5 -5
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/__init__.py +4 -4
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/__main__.py +4 -29
- modal-1.3.1.dev20/modal/_billing.py +84 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_clustered_functions.py +1 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_container_entrypoint.py +52 -249
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_functions.py +204 -198
- modal-1.3.1.dev20/modal/_grpc_client.py +191 -0
- modal-1.3.1.dev20/modal/_ipython.py +21 -0
- modal-1.3.1.dev20/modal/_load_context.py +106 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_object.py +72 -21
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_output.py +55 -32
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_partial_function.py +31 -25
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_resolver.py +44 -57
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/container_io_manager.py +287 -179
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/container_io_manager.pyi +72 -90
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/gpu_memory_snapshot.py +24 -19
- modal-1.3.1.dev20/modal/_runtime/user_code_event_loop.py +80 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/user_code_imports.py +251 -15
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_serialization.py +59 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_traceback.py +4 -13
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_tunnel.py +16 -11
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_tunnel.pyi +25 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/async_utils.py +337 -10
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/auth_token_manager.py +1 -4
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/blob_utils.py +33 -22
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/function_utils.py +47 -29
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/grpc_testing.py +6 -3
- modal-1.3.1.dev20/modal/_utils/grpc_utils.py +450 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/mount_utils.py +26 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/name_utils.py +17 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/package_utils.py +0 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/rand_pb_testing.py +8 -1
- modal-1.3.1.dev20/modal/_utils/task_command_router_client.py +524 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_vendor/cloudpickle.py +144 -48
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/app.py +299 -109
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/app.pyi +233 -56
- modal-1.3.1.dev20/modal/billing.py +5 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/2025.06.txt +6 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/PREVIEW.txt +2 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/base-images.json +4 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/_download.py +19 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/cluster.py +4 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/config.py +3 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/container.py +10 -6
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/dict.py +5 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/entry_point.py +26 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/environment.py +6 -19
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/launch.py +1 -76
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/network_file_system.py +5 -20
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/programs/run_jupyter.py +1 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/programs/vscode.py +1 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/queues.py +5 -4
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/run.py +37 -198
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/secret.py +1 -2
- modal-1.3.1.dev20/modal/cli/shell.py +375 -0
- modal-1.3.1.dev20/modal/cli/token.py +108 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/utils.py +1 -13
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/volume.py +11 -17
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/client.py +16 -125
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/client.pyi +94 -144
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cloud_bucket_mount.py +3 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cloud_bucket_mount.pyi +4 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cls.py +98 -105
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cls.pyi +8 -85
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/config.py +26 -1
- modal-1.3.1.dev20/modal/container_process.py +472 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/container_process.pyi +99 -38
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/dict.py +86 -75
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/dict.pyi +109 -139
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/environments.py +15 -27
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/environments.pyi +5 -15
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/exception.py +154 -16
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/experimental/__init__.py +34 -38
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/experimental/flash.py +167 -74
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/experimental/flash.pyi +102 -47
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/file_io.py +50 -92
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/file_io.pyi +117 -89
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/functions.pyi +71 -136
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/image.py +126 -89
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/image.pyi +55 -35
- modal-1.3.1.dev20/modal/io_streams.py +822 -0
- modal-1.3.1.dev20/modal/io_streams.pyi +530 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/mount.py +66 -164
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/mount.pyi +33 -179
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/network_file_system.py +20 -51
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/network_file_system.pyi +53 -94
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/object.pyi +114 -22
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/output.py +2 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/parallel_map.py +44 -48
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/parallel_map.pyi +9 -17
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/partial_function.pyi +4 -3
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/proxy.py +14 -6
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/proxy.pyi +10 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/queue.py +44 -76
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/queue.pyi +81 -119
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/runner.py +111 -98
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/runner.pyi +45 -27
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/sandbox.py +231 -113
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/sandbox.pyi +232 -66
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/secret.py +57 -84
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/secret.pyi +28 -51
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/serving.py +7 -11
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/serving.pyi +7 -8
- modal-1.3.1.dev20/modal/snapshot.py +56 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/snapshot.pyi +18 -10
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/token_flow.py +1 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/token_flow.pyi +4 -6
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/volume.py +102 -96
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/volume.pyi +102 -120
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/PKG-INFO +11 -9
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/SOURCES.txt +13 -9
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/requires.txt +8 -2
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api.proto +225 -58
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api_grpc.py +91 -10
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api_pb2.py +1242 -1074
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api_pb2.pyi +621 -54
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api_pb2_grpc.py +180 -16
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/api_pb2_grpc.pyi +59 -11
- modal-1.3.1.dev20/modal_proto/modal_api_grpc.py +195 -0
- modal-1.3.1.dev20/modal_proto/task_command_router.proto +164 -0
- modal-1.3.1.dev20/modal_proto/task_command_router_grpc.py +138 -0
- modal-1.3.1.dev20/modal_proto/task_command_router_pb2.py +180 -0
- modal-1.3.1.dev20/modal_proto/task_command_router_pb2.pyi +384 -0
- modal-1.3.1.dev20/modal_proto/task_command_router_pb2_grpc.py +272 -0
- modal-1.3.1.dev20/modal_proto/task_command_router_pb2_grpc.pyi +100 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_version/__init__.py +1 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_version/__main__.py +1 -1
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/pyproject.toml +36 -10
- modal-1.1.5.dev35/modal/_ipython.py +0 -11
- modal-1.1.5.dev35/modal/_utils/grpc_utils.py +0 -293
- modal-1.1.5.dev35/modal/cli/programs/launch_instance_ssh.py +0 -94
- modal-1.1.5.dev35/modal/cli/programs/run_marimo.py +0 -95
- modal-1.1.5.dev35/modal/cli/token.py +0 -60
- modal-1.1.5.dev35/modal/container_process.py +0 -196
- modal-1.1.5.dev35/modal/io_streams.py +0 -471
- modal-1.1.5.dev35/modal/io_streams.pyi +0 -440
- modal-1.1.5.dev35/modal/snapshot.py +0 -42
- modal-1.1.5.dev35/modal_proto/modal_api_grpc.py +0 -190
- modal-1.1.5.dev35/modal_proto/modal_options_grpc.py +0 -3
- modal-1.1.5.dev35/modal_proto/options.proto +0 -19
- modal-1.1.5.dev35/modal_proto/options_grpc.py +0 -3
- modal-1.1.5.dev35/modal_proto/options_pb2.py +0 -35
- modal-1.1.5.dev35/modal_proto/options_pb2.pyi +0 -20
- modal-1.1.5.dev35/modal_proto/options_pb2_grpc.py +0 -4
- modal-1.1.5.dev35/modal_proto/options_pb2_grpc.pyi +0 -7
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/LICENSE +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_clustered_functions.pyi +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_location.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_pty.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_resources.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/asgi.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/execution_context.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_runtime/telemetry.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_type_manager.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/app_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/deprecation.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/docker_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/git_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/hash_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/http_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/logger.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/shell_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_utils/time_utils.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_vendor/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_vendor/tblib.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/_watcher.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/2023.12.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/2024.04.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/2024.10.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/builder/README.md +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/call_graph.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/_traceback.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/app.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/import_refs.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/profile.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/cli/programs/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/experimental/ipython.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/file_pattern_matcher.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/functions.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/gpu.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/object.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/partial_function.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/py.typed +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/retries.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/running_app.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/schedule.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/scheduler_placement.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal/stream_type.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal.egg-info/top_level.txt +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/__init__.py +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/modal_proto/py.typed +0 -0
- {modal-1.1.5.dev35 → modal-1.3.1.dev20}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modal
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.3.1.dev20
|
|
4
4
|
Summary: Python client library for Modal
|
|
5
5
|
Author-email: Modal Labs <support@modal.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -13,16 +13,18 @@ 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:
|
|
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
|
+
Requires-Dist: cbor2
|
|
20
21
|
Requires-Dist: certifi
|
|
21
22
|
Requires-Dist: click~=8.1
|
|
22
|
-
Requires-Dist: grpclib<0.4.
|
|
23
|
+
Requires-Dist: grpclib<0.4.10,>=0.4.7; python_version < "3.14"
|
|
24
|
+
Requires-Dist: grpclib<0.4.10,>=0.4.9; python_version >= "3.14"
|
|
23
25
|
Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
|
|
24
26
|
Requires-Dist: rich>=12.0.0
|
|
25
|
-
Requires-Dist: synchronicity~=0.
|
|
27
|
+
Requires-Dist: synchronicity~=0.11.1
|
|
26
28
|
Requires-Dist: toml
|
|
27
29
|
Requires-Dist: typer>=0.9
|
|
28
30
|
Requires-Dist: types-certifi
|
|
@@ -31,14 +33,14 @@ Requires-Dist: watchfiles
|
|
|
31
33
|
Requires-Dist: typing_extensions~=4.6
|
|
32
34
|
Dynamic: license-file
|
|
33
35
|
|
|
34
|
-
# Modal Python
|
|
36
|
+
# Modal Python SDK
|
|
35
37
|
|
|
36
38
|
[](https://pypi.org/project/modal/)
|
|
37
39
|
[](https://github.com/modal-labs/modal-client/blob/master/LICENSE)
|
|
38
40
|
[](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml)
|
|
39
41
|
[](https://modal.com/slack)
|
|
40
42
|
|
|
41
|
-
The [Modal](https://modal.com/) Python
|
|
43
|
+
The [Modal](https://modal.com/) Python SDK provides convenient, on-demand
|
|
42
44
|
access to serverless cloud compute from Python scripts on your local computer.
|
|
43
45
|
|
|
44
46
|
## Documentation
|
|
@@ -50,12 +52,12 @@ a [user guide](https://modal.com/docs/guide), and the detailed
|
|
|
50
52
|
|
|
51
53
|
## Installation
|
|
52
54
|
|
|
53
|
-
**This library requires Python 3.
|
|
55
|
+
**This library requires Python 3.10 – 3.14.**
|
|
54
56
|
|
|
55
|
-
Install the package with `pip`:
|
|
57
|
+
Install the package with `uv` or `pip`:
|
|
56
58
|
|
|
57
59
|
```bash
|
|
58
|
-
pip install modal
|
|
60
|
+
uv pip install modal
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
You can create a Modal account (or link your existing one) directly on the
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Modal Python
|
|
1
|
+
# Modal Python SDK
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/modal/)
|
|
4
4
|
[](https://github.com/modal-labs/modal-client/blob/master/LICENSE)
|
|
5
5
|
[](https://github.com/modal-labs/modal-client/actions/workflows/ci-cd.yml)
|
|
6
6
|
[](https://modal.com/slack)
|
|
7
7
|
|
|
8
|
-
The [Modal](https://modal.com/) Python
|
|
8
|
+
The [Modal](https://modal.com/) Python SDK provides convenient, on-demand
|
|
9
9
|
access to serverless cloud compute from Python scripts on your local computer.
|
|
10
10
|
|
|
11
11
|
## Documentation
|
|
@@ -17,12 +17,12 @@ a [user guide](https://modal.com/docs/guide), and the detailed
|
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
20
|
-
**This library requires Python 3.
|
|
20
|
+
**This library requires Python 3.10 – 3.14.**
|
|
21
21
|
|
|
22
|
-
Install the package with `pip`:
|
|
22
|
+
Install the package with `uv` or `pip`:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
pip install modal
|
|
25
|
+
uv pip install modal
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
You can create a Modal account (or link your existing one) directly on the
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
2
|
import sys
|
|
3
3
|
|
|
4
|
-
if sys.version_info[:2] < (3,
|
|
5
|
-
raise RuntimeError("This version of Modal requires at least Python 3.
|
|
6
|
-
if sys.version_info[:2] >= (3,
|
|
7
|
-
raise RuntimeError("This version of Modal does not support Python 3.
|
|
4
|
+
if sys.version_info[:2] < (3, 10):
|
|
5
|
+
raise RuntimeError("This version of Modal requires at least Python 3.10")
|
|
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
|
|
|
@@ -35,37 +35,12 @@ def main():
|
|
|
35
35
|
):
|
|
36
36
|
raise
|
|
37
37
|
|
|
38
|
-
from grpclib import GRPCError, Status
|
|
39
38
|
from rich.panel import Panel
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Status.CANCELLED: "Cancelled",
|
|
46
|
-
Status.DATA_LOSS: "Data loss",
|
|
47
|
-
Status.DEADLINE_EXCEEDED: "Deadline exceeded",
|
|
48
|
-
Status.FAILED_PRECONDITION: "Failed precondition",
|
|
49
|
-
Status.INTERNAL: "Internal",
|
|
50
|
-
Status.INVALID_ARGUMENT: "Invalid",
|
|
51
|
-
Status.NOT_FOUND: "Not found",
|
|
52
|
-
Status.OUT_OF_RANGE: "Out of range",
|
|
53
|
-
Status.PERMISSION_DENIED: "Permission denied",
|
|
54
|
-
Status.RESOURCE_EXHAUSTED: "Resource exhausted",
|
|
55
|
-
Status.UNAUTHENTICATED: "Unauthenticaed",
|
|
56
|
-
Status.UNAVAILABLE: "Unavailable",
|
|
57
|
-
Status.UNIMPLEMENTED: "Unimplemented",
|
|
58
|
-
Status.UNKNOWN: "Unknown",
|
|
59
|
-
}
|
|
60
|
-
title = f"Error: {status_map.get(exc.status, 'Unknown')}"
|
|
61
|
-
content = str(exc.message)
|
|
62
|
-
if exc.details:
|
|
63
|
-
content += f"\n\nDetails: {exc.details}"
|
|
64
|
-
else:
|
|
65
|
-
title = "Error"
|
|
66
|
-
content = str(exc)
|
|
67
|
-
if notes := getattr(exc, "__notes__", []):
|
|
68
|
-
content = f"{content}\n\nNote: {' '.join(notes)}"
|
|
40
|
+
title = "Error"
|
|
41
|
+
content = str(exc)
|
|
42
|
+
if notes := getattr(exc, "__notes__", []):
|
|
43
|
+
content = f"{content}\n\nNote: {' '.join(notes)}"
|
|
69
44
|
|
|
70
45
|
console = make_console(stderr=True)
|
|
71
46
|
panel = Panel(content, title=title, title_align="left", border_style="red")
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Copyright Modal Labs 2025
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from typing import Any, Optional, TypedDict
|
|
5
|
+
|
|
6
|
+
from modal_proto import api_pb2
|
|
7
|
+
|
|
8
|
+
from .client import _Client
|
|
9
|
+
from .exception import InvalidError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WorkspaceBillingReportItem(TypedDict):
|
|
13
|
+
object_id: str
|
|
14
|
+
description: str
|
|
15
|
+
environment_name: str
|
|
16
|
+
interval_start: datetime
|
|
17
|
+
cost: Decimal
|
|
18
|
+
tags: dict[str, str]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def _workspace_billing_report(
|
|
22
|
+
*,
|
|
23
|
+
start: datetime, # Start of the report, inclusive
|
|
24
|
+
end: Optional[datetime] = None, # End of the report, exclusive
|
|
25
|
+
resolution: str = "d", # Resolution, e.g. "d" for daily or "h" for hourly
|
|
26
|
+
tag_names: Optional[list[str]] = None, # Optional additional metadata to include
|
|
27
|
+
client: Optional[_Client] = None,
|
|
28
|
+
) -> list[dict[str, Any]]:
|
|
29
|
+
"""Generate a tabular report of workspace usage by object and time.
|
|
30
|
+
|
|
31
|
+
The result will be a list of dictionaries for each interval (determined by `resolution`)
|
|
32
|
+
between the `start` and `end` limits. The dictionary represents a single Modal object
|
|
33
|
+
that billing can be attributed to (e.g., an App) along with metadata (including user-defined
|
|
34
|
+
tags) for identifying that object.
|
|
35
|
+
|
|
36
|
+
The `start` and `end` parameters are required to either have a UTC timezone or to be
|
|
37
|
+
timezone-naive (which will be interpreted as UTC times). The timestamps in the result will
|
|
38
|
+
be in UTC. Cost will be reported for full intervals, even if the provided `start` or `end`
|
|
39
|
+
parameters are partial: `start` will be rounded to the beginning of its interval, while
|
|
40
|
+
partial `end` intervals will be excluded.
|
|
41
|
+
|
|
42
|
+
Additional user-provided metadata can be included in the report if the objects have tags
|
|
43
|
+
and `tag_names` (i.e., keys) are specified in the request. Note that tags will be attributed
|
|
44
|
+
to the entire interval even if they were added or removed at some point within it.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
if client is None:
|
|
48
|
+
client = await _Client.from_env()
|
|
49
|
+
|
|
50
|
+
tag_names = tag_names or []
|
|
51
|
+
|
|
52
|
+
if end is None:
|
|
53
|
+
end = datetime.now(timezone.utc)
|
|
54
|
+
|
|
55
|
+
if start.tzinfo is None:
|
|
56
|
+
start = start.replace(tzinfo=timezone.utc)
|
|
57
|
+
elif start.tzinfo != timezone.utc:
|
|
58
|
+
raise InvalidError("Timezone-aware 'start' parameter must be in UTC.")
|
|
59
|
+
|
|
60
|
+
if end.tzinfo is None:
|
|
61
|
+
end = end.replace(tzinfo=timezone.utc)
|
|
62
|
+
elif end.tzinfo != timezone.utc:
|
|
63
|
+
raise InvalidError("Timezone-aware 'end' parameter must be in UTC.")
|
|
64
|
+
|
|
65
|
+
request = api_pb2.WorkspaceBillingReportRequest(
|
|
66
|
+
resolution=resolution,
|
|
67
|
+
tag_names=tag_names,
|
|
68
|
+
)
|
|
69
|
+
request.start_timestamp.FromDatetime(start)
|
|
70
|
+
request.end_timestamp.FromDatetime(end)
|
|
71
|
+
|
|
72
|
+
rows = []
|
|
73
|
+
async for pb_item in client.stub.WorkspaceBillingReport.unary_stream(request):
|
|
74
|
+
item = {
|
|
75
|
+
"object_id": pb_item.object_id,
|
|
76
|
+
"description": pb_item.description,
|
|
77
|
+
"environment_name": pb_item.environment_name,
|
|
78
|
+
"interval_start": pb_item.interval.ToDatetime().replace(tzinfo=timezone.utc),
|
|
79
|
+
"cost": Decimal(pb_item.cost),
|
|
80
|
+
"tags": dict(pb_item.tags),
|
|
81
|
+
}
|
|
82
|
+
rows.append(item)
|
|
83
|
+
|
|
84
|
+
return rows
|
|
@@ -5,7 +5,6 @@ from dataclasses import dataclass
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
from modal._utils.async_utils import synchronize_api
|
|
8
|
-
from modal._utils.grpc_utils import retry_transient_errors
|
|
9
8
|
from modal.client import _Client
|
|
10
9
|
from modal.exception import InvalidError
|
|
11
10
|
from modal_proto import api_pb2
|
|
@@ -61,8 +60,7 @@ async def _initialize_clustered_function(client: _Client, task_id: str, world_si
|
|
|
61
60
|
os.environ["NCCL_NSOCKS_PERTHREAD"] = "1"
|
|
62
61
|
|
|
63
62
|
if world_size > 1:
|
|
64
|
-
resp
|
|
65
|
-
client.stub.TaskClusterHello,
|
|
63
|
+
resp = await client.stub.TaskClusterHello(
|
|
66
64
|
api_pb2.TaskClusterHelloRequest(
|
|
67
65
|
task_id=task_id,
|
|
68
66
|
container_ip=container_ip,
|