modal 1.5.1.dev14__tar.gz → 1.5.2.dev0__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.5.1.dev14 → modal-1.5.2.dev0}/PKG-INFO +1 -1
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_billing.py +2 -23
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_environments.py +27 -20
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_functions.py +5 -5
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_image.py +3 -4
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/gpu_memory_snapshot.py +5 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/task_lifecycle_manager.py +9 -4
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_server.py +31 -4
- modal-1.5.2.dev0/modal/_utils/curl_utils.py +115 -0
- modal-1.5.2.dev0/modal/_workspace.py +342 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/app.py +15 -13
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/app.pyi +30 -26
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/billing.pyi +0 -8
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/app.py +24 -3
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/billing.py +9 -9
- modal-1.5.2.dev0/modal/cli/curl.py +137 -0
- modal-1.5.2.dev0/modal/cli/endpoint.py +352 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/entry_point.py +8 -2
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/environment.py +10 -11
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/profile.py +20 -5
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/utils.py +8 -3
- modal-1.5.2.dev0/modal/cli/workspace.py +129 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/client.pyi +2 -2
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/config.py +3 -1
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/environments.pyi +57 -2
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/functions.pyi +16 -16
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox.py +16 -21
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox.pyi +18 -12
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/secret.py +39 -9
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/secret.pyi +19 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/server.pyi +65 -12
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/workspace.py +13 -1
- modal-1.5.2.dev0/modal/workspace.pyi +450 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/SOURCES.txt +4 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/mdmd.py +10 -1
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/types.py +1 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_grpc.py +16 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2.py +969 -949
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2.pyi +36 -2
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2_grpc.py +34 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/api_pb2_grpc.pyi +12 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/modal_api_grpc.py +1 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_version/__init__.py +1 -1
- modal-1.5.1.dev14/modal/_workspace.py +0 -191
- modal-1.5.1.dev14/modal/workspace.pyi +0 -139
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/LICENSE +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/README.md +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/__main__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_clustered_functions.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_clustered_functions.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_container_entrypoint.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_function_variants.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_grpc_client.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_ipython.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_load_context.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_location.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_logs.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_object.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/manager.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/pty.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/rich.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_output/status.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_partial_function.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_resolver.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_resources.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/asgi.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/execution_context.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/telemetry.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_serialization.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_traceback.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_tunnel.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_tunnel.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_type_manager.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/app_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/async_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/blob_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/browser_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/deprecation.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/docker_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/function_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/git_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/hash_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/http_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/logger.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/mount_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/name_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/package_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/proxy_support.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/shell_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_utils/time_utils.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/tblib.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_vendor/version.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/_watcher.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/billing.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2023.12.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2024.04.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2024.10.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/2025.06.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/README.md +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/builder/base-images.json +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/call_graph.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_download.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_help.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/_traceback.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/bootstrap.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/changelog.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/cluster.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/config.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/container.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/dashboard.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/dict.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/image.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/import_refs.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/launch.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/logo.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/network_file_system.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/programs/vscode.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/queues.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/run.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/secret.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/selector.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/shell.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/skills.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/token.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cli/volume.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/client.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cls.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/cls.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/container_process.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/container_process.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/dict.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/dict.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/environments.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/exception.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/flash.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/flash.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/experimental/ipython.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_io.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_io.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/file_pattern_matcher.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/functions.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/image.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/image.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/io_streams.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/io_streams.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/mount.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/mount.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/network_file_system.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/network_file_system.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/object.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/object.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/output.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/parallel_map.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/parallel_map.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/partial_function.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/partial_function.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/proxy.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/proxy.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/py.typed +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/queue.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/queue.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/retries.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/runner.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/runner.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/running_app.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox_fs.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/sandbox_fs.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/schedule.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/scheduler_placement.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/server.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/serving.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/serving.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/skills/modal/SKILL.md +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/snapshot.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/snapshot.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/stream_type.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/token_flow.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/token_flow.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/volume.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal/volume.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/requires.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal.egg-info/top_level.txt +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/__init__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/py.typed +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/modal_version/__main__.py +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/pyproject.toml +0 -0
- {modal-1.5.1.dev14 → modal-1.5.2.dev0}/setup.cfg +0 -0
|
@@ -9,24 +9,6 @@ from modal_proto import api_pb2
|
|
|
9
9
|
from ._utils.deprecation import deprecation_warning
|
|
10
10
|
from .client import _Client
|
|
11
11
|
|
|
12
|
-
BILLING_DOCSTRING = """
|
|
13
|
-
The `start` and `end` parameters are required to either have a UTC timezone or to be
|
|
14
|
-
timezone-naive (which will be interpreted as UTC times). The timestamps in the result will
|
|
15
|
-
be in UTC. Cost will be reported for full intervals, even if the provided `start` or `end`
|
|
16
|
-
parameters are partial: `start` will be rounded to the beginning of its interval, while
|
|
17
|
-
partial `end` intervals will be excluded.
|
|
18
|
-
|
|
19
|
-
Additional user-provided metadata can be included in the report if the objects have tags
|
|
20
|
-
and `tag_names` (i.e., keys) are specified in the request. Alternatively, pass `tag_names=["*"]`
|
|
21
|
-
to include all tags in the report. Note that tags will be attributed to the entire interval even
|
|
22
|
-
if they were added or removed at some point within it. If the tag name was not in use during an
|
|
23
|
-
interval, it will be absent from the tags dictionary in that output row.
|
|
24
|
-
|
|
25
|
-
In most cases, billing data will be available in the database that this API queries within
|
|
26
|
-
minutes, although there may be collection delays. If completeness is important for your use
|
|
27
|
-
case, we recommend leaving a buffer after the end of the query interval.
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
12
|
|
|
31
13
|
class WorkspaceBillingReportItem(TypedDict):
|
|
32
14
|
object_id: str
|
|
@@ -115,10 +97,6 @@ async def _workspace_billing_report(
|
|
|
115
97
|
if they were added or removed at some point within it. If the tag name was not in use during an
|
|
116
98
|
interval, it will be absent from the tags dictionary in that output row.
|
|
117
99
|
|
|
118
|
-
In most cases, billing data will be available in the database that this API queries within
|
|
119
|
-
minutes, although there may be collection delays. If completeness is important for your use
|
|
120
|
-
case, we recommend leaving a buffer after the end of the query interval.
|
|
121
|
-
|
|
122
100
|
It's also possible to generate reports using the
|
|
123
101
|
[`modal billing report`](https://modal.com/docs/cli/latest/billing) CLI command. The CLI
|
|
124
102
|
has a few convenience features for generating reports across relative time ranges.
|
|
@@ -127,7 +105,8 @@ async def _workspace_billing_report(
|
|
|
127
105
|
|
|
128
106
|
deprecation_warning(
|
|
129
107
|
(2026, 6, 18),
|
|
130
|
-
"`workspace_billing_report()` is deprecated.
|
|
108
|
+
"The `modal.billing.workspace_billing_report()` function is deprecated. "
|
|
109
|
+
"Use the `workspace.billing.report()` method on the `modal.Workspace` object instead.",
|
|
131
110
|
)
|
|
132
111
|
|
|
133
112
|
from ._workspace import _Workspace
|
|
@@ -13,7 +13,7 @@ from synchronicity import classproperty
|
|
|
13
13
|
|
|
14
14
|
from modal_proto import api_pb2
|
|
15
15
|
|
|
16
|
-
from ._billing import
|
|
16
|
+
from ._billing import BillingReportItem
|
|
17
17
|
from ._load_context import LoadContext
|
|
18
18
|
from ._object import _Object
|
|
19
19
|
from ._resolver import Resolver
|
|
@@ -416,26 +416,33 @@ class _EnvironmentBillingManager:
|
|
|
416
416
|
resolution: str = "d", # Resolution, e.g. "d" for daily or "h" for hourly
|
|
417
417
|
tag_names: list[str] | None = None, # Optional additional metadata to include
|
|
418
418
|
) -> list[BillingReportItem]:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
419
|
+
"""Return a cost report for Environment usage, broken down by object and time.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
start: Start of the report, inclusive and rounded to the beginning of the interval.
|
|
423
|
+
Must be in UTC or timezone-naive (interpreted as UTC).
|
|
424
|
+
end: End of the report, exclusive. Must be in UTC or timezone-naive. Partial final
|
|
425
|
+
intervals will be excluded from the report.
|
|
426
|
+
resolution: Resolution, e.g. "d" for daily or "h" for hourly.
|
|
427
|
+
tag_names: List of tag names; each row will include the tag name and value in use
|
|
428
|
+
for that object during the relevant time interval. Pass `["*"]` to include all
|
|
429
|
+
tags in the report.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
A list of `BillingReportItem` dataclasses. Each item reports the cost attributed to
|
|
433
|
+
a specific Modal object during a given time interval. Cost is further broken down by
|
|
434
|
+
the resource type that generated it (e.g. CPU, Memory, specific GPU usage).
|
|
435
|
+
Note that the specific resource types included in the breakdown are subject to change
|
|
436
|
+
as Modal's billing model evolves.
|
|
437
|
+
|
|
438
|
+
See also:
|
|
439
|
+
- [`modal environment billing report`](https://modal.com/docs/cli/latest/environment#modal-environment-billing-report):
|
|
440
|
+
An environment report CLI that has convenience features around relative time range queries
|
|
441
|
+
and JSON/CSV output.
|
|
442
|
+
- [`Workspace.billing.report()`](https://modal.com/docs/sdk/py/latest/modal.Workspace#billingreport):
|
|
443
|
+
An analogous report API for the entire Workspace.
|
|
438
444
|
|
|
445
|
+
"""
|
|
439
446
|
if tag_names is None:
|
|
440
447
|
tag_names = []
|
|
441
448
|
|
|
@@ -1195,10 +1195,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1195
1195
|
its static configuration.
|
|
1196
1196
|
|
|
1197
1197
|
Args:
|
|
1198
|
-
min_containers: Minimum number of containers to keep running
|
|
1199
|
-
max_containers: Maximum concurrent containers
|
|
1200
|
-
buffer_containers: Extra containers to keep warm beyond demand
|
|
1201
|
-
scaledown_window:
|
|
1198
|
+
min_containers: Minimum number of containers to keep running.
|
|
1199
|
+
max_containers: Maximum concurrent containers.
|
|
1200
|
+
buffer_containers: Extra containers to keep warm beyond current demand.
|
|
1201
|
+
scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
|
|
1202
1202
|
|
|
1203
1203
|
Examples:
|
|
1204
1204
|
```python notest
|
|
@@ -1212,7 +1212,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1212
1212
|
|
|
1213
1213
|
# Extend the scaledown window to increase the amount of time that idle containers stay alive
|
|
1214
1214
|
f.update_autoscaler(scaledown_window=300)
|
|
1215
|
-
|
|
1215
|
+
```
|
|
1216
1216
|
|
|
1217
1217
|
"""
|
|
1218
1218
|
# Assert .update_autoscaler() is not called on a method as opposed to the Object. Applicable for Cls only.
|
|
@@ -2965,17 +2965,16 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2965
2965
|
"""
|
|
2966
2966
|
tag = _parse_named_image_ref(name)
|
|
2967
2967
|
|
|
2968
|
-
if
|
|
2968
|
+
if self._object_id is None:
|
|
2969
2969
|
raise InvalidError("Cannot publish an image that has not been created yet. Call `.build()` first.")
|
|
2970
2970
|
|
|
2971
|
-
_client = client or
|
|
2972
|
-
assert _client is not None
|
|
2971
|
+
_client = client or await _Client.from_env()
|
|
2973
2972
|
|
|
2974
2973
|
resolved_env = environment_name or config.get("environment") or ""
|
|
2975
2974
|
|
|
2976
2975
|
await _client.stub.ImagePublish(
|
|
2977
2976
|
api_pb2.ImagePublishRequest(
|
|
2978
|
-
image_id=self.
|
|
2977
|
+
image_id=self._object_id,
|
|
2979
2978
|
environment_name=resolved_env,
|
|
2980
2979
|
is_public=False,
|
|
2981
2980
|
tag=tag,
|
|
@@ -17,6 +17,11 @@ from modal.config import config, logger
|
|
|
17
17
|
|
|
18
18
|
CUDA_CHECKPOINT_PATH: str = config.get("cuda_checkpoint_path")
|
|
19
19
|
|
|
20
|
+
# Exit code used to signal to modal-runtime that a GPU memory snapshot restore failed
|
|
21
|
+
# and the task should be retried without a snapshot. This is a sentinel value that must
|
|
22
|
+
# stay in sync with `GPU_SNAPSHOT_RESTORE_FAILED_EXIT_CODE` in runner.rs.
|
|
23
|
+
SNAPSHOT_RESTORE_FAILED_EXIT_CODE: int = 222
|
|
24
|
+
|
|
20
25
|
# Maximum total duration for each individual `cuda-checkpoint` invocation.
|
|
21
26
|
CUDA_CHECKPOINT_TIMEOUT: float = 3 * 60.0
|
|
22
27
|
|
|
@@ -180,10 +180,15 @@ class _TaskLifecycleManager:
|
|
|
180
180
|
if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
|
|
181
181
|
logger.debug("GPU memory snapshot enabled. Attempting to restore GPU memory.")
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
try:
|
|
184
|
+
if self._cuda_checkpoint_session is None:
|
|
185
|
+
raise gpu_memory_snapshot.CudaCheckpointException("CudaCheckpointSession not found")
|
|
186
|
+
self._cuda_checkpoint_session.restore()
|
|
187
|
+
except gpu_memory_snapshot.CudaCheckpointException as exc:
|
|
188
|
+
logger.warning(f"GPU memory snapshot restore failed; retrying task without snapshot. Error: {exc}")
|
|
189
|
+
sys.stderr.flush()
|
|
190
|
+
# Exit with a sentinel code that the runtime will use to retry the task without a snapshot.
|
|
191
|
+
os._exit(gpu_memory_snapshot.SNAPSHOT_RESTORE_FAILED_EXIT_CODE)
|
|
187
192
|
|
|
188
193
|
self._client = await _Client.from_env()
|
|
189
194
|
|
|
@@ -46,7 +46,7 @@ def validate_http_server_config(
|
|
|
46
46
|
class _Server:
|
|
47
47
|
"""Server runs an HTTP server started in an `@modal.enter` method.
|
|
48
48
|
|
|
49
|
-
See [
|
|
49
|
+
See the [guide](https://modal.com/docs/guide/servers) for more information.
|
|
50
50
|
|
|
51
51
|
Generally, you will not construct a Server directly.
|
|
52
52
|
Instead, use the [`@app.server()`](https://modal.com/docs/sdk/py/latest/modal.App#server) decorator.
|
|
@@ -77,6 +77,7 @@ class _Server:
|
|
|
77
77
|
|
|
78
78
|
@property
|
|
79
79
|
def object_id(self) -> str:
|
|
80
|
+
"""Modal's internal ID for this Server instance."""
|
|
80
81
|
return self._service_function.object_id
|
|
81
82
|
|
|
82
83
|
@staticmethod
|
|
@@ -91,6 +92,7 @@ class _Server:
|
|
|
91
92
|
|
|
92
93
|
@live_method
|
|
93
94
|
async def get_url(self) -> str | None:
|
|
95
|
+
"""The URL for making requests to this Server."""
|
|
94
96
|
urls = await self._get_service_function()._experimental_get_flash_urls()
|
|
95
97
|
# Return the first URL if it exists. Servers should only have one URL
|
|
96
98
|
# since they only have one region.
|
|
@@ -101,16 +103,28 @@ class _Server:
|
|
|
101
103
|
async def update_autoscaler(
|
|
102
104
|
self,
|
|
103
105
|
*,
|
|
106
|
+
target_concurrency: int | None = None,
|
|
104
107
|
min_containers: int | None = None,
|
|
105
108
|
max_containers: int | None = None,
|
|
106
109
|
buffer_containers: int | None = None,
|
|
107
110
|
scaleup_window: int | None = None,
|
|
108
111
|
scaledown_window: int | None = None,
|
|
109
|
-
target_concurrency: int | None = None,
|
|
110
112
|
) -> None:
|
|
111
113
|
"""Override the current autoscaler behavior for this Server.
|
|
112
114
|
|
|
113
|
-
Unspecified parameters will retain their current value.
|
|
115
|
+
Unspecified parameters will retain their current value, i.e. either the static value
|
|
116
|
+
from the `@app.server()` decorator, or an override value from a previous call to this method.
|
|
117
|
+
|
|
118
|
+
Subsequent deployments of the App containing this Server will reset the autoscaler back to
|
|
119
|
+
its static configuration.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
target_concurrency: Target number of concurrent requests per container.
|
|
123
|
+
min_containers: Minimum number of containers to keep running regardless of demand.
|
|
124
|
+
max_containers: Limit on the number of containers that can be concurrently running.
|
|
125
|
+
buffer_containers: Extra containers to scale up beyond current demand.
|
|
126
|
+
scaleup_window: Seconds of sustained demand required before scaling up new containers.
|
|
127
|
+
scaledown_window: Maximum duration (in seconds) idle containers wait before scaling down.
|
|
114
128
|
|
|
115
129
|
Examples:
|
|
116
130
|
```python notest
|
|
@@ -130,7 +144,7 @@ class _Server:
|
|
|
130
144
|
|
|
131
145
|
# Disable the Server autoscaling by setting target_concurrency to 0
|
|
132
146
|
server.update_autoscaler(target_concurrency=0)
|
|
133
|
-
|
|
147
|
+
```
|
|
134
148
|
|
|
135
149
|
"""
|
|
136
150
|
return await self._get_service_function()._update_autoscaler(
|
|
@@ -144,6 +158,13 @@ class _Server:
|
|
|
144
158
|
|
|
145
159
|
# ============ Hydration ============
|
|
146
160
|
async def hydrate(self, client: _Client | None = None) -> "_Server":
|
|
161
|
+
"""Synchronize the local object with its identity on the Modal server.
|
|
162
|
+
|
|
163
|
+
It is rarely necessary to call this method explicitly, as most operations will
|
|
164
|
+
lazily hydrate when needed. The main use case is when you need to access object
|
|
165
|
+
metadata, such as its ID.
|
|
166
|
+
|
|
167
|
+
"""
|
|
147
168
|
# This is required since we want to support @livemethod() decorated methods
|
|
148
169
|
service_function = self._get_service_function()
|
|
149
170
|
await service_function.hydrate(client)
|
|
@@ -183,6 +204,12 @@ class _Server:
|
|
|
183
204
|
object with metadata from Modal servers until the first
|
|
184
205
|
time it is actually used.
|
|
185
206
|
|
|
207
|
+
Args:
|
|
208
|
+
app_name: Name of the App containing the Server.
|
|
209
|
+
name: Name of the Server within the App.
|
|
210
|
+
environment_name: Name of the Environment where the App is deployed.
|
|
211
|
+
client: Modal client instance for this session.
|
|
212
|
+
|
|
186
213
|
```python notest
|
|
187
214
|
server = modal.Server.from_name("other-app", "Server")
|
|
188
215
|
```
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Copyright Modal Labs 2026
|
|
2
|
+
from urllib.parse import urlparse
|
|
3
|
+
|
|
4
|
+
# Short curl flags (single dash, single letter) that consume the following argument.
|
|
5
|
+
_CURL_SHORT_VALUE_FLAGS = frozenset("AbCcDdEeFHhKmoQrTtUuwXxYyz")
|
|
6
|
+
|
|
7
|
+
# Long curl flags that consume the following argument (when given as `--flag value`).
|
|
8
|
+
# Flags given as `--flag=value` are self-contained and handled generically.
|
|
9
|
+
_CURL_LONG_VALUE_FLAGS = frozenset(
|
|
10
|
+
{
|
|
11
|
+
"--cacert",
|
|
12
|
+
"--capath",
|
|
13
|
+
"--cert",
|
|
14
|
+
"--cert-type",
|
|
15
|
+
"--config",
|
|
16
|
+
"--connect-timeout",
|
|
17
|
+
"--connect-to",
|
|
18
|
+
"--continue-at",
|
|
19
|
+
"--cookie",
|
|
20
|
+
"--cookie-jar",
|
|
21
|
+
"--data",
|
|
22
|
+
"--data-ascii",
|
|
23
|
+
"--data-binary",
|
|
24
|
+
"--data-raw",
|
|
25
|
+
"--data-urlencode",
|
|
26
|
+
"--dump-header",
|
|
27
|
+
"--form",
|
|
28
|
+
"--form-string",
|
|
29
|
+
"--header",
|
|
30
|
+
"--interface",
|
|
31
|
+
"--key",
|
|
32
|
+
"--key-type",
|
|
33
|
+
"--limit-rate",
|
|
34
|
+
"--max-filesize",
|
|
35
|
+
"--max-redirs",
|
|
36
|
+
"--max-time",
|
|
37
|
+
"--oauth2-bearer",
|
|
38
|
+
"--output",
|
|
39
|
+
"--pass",
|
|
40
|
+
"--proxy",
|
|
41
|
+
"--proxy-user",
|
|
42
|
+
"--range",
|
|
43
|
+
"--referer",
|
|
44
|
+
"--request",
|
|
45
|
+
"--resolve",
|
|
46
|
+
"--retry",
|
|
47
|
+
"--retry-delay",
|
|
48
|
+
"--retry-max-time",
|
|
49
|
+
"--unix-socket",
|
|
50
|
+
"--upload-file",
|
|
51
|
+
"--url",
|
|
52
|
+
"--user",
|
|
53
|
+
"--user-agent",
|
|
54
|
+
"--write-out",
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def endpoint_cache_host(url: str) -> str:
|
|
60
|
+
parsed = urlparse(url if "://" in url else f"https://{url}")
|
|
61
|
+
return (parsed.hostname or url).lower().rstrip(".")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def is_modal_direct_url(url: str) -> bool:
|
|
65
|
+
# Only fetch token for app.server() functions
|
|
66
|
+
host = endpoint_cache_host(url)
|
|
67
|
+
return host.endswith("modal.direct") or host.endswith("modal-dev.direct")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _is_modal_direct_candidate(arg: str) -> bool:
|
|
71
|
+
try:
|
|
72
|
+
return is_modal_direct_url(arg)
|
|
73
|
+
except ValueError:
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def find_url(curl_args: tuple[str, ...]) -> str | None:
|
|
78
|
+
"""Find the Modal direct URL operand within a curl argument list.
|
|
79
|
+
|
|
80
|
+
Parses the args the way curl does well enough to skip over flag values, so that
|
|
81
|
+
a `modal.direct` host appearing as e.g. a header or data value is not mistaken
|
|
82
|
+
for the request URL.
|
|
83
|
+
"""
|
|
84
|
+
i = 0
|
|
85
|
+
n = len(curl_args)
|
|
86
|
+
while i < n:
|
|
87
|
+
arg = curl_args[i]
|
|
88
|
+
|
|
89
|
+
if arg.startswith("--"):
|
|
90
|
+
flag, sep, value = arg.partition("=")
|
|
91
|
+
if sep:
|
|
92
|
+
# `--flag=value`: the value is self-contained.
|
|
93
|
+
if flag == "--url" and _is_modal_direct_candidate(value):
|
|
94
|
+
return value
|
|
95
|
+
elif flag in _CURL_LONG_VALUE_FLAGS:
|
|
96
|
+
# `--flag value`: the next argument is this flag's value.
|
|
97
|
+
value = curl_args[i + 1] if i + 1 < n else ""
|
|
98
|
+
if flag == "--url" and _is_modal_direct_candidate(value):
|
|
99
|
+
return value
|
|
100
|
+
i += 2
|
|
101
|
+
continue
|
|
102
|
+
elif arg.startswith("-") and len(arg) >= 2:
|
|
103
|
+
last = arg[-1]
|
|
104
|
+
if len(arg) == 2 and last in _CURL_SHORT_VALUE_FLAGS:
|
|
105
|
+
# `-X value`: the next argument is this flag's value.
|
|
106
|
+
i += 2
|
|
107
|
+
continue
|
|
108
|
+
# `-Xvalue` (attached value) or a cluster of boolean flags: nothing to skip.
|
|
109
|
+
elif _is_modal_direct_candidate(arg):
|
|
110
|
+
# A bare (positional) URL operand.
|
|
111
|
+
return arg
|
|
112
|
+
|
|
113
|
+
i += 1
|
|
114
|
+
|
|
115
|
+
return None
|