modAL 1.2.7.dev5__tar.gz → 1.2.7.dev7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/PKG-INFO +1 -1
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_functions.py +3 -10
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/container_io_manager.py +3 -2
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/app.py +34 -8
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/app.pyi +8 -4
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/client.pyi +2 -2
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/file_io.py +8 -45
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/file_io.pyi +12 -27
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/functions.pyi +7 -7
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api.proto +5 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api_pb2.py +656 -656
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api_pb2.pyi +8 -1
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_version/__init__.py +1 -1
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/LICENSE +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/README.md +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/__main__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_billing.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_clustered_functions.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_grpc_client.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_ipython.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_load_context.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_location.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_object.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_output.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_partial_function.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_pty.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_resolver.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_resources.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_serialization.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_traceback.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_tunnel.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_tunnel.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_type_manager.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/async_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/logger.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/_watcher.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/billing.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/2025.06.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/README.md +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/builder/base-images.json +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/call_graph.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/_download.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/_traceback.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/app.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/cluster.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/config.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/container.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/dict.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/entry_point.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/environment.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/import_refs.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/launch.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/profile.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/queues.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/run.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/secret.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/shell.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/token.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/utils.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cli/volume.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/client.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cls.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/cls.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/config.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/container_process.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/container_process.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/dict.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/dict.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/environments.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/environments.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/exception.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/experimental/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/experimental/flash.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/experimental/flash.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/experimental/ipython.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/functions.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/gpu.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/image.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/image.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/io_streams.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/io_streams.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/mount.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/mount.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/network_file_system.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/network_file_system.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/object.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/object.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/output.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/parallel_map.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/parallel_map.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/partial_function.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/partial_function.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/proxy.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/proxy.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/py.typed +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/queue.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/queue.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/retries.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/runner.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/runner.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/running_app.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/sandbox.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/sandbox.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/schedule.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/scheduler_placement.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/secret.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/secret.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/serving.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/serving.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/snapshot.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/snapshot.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/stream_type.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/token_flow.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/token_flow.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/volume.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal/volume.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/requires.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/__init__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/py.typed +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/modal_version/__main__.py +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/pyproject.toml +0 -0
- {modal-1.2.7.dev5 → modal-1.2.7.dev7}/setup.cfg +0 -0
|
@@ -694,7 +694,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
694
694
|
# Experimental: Clustered functions
|
|
695
695
|
cluster_size: Optional[int] = None,
|
|
696
696
|
rdma: Optional[bool] = None,
|
|
697
|
-
|
|
697
|
+
single_use_containers: bool = False,
|
|
698
698
|
ephemeral_disk: Optional[int] = None,
|
|
699
699
|
include_source: bool = True,
|
|
700
700
|
experimental_options: Optional[dict[str, str]] = None,
|
|
@@ -810,14 +810,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
810
810
|
if arg.default is not inspect.Parameter.empty:
|
|
811
811
|
raise InvalidError(f"Modal batched function {func_name} does not accept default arguments.")
|
|
812
812
|
|
|
813
|
-
if max_inputs is not None:
|
|
814
|
-
if not isinstance(max_inputs, int):
|
|
815
|
-
raise InvalidError(f"`max_inputs` must be an int, not {type(max_inputs).__name__}")
|
|
816
|
-
if max_inputs <= 0:
|
|
817
|
-
raise InvalidError("`max_inputs` must be positive")
|
|
818
|
-
if max_inputs > 1:
|
|
819
|
-
raise InvalidError("Only `max_inputs=1` is currently supported")
|
|
820
|
-
|
|
821
813
|
# Validate volumes
|
|
822
814
|
validated_volumes = validate_volumes(volumes)
|
|
823
815
|
cloud_bucket_mounts = [(k, v) for k, v in validated_volumes if isinstance(v, _CloudBucketMount)]
|
|
@@ -1024,7 +1016,8 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1024
1016
|
object_dependencies=object_dependencies,
|
|
1025
1017
|
block_network=block_network,
|
|
1026
1018
|
untrusted=restrict_modal_access,
|
|
1027
|
-
|
|
1019
|
+
single_use_containers=single_use_containers,
|
|
1020
|
+
max_inputs=int(single_use_containers), # TODO(michael) remove after worker rollover
|
|
1028
1021
|
cloud_bucket_mounts=cloud_bucket_mounts_to_proto(cloud_bucket_mounts),
|
|
1029
1022
|
scheduler_placement=scheduler_placement,
|
|
1030
1023
|
is_class=info.is_service_class(),
|
|
@@ -845,8 +845,9 @@ class _ContainerIOManager:
|
|
|
845
845
|
yield inputs
|
|
846
846
|
yielded = True
|
|
847
847
|
|
|
848
|
-
#
|
|
849
|
-
|
|
848
|
+
# TODO(michael): Remove use of max_inputs after worker rollover
|
|
849
|
+
single_use_container = self.function_def.single_use_containers or self.function_def.max_inputs == 1
|
|
850
|
+
if final_input_received or single_use_container:
|
|
850
851
|
return
|
|
851
852
|
finally:
|
|
852
853
|
if not yielded:
|
|
@@ -725,9 +725,7 @@ class _App:
|
|
|
725
725
|
enable_memory_snapshot: bool = False, # Enable memory checkpointing for faster cold starts.
|
|
726
726
|
block_network: bool = False, # Whether to block network access
|
|
727
727
|
restrict_modal_access: bool = False, # Whether to allow this function access to other Modal resources
|
|
728
|
-
#
|
|
729
|
-
# With `max_inputs = 1`, containers will be single-use.
|
|
730
|
-
max_inputs: Optional[int] = None,
|
|
728
|
+
single_use_containers: bool = False, # When True, containers will shut down after handling a single input
|
|
731
729
|
i6pn: Optional[bool] = None, # Whether to enable IPv6 container networking within the region.
|
|
732
730
|
# Whether the file or directory containing the Function's source should automatically be included
|
|
733
731
|
# in the container. When unset, falls back to the App-level configuration, or is otherwise True by default.
|
|
@@ -742,6 +740,7 @@ class _App:
|
|
|
742
740
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
|
743
741
|
container_idle_timeout: Optional[int] = None, # Replaced with `scaledown_window`
|
|
744
742
|
allow_concurrent_inputs: Optional[int] = None, # Replaced with the `@modal.concurrent` decorator
|
|
743
|
+
max_inputs: Optional[int] = None, # Replaced with `single_use_containers`
|
|
745
744
|
_experimental_buffer_containers: Optional[int] = None, # Now stable API with `buffer_containers`
|
|
746
745
|
_experimental_scheduler_placement: Optional[SchedulerPlacement] = None, # Replaced in favor of
|
|
747
746
|
# using `region` and `nonpreemptible`
|
|
@@ -764,6 +763,20 @@ class _App:
|
|
|
764
763
|
"\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
|
|
765
764
|
)
|
|
766
765
|
|
|
766
|
+
if max_inputs is not None:
|
|
767
|
+
if not isinstance(max_inputs, int):
|
|
768
|
+
raise InvalidError(f"`max_inputs` must be an int, not {type(max_inputs).__name__}")
|
|
769
|
+
if max_inputs <= 0:
|
|
770
|
+
raise InvalidError("`max_inputs` must be positive")
|
|
771
|
+
if max_inputs > 1:
|
|
772
|
+
raise InvalidError("Only `max_inputs=1` is currently supported")
|
|
773
|
+
deprecation_warning(
|
|
774
|
+
(2025, 12, 16),
|
|
775
|
+
"The `max_inputs` parameter is deprecated. Please set `single_use_containers=True` instead.",
|
|
776
|
+
pending=True,
|
|
777
|
+
)
|
|
778
|
+
single_use_containers = max_inputs == 1
|
|
779
|
+
|
|
767
780
|
if _experimental_scheduler_placement is not None:
|
|
768
781
|
deprecation_warning(
|
|
769
782
|
(2025, 11, 17),
|
|
@@ -912,7 +925,7 @@ class _App:
|
|
|
912
925
|
enable_memory_snapshot=enable_memory_snapshot,
|
|
913
926
|
block_network=block_network,
|
|
914
927
|
restrict_modal_access=restrict_modal_access,
|
|
915
|
-
|
|
928
|
+
single_use_containers=single_use_containers,
|
|
916
929
|
i6pn_enabled=i6pn_enabled,
|
|
917
930
|
cluster_size=cluster_size, # Experimental: Clustered functions
|
|
918
931
|
rdma=rdma,
|
|
@@ -969,9 +982,7 @@ class _App:
|
|
|
969
982
|
enable_memory_snapshot: bool = False, # Enable memory checkpointing for faster cold starts.
|
|
970
983
|
block_network: bool = False, # Whether to block network access
|
|
971
984
|
restrict_modal_access: bool = False, # Whether to allow this class access to other Modal resources
|
|
972
|
-
#
|
|
973
|
-
# Use `max_inputs = 1` for single-use containers.
|
|
974
|
-
max_inputs: Optional[int] = None,
|
|
985
|
+
single_use_containers: bool = False, # When True, containers will shut down after handling a single input
|
|
975
986
|
i6pn: Optional[bool] = None, # Whether to enable IPv6 container networking within the region.
|
|
976
987
|
include_source: Optional[bool] = None, # When `False`, don't automatically add the App source to the container.
|
|
977
988
|
experimental_options: Optional[dict[str, Any]] = None,
|
|
@@ -984,6 +995,7 @@ class _App:
|
|
|
984
995
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
|
985
996
|
container_idle_timeout: Optional[int] = None, # Replaced with `scaledown_window`
|
|
986
997
|
allow_concurrent_inputs: Optional[int] = None, # Replaced with the `@modal.concurrent` decorator
|
|
998
|
+
max_inputs: Optional[int] = None, # Replaced with `single_use_containers`
|
|
987
999
|
_experimental_buffer_containers: Optional[int] = None, # Now stable API with `buffer_containers`
|
|
988
1000
|
_experimental_scheduler_placement: Optional[SchedulerPlacement] = None, # Replaced in favor of
|
|
989
1001
|
# using `region` and `nonpreemptible`
|
|
@@ -1002,6 +1014,20 @@ class _App:
|
|
|
1002
1014
|
"\n\nSee https://modal.com/docs/guide/modal-1-0-migration for more information.",
|
|
1003
1015
|
)
|
|
1004
1016
|
|
|
1017
|
+
if max_inputs is not None:
|
|
1018
|
+
if not isinstance(max_inputs, int):
|
|
1019
|
+
raise InvalidError(f"`max_inputs` must be an int, not {type(max_inputs).__name__}")
|
|
1020
|
+
if max_inputs <= 0:
|
|
1021
|
+
raise InvalidError("`max_inputs` must be positive")
|
|
1022
|
+
if max_inputs > 1:
|
|
1023
|
+
raise InvalidError("Only `max_inputs=1` is currently supported")
|
|
1024
|
+
deprecation_warning(
|
|
1025
|
+
(2025, 12, 16),
|
|
1026
|
+
"The `max_inputs` parameter is deprecated. Please set `single_use_containers=True` instead.",
|
|
1027
|
+
pending=True,
|
|
1028
|
+
)
|
|
1029
|
+
single_use_containers = max_inputs == 1
|
|
1030
|
+
|
|
1005
1031
|
if _experimental_scheduler_placement is not None:
|
|
1006
1032
|
deprecation_warning(
|
|
1007
1033
|
(2025, 11, 17),
|
|
@@ -1139,7 +1165,7 @@ class _App:
|
|
|
1139
1165
|
enable_memory_snapshot=enable_memory_snapshot,
|
|
1140
1166
|
block_network=block_network,
|
|
1141
1167
|
restrict_modal_access=restrict_modal_access,
|
|
1142
|
-
|
|
1168
|
+
single_use_containers=single_use_containers,
|
|
1143
1169
|
http_config=http_config,
|
|
1144
1170
|
i6pn_enabled=i6pn_enabled,
|
|
1145
1171
|
cluster_size=cluster_size,
|
|
@@ -491,7 +491,7 @@ class _App:
|
|
|
491
491
|
enable_memory_snapshot: bool = False,
|
|
492
492
|
block_network: bool = False,
|
|
493
493
|
restrict_modal_access: bool = False,
|
|
494
|
-
|
|
494
|
+
single_use_containers: bool = False,
|
|
495
495
|
i6pn: typing.Optional[bool] = None,
|
|
496
496
|
include_source: typing.Optional[bool] = None,
|
|
497
497
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
@@ -502,6 +502,7 @@ class _App:
|
|
|
502
502
|
concurrency_limit: typing.Optional[int] = None,
|
|
503
503
|
container_idle_timeout: typing.Optional[int] = None,
|
|
504
504
|
allow_concurrent_inputs: typing.Optional[int] = None,
|
|
505
|
+
max_inputs: typing.Optional[int] = None,
|
|
505
506
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
|
506
507
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
507
508
|
) -> _FunctionDecoratorType:
|
|
@@ -545,7 +546,7 @@ class _App:
|
|
|
545
546
|
enable_memory_snapshot: bool = False,
|
|
546
547
|
block_network: bool = False,
|
|
547
548
|
restrict_modal_access: bool = False,
|
|
548
|
-
|
|
549
|
+
single_use_containers: bool = False,
|
|
549
550
|
i6pn: typing.Optional[bool] = None,
|
|
550
551
|
include_source: typing.Optional[bool] = None,
|
|
551
552
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
@@ -556,6 +557,7 @@ class _App:
|
|
|
556
557
|
concurrency_limit: typing.Optional[int] = None,
|
|
557
558
|
container_idle_timeout: typing.Optional[int] = None,
|
|
558
559
|
allow_concurrent_inputs: typing.Optional[int] = None,
|
|
560
|
+
max_inputs: typing.Optional[int] = None,
|
|
559
561
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
|
560
562
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
561
563
|
) -> collections.abc.Callable[[typing.Union[CLS_T, modal._partial_function._PartialFunction]], CLS_T]:
|
|
@@ -1154,7 +1156,7 @@ class App:
|
|
|
1154
1156
|
enable_memory_snapshot: bool = False,
|
|
1155
1157
|
block_network: bool = False,
|
|
1156
1158
|
restrict_modal_access: bool = False,
|
|
1157
|
-
|
|
1159
|
+
single_use_containers: bool = False,
|
|
1158
1160
|
i6pn: typing.Optional[bool] = None,
|
|
1159
1161
|
include_source: typing.Optional[bool] = None,
|
|
1160
1162
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
@@ -1165,6 +1167,7 @@ class App:
|
|
|
1165
1167
|
concurrency_limit: typing.Optional[int] = None,
|
|
1166
1168
|
container_idle_timeout: typing.Optional[int] = None,
|
|
1167
1169
|
allow_concurrent_inputs: typing.Optional[int] = None,
|
|
1170
|
+
max_inputs: typing.Optional[int] = None,
|
|
1168
1171
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
|
1169
1172
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
1170
1173
|
) -> _FunctionDecoratorType:
|
|
@@ -1208,7 +1211,7 @@ class App:
|
|
|
1208
1211
|
enable_memory_snapshot: bool = False,
|
|
1209
1212
|
block_network: bool = False,
|
|
1210
1213
|
restrict_modal_access: bool = False,
|
|
1211
|
-
|
|
1214
|
+
single_use_containers: bool = False,
|
|
1212
1215
|
i6pn: typing.Optional[bool] = None,
|
|
1213
1216
|
include_source: typing.Optional[bool] = None,
|
|
1214
1217
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
@@ -1219,6 +1222,7 @@ class App:
|
|
|
1219
1222
|
concurrency_limit: typing.Optional[int] = None,
|
|
1220
1223
|
container_idle_timeout: typing.Optional[int] = None,
|
|
1221
1224
|
allow_concurrent_inputs: typing.Optional[int] = None,
|
|
1225
|
+
max_inputs: typing.Optional[int] = None,
|
|
1222
1226
|
_experimental_buffer_containers: typing.Optional[int] = None,
|
|
1223
1227
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
1224
1228
|
) -> collections.abc.Callable[[typing.Union[CLS_T, modal.partial_function.PartialFunction]], CLS_T]:
|
|
@@ -32,7 +32,7 @@ class _Client:
|
|
|
32
32
|
server_url: str,
|
|
33
33
|
client_type: int,
|
|
34
34
|
credentials: typing.Optional[tuple[str, str]],
|
|
35
|
-
version: str = "1.2.7.
|
|
35
|
+
version: str = "1.2.7.dev7",
|
|
36
36
|
):
|
|
37
37
|
"""mdmd:hidden
|
|
38
38
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -163,7 +163,7 @@ class Client:
|
|
|
163
163
|
server_url: str,
|
|
164
164
|
client_type: int,
|
|
165
165
|
credentials: typing.Optional[tuple[str, str]],
|
|
166
|
-
version: str = "1.2.7.
|
|
166
|
+
version: str = "1.2.7.dev7",
|
|
167
167
|
):
|
|
168
168
|
"""mdmd:hidden
|
|
169
169
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -17,9 +17,10 @@ from modal.exception import ClientClosed
|
|
|
17
17
|
from modal_proto import api_pb2
|
|
18
18
|
|
|
19
19
|
from ._utils.async_utils import synchronize_api
|
|
20
|
+
from ._utils.deprecation import deprecation_error
|
|
20
21
|
from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES
|
|
21
22
|
from .client import _Client
|
|
22
|
-
from .exception import FilesystemExecutionError
|
|
23
|
+
from .exception import FilesystemExecutionError
|
|
23
24
|
|
|
24
25
|
WRITE_CHUNK_SIZE = 16 * 1024 * 1024 # 16 MiB
|
|
25
26
|
WRITE_FILE_SIZE_LIMIT = 1024 * 1024 * 1024 # 1 GiB
|
|
@@ -46,55 +47,17 @@ T = TypeVar("T", str, bytes)
|
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
async def _delete_bytes(file: "_FileIO", start: Optional[int] = None, end: Optional[int] = None) -> None:
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
52
|
-
If either is None, the start or end of the file is used, respectively.
|
|
50
|
+
"""mdmd:hidden
|
|
51
|
+
This method has been removed.
|
|
53
52
|
"""
|
|
54
|
-
|
|
55
|
-
file._check_closed()
|
|
56
|
-
if start is not None and end is not None:
|
|
57
|
-
if start >= end:
|
|
58
|
-
raise ValueError("start must be less than end")
|
|
59
|
-
resp = await file._client.stub.ContainerFilesystemExec(
|
|
60
|
-
api_pb2.ContainerFilesystemExecRequest(
|
|
61
|
-
file_delete_bytes_request=api_pb2.ContainerFileDeleteBytesRequest(
|
|
62
|
-
file_descriptor=file._file_descriptor,
|
|
63
|
-
start_inclusive=start,
|
|
64
|
-
end_exclusive=end,
|
|
65
|
-
),
|
|
66
|
-
task_id=file._task_id,
|
|
67
|
-
),
|
|
68
|
-
)
|
|
69
|
-
await file._wait(resp.exec_id)
|
|
53
|
+
deprecation_error((2025, 12, 3), "delete_bytes has been removed.")
|
|
70
54
|
|
|
71
55
|
|
|
72
56
|
async def _replace_bytes(file: "_FileIO", data: bytes, start: Optional[int] = None, end: Optional[int] = None) -> None:
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
77
|
-
If either is None, the start or end of the file is used, respectively.
|
|
57
|
+
"""mdmd:hidden
|
|
58
|
+
This method has been removed.
|
|
78
59
|
"""
|
|
79
|
-
|
|
80
|
-
file._check_closed()
|
|
81
|
-
if start is not None and end is not None:
|
|
82
|
-
if start >= end:
|
|
83
|
-
raise InvalidError("start must be less than end")
|
|
84
|
-
if len(data) > WRITE_CHUNK_SIZE:
|
|
85
|
-
raise InvalidError("Write request payload exceeds 16 MiB limit")
|
|
86
|
-
resp = await file._client.stub.ContainerFilesystemExec(
|
|
87
|
-
api_pb2.ContainerFilesystemExecRequest(
|
|
88
|
-
file_write_replace_bytes_request=api_pb2.ContainerFileWriteReplaceBytesRequest(
|
|
89
|
-
file_descriptor=file._file_descriptor,
|
|
90
|
-
data=data,
|
|
91
|
-
start_inclusive=start,
|
|
92
|
-
end_exclusive=end,
|
|
93
|
-
),
|
|
94
|
-
task_id=file._task_id,
|
|
95
|
-
),
|
|
96
|
-
)
|
|
97
|
-
await file._wait(resp.exec_id)
|
|
60
|
+
deprecation_error((2025, 12, 3), "replace_bytes has been removed.")
|
|
98
61
|
|
|
99
62
|
|
|
100
63
|
class FileWatchEventType(enum.Enum):
|
|
@@ -7,21 +7,16 @@ import typing_extensions
|
|
|
7
7
|
T = typing.TypeVar("T")
|
|
8
8
|
|
|
9
9
|
async def _delete_bytes(file: _FileIO, start: typing.Optional[int] = None, end: typing.Optional[int] = None) -> None:
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
13
|
-
If either is None, the start or end of the file is used, respectively.
|
|
10
|
+
"""mdmd:hidden
|
|
11
|
+
This method has been removed.
|
|
14
12
|
"""
|
|
15
13
|
...
|
|
16
14
|
|
|
17
15
|
async def _replace_bytes(
|
|
18
16
|
file: _FileIO, data: bytes, start: typing.Optional[int] = None, end: typing.Optional[int] = None
|
|
19
17
|
) -> None:
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
24
|
-
If either is None, the start or end of the file is used, respectively.
|
|
18
|
+
"""mdmd:hidden
|
|
19
|
+
This method has been removed.
|
|
25
20
|
"""
|
|
26
21
|
...
|
|
27
22
|
|
|
@@ -174,18 +169,14 @@ class _FileIO(typing.Generic[T]):
|
|
|
174
169
|
|
|
175
170
|
class __delete_bytes_spec(typing_extensions.Protocol):
|
|
176
171
|
def __call__(self, /, file: FileIO, start: typing.Optional[int] = None, end: typing.Optional[int] = None) -> None:
|
|
177
|
-
"""
|
|
178
|
-
|
|
179
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
180
|
-
If either is None, the start or end of the file is used, respectively.
|
|
172
|
+
"""mdmd:hidden
|
|
173
|
+
This method has been removed.
|
|
181
174
|
"""
|
|
182
175
|
...
|
|
183
176
|
|
|
184
177
|
async def aio(self, /, file: FileIO, start: typing.Optional[int] = None, end: typing.Optional[int] = None) -> None:
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
188
|
-
If either is None, the start or end of the file is used, respectively.
|
|
178
|
+
"""mdmd:hidden
|
|
179
|
+
This method has been removed.
|
|
189
180
|
"""
|
|
190
181
|
...
|
|
191
182
|
|
|
@@ -195,22 +186,16 @@ class __replace_bytes_spec(typing_extensions.Protocol):
|
|
|
195
186
|
def __call__(
|
|
196
187
|
self, /, file: FileIO, data: bytes, start: typing.Optional[int] = None, end: typing.Optional[int] = None
|
|
197
188
|
) -> None:
|
|
198
|
-
"""
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
202
|
-
If either is None, the start or end of the file is used, respectively.
|
|
189
|
+
"""mdmd:hidden
|
|
190
|
+
This method has been removed.
|
|
203
191
|
"""
|
|
204
192
|
...
|
|
205
193
|
|
|
206
194
|
async def aio(
|
|
207
195
|
self, /, file: FileIO, data: bytes, start: typing.Optional[int] = None, end: typing.Optional[int] = None
|
|
208
196
|
) -> None:
|
|
209
|
-
"""
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
`start` and `end` are byte offsets. `start` is inclusive, `end` is exclusive.
|
|
213
|
-
If either is None, the start or end of the file is used, respectively.
|
|
197
|
+
"""mdmd:hidden
|
|
198
|
+
This method has been removed.
|
|
214
199
|
"""
|
|
215
200
|
...
|
|
216
201
|
|
|
@@ -106,7 +106,7 @@ class Function(
|
|
|
106
106
|
i6pn_enabled: bool = False,
|
|
107
107
|
cluster_size: typing.Optional[int] = None,
|
|
108
108
|
rdma: typing.Optional[bool] = None,
|
|
109
|
-
|
|
109
|
+
single_use_containers: bool = False,
|
|
110
110
|
ephemeral_disk: typing.Optional[int] = None,
|
|
111
111
|
include_source: bool = True,
|
|
112
112
|
experimental_options: typing.Optional[dict[str, str]] = None,
|
|
@@ -409,7 +409,7 @@ class Function(
|
|
|
409
409
|
|
|
410
410
|
_call_generator: ___call_generator_spec[typing_extensions.Self]
|
|
411
411
|
|
|
412
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
412
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
|
413
413
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
414
414
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
415
415
|
...
|
|
@@ -418,7 +418,7 @@ class Function(
|
|
|
418
418
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
419
419
|
...
|
|
420
420
|
|
|
421
|
-
remote: __remote_spec[modal._functions.
|
|
421
|
+
remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
|
422
422
|
|
|
423
423
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
424
424
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -445,7 +445,7 @@ class Function(
|
|
|
445
445
|
"""
|
|
446
446
|
...
|
|
447
447
|
|
|
448
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
448
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
|
449
449
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
450
450
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
451
451
|
|
|
@@ -469,7 +469,7 @@ class Function(
|
|
|
469
469
|
...
|
|
470
470
|
|
|
471
471
|
_experimental_spawn: ___experimental_spawn_spec[
|
|
472
|
-
modal._functions.
|
|
472
|
+
modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
|
|
473
473
|
]
|
|
474
474
|
|
|
475
475
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
|
|
@@ -478,7 +478,7 @@ class Function(
|
|
|
478
478
|
|
|
479
479
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
|
|
480
480
|
|
|
481
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
481
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
|
482
482
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
483
483
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
484
484
|
|
|
@@ -499,7 +499,7 @@ class Function(
|
|
|
499
499
|
"""
|
|
500
500
|
...
|
|
501
501
|
|
|
502
|
-
spawn: __spawn_spec[modal._functions.
|
|
502
|
+
spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
|
503
503
|
|
|
504
504
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
505
505
|
"""Return the inner Python object wrapped by this Modal Function."""
|
|
@@ -1469,6 +1469,8 @@ message Function {
|
|
|
1469
1469
|
|
|
1470
1470
|
bool block_network = 44;
|
|
1471
1471
|
|
|
1472
|
+
// In the SDK, we've deprecated `max_inputs` (which only every implemented `max_inputs=1`)
|
|
1473
|
+
// in favor of a boolean `single_use_containers` parameter.
|
|
1472
1474
|
uint32 max_inputs = 46;
|
|
1473
1475
|
|
|
1474
1476
|
repeated S3Mount s3_mounts = 47;
|
|
@@ -1556,6 +1558,9 @@ message Function {
|
|
|
1556
1558
|
// Attribute on the module with the implementation, which may differ from function_name
|
|
1557
1559
|
// when the user provided a custom name= for the Function inside the Application namespace
|
|
1558
1560
|
string implementation_name = 90;
|
|
1561
|
+
|
|
1562
|
+
bool single_use_containers = 91; // When True, containers will shut down after handling a single input
|
|
1563
|
+
|
|
1559
1564
|
}
|
|
1560
1565
|
|
|
1561
1566
|
message FunctionAsyncInvokeRequest {
|