modal 1.0.5.dev2__tar.gz → 1.0.5.dev4__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.0.5.dev2 → modal-1.0.5.dev4}/PKG-INFO +1 -1
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_clustered_functions.pyi +13 -3
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_functions.py +5 -4
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_partial_function.py +1 -1
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/container_io_manager.pyi +222 -40
- modal-1.0.5.dev4/modal/_runtime/execution_context.pyi +78 -0
- modal-1.0.5.dev4/modal/_tunnel.pyi +405 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/app.py +4 -4
- modal-1.0.5.dev4/modal/app.pyi +1120 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/run.py +2 -1
- modal-1.0.5.dev4/modal/client.pyi +419 -0
- modal-1.0.5.dev4/modal/cloud_bucket_mount.pyi +239 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cls.py +3 -3
- modal-1.0.5.dev4/modal/cls.pyi +715 -0
- modal-1.0.5.dev4/modal/container_process.pyi +175 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/dict.py +1 -1
- modal-1.0.5.dev4/modal/dict.pyi +611 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/environments.pyi +41 -9
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/exception.py +2 -2
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/file_io.pyi +236 -45
- modal-1.0.5.dev4/modal/functions.pyi +890 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/gpu.py +1 -1
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/image.py +1 -1
- modal-1.0.5.dev4/modal/image.pyi +1792 -0
- modal-1.0.5.dev4/modal/io_streams.pyi +427 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/mount.pyi +261 -31
- modal-1.0.5.dev4/modal/network_file_system.pyi +503 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/object.pyi +48 -9
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/parallel_map.pyi +144 -14
- modal-1.0.5.dev4/modal/partial_function.pyi +413 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/proxy.py +1 -1
- modal-1.0.5.dev4/modal/proxy.pyi +37 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/queue.py +1 -1
- modal-1.0.5.dev4/modal/queue.pyi +717 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/runner.pyi +160 -22
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/sandbox.py +7 -7
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/sandbox.pyi +310 -50
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/schedule.py +1 -1
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/secret.py +2 -2
- modal-1.0.5.dev4/modal/secret.pyi +242 -0
- modal-1.0.5.dev4/modal/snapshot.pyi +39 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/token_flow.pyi +28 -8
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/volume.py +1 -1
- modal-1.0.5.dev4/modal/volume.pyi +1127 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_version/__init__.py +1 -1
- modal-1.0.5.dev2/modal/_runtime/execution_context.pyi +0 -24
- modal-1.0.5.dev2/modal/_tunnel.pyi +0 -37
- modal-1.0.5.dev2/modal/app.pyi +0 -510
- modal-1.0.5.dev2/modal/client.pyi +0 -223
- modal-1.0.5.dev2/modal/cloud_bucket_mount.pyi +0 -51
- modal-1.0.5.dev2/modal/cls.pyi +0 -308
- modal-1.0.5.dev2/modal/container_process.pyi +0 -86
- modal-1.0.5.dev2/modal/dict.pyi +0 -209
- modal-1.0.5.dev2/modal/functions.pyi +0 -401
- modal-1.0.5.dev2/modal/image.pyi +0 -610
- modal-1.0.5.dev2/modal/io_streams.pyi +0 -124
- modal-1.0.5.dev2/modal/network_file_system.pyi +0 -222
- modal-1.0.5.dev2/modal/partial_function.pyi +0 -172
- modal-1.0.5.dev2/modal/proxy.pyi +0 -12
- modal-1.0.5.dev2/modal/queue.pyi +0 -300
- modal-1.0.5.dev2/modal/secret.pyi +0 -93
- modal-1.0.5.dev2/modal/snapshot.pyi +0 -18
- modal-1.0.5.dev2/modal/volume.pyi +0 -537
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/LICENSE +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/README.md +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/__main__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_clustered_functions.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_ipython.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_location.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_object.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_output.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_pty.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_resolver.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_resources.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_serialization.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_traceback.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_tunnel.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_type_manager.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/blob_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/function_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/logger.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/_watcher.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/call_graph.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/_download.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/_traceback.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/app.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/cluster.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/config.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/container.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/dict.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/entry_point.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/environment.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/import_refs.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/launch.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/profile.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/queues.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/secret.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/token.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/utils.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cli/volume.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/client.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/config.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/container_process.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/environments.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/experimental/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/experimental/ipython.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/file_io.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/functions.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/io_streams.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/mount.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/network_file_system.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/object.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/output.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/parallel_map.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/partial_function.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/py.typed +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/README.md +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/requirements/base-images.json +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/retries.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/runner.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/running_app.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/scheduler_placement.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/serving.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/serving.pyi +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/snapshot.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/stream_type.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal/token_flow.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/requires.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/__init__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api.proto +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api_pb2.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options.proto +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_proto/py.typed +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/modal_version/__main__.py +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/pyproject.toml +0 -0
- {modal-1.0.5.dev2 → modal-1.0.5.dev4}/setup.cfg +0 -0
@@ -3,12 +3,22 @@ import typing
|
|
3
3
|
import typing_extensions
|
4
4
|
|
5
5
|
class ClusterInfo:
|
6
|
+
"""ClusterInfo(rank: int, container_ips: list[str])"""
|
7
|
+
|
6
8
|
rank: int
|
7
9
|
container_ips: list[str]
|
8
10
|
|
9
|
-
def __init__(self, rank: int, container_ips: list[str]) -> None:
|
10
|
-
|
11
|
-
|
11
|
+
def __init__(self, rank: int, container_ips: list[str]) -> None:
|
12
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
13
|
+
...
|
14
|
+
|
15
|
+
def __repr__(self):
|
16
|
+
"""Return repr(self)."""
|
17
|
+
...
|
18
|
+
|
19
|
+
def __eq__(self, other):
|
20
|
+
"""Return self==value."""
|
21
|
+
...
|
12
22
|
|
13
23
|
def get_cluster_info() -> ClusterInfo: ...
|
14
24
|
async def _initialize_clustered_function(client: modal.client._Client, task_id: str, world_size: int): ...
|
@@ -1671,8 +1671,9 @@ Use the `Function.get_web_url()` method instead.
|
|
1671
1671
|
async def spawn(self, *args: P.args, **kwargs: P.kwargs) -> "_FunctionCall[ReturnType]":
|
1672
1672
|
"""Calls the function with the given arguments, without waiting for the results.
|
1673
1673
|
|
1674
|
-
Returns a [`modal.FunctionCall`](/docs/reference/modal.FunctionCall) object
|
1675
|
-
waited for using
|
1674
|
+
Returns a [`modal.FunctionCall`](https://modal.com/docs/reference/modal.FunctionCall) object
|
1675
|
+
that can later be polled or waited for using
|
1676
|
+
[`.get(timeout=...)`](https://modal.com/docs/reference/modal.FunctionCall#get).
|
1676
1677
|
Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
|
1677
1678
|
"""
|
1678
1679
|
self._check_no_web_url("spawn")
|
@@ -1748,7 +1749,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
1748
1749
|
"""Returns a structure representing the call graph from a given root
|
1749
1750
|
call ID, along with the status of execution for each node.
|
1750
1751
|
|
1751
|
-
See [`modal.call_graph`](/docs/reference/modal.call_graph) reference page
|
1752
|
+
See [`modal.call_graph`](https://modal.com/docs/reference/modal.call_graph) reference page
|
1752
1753
|
for documentation on the structure of the returned `InputInfo` items.
|
1753
1754
|
"""
|
1754
1755
|
assert self._client and self._client.stub
|
@@ -1762,7 +1763,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
1762
1763
|
terminate_containers: bool = False,
|
1763
1764
|
):
|
1764
1765
|
"""Cancels the function call, which will stop its execution and mark its inputs as
|
1765
|
-
[`TERMINATED`](/docs/reference/modal.call_graph#modalcall_graphinputstatus).
|
1766
|
+
[`TERMINATED`](https://modal.com/docs/reference/modal.call_graph#modalcall_graphinputstatus).
|
1766
1767
|
|
1767
1768
|
If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
|
1768
1769
|
causing any non-cancelled inputs on those containers to be rescheduled in new containers.
|
@@ -538,7 +538,7 @@ def _wsgi_app(
|
|
538
538
|
Web Server Gateway Interface (WSGI) is a standard for synchronous Python web apps.
|
539
539
|
It has been [succeeded by the ASGI interface](https://asgi.readthedocs.io/en/latest/introduction.html#wsgi-compatibility)
|
540
540
|
which is compatible with ASGI and supports additional functionality such as web sockets.
|
541
|
-
Modal supports ASGI via [`asgi_app`](/docs/reference/modal.asgi_app).
|
541
|
+
Modal supports ASGI via [`asgi_app`](https://modal.com/docs/reference/modal.asgi_app).
|
542
542
|
|
543
543
|
**Usage:**
|
544
544
|
|
@@ -9,10 +9,21 @@ import synchronicity.combined_types
|
|
9
9
|
import typing
|
10
10
|
import typing_extensions
|
11
11
|
|
12
|
-
class UserException(Exception):
|
13
|
-
|
12
|
+
class UserException(Exception):
|
13
|
+
"""Used to shut down the task gracefully."""
|
14
|
+
|
15
|
+
...
|
16
|
+
|
17
|
+
class Sentinel:
|
18
|
+
"""Used to get type-stubs to work with this object."""
|
19
|
+
|
20
|
+
...
|
14
21
|
|
15
22
|
class IOContext:
|
23
|
+
"""Context object for managing input, function calls, and function executions
|
24
|
+
in a batched or single input context.
|
25
|
+
"""
|
26
|
+
|
16
27
|
input_ids: list[str]
|
17
28
|
retry_counts: list[int]
|
18
29
|
function_call_ids: list[str]
|
@@ -30,7 +41,10 @@ class IOContext:
|
|
30
41
|
function_inputs: list[modal_proto.api_pb2.FunctionInput],
|
31
42
|
is_batched: bool,
|
32
43
|
client: modal.client._Client,
|
33
|
-
):
|
44
|
+
):
|
45
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
46
|
+
...
|
47
|
+
|
34
48
|
@classmethod
|
35
49
|
async def create(
|
36
50
|
cls,
|
@@ -46,12 +60,17 @@ class IOContext:
|
|
46
60
|
def validate_output_data(self, data: typing.Any) -> list[typing.Any]: ...
|
47
61
|
|
48
62
|
class InputSlots:
|
63
|
+
"""A semaphore that allows dynamically adjusting the concurrency."""
|
64
|
+
|
49
65
|
active: int
|
50
66
|
value: int
|
51
67
|
waiter: typing.Optional[asyncio.Future]
|
52
68
|
closed: bool
|
53
69
|
|
54
|
-
def __init__(self, value: int) -> None:
|
70
|
+
def __init__(self, value: int) -> None:
|
71
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
72
|
+
...
|
73
|
+
|
55
74
|
async def acquire(self) -> None: ...
|
56
75
|
def _wake_waiter(self) -> None: ...
|
57
76
|
def release(self) -> None: ...
|
@@ -59,6 +78,12 @@ class InputSlots:
|
|
59
78
|
async def close(self) -> None: ...
|
60
79
|
|
61
80
|
class _ContainerIOManager:
|
81
|
+
"""Synchronizes all RPC calls and network operations for a running container.
|
82
|
+
|
83
|
+
TODO: maybe we shouldn't synchronize the whole class.
|
84
|
+
Then we could potentially move a bunch of the global functions onto it.
|
85
|
+
"""
|
86
|
+
|
62
87
|
task_id: str
|
63
88
|
function_id: str
|
64
89
|
app_id: str
|
@@ -90,9 +115,15 @@ class _ContainerIOManager:
|
|
90
115
|
@staticmethod
|
91
116
|
def __new__(
|
92
117
|
cls, container_args: modal_proto.api_pb2.ContainerArguments, client: modal.client._Client
|
93
|
-
) -> _ContainerIOManager:
|
118
|
+
) -> _ContainerIOManager:
|
119
|
+
"""Create and return a new object. See help(type) for accurate signature."""
|
120
|
+
...
|
121
|
+
|
94
122
|
@classmethod
|
95
|
-
def _reset_singleton(cls):
|
123
|
+
def _reset_singleton(cls):
|
124
|
+
"""Only used for tests."""
|
125
|
+
...
|
126
|
+
|
96
127
|
async def hello(self): ...
|
97
128
|
async def _run_heartbeat_loop(self): ...
|
98
129
|
async def _heartbeat_handle_cancellations(self) -> bool: ...
|
@@ -102,15 +133,35 @@ class _ContainerIOManager:
|
|
102
133
|
async def _dynamic_concurrency_loop(self): ...
|
103
134
|
def serialize_data_format(self, obj: typing.Any, data_format: int) -> bytes: ...
|
104
135
|
async def format_blob_data(self, data: bytes) -> dict[str, typing.Any]: ...
|
105
|
-
def get_data_in(self, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]:
|
136
|
+
def get_data_in(self, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]:
|
137
|
+
"""Read from the `data_in` stream of a function call."""
|
138
|
+
...
|
139
|
+
|
106
140
|
async def put_data_out(
|
107
141
|
self, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
108
|
-
) -> None:
|
142
|
+
) -> None:
|
143
|
+
"""Put data onto the `data_out` stream of a function call.
|
144
|
+
|
145
|
+
This is used for generator outputs, which includes web endpoint responses. Note that this
|
146
|
+
was introduced as a performance optimization in client version 0.57, so older clients will
|
147
|
+
still use the previous Postgres-backed system based on `FunctionPutOutputs()`.
|
148
|
+
"""
|
149
|
+
...
|
150
|
+
|
109
151
|
async def generator_output_task(
|
110
152
|
self, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue
|
111
|
-
) -> None:
|
112
|
-
|
113
|
-
|
153
|
+
) -> None:
|
154
|
+
"""Task that feeds generator outputs into a function call's `data_out` stream."""
|
155
|
+
...
|
156
|
+
|
157
|
+
async def _queue_create(self, size: int) -> asyncio.queues.Queue:
|
158
|
+
"""Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
|
159
|
+
...
|
160
|
+
|
161
|
+
async def _queue_put(self, queue: asyncio.queues.Queue, value: typing.Any) -> None:
|
162
|
+
"""Put a value onto a queue, using the synchronicity event loop."""
|
163
|
+
...
|
164
|
+
|
114
165
|
def get_average_call_time(self) -> float: ...
|
115
166
|
def get_max_inputs_to_fetch(self): ...
|
116
167
|
def _generate_inputs(
|
@@ -131,15 +182,33 @@ class _ContainerIOManager:
|
|
131
182
|
) -> None: ...
|
132
183
|
def serialize_exception(self, exc: BaseException) -> bytes: ...
|
133
184
|
def serialize_traceback(self, exc: BaseException) -> tuple[typing.Optional[bytes], typing.Optional[bytes]]: ...
|
134
|
-
def handle_user_exception(self) -> typing.AsyncContextManager[None]:
|
135
|
-
|
185
|
+
def handle_user_exception(self) -> typing.AsyncContextManager[None]:
|
186
|
+
"""Sets the task as failed in a way where it's not retried.
|
187
|
+
|
188
|
+
Used for handling exceptions from container lifecycle methods at the moment, which should
|
189
|
+
trigger a task failure state.
|
190
|
+
"""
|
191
|
+
...
|
192
|
+
|
193
|
+
def handle_input_exception(self, io_context: IOContext, started_at: float) -> typing.AsyncContextManager[None]:
|
194
|
+
"""Handle an exception while processing a function input."""
|
195
|
+
...
|
196
|
+
|
136
197
|
def exit_context(self, started_at, input_ids: list[str]): ...
|
137
198
|
async def push_outputs(
|
138
199
|
self, io_context: IOContext, started_at: float, data: typing.Any, data_format: int
|
139
200
|
) -> None: ...
|
140
201
|
async def memory_restore(self) -> None: ...
|
141
|
-
async def memory_snapshot(self) -> None:
|
142
|
-
|
202
|
+
async def memory_snapshot(self) -> None:
|
203
|
+
"""Message server indicating that function is ready to be checkpointed."""
|
204
|
+
...
|
205
|
+
|
206
|
+
async def volume_commit(self, volume_ids: list[str]) -> None:
|
207
|
+
"""Perform volume commit for given `volume_ids`.
|
208
|
+
Only used on container exit to persist uncommitted changes on behalf of user.
|
209
|
+
"""
|
210
|
+
...
|
211
|
+
|
143
212
|
async def interact(self, from_breakpoint: bool = False): ...
|
144
213
|
@property
|
145
214
|
def target_concurrency(self) -> int: ...
|
@@ -148,15 +217,35 @@ class _ContainerIOManager:
|
|
148
217
|
@property
|
149
218
|
def input_concurrency_enabled(self) -> int: ...
|
150
219
|
@classmethod
|
151
|
-
def get_input_concurrency(cls) -> int:
|
220
|
+
def get_input_concurrency(cls) -> int:
|
221
|
+
"""Returns the number of usable input slots.
|
222
|
+
|
223
|
+
If concurrency is reduced, active slots can exceed allotted slots. Returns the larger value
|
224
|
+
in this case.
|
225
|
+
"""
|
226
|
+
...
|
227
|
+
|
152
228
|
@classmethod
|
153
|
-
def set_input_concurrency(cls, concurrency: int):
|
229
|
+
def set_input_concurrency(cls, concurrency: int):
|
230
|
+
"""Edit the number of input slots.
|
231
|
+
|
232
|
+
This disables the background loop which automatically adjusts concurrency
|
233
|
+
within [target_concurrency, max_concurrency].
|
234
|
+
"""
|
235
|
+
...
|
236
|
+
|
154
237
|
@classmethod
|
155
238
|
def stop_fetching_inputs(cls): ...
|
156
239
|
|
157
240
|
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
158
241
|
|
159
242
|
class ContainerIOManager:
|
243
|
+
"""Synchronizes all RPC calls and network operations for a running container.
|
244
|
+
|
245
|
+
TODO: maybe we shouldn't synchronize the whole class.
|
246
|
+
Then we could potentially move a bunch of the global functions onto it.
|
247
|
+
"""
|
248
|
+
|
160
249
|
task_id: str
|
161
250
|
function_id: str
|
162
251
|
app_id: str
|
@@ -182,12 +271,17 @@ class ContainerIOManager:
|
|
182
271
|
_GENERATOR_STOP_SENTINEL: typing.ClassVar[Sentinel]
|
183
272
|
_singleton: typing.ClassVar[typing.Optional[ContainerIOManager]]
|
184
273
|
|
185
|
-
def __init__(self, /, *args, **kwargs):
|
274
|
+
def __init__(self, /, *args, **kwargs):
|
275
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
276
|
+
...
|
277
|
+
|
186
278
|
def _init(self, container_args: modal_proto.api_pb2.ContainerArguments, client: modal.client.Client): ...
|
187
279
|
@property
|
188
280
|
def heartbeat_condition(self) -> asyncio.locks.Condition: ...
|
189
281
|
@classmethod
|
190
|
-
def _reset_singleton(cls):
|
282
|
+
def _reset_singleton(cls):
|
283
|
+
"""Only used for tests."""
|
284
|
+
...
|
191
285
|
|
192
286
|
class __hello_spec(typing_extensions.Protocol[SUPERSELF]):
|
193
287
|
def __call__(self, /): ...
|
@@ -238,36 +332,71 @@ class ContainerIOManager:
|
|
238
332
|
format_blob_data: __format_blob_data_spec[typing_extensions.Self]
|
239
333
|
|
240
334
|
class __get_data_in_spec(typing_extensions.Protocol[SUPERSELF]):
|
241
|
-
def __call__(self, /, function_call_id: str) -> typing.Iterator[typing.Any]:
|
242
|
-
|
335
|
+
def __call__(self, /, function_call_id: str) -> typing.Iterator[typing.Any]:
|
336
|
+
"""Read from the `data_in` stream of a function call."""
|
337
|
+
...
|
338
|
+
|
339
|
+
def aio(self, /, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]:
|
340
|
+
"""Read from the `data_in` stream of a function call."""
|
341
|
+
...
|
243
342
|
|
244
343
|
get_data_in: __get_data_in_spec[typing_extensions.Self]
|
245
344
|
|
246
345
|
class __put_data_out_spec(typing_extensions.Protocol[SUPERSELF]):
|
247
346
|
def __call__(
|
248
347
|
self, /, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
249
|
-
) -> None:
|
348
|
+
) -> None:
|
349
|
+
"""Put data onto the `data_out` stream of a function call.
|
350
|
+
|
351
|
+
This is used for generator outputs, which includes web endpoint responses. Note that this
|
352
|
+
was introduced as a performance optimization in client version 0.57, so older clients will
|
353
|
+
still use the previous Postgres-backed system based on `FunctionPutOutputs()`.
|
354
|
+
"""
|
355
|
+
...
|
356
|
+
|
250
357
|
async def aio(
|
251
358
|
self, /, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
|
252
|
-
) -> None:
|
359
|
+
) -> None:
|
360
|
+
"""Put data onto the `data_out` stream of a function call.
|
361
|
+
|
362
|
+
This is used for generator outputs, which includes web endpoint responses. Note that this
|
363
|
+
was introduced as a performance optimization in client version 0.57, so older clients will
|
364
|
+
still use the previous Postgres-backed system based on `FunctionPutOutputs()`.
|
365
|
+
"""
|
366
|
+
...
|
253
367
|
|
254
368
|
put_data_out: __put_data_out_spec[typing_extensions.Self]
|
255
369
|
|
256
370
|
class __generator_output_task_spec(typing_extensions.Protocol[SUPERSELF]):
|
257
|
-
def __call__(self, /, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue) -> None:
|
258
|
-
|
371
|
+
def __call__(self, /, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue) -> None:
|
372
|
+
"""Task that feeds generator outputs into a function call's `data_out` stream."""
|
373
|
+
...
|
374
|
+
|
375
|
+
async def aio(self, /, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue) -> None:
|
376
|
+
"""Task that feeds generator outputs into a function call's `data_out` stream."""
|
377
|
+
...
|
259
378
|
|
260
379
|
generator_output_task: __generator_output_task_spec[typing_extensions.Self]
|
261
380
|
|
262
381
|
class ___queue_create_spec(typing_extensions.Protocol[SUPERSELF]):
|
263
|
-
def __call__(self, /, size: int) -> asyncio.queues.Queue:
|
264
|
-
|
382
|
+
def __call__(self, /, size: int) -> asyncio.queues.Queue:
|
383
|
+
"""Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
|
384
|
+
...
|
385
|
+
|
386
|
+
async def aio(self, /, size: int) -> asyncio.queues.Queue:
|
387
|
+
"""Create a queue, on the synchronicity event loop (needed on Python 3.8 and 3.9)."""
|
388
|
+
...
|
265
389
|
|
266
390
|
_queue_create: ___queue_create_spec[typing_extensions.Self]
|
267
391
|
|
268
392
|
class ___queue_put_spec(typing_extensions.Protocol[SUPERSELF]):
|
269
|
-
def __call__(self, /, queue: asyncio.queues.Queue, value: typing.Any) -> None:
|
270
|
-
|
393
|
+
def __call__(self, /, queue: asyncio.queues.Queue, value: typing.Any) -> None:
|
394
|
+
"""Put a value onto a queue, using the synchronicity event loop."""
|
395
|
+
...
|
396
|
+
|
397
|
+
async def aio(self, /, queue: asyncio.queues.Queue, value: typing.Any) -> None:
|
398
|
+
"""Put a value onto a queue, using the synchronicity event loop."""
|
399
|
+
...
|
271
400
|
|
272
401
|
_queue_put: ___queue_put_spec[typing_extensions.Self]
|
273
402
|
|
@@ -326,16 +455,34 @@ class ContainerIOManager:
|
|
326
455
|
def serialize_traceback(self, exc: BaseException) -> tuple[typing.Optional[bytes], typing.Optional[bytes]]: ...
|
327
456
|
|
328
457
|
class __handle_user_exception_spec(typing_extensions.Protocol[SUPERSELF]):
|
329
|
-
def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
330
|
-
|
458
|
+
def __call__(self, /) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
459
|
+
"""Sets the task as failed in a way where it's not retried.
|
460
|
+
|
461
|
+
Used for handling exceptions from container lifecycle methods at the moment, which should
|
462
|
+
trigger a task failure state.
|
463
|
+
"""
|
464
|
+
...
|
465
|
+
|
466
|
+
def aio(self, /) -> typing.AsyncContextManager[None]:
|
467
|
+
"""Sets the task as failed in a way where it's not retried.
|
468
|
+
|
469
|
+
Used for handling exceptions from container lifecycle methods at the moment, which should
|
470
|
+
trigger a task failure state.
|
471
|
+
"""
|
472
|
+
...
|
331
473
|
|
332
474
|
handle_user_exception: __handle_user_exception_spec[typing_extensions.Self]
|
333
475
|
|
334
476
|
class __handle_input_exception_spec(typing_extensions.Protocol[SUPERSELF]):
|
335
477
|
def __call__(
|
336
478
|
self, /, io_context: IOContext, started_at: float
|
337
|
-
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
338
|
-
|
479
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
|
480
|
+
"""Handle an exception while processing a function input."""
|
481
|
+
...
|
482
|
+
|
483
|
+
def aio(self, /, io_context: IOContext, started_at: float) -> typing.AsyncContextManager[None]:
|
484
|
+
"""Handle an exception while processing a function input."""
|
485
|
+
...
|
339
486
|
|
340
487
|
handle_input_exception: __handle_input_exception_spec[typing_extensions.Self]
|
341
488
|
|
@@ -356,14 +503,28 @@ class ContainerIOManager:
|
|
356
503
|
memory_restore: __memory_restore_spec[typing_extensions.Self]
|
357
504
|
|
358
505
|
class __memory_snapshot_spec(typing_extensions.Protocol[SUPERSELF]):
|
359
|
-
def __call__(self, /) -> None:
|
360
|
-
|
506
|
+
def __call__(self, /) -> None:
|
507
|
+
"""Message server indicating that function is ready to be checkpointed."""
|
508
|
+
...
|
509
|
+
|
510
|
+
async def aio(self, /) -> None:
|
511
|
+
"""Message server indicating that function is ready to be checkpointed."""
|
512
|
+
...
|
361
513
|
|
362
514
|
memory_snapshot: __memory_snapshot_spec[typing_extensions.Self]
|
363
515
|
|
364
516
|
class __volume_commit_spec(typing_extensions.Protocol[SUPERSELF]):
|
365
|
-
def __call__(self, /, volume_ids: list[str]) -> None:
|
366
|
-
|
517
|
+
def __call__(self, /, volume_ids: list[str]) -> None:
|
518
|
+
"""Perform volume commit for given `volume_ids`.
|
519
|
+
Only used on container exit to persist uncommitted changes on behalf of user.
|
520
|
+
"""
|
521
|
+
...
|
522
|
+
|
523
|
+
async def aio(self, /, volume_ids: list[str]) -> None:
|
524
|
+
"""Perform volume commit for given `volume_ids`.
|
525
|
+
Only used on container exit to persist uncommitted changes on behalf of user.
|
526
|
+
"""
|
527
|
+
...
|
367
528
|
|
368
529
|
volume_commit: __volume_commit_spec[typing_extensions.Self]
|
369
530
|
|
@@ -380,13 +541,34 @@ class ContainerIOManager:
|
|
380
541
|
@property
|
381
542
|
def input_concurrency_enabled(self) -> int: ...
|
382
543
|
@classmethod
|
383
|
-
def get_input_concurrency(cls) -> int:
|
544
|
+
def get_input_concurrency(cls) -> int:
|
545
|
+
"""Returns the number of usable input slots.
|
546
|
+
|
547
|
+
If concurrency is reduced, active slots can exceed allotted slots. Returns the larger value
|
548
|
+
in this case.
|
549
|
+
"""
|
550
|
+
...
|
551
|
+
|
384
552
|
@classmethod
|
385
|
-
def set_input_concurrency(cls, concurrency: int):
|
553
|
+
def set_input_concurrency(cls, concurrency: int):
|
554
|
+
"""Edit the number of input slots.
|
555
|
+
|
556
|
+
This disables the background loop which automatically adjusts concurrency
|
557
|
+
within [target_concurrency, max_concurrency].
|
558
|
+
"""
|
559
|
+
...
|
560
|
+
|
386
561
|
@classmethod
|
387
562
|
def stop_fetching_inputs(cls): ...
|
388
563
|
|
389
|
-
def check_fastapi_pydantic_compatibility(exc: ImportError) -> None:
|
564
|
+
def check_fastapi_pydantic_compatibility(exc: ImportError) -> None:
|
565
|
+
"""Add a helpful note to an exception that is likely caused by a pydantic<>fastapi version incompatibility.
|
566
|
+
|
567
|
+
We need this becasue the legacy set of container requirements (image_builder_version=2023.12) contains a
|
568
|
+
version of fastapi that is not forwards-compatible with pydantic 2.0+, and users commonly run into issues
|
569
|
+
building an image that specifies a more recent version only for pydantic.
|
570
|
+
"""
|
571
|
+
...
|
390
572
|
|
391
573
|
MAX_OUTPUT_BATCH_SIZE: int
|
392
574
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import collections.abc
|
2
|
+
import contextvars
|
3
|
+
import typing
|
4
|
+
import typing_extensions
|
5
|
+
|
6
|
+
def is_local() -> bool:
|
7
|
+
"""Returns if we are currently on the machine launching/deploying a Modal app
|
8
|
+
|
9
|
+
Returns `True` when executed locally on the user's machine.
|
10
|
+
Returns `False` when executed from a Modal container in the cloud.
|
11
|
+
"""
|
12
|
+
...
|
13
|
+
|
14
|
+
async def _interact() -> None:
|
15
|
+
"""Enable interactivity with user input inside a Modal container.
|
16
|
+
|
17
|
+
See the [interactivity guide](https://modal.com/docs/guide/developing-debugging#interactivity)
|
18
|
+
for more information on how to use this function.
|
19
|
+
"""
|
20
|
+
...
|
21
|
+
|
22
|
+
class __interact_spec(typing_extensions.Protocol):
|
23
|
+
def __call__(self, /) -> None:
|
24
|
+
"""Enable interactivity with user input inside a Modal container.
|
25
|
+
|
26
|
+
See the [interactivity guide](https://modal.com/docs/guide/developing-debugging#interactivity)
|
27
|
+
for more information on how to use this function.
|
28
|
+
"""
|
29
|
+
...
|
30
|
+
|
31
|
+
async def aio(self, /) -> None:
|
32
|
+
"""Enable interactivity with user input inside a Modal container.
|
33
|
+
|
34
|
+
See the [interactivity guide](https://modal.com/docs/guide/developing-debugging#interactivity)
|
35
|
+
for more information on how to use this function.
|
36
|
+
"""
|
37
|
+
...
|
38
|
+
|
39
|
+
interact: __interact_spec
|
40
|
+
|
41
|
+
def current_input_id() -> typing.Optional[str]:
|
42
|
+
"""Returns the input ID for the current input.
|
43
|
+
|
44
|
+
Can only be called from Modal function (i.e. in a container context).
|
45
|
+
|
46
|
+
```python
|
47
|
+
from modal import current_input_id
|
48
|
+
|
49
|
+
@app.function()
|
50
|
+
def process_stuff():
|
51
|
+
print(f"Starting to process {current_input_id()}")
|
52
|
+
```
|
53
|
+
"""
|
54
|
+
...
|
55
|
+
|
56
|
+
def current_function_call_id() -> typing.Optional[str]:
|
57
|
+
"""Returns the function call ID for the current input.
|
58
|
+
|
59
|
+
Can only be called from Modal function (i.e. in a container context).
|
60
|
+
|
61
|
+
```python
|
62
|
+
from modal import current_function_call_id
|
63
|
+
|
64
|
+
@app.function()
|
65
|
+
def process_stuff():
|
66
|
+
print(f"Starting to process input from {current_function_call_id()}")
|
67
|
+
```
|
68
|
+
"""
|
69
|
+
...
|
70
|
+
|
71
|
+
def _set_current_context_ids(
|
72
|
+
input_ids: list[str], function_call_ids: list[str]
|
73
|
+
) -> collections.abc.Callable[[], None]: ...
|
74
|
+
def _import_context(): ...
|
75
|
+
|
76
|
+
_current_input_id: contextvars.ContextVar
|
77
|
+
|
78
|
+
_current_function_call_id: contextvars.ContextVar
|