modal 1.4.4.dev0__tar.gz → 1.4.4.dev1__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.4.4.dev0 → modal-1.4.4.dev1}/PKG-INFO +1 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/user_code_imports.py +1 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_server.py +5 -2
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/app.py +5 -4
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/app.pyi +4 -4
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/client.pyi +2 -2
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/experimental/flash.py +12 -3
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/experimental/flash.pyi +5 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/sandbox.py +7 -5
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/sandbox.pyi +18 -6
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/server.pyi +1 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_version/__init__.py +1 -1
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/LICENSE +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/README.md +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/__main__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_billing.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_clustered_functions.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_container_entrypoint.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_environments.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_function_variants.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_functions.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_grpc_client.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_ipython.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_load_context.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_location.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_logs.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_object.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_output/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_output/manager.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_output/pty.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_output/rich.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_output/status.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_partial_function.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_resolver.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_resources.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_serialization.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_traceback.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_tunnel.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_tunnel.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_type_manager.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/async_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/logger.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_vendor/version.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/_watcher.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/billing.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/README.md +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/builder/base-images.json +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/call_graph.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/_download.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/_help.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/_traceback.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/app.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/billing.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/bootstrap.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/changelog.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/cluster.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/config.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/container.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/dashboard.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/dict.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/entry_point.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/environment.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/import_refs.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/launch.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/logo.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/profile.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/queues.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/run.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/secret.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/selector.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/shell.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/token.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/utils.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cli/volume.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/client.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cls.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/cls.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/config.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/container_process.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/container_process.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/dict.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/dict.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/environments.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/environments.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/exception.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/experimental/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/experimental/ipython.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/file_io.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/file_io.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/functions.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/functions.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/image.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/image.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/io_streams.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/io_streams.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/mount.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/mount.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/network_file_system.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/network_file_system.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/object.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/object.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/output.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/parallel_map.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/parallel_map.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/partial_function.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/partial_function.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/proxy.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/proxy.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/py.typed +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/queue.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/queue.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/retries.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/runner.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/runner.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/running_app.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/sandbox_fs.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/sandbox_fs.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/schedule.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/scheduler_placement.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/secret.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/secret.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/server.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/serving.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/serving.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/snapshot.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/snapshot.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/stream_type.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/token_flow.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/token_flow.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/volume.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal/volume.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/__init__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/api_grpc.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/api_pb2.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/py.typed +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/modal_version/__main__.py +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/pyproject.toml +0 -0
- {modal-1.4.4.dev0 → modal-1.4.4.dev1}/setup.cfg +0 -0
|
@@ -337,7 +337,7 @@ class _LifecycleManager:
|
|
|
337
337
|
container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
|
|
338
338
|
):
|
|
339
339
|
# Identify the "enter" methods to run after resuming from a snapshot.
|
|
340
|
-
flash_entry = _FlashContainerEntry(self.function_def.http_config)
|
|
340
|
+
flash_entry = _FlashContainerEntry(self.function_def.http_config, is_server=self.function_def.is_server)
|
|
341
341
|
if not self.function_def.is_auto_snapshot:
|
|
342
342
|
post_snapshot_methods = _find_callables_for_obj(
|
|
343
343
|
self.user_cls_instance, _PartialFunctionFlags.ENTER_POST_SNAPSHOT
|
|
@@ -24,6 +24,7 @@ def validate_http_server_config(
|
|
|
24
24
|
proxy_regions: list[str], # The regions to proxy the HTTP server to.
|
|
25
25
|
startup_timeout: int, # Maximum number of seconds to wait for the HTTP server to start.
|
|
26
26
|
exit_grace_period: Optional[int], # The time to wait for the HTTP server to exit gracefully.
|
|
27
|
+
is_server: bool = False, # Whether this validates a `_experimental_server` config.
|
|
27
28
|
):
|
|
28
29
|
if not isinstance(port, int) or port < 1 or port > 65535:
|
|
29
30
|
raise InvalidError("Port must be a positive integer between 1 and 65535.")
|
|
@@ -31,10 +32,12 @@ def validate_http_server_config(
|
|
|
31
32
|
raise InvalidError("The `startup_timeout` argument must be positive.")
|
|
32
33
|
if exit_grace_period is not None and exit_grace_period < 0:
|
|
33
34
|
raise InvalidError("The `exit_grace_period` argument must be non-negative.")
|
|
34
|
-
if exit_grace_period is not None and exit_grace_period > 25:
|
|
35
|
+
if not is_server and exit_grace_period is not None and exit_grace_period > 25:
|
|
35
36
|
raise InvalidError("The `exit_grace_period` argument must not exceed 25 seconds.")
|
|
36
37
|
|
|
37
38
|
if not proxy_regions:
|
|
39
|
+
if is_server:
|
|
40
|
+
raise InvalidError("The `routing_regions` argument must be non-empty.")
|
|
38
41
|
raise InvalidError("The `proxy_regions` argument must be non-empty.")
|
|
39
42
|
|
|
40
43
|
|
|
@@ -47,7 +50,7 @@ class _Server:
|
|
|
47
50
|
Instead, use the [`@app._experimental_server()`](https://modal.com/docs/reference/modal.App#server) decorator.
|
|
48
51
|
|
|
49
52
|
```python notest
|
|
50
|
-
@app._experimental_server(port=8000,
|
|
53
|
+
@app._experimental_server(port=8000, routing_regions=["us-east", "us-west"])
|
|
51
54
|
class MyServer:
|
|
52
55
|
@modal.enter()
|
|
53
56
|
def start_server(self):
|
|
@@ -1156,7 +1156,7 @@ class _App:
|
|
|
1156
1156
|
port: int = 8000, # Port the HTTP server listens on
|
|
1157
1157
|
startup_timeout: int = 30, # Maximum startup time in seconds
|
|
1158
1158
|
exit_grace_period: int = 0, # Grace period for in-flight requests on shutdown
|
|
1159
|
-
|
|
1159
|
+
routing_regions: list[str] = ["us-east"], # Required: Regions to deploy proxy endpoints
|
|
1160
1160
|
h2_enabled: bool = False, # Enable HTTP/2
|
|
1161
1161
|
target_concurrency: Optional[int] = None, # Target concurrency for the server
|
|
1162
1162
|
cloud: Optional[str] = None, # Cloud provider (aws, gcp, oci, auto)
|
|
@@ -1178,7 +1178,7 @@ class _App:
|
|
|
1178
1178
|
Example:
|
|
1179
1179
|
|
|
1180
1180
|
```python
|
|
1181
|
-
@app._experimental_server(port=8000,
|
|
1181
|
+
@app._experimental_server(port=8000, routing_regions=["us-east"])
|
|
1182
1182
|
class MyServer:
|
|
1183
1183
|
@modal.enter()
|
|
1184
1184
|
def start(self):
|
|
@@ -1195,9 +1195,10 @@ class _App:
|
|
|
1195
1195
|
# Validate HTTP server config
|
|
1196
1196
|
validate_http_server_config(
|
|
1197
1197
|
port=port,
|
|
1198
|
-
proxy_regions=
|
|
1198
|
+
proxy_regions=routing_regions,
|
|
1199
1199
|
startup_timeout=startup_timeout,
|
|
1200
1200
|
exit_grace_period=exit_grace_period,
|
|
1201
|
+
is_server=True,
|
|
1201
1202
|
)
|
|
1202
1203
|
|
|
1203
1204
|
if target_concurrency is not None:
|
|
@@ -1206,7 +1207,7 @@ class _App:
|
|
|
1206
1207
|
|
|
1207
1208
|
http_config = api_pb2.HTTPConfig(
|
|
1208
1209
|
port=port,
|
|
1209
|
-
proxy_regions=
|
|
1210
|
+
proxy_regions=routing_regions,
|
|
1210
1211
|
startup_timeout=startup_timeout,
|
|
1211
1212
|
exit_grace_period=exit_grace_period,
|
|
1212
1213
|
h2_enabled=h2_enabled,
|
|
@@ -577,7 +577,7 @@ class _App:
|
|
|
577
577
|
port: int = 8000,
|
|
578
578
|
startup_timeout: int = 30,
|
|
579
579
|
exit_grace_period: int = 0,
|
|
580
|
-
|
|
580
|
+
routing_regions: list[str] = ["us-east"],
|
|
581
581
|
h2_enabled: bool = False,
|
|
582
582
|
target_concurrency: typing.Optional[int] = None,
|
|
583
583
|
cloud: typing.Optional[str] = None,
|
|
@@ -599,7 +599,7 @@ class _App:
|
|
|
599
599
|
Example:
|
|
600
600
|
|
|
601
601
|
```python
|
|
602
|
-
@app._experimental_server(port=8000,
|
|
602
|
+
@app._experimental_server(port=8000, routing_regions=["us-east"])
|
|
603
603
|
class MyServer:
|
|
604
604
|
@modal.enter()
|
|
605
605
|
def start(self):
|
|
@@ -1297,7 +1297,7 @@ class App:
|
|
|
1297
1297
|
port: int = 8000,
|
|
1298
1298
|
startup_timeout: int = 30,
|
|
1299
1299
|
exit_grace_period: int = 0,
|
|
1300
|
-
|
|
1300
|
+
routing_regions: list[str] = ["us-east"],
|
|
1301
1301
|
h2_enabled: bool = False,
|
|
1302
1302
|
target_concurrency: typing.Optional[int] = None,
|
|
1303
1303
|
cloud: typing.Optional[str] = None,
|
|
@@ -1317,7 +1317,7 @@ class App:
|
|
|
1317
1317
|
Example:
|
|
1318
1318
|
|
|
1319
1319
|
```python
|
|
1320
|
-
@app._experimental_server(port=8000,
|
|
1320
|
+
@app._experimental_server(port=8000, routing_regions=["us-east"])
|
|
1321
1321
|
class MyServer:
|
|
1322
1322
|
@modal.enter()
|
|
1323
1323
|
def start(self):
|
|
@@ -35,7 +35,7 @@ class _Client:
|
|
|
35
35
|
server_url: str,
|
|
36
36
|
client_type: int,
|
|
37
37
|
credentials: typing.Optional[tuple[str, str]],
|
|
38
|
-
version: str = "1.4.4.
|
|
38
|
+
version: str = "1.4.4.dev1",
|
|
39
39
|
):
|
|
40
40
|
"""mdmd:hidden
|
|
41
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -175,7 +175,7 @@ class Client:
|
|
|
175
175
|
server_url: str,
|
|
176
176
|
client_type: int,
|
|
177
177
|
credentials: typing.Optional[tuple[str, str]],
|
|
178
|
-
version: str = "1.4.4.
|
|
178
|
+
version: str = "1.4.4.dev1",
|
|
179
179
|
):
|
|
180
180
|
"""mdmd:hidden
|
|
181
181
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -37,6 +37,7 @@ class _FlashManager:
|
|
|
37
37
|
startup_timeout: int = 30,
|
|
38
38
|
exit_grace_period: int = 0,
|
|
39
39
|
h2_enabled: bool = False,
|
|
40
|
+
is_server: bool = False,
|
|
40
41
|
):
|
|
41
42
|
self.client = client
|
|
42
43
|
self.port = port
|
|
@@ -46,6 +47,7 @@ class _FlashManager:
|
|
|
46
47
|
self.startup_timeout = startup_timeout
|
|
47
48
|
self.exit_grace_period = exit_grace_period
|
|
48
49
|
self.tunnel_manager = _forward_tunnel(port, h2_enabled=h2_enabled, client=client)
|
|
50
|
+
self.is_server = is_server
|
|
49
51
|
self.stopped = False
|
|
50
52
|
self.num_heartbeat_failures = 0
|
|
51
53
|
self.task_id = os.environ["MODAL_TASK_ID"]
|
|
@@ -222,7 +224,10 @@ class _FlashManager:
|
|
|
222
224
|
if not self.stopped:
|
|
223
225
|
await self.stop()
|
|
224
226
|
|
|
225
|
-
|
|
227
|
+
# Server tasks drain via the worker-side HTTP relay, so skip the
|
|
228
|
+
# Python-side sleep here to avoid double-counting the grace period.
|
|
229
|
+
if not self.is_server:
|
|
230
|
+
await asyncio.sleep(self.exit_grace_period)
|
|
226
231
|
|
|
227
232
|
logger.warning(f"[Modal Flash] Closing tunnel on {self.tunnel.url}.")
|
|
228
233
|
await self.tunnel_manager.__aexit__(*sys.exc_info())
|
|
@@ -239,6 +244,7 @@ async def flash_forward(
|
|
|
239
244
|
startup_timeout: int = 30,
|
|
240
245
|
exit_grace_period: int = 0,
|
|
241
246
|
h2_enabled: bool = False,
|
|
247
|
+
is_server: bool = False,
|
|
242
248
|
) -> _FlashManager:
|
|
243
249
|
"""
|
|
244
250
|
Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
|
|
@@ -255,6 +261,7 @@ async def flash_forward(
|
|
|
255
261
|
startup_timeout=startup_timeout,
|
|
256
262
|
exit_grace_period=exit_grace_period,
|
|
257
263
|
h2_enabled=h2_enabled,
|
|
264
|
+
is_server=is_server,
|
|
258
265
|
)
|
|
259
266
|
await manager._start()
|
|
260
267
|
return manager
|
|
@@ -716,7 +723,7 @@ def _http_server(
|
|
|
716
723
|
raise InvalidError(
|
|
717
724
|
"Positional arguments are not allowed. Did you forget parentheses? Suggestion: `@modal.http_server()`."
|
|
718
725
|
)
|
|
719
|
-
validate_http_server_config(port, proxy_regions, startup_timeout, exit_grace_period)
|
|
726
|
+
validate_http_server_config(port, proxy_regions, startup_timeout, exit_grace_period, is_server=False)
|
|
720
727
|
|
|
721
728
|
from modal._partial_function import _PartialFunction, _PartialFunctionParams
|
|
722
729
|
|
|
@@ -757,9 +764,10 @@ class _FlashContainerEntry:
|
|
|
757
764
|
|
|
758
765
|
flash_manager: Optional[FlashManager] # type: ignore
|
|
759
766
|
|
|
760
|
-
def __init__(self, http_config: api_pb2.HTTPConfig):
|
|
767
|
+
def __init__(self, http_config: api_pb2.HTTPConfig, is_server: bool = False):
|
|
761
768
|
self.http_config: api_pb2.HTTPConfig = http_config
|
|
762
769
|
self.flash_manager = None
|
|
770
|
+
self.is_server = is_server
|
|
763
771
|
|
|
764
772
|
def enter(self):
|
|
765
773
|
if self.http_config != api_pb2.HTTPConfig():
|
|
@@ -775,6 +783,7 @@ class _FlashContainerEntry:
|
|
|
775
783
|
startup_timeout=self.http_config.startup_timeout,
|
|
776
784
|
exit_grace_period=self.http_config.exit_grace_period,
|
|
777
785
|
h2_enabled=self.http_config.h2_enabled,
|
|
786
|
+
is_server=self.is_server,
|
|
778
787
|
)
|
|
779
788
|
except Exception as e:
|
|
780
789
|
logger.warning(f"[Modal Flash] Startup failed: {e}")
|
|
@@ -14,6 +14,7 @@ class _FlashManager:
|
|
|
14
14
|
startup_timeout: int = 30,
|
|
15
15
|
exit_grace_period: int = 0,
|
|
16
16
|
h2_enabled: bool = False,
|
|
17
|
+
is_server: bool = False,
|
|
17
18
|
):
|
|
18
19
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
19
20
|
...
|
|
@@ -43,6 +44,7 @@ class FlashManager:
|
|
|
43
44
|
startup_timeout: int = 30,
|
|
44
45
|
exit_grace_period: int = 0,
|
|
45
46
|
h2_enabled: bool = False,
|
|
47
|
+
is_server: bool = False,
|
|
46
48
|
): ...
|
|
47
49
|
|
|
48
50
|
class __is_port_connection_healthy_spec(typing_extensions.Protocol):
|
|
@@ -114,6 +116,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
|
|
|
114
116
|
startup_timeout: int = 30,
|
|
115
117
|
exit_grace_period: int = 0,
|
|
116
118
|
h2_enabled: bool = False,
|
|
119
|
+
is_server: bool = False,
|
|
117
120
|
) -> FlashManager:
|
|
118
121
|
"""Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
|
|
119
122
|
This is a highly experimental method that can break or be removed at any time without warning.
|
|
@@ -130,6 +133,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
|
|
|
130
133
|
startup_timeout: int = 30,
|
|
131
134
|
exit_grace_period: int = 0,
|
|
132
135
|
h2_enabled: bool = False,
|
|
136
|
+
is_server: bool = False,
|
|
133
137
|
) -> FlashManager:
|
|
134
138
|
"""Forward a port to the Modal Flash service, exposing that port as a stable endpoint.
|
|
135
139
|
This is a highly experimental method that can break or be removed at any time without warning.
|
|
@@ -450,7 +454,7 @@ class _FlashContainerEntry:
|
|
|
450
454
|
|
|
451
455
|
flash_manager: typing.Optional[FlashManager]
|
|
452
456
|
|
|
453
|
-
def __init__(self, http_config: modal_proto.api_pb2.HTTPConfig):
|
|
457
|
+
def __init__(self, http_config: modal_proto.api_pb2.HTTPConfig, is_server: bool = False):
|
|
454
458
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
455
459
|
...
|
|
456
460
|
|
|
@@ -669,8 +669,12 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
669
669
|
) -> "_Sandbox":
|
|
670
670
|
"""Create a sandbox using the V2 backend.
|
|
671
671
|
|
|
672
|
-
|
|
673
|
-
|
|
672
|
+
Supported features include exec, encrypted tunnels, wait/poll/terminate,
|
|
673
|
+
CPU and memory configuration, region placement,
|
|
674
|
+
and filesystem snapshots.
|
|
675
|
+
|
|
676
|
+
Features like tags, memory snapshots, volumes, network file systems, GPUs,
|
|
677
|
+
custom domains, OIDC identity tokens, and proxies are not supported.
|
|
674
678
|
"""
|
|
675
679
|
from .app import _App
|
|
676
680
|
|
|
@@ -951,11 +955,9 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
951
955
|
`timeout` If the snapshot does not return within that window, the call is cancelled
|
|
952
956
|
and `modal.exception.TimeoutError` is raised.
|
|
953
957
|
"""
|
|
954
|
-
if os.environ.get("MODAL_USE_LEGACY_FILESYSTEM_SNAPSHOT") == "1":
|
|
958
|
+
if os.environ.get("MODAL_USE_LEGACY_FILESYSTEM_SNAPSHOT") == "1" and not self._is_v2:
|
|
955
959
|
return await self._legacy_snapshot_filesystem(timeout)
|
|
956
960
|
|
|
957
|
-
self._ensure_v1("snapshot_filesystem")
|
|
958
|
-
|
|
959
961
|
task_id = await self._get_task_id()
|
|
960
962
|
command_router_client = await self._get_command_router_client(task_id)
|
|
961
963
|
|
|
@@ -327,8 +327,12 @@ class _Sandbox(modal._object._Object):
|
|
|
327
327
|
) -> _Sandbox:
|
|
328
328
|
"""Create a sandbox using the V2 backend.
|
|
329
329
|
|
|
330
|
-
|
|
331
|
-
|
|
330
|
+
Supported features include exec, encrypted tunnels, wait/poll/terminate,
|
|
331
|
+
CPU and memory configuration, region placement,
|
|
332
|
+
and filesystem snapshots.
|
|
333
|
+
|
|
334
|
+
Features like tags, memory snapshots, volumes, network file systems, GPUs,
|
|
335
|
+
custom domains, OIDC identity tokens, and proxies are not supported.
|
|
332
336
|
"""
|
|
333
337
|
...
|
|
334
338
|
|
|
@@ -1209,8 +1213,12 @@ class Sandbox(modal.object.Object):
|
|
|
1209
1213
|
) -> Sandbox:
|
|
1210
1214
|
"""Create a sandbox using the V2 backend.
|
|
1211
1215
|
|
|
1212
|
-
|
|
1213
|
-
|
|
1216
|
+
Supported features include exec, encrypted tunnels, wait/poll/terminate,
|
|
1217
|
+
CPU and memory configuration, region placement,
|
|
1218
|
+
and filesystem snapshots.
|
|
1219
|
+
|
|
1220
|
+
Features like tags, memory snapshots, volumes, network file systems, GPUs,
|
|
1221
|
+
custom domains, OIDC identity tokens, and proxies are not supported.
|
|
1214
1222
|
"""
|
|
1215
1223
|
...
|
|
1216
1224
|
|
|
@@ -1243,8 +1251,12 @@ class Sandbox(modal.object.Object):
|
|
|
1243
1251
|
) -> Sandbox:
|
|
1244
1252
|
"""Create a sandbox using the V2 backend.
|
|
1245
1253
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1254
|
+
Supported features include exec, encrypted tunnels, wait/poll/terminate,
|
|
1255
|
+
CPU and memory configuration, region placement,
|
|
1256
|
+
and filesystem snapshots.
|
|
1257
|
+
|
|
1258
|
+
Features like tags, memory snapshots, volumes, network file systems, GPUs,
|
|
1259
|
+
custom domains, OIDC identity tokens, and proxies are not supported.
|
|
1248
1260
|
"""
|
|
1249
1261
|
...
|
|
1250
1262
|
|
|
@@ -14,7 +14,7 @@ class Server:
|
|
|
14
14
|
Instead, use the [`@app._experimental_server()`](https://modal.com/docs/reference/modal.App#server) decorator.
|
|
15
15
|
|
|
16
16
|
```python notest
|
|
17
|
-
@app._experimental_server(port=8000,
|
|
17
|
+
@app._experimental_server(port=8000, routing_regions=["us-east", "us-west"])
|
|
18
18
|
class MyServer:
|
|
19
19
|
@modal.enter()
|
|
20
20
|
def start_server(self):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|