modal 1.4.4.dev17__tar.gz → 1.4.4.dev18__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.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/PKG-INFO +1 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_container_entrypoint.py +10 -12
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_function_variants.py +43 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_functions.py +10 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/user_code_imports.py +2 -4
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/sandbox_fs_utils.py +47 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/billing.py +5 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/client.pyi +2 -2
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/file_io.py +4 -19
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/file_io.pyi +9 -34
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/functions.pyi +6 -6
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/sandbox.py +15 -8
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/sandbox.pyi +21 -15
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/sandbox_fs.py +141 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/sandbox_fs.pyi +196 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/api_grpc.py +32 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/api_pb2.py +621 -581
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/api_pb2.pyi +74 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/api_pb2_grpc.py +66 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/api_pb2_grpc.pyi +20 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/modal_api_grpc.py +2 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_version/__init__.py +1 -1
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/LICENSE +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/README.md +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/__main__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_billing.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_clustered_functions.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_environments.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_grpc_client.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_image.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_ipython.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_load_context.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_location.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_logs.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_object.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_output/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_output/manager.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_output/pty.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_output/rich.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_output/status.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_partial_function.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_resolver.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_resources.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/task_lifecycle_manager.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_serialization.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_server.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_traceback.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_tunnel.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_tunnel.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_type_manager.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/async_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/logger.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_vendor/version.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_watcher.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/_workspace.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/app.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/app.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/README.md +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/builder/base-images.json +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/call_graph.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/_download.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/_help.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/_traceback.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/app.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/billing.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/bootstrap.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/changelog.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/cluster.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/config.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/container.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/dashboard.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/dict.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/entry_point.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/environment.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/import_refs.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/launch.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/logo.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/profile.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/queues.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/run.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/secret.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/selector.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/shell.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/skills.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/token.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/utils.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cli/volume.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/client.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cls.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/cls.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/config.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/container_process.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/container_process.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/dict.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/dict.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/environments.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/environments.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/exception.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/experimental/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/experimental/flash.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/experimental/flash.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/experimental/ipython.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/functions.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/image.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/image.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/io_streams.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/io_streams.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/mount.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/mount.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/network_file_system.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/network_file_system.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/object.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/object.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/output.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/parallel_map.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/parallel_map.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/partial_function.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/partial_function.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/proxy.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/proxy.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/py.typed +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/queue.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/queue.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/retries.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/runner.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/runner.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/running_app.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/schedule.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/scheduler_placement.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/secret.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/secret.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/server.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/server.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/serving.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/serving.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/skills/modal/SKILL.md +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/snapshot.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/snapshot.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/stream_type.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/token_flow.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/token_flow.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/volume.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/volume.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/workspace.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal/workspace.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_docs/mdmd/types.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/__init__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/py.typed +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/modal_version/__main__.py +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/pyproject.toml +0 -0
- {modal-1.4.4.dev17 → modal-1.4.4.dev18}/setup.cfg +0 -0
|
@@ -28,7 +28,7 @@ from modal._clustered_functions import initialize_clustered_function
|
|
|
28
28
|
from modal._runtime.user_code_event_loop import UserCodeEventLoop
|
|
29
29
|
from modal._serialization import deserialize, deserialize_params
|
|
30
30
|
from modal._utils.async_utils import TaskContext, aclosing, synchronizer
|
|
31
|
-
from modal.app import
|
|
31
|
+
from modal.app import _App
|
|
32
32
|
from modal.client import Client, _Client
|
|
33
33
|
from modal.config import logger
|
|
34
34
|
from modal.exception import ExecutionError, InputCancellation
|
|
@@ -288,7 +288,7 @@ def get_serialized_user_class_and_function(
|
|
|
288
288
|
|
|
289
289
|
|
|
290
290
|
def get_server_service(
|
|
291
|
-
container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client
|
|
291
|
+
container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client
|
|
292
292
|
) -> Service:
|
|
293
293
|
ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
|
|
294
294
|
service_base_function_id = container_args.app_layout.function_ids[function_def.function_name]
|
|
@@ -298,14 +298,14 @@ def get_server_service(
|
|
|
298
298
|
service = import_server_service(
|
|
299
299
|
function_def,
|
|
300
300
|
service_function_hydration_data,
|
|
301
|
-
|
|
301
|
+
_client,
|
|
302
302
|
ser_usr_cls,
|
|
303
303
|
)
|
|
304
304
|
return service
|
|
305
305
|
|
|
306
306
|
|
|
307
307
|
def get_class_service(
|
|
308
|
-
container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client
|
|
308
|
+
container_args: api_pb2.ContainerArguments, function_def: api_pb2.Function, _client: _Client
|
|
309
309
|
) -> Service:
|
|
310
310
|
ser_usr_cls, ser_fun = get_serialized_user_class_and_function(function_def, _client)
|
|
311
311
|
if container_args.serialized_params:
|
|
@@ -326,7 +326,7 @@ def get_class_service(
|
|
|
326
326
|
function_def,
|
|
327
327
|
service_function_hydration_data,
|
|
328
328
|
class_id,
|
|
329
|
-
|
|
329
|
+
_client,
|
|
330
330
|
ser_usr_cls,
|
|
331
331
|
param_args,
|
|
332
332
|
param_kwargs,
|
|
@@ -349,16 +349,15 @@ def hydrate_function(
|
|
|
349
349
|
task_lifecycle_manager: TaskLifecycleManager,
|
|
350
350
|
function_def: api_pb2.Function,
|
|
351
351
|
_client: _Client,
|
|
352
|
-
client: Client,
|
|
353
352
|
) -> Service:
|
|
354
353
|
active_app: _App
|
|
355
354
|
service: Service
|
|
356
355
|
with task_lifecycle_manager.handle_task_lifecycle_exception():
|
|
357
356
|
with execution_context._import_context():
|
|
358
357
|
if function_def.is_server:
|
|
359
|
-
service = get_server_service(container_args, function_def, _client
|
|
358
|
+
service = get_server_service(container_args, function_def, _client)
|
|
360
359
|
elif function_def.is_class:
|
|
361
|
-
service = get_class_service(container_args, function_def, _client
|
|
360
|
+
service = get_class_service(container_args, function_def, _client)
|
|
362
361
|
else:
|
|
363
362
|
service = get_function_service(function_def, _client)
|
|
364
363
|
|
|
@@ -369,8 +368,7 @@ def hydrate_function(
|
|
|
369
368
|
|
|
370
369
|
# Initialize objects on the app.
|
|
371
370
|
# This is basically only functions and classes - anything else is deprecated and will be unsupported soon
|
|
372
|
-
|
|
373
|
-
app._init_container(client, container_app)
|
|
371
|
+
active_app._init_container(_client, container_app)
|
|
374
372
|
|
|
375
373
|
# Hydrate all function dependencies.
|
|
376
374
|
# TODO(erikbern): we an remove this once we
|
|
@@ -406,7 +404,7 @@ def run_server(container_args: api_pb2.ContainerArguments, client: Client):
|
|
|
406
404
|
client,
|
|
407
405
|
)
|
|
408
406
|
|
|
409
|
-
service: Service = hydrate_function(container_args, task_lifecycle_manager, function_def, _client
|
|
407
|
+
service: Service = hydrate_function(container_args, task_lifecycle_manager, function_def, _client)
|
|
410
408
|
# Initialize clustered functions.
|
|
411
409
|
if function_def._experimental_group_size > 0:
|
|
412
410
|
initialize_clustered_function(
|
|
@@ -442,7 +440,7 @@ def run_function(container_args: api_pb2.ContainerArguments, client: Client):
|
|
|
442
440
|
with container_io_manager.heartbeats(is_snapshotting_function), UserCodeEventLoop() as event_loop:
|
|
443
441
|
# Initialize the function, importing user code.
|
|
444
442
|
service: Service = hydrate_function(
|
|
445
|
-
container_args, container_io_manager.get_task_lifecycle_manager(), function_def, _client
|
|
443
|
+
container_args, container_io_manager.get_task_lifecycle_manager(), function_def, _client
|
|
446
444
|
)
|
|
447
445
|
if function_def.pty_info.pty_type == api_pb2.PTYInfo.PTY_TYPE_SHELL:
|
|
448
446
|
# Concurrency and batching doesn't apply for `modal shell`.
|
|
@@ -185,6 +185,48 @@ class _FunctionOptions:
|
|
|
185
185
|
)
|
|
186
186
|
|
|
187
187
|
|
|
188
|
+
async def _function_bind_params_cached(
|
|
189
|
+
base_function: "_Function",
|
|
190
|
+
req: api_pb2.FunctionBindParamsRequest,
|
|
191
|
+
) -> api_pb2.FunctionBindParamsResponse:
|
|
192
|
+
"""Cache layer for FunctionBindParams RPCs, scoped to a base Function handle.
|
|
193
|
+
|
|
194
|
+
We have this because users probably do not realize that Function invocations structured as
|
|
195
|
+
|
|
196
|
+
res = f.with_options(...).remote(...)
|
|
197
|
+
|
|
198
|
+
would always need to do two sequential RPCs (bind params / call function variant).
|
|
199
|
+
|
|
200
|
+
The bound Function ID from FunctionBindParams is deterministic with respect to the full request,
|
|
201
|
+
so we can avoid the unnecessary call and hydrate the new instance from a cached response.
|
|
202
|
+
|
|
203
|
+
The cache is stored on the base Function handle so that the variant cache behaves similarly to
|
|
204
|
+
the local reference to the base Function metadata.
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
cache = base_function._bind_params_cache
|
|
208
|
+
cache_key = req.SerializeToString(deterministic=True)
|
|
209
|
+
|
|
210
|
+
cached_response = cache.get(cache_key)
|
|
211
|
+
if cached_response is not None:
|
|
212
|
+
cache.move_to_end(cache_key)
|
|
213
|
+
response = api_pb2.FunctionBindParamsResponse()
|
|
214
|
+
response.ParseFromString(cached_response)
|
|
215
|
+
return response
|
|
216
|
+
|
|
217
|
+
assert base_function._client and base_function._client.stub
|
|
218
|
+
response = await base_function._client.stub.FunctionBindParams(req)
|
|
219
|
+
|
|
220
|
+
cache[cache_key] = response.SerializeToString(deterministic=True)
|
|
221
|
+
cache.move_to_end(cache_key)
|
|
222
|
+
|
|
223
|
+
max_cache_size = 32
|
|
224
|
+
while len(cache) > max_cache_size:
|
|
225
|
+
cache.popitem(last=False)
|
|
226
|
+
|
|
227
|
+
return response
|
|
228
|
+
|
|
229
|
+
|
|
188
230
|
def _make_function_variant(
|
|
189
231
|
base_function: "_Function",
|
|
190
232
|
options: _FunctionOptions | None,
|
|
@@ -229,7 +271,7 @@ def _make_function_variant(
|
|
|
229
271
|
or "", # TODO: investigate shouldn't environment name always be specified here?
|
|
230
272
|
)
|
|
231
273
|
|
|
232
|
-
response = await base_function
|
|
274
|
+
response = await _function_bind_params_cached(base_function, req)
|
|
233
275
|
function_variant._hydrate(response.bound_function_id, base_function._client, response.handle_metadata)
|
|
234
276
|
|
|
235
277
|
def _deps():
|
|
@@ -5,6 +5,7 @@ import inspect
|
|
|
5
5
|
import time
|
|
6
6
|
import typing
|
|
7
7
|
import warnings
|
|
8
|
+
from collections import OrderedDict
|
|
8
9
|
from collections.abc import AsyncGenerator, AsyncIterator, Callable, Collection, Sequence
|
|
9
10
|
from dataclasses import dataclass
|
|
10
11
|
from pathlib import PurePosixPath
|
|
@@ -1354,6 +1355,11 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1354
1355
|
self._options = _FunctionOptions()
|
|
1355
1356
|
self._base_function = None
|
|
1356
1357
|
|
|
1358
|
+
# An OrderedDict[bytes, bytes] LRU of FunctionBindParams responses for
|
|
1359
|
+
# variants derived from this base Function. Omitted from class-level annotations because
|
|
1360
|
+
# Synchronicity doesn't understand OrderedDict as a type hint.
|
|
1361
|
+
self._bind_params_cache = OrderedDict()
|
|
1362
|
+
|
|
1357
1363
|
def _hydrate_metadata(self, metadata: Message | None):
|
|
1358
1364
|
# Overridden concrete implementation of base class method
|
|
1359
1365
|
assert metadata and isinstance(metadata, api_pb2.FunctionHandleMetadata), (
|
|
@@ -1382,6 +1388,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1382
1388
|
)
|
|
1383
1389
|
self._experimental_flash_urls = metadata._experimental_flash_urls
|
|
1384
1390
|
|
|
1391
|
+
# Invalidate the Function variant cache when we load new metadata, since the base Function handle
|
|
1392
|
+
# is now in sync with the server but any previously-cached variants may be stale.
|
|
1393
|
+
self._bind_params_cache.clear()
|
|
1394
|
+
|
|
1385
1395
|
def _get_metadata(self):
|
|
1386
1396
|
# Overridden concrete implementation of base class method
|
|
1387
1397
|
assert self._function_name, f"Function name must be set before metadata can be retrieved for {self}"
|
|
@@ -571,7 +571,7 @@ def import_class_service(
|
|
|
571
571
|
function_def: api_pb2.Function,
|
|
572
572
|
service_function_hydration_data: api_pb2.Object,
|
|
573
573
|
class_id: str,
|
|
574
|
-
|
|
574
|
+
_client: "modal.client._Client",
|
|
575
575
|
ser_user_cls: type | None,
|
|
576
576
|
cls_args,
|
|
577
577
|
cls_kwargs,
|
|
@@ -599,7 +599,6 @@ def import_class_service(
|
|
|
599
599
|
# Undecorated user class (serialized or local scope-decoration).
|
|
600
600
|
service_deps = None # we can't infer service deps for now
|
|
601
601
|
active_app = get_active_app_fallback(function_def)
|
|
602
|
-
_client = typing.cast("modal.client._Client", synchronizer._translate_in(client))
|
|
603
602
|
_service_function: modal._functions._Function[Any, Any, Any] = modal._functions._Function._new_hydrated(
|
|
604
603
|
service_function_hydration_data.object_id,
|
|
605
604
|
_client,
|
|
@@ -627,7 +626,7 @@ def import_class_service(
|
|
|
627
626
|
def import_server_service(
|
|
628
627
|
function_def: api_pb2.Function,
|
|
629
628
|
service_function_hydration_data: api_pb2.Object,
|
|
630
|
-
|
|
629
|
+
_client: "modal.client._Client",
|
|
631
630
|
ser_user_cls: type | None,
|
|
632
631
|
) -> Service:
|
|
633
632
|
"""
|
|
@@ -654,7 +653,6 @@ def import_server_service(
|
|
|
654
653
|
# Undecorated user class (serialized or local scope-decoration).
|
|
655
654
|
service_deps = None # we can't infer service deps for now
|
|
656
655
|
active_app = get_active_app_fallback(function_def)
|
|
657
|
-
_client = typing.cast("modal.client._Client", synchronizer._translate_in(client))
|
|
658
656
|
_service_function: modal._functions._Function[Any, Any, Any] = modal._functions._Function._new_hydrated(
|
|
659
657
|
service_function_hydration_data.object_id,
|
|
660
658
|
_client,
|
|
@@ -285,6 +285,53 @@ def make_stat_command(remote_path: str) -> str:
|
|
|
285
285
|
return json.dumps({"Stat": {"path": remote_path}})
|
|
286
286
|
|
|
287
287
|
|
|
288
|
+
def raise_watch_error(returncode: int, stderr: str | bytes, remote_path: str) -> NoReturn:
|
|
289
|
+
if payload := try_parse_error_payload(stderr):
|
|
290
|
+
logger.debug(
|
|
291
|
+
f"sandbox-fs-tools watch error: path={remote_path}, "
|
|
292
|
+
f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
|
|
293
|
+
)
|
|
294
|
+
if payload.error_kind == "NotFound":
|
|
295
|
+
raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
|
|
296
|
+
if payload.error_kind == "PermissionDenied":
|
|
297
|
+
raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
|
|
298
|
+
if payload.error_kind == "NotSupported":
|
|
299
|
+
raise InvalidError(
|
|
300
|
+
f"{payload.message}: {remote_path} - this operation is not supported for CloudBucketMounts"
|
|
301
|
+
)
|
|
302
|
+
raise SandboxFilesystemError(payload.message)
|
|
303
|
+
|
|
304
|
+
if stderr_text := _stderr_to_text(stderr):
|
|
305
|
+
logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
|
|
306
|
+
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def make_watch_command(
|
|
310
|
+
remote_path: str,
|
|
311
|
+
*,
|
|
312
|
+
recursive: bool,
|
|
313
|
+
filter: list[str] | None,
|
|
314
|
+
timeout: int | None,
|
|
315
|
+
) -> str:
|
|
316
|
+
"""Build the JSON command string for a Watch operation.
|
|
317
|
+
|
|
318
|
+
The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
|
|
319
|
+
Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
|
|
320
|
+
this schema like protobuf changes: fields must not be removed or renamed,
|
|
321
|
+
only added with backwards-compatible defaults.
|
|
322
|
+
"""
|
|
323
|
+
return json.dumps(
|
|
324
|
+
{
|
|
325
|
+
"Watch": {
|
|
326
|
+
"path": remote_path,
|
|
327
|
+
"recursive": recursive,
|
|
328
|
+
"filter": filter,
|
|
329
|
+
"timeout_secs": timeout,
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
288
335
|
def validate_absolute_remote_path(remote_path: str, operation: str) -> None:
|
|
289
336
|
if not PurePosixPath(remote_path).is_absolute():
|
|
290
337
|
raise InvalidError(f"Sandbox.filesystem.{operation}() currently only supports absolute remote_path values")
|
|
@@ -3,4 +3,8 @@ from ._billing import WorkspaceBillingReportItem, _workspace_billing_report
|
|
|
3
3
|
from ._utils.async_utils import synchronize_api
|
|
4
4
|
|
|
5
5
|
workspace_billing_report = synchronize_api(_workspace_billing_report)
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"workspace_billing_report",
|
|
9
|
+
"WorkspaceBillingReportItem",
|
|
10
|
+
]
|
|
@@ -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.dev18",
|
|
39
39
|
):
|
|
40
40
|
"""mdmd:hidden
|
|
41
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -205,7 +205,7 @@ class Client:
|
|
|
205
205
|
server_url: str,
|
|
206
206
|
client_type: int,
|
|
207
207
|
credentials: typing.Optional[tuple[str, str]],
|
|
208
|
-
version: str = "1.4.4.
|
|
208
|
+
version: str = "1.4.4.dev18",
|
|
209
209
|
):
|
|
210
210
|
"""mdmd:hidden
|
|
211
211
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# Copyright Modal Labs 2024
|
|
2
2
|
import asyncio
|
|
3
|
-
import enum
|
|
4
3
|
import io
|
|
5
4
|
from collections.abc import AsyncIterator, Sequence
|
|
6
|
-
from
|
|
7
|
-
from typing import TYPE_CHECKING, Generic, TypeVar, Union, cast
|
|
5
|
+
from typing import TYPE_CHECKING, Generic, Optional, TypeVar, Union, cast
|
|
8
6
|
|
|
9
7
|
if TYPE_CHECKING:
|
|
10
8
|
import _typeshed
|
|
@@ -15,6 +13,7 @@ from grpclib.exceptions import StreamTerminatedError
|
|
|
15
13
|
|
|
16
14
|
from modal._utils.async_utils import TaskContext
|
|
17
15
|
from modal.exception import ClientClosed
|
|
16
|
+
from modal.sandbox_fs import FileWatchEvent, FileWatchEventType
|
|
18
17
|
from modal_proto import api_pb2
|
|
19
18
|
|
|
20
19
|
from ._utils.async_utils import synchronize_api
|
|
@@ -60,21 +59,7 @@ async def _replace_bytes(file: "_FileIO", data: bytes, start: int | None = None,
|
|
|
60
59
|
deprecation_error((2025, 12, 3), "replace_bytes has been removed.")
|
|
61
60
|
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
Unknown = "Unknown"
|
|
65
|
-
Access = "Access"
|
|
66
|
-
Create = "Create"
|
|
67
|
-
Modify = "Modify"
|
|
68
|
-
Remove = "Remove"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@dataclass
|
|
72
|
-
class FileWatchEvent:
|
|
73
|
-
paths: list[str]
|
|
74
|
-
type: FileWatchEventType
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
async def _consume_output(client: _Client, exec_id: str) -> AsyncIterator[bytes | None | Exception]:
|
|
62
|
+
async def _consume_output(client: _Client, exec_id: str) -> AsyncIterator[Optional[bytes] | Exception]:
|
|
78
63
|
req = api_pb2.ContainerFilesystemExecGetOutputRequest(
|
|
79
64
|
exec_id=exec_id,
|
|
80
65
|
timeout=55,
|
|
@@ -424,7 +409,7 @@ class _FileIO(Generic[T]):
|
|
|
424
409
|
) -> AsyncIterator[FileWatchEvent]:
|
|
425
410
|
deprecation_warning(
|
|
426
411
|
(2026, 3, 9),
|
|
427
|
-
"`FileIO.watch()` is deprecated. Use `Sandbox.watch()` instead.",
|
|
412
|
+
"`FileIO.watch()` is deprecated. Use `Sandbox.filesystem.watch()` instead.",
|
|
428
413
|
)
|
|
429
414
|
async for event in watch(path, client, task_id, filter, recursive, timeout):
|
|
430
415
|
yield event
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import _io
|
|
2
2
|
import _typeshed
|
|
3
3
|
import collections.abc
|
|
4
|
-
import enum
|
|
5
4
|
import modal.client
|
|
5
|
+
import modal.sandbox_fs
|
|
6
6
|
import typing
|
|
7
7
|
import typing_extensions
|
|
8
8
|
|
|
@@ -22,31 +22,6 @@ async def _replace_bytes(
|
|
|
22
22
|
"""
|
|
23
23
|
...
|
|
24
24
|
|
|
25
|
-
class FileWatchEventType(enum.Enum):
|
|
26
|
-
Unknown = "Unknown"
|
|
27
|
-
Access = "Access"
|
|
28
|
-
Create = "Create"
|
|
29
|
-
Modify = "Modify"
|
|
30
|
-
Remove = "Remove"
|
|
31
|
-
|
|
32
|
-
class FileWatchEvent:
|
|
33
|
-
"""FileWatchEvent(paths: list[str], type: modal.file_io.FileWatchEventType)"""
|
|
34
|
-
|
|
35
|
-
paths: list[str]
|
|
36
|
-
type: FileWatchEventType
|
|
37
|
-
|
|
38
|
-
def __init__(self, paths: list[str], type: FileWatchEventType) -> None:
|
|
39
|
-
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
40
|
-
...
|
|
41
|
-
|
|
42
|
-
def __repr__(self):
|
|
43
|
-
"""Return repr(self)."""
|
|
44
|
-
...
|
|
45
|
-
|
|
46
|
-
def __eq__(self, other):
|
|
47
|
-
"""Return self==value."""
|
|
48
|
-
...
|
|
49
|
-
|
|
50
25
|
def _consume_output(
|
|
51
26
|
client: modal.client._Client, exec_id: str
|
|
52
27
|
) -> collections.abc.AsyncIterator[typing.Union[bytes, None, Exception]]: ...
|
|
@@ -157,10 +132,10 @@ class _FileIO(typing.Generic[T]):
|
|
|
157
132
|
path: str,
|
|
158
133
|
client: modal.client._Client,
|
|
159
134
|
task_id: str,
|
|
160
|
-
filter: typing.Optional[list[FileWatchEventType]] = None,
|
|
135
|
+
filter: typing.Optional[list[modal.sandbox_fs.FileWatchEventType]] = None,
|
|
161
136
|
recursive: bool = False,
|
|
162
137
|
timeout: typing.Optional[int] = None,
|
|
163
|
-
) -> collections.abc.AsyncIterator[FileWatchEvent]: ...
|
|
138
|
+
) -> collections.abc.AsyncIterator[modal.sandbox_fs.FileWatchEvent]: ...
|
|
164
139
|
async def _close(self) -> None: ...
|
|
165
140
|
async def close(self) -> None:
|
|
166
141
|
"""Flush the buffer and close the file."""
|
|
@@ -190,10 +165,10 @@ def watch(
|
|
|
190
165
|
path: str,
|
|
191
166
|
client: modal.client._Client,
|
|
192
167
|
task_id: str,
|
|
193
|
-
filter: typing.Optional[list[FileWatchEventType]] = None,
|
|
168
|
+
filter: typing.Optional[list[modal.sandbox_fs.FileWatchEventType]] = None,
|
|
194
169
|
recursive: bool = False,
|
|
195
170
|
timeout: typing.Optional[int] = None,
|
|
196
|
-
) -> collections.abc.AsyncIterator[FileWatchEvent]:
|
|
171
|
+
) -> collections.abc.AsyncIterator[modal.sandbox_fs.FileWatchEvent]:
|
|
197
172
|
"""Watch a file or directory for changes."""
|
|
198
173
|
...
|
|
199
174
|
|
|
@@ -428,20 +403,20 @@ class FileIO(typing.Generic[T]):
|
|
|
428
403
|
path: str,
|
|
429
404
|
client: modal.client.Client,
|
|
430
405
|
task_id: str,
|
|
431
|
-
filter: typing.Optional[list[FileWatchEventType]] = None,
|
|
406
|
+
filter: typing.Optional[list[modal.sandbox_fs.FileWatchEventType]] = None,
|
|
432
407
|
recursive: bool = False,
|
|
433
408
|
timeout: typing.Optional[int] = None,
|
|
434
|
-
) -> typing.Iterator[FileWatchEvent]: ...
|
|
409
|
+
) -> typing.Iterator[modal.sandbox_fs.FileWatchEvent]: ...
|
|
435
410
|
def aio(
|
|
436
411
|
self,
|
|
437
412
|
/,
|
|
438
413
|
path: str,
|
|
439
414
|
client: modal.client.Client,
|
|
440
415
|
task_id: str,
|
|
441
|
-
filter: typing.Optional[list[FileWatchEventType]] = None,
|
|
416
|
+
filter: typing.Optional[list[modal.sandbox_fs.FileWatchEventType]] = None,
|
|
442
417
|
recursive: bool = False,
|
|
443
418
|
timeout: typing.Optional[int] = None,
|
|
444
|
-
) -> collections.abc.AsyncIterator[FileWatchEvent]: ...
|
|
419
|
+
) -> collections.abc.AsyncIterator[modal.sandbox_fs.FileWatchEvent]: ...
|
|
445
420
|
|
|
446
421
|
watch: typing.ClassVar[__watch_spec]
|
|
447
422
|
|
|
@@ -465,7 +465,7 @@ class Function(
|
|
|
465
465
|
|
|
466
466
|
_call_generator: ___call_generator_spec
|
|
467
467
|
|
|
468
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
468
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
469
469
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
470
470
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result.
|
|
471
471
|
|
|
@@ -490,7 +490,7 @@ class Function(
|
|
|
490
490
|
"""
|
|
491
491
|
...
|
|
492
492
|
|
|
493
|
-
remote: __remote_spec[modal._functions.
|
|
493
|
+
remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
|
|
494
494
|
|
|
495
495
|
class __remote_gen_spec(typing_extensions.Protocol):
|
|
496
496
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -540,7 +540,7 @@ class Function(
|
|
|
540
540
|
"""
|
|
541
541
|
...
|
|
542
542
|
|
|
543
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
543
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
544
544
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
545
545
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
546
546
|
|
|
@@ -573,7 +573,7 @@ class Function(
|
|
|
573
573
|
"""
|
|
574
574
|
...
|
|
575
575
|
|
|
576
|
-
_experimental_spawn: ___experimental_spawn_spec[modal._functions.
|
|
576
|
+
_experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
|
|
577
577
|
|
|
578
578
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
|
|
579
579
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
|
|
@@ -581,7 +581,7 @@ class Function(
|
|
|
581
581
|
|
|
582
582
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
|
|
583
583
|
|
|
584
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
584
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
585
585
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
586
586
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
587
587
|
|
|
@@ -614,7 +614,7 @@ class Function(
|
|
|
614
614
|
"""
|
|
615
615
|
...
|
|
616
616
|
|
|
617
|
-
spawn: __spawn_spec[modal._functions.
|
|
617
|
+
spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
|
|
618
618
|
|
|
619
619
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
620
620
|
"""Return the inner Python object wrapped by this Modal Function.
|
|
@@ -1953,7 +1953,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1953
1953
|
):
|
|
1954
1954
|
"""[Alpha] Open a file in the Sandbox and return a FileIO handle.
|
|
1955
1955
|
|
|
1956
|
-
**Deprecated (2026-03-09):** Use the `Sandbox.filesystem` APIs instead.
|
|
1956
|
+
**Deprecated (2026-03-09):** Use the `Sandbox.filesystem` APIs instead for improved reliability.
|
|
1957
1957
|
|
|
1958
1958
|
See the [`FileIO`](https://modal.com/docs/reference/modal.file_io#modalfile_iofileio) docs for more information.
|
|
1959
1959
|
|
|
@@ -1975,7 +1975,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1975
1975
|
self._ensure_v1("open")
|
|
1976
1976
|
deprecation_warning(
|
|
1977
1977
|
(2026, 3, 9),
|
|
1978
|
-
"`Sandbox.open()` is deprecated. Use the `Sandbox.filesystem` APIs instead.",
|
|
1978
|
+
"`Sandbox.open()` is deprecated. Use the `Sandbox.filesystem` APIs instead for improved reliability.",
|
|
1979
1979
|
)
|
|
1980
1980
|
task_id = await self._get_task_id()
|
|
1981
1981
|
return await _FileIO.create(path, mode, self._client, task_id)
|
|
@@ -1983,7 +1983,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1983
1983
|
async def ls(self, path: str) -> builtins.list[str]:
|
|
1984
1984
|
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1985
1985
|
|
|
1986
|
-
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.list_files()` instead.
|
|
1986
|
+
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.list_files()` instead for improved reliability.
|
|
1987
1987
|
|
|
1988
1988
|
Args:
|
|
1989
1989
|
path: Absolute directory path inside the sandbox.
|
|
@@ -1994,7 +1994,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1994
1994
|
self._ensure_v1("ls")
|
|
1995
1995
|
deprecation_warning(
|
|
1996
1996
|
(2026, 4, 15),
|
|
1997
|
-
"`Sandbox.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead.",
|
|
1997
|
+
"`Sandbox.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead for improved reliability.",
|
|
1998
1998
|
)
|
|
1999
1999
|
task_id = await self._get_task_id()
|
|
2000
2000
|
return await ls(path, self._client, task_id)
|
|
@@ -2002,12 +2002,13 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
2002
2002
|
async def mkdir(self, path: str, parents: bool = False) -> None:
|
|
2003
2003
|
"""[Alpha] Create a new directory in the Sandbox.
|
|
2004
2004
|
|
|
2005
|
-
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.make_directory()` instead.
|
|
2005
|
+
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.make_directory()` instead for improved reliability.
|
|
2006
2006
|
"""
|
|
2007
2007
|
self._ensure_v1("mkdir")
|
|
2008
2008
|
deprecation_warning(
|
|
2009
2009
|
(2026, 4, 15),
|
|
2010
|
-
"`Sandbox.mkdir()` is deprecated. Use `Sandbox.filesystem.make_directory()` instead
|
|
2010
|
+
"`Sandbox.mkdir()` is deprecated. Use `Sandbox.filesystem.make_directory()` instead for improved "
|
|
2011
|
+
"reliability.",
|
|
2011
2012
|
)
|
|
2012
2013
|
task_id = await self._get_task_id()
|
|
2013
2014
|
return await mkdir(path, self._client, task_id, parents)
|
|
@@ -2015,12 +2016,12 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
2015
2016
|
async def rm(self, path: str, recursive: bool = False) -> None:
|
|
2016
2017
|
"""[Alpha] Remove a file or directory in the Sandbox.
|
|
2017
2018
|
|
|
2018
|
-
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.remove()` instead.
|
|
2019
|
+
**Deprecated (2026-04-15):** Use `Sandbox.filesystem.remove()` instead for improved reliability.
|
|
2019
2020
|
"""
|
|
2020
2021
|
self._ensure_v1("rm")
|
|
2021
2022
|
deprecation_warning(
|
|
2022
2023
|
(2026, 4, 15),
|
|
2023
|
-
"`Sandbox.rm()` is deprecated. Use `Sandbox.filesystem.remove()` instead.",
|
|
2024
|
+
"`Sandbox.rm()` is deprecated. Use `Sandbox.filesystem.remove()` instead for improved reliability.",
|
|
2024
2025
|
)
|
|
2025
2026
|
task_id = await self._get_task_id()
|
|
2026
2027
|
return await rm(path, self._client, task_id, recursive)
|
|
@@ -2034,6 +2035,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
2034
2035
|
) -> AsyncIterator[FileWatchEvent]:
|
|
2035
2036
|
"""[Alpha] Watch a file or directory in the Sandbox for changes.
|
|
2036
2037
|
|
|
2038
|
+
**Deprecated (2026-05-08):** Use `Sandbox.filesystem.watch()` instead for improved reliability.
|
|
2039
|
+
|
|
2037
2040
|
Args:
|
|
2038
2041
|
path: Absolute path to watch.
|
|
2039
2042
|
filter: Optional list of event types to include.
|
|
@@ -2044,6 +2047,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
2044
2047
|
An async iterator of `FileWatchEvent` values.
|
|
2045
2048
|
"""
|
|
2046
2049
|
self._ensure_v1("watch")
|
|
2050
|
+
deprecation_warning(
|
|
2051
|
+
(2026, 5, 8),
|
|
2052
|
+
"`Sandbox.watch()` is deprecated. Use `Sandbox.filesystem.watch()` instead for improved reliability.",
|
|
2053
|
+
)
|
|
2047
2054
|
task_id = await self._get_task_id()
|
|
2048
2055
|
async for event in watch(path, self._client, task_id, filter, recursive, timeout):
|
|
2049
2056
|
yield event
|