modal 1.1.2.dev7__tar.gz → 1.1.2.dev8__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.1.2.dev7 → modal-1.1.2.dev8}/PKG-INFO +1 -1
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_functions.py +19 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/client.pyi +2 -2
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/functions.pyi +33 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/parallel_map.py +131 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/parallel_map.pyi +42 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_version/__init__.py +1 -1
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/LICENSE +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/README.md +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/__main__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_clustered_functions.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_clustered_functions.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_container_entrypoint.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_ipython.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_location.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_object.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_output.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_partial_function.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_pty.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_resolver.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_resources.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/asgi.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/execution_context.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/telemetry.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_serialization.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_traceback.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_tunnel.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_tunnel.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_type_manager.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/app_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/async_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/blob_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/deprecation.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/docker_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/function_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/git_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/hash_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/http_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/logger.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/mount_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/name_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/package_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/shell_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_utils/time_utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_vendor/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_vendor/tblib.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/_watcher.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/app.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/app.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/2023.12.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/2024.04.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/2024.10.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/2025.06.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/README.md +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/builder/base-images.json +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/call_graph.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/_download.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/_traceback.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/app.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/cluster.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/config.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/container.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/dict.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/entry_point.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/environment.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/import_refs.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/launch.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/network_file_system.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/profile.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/programs/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/programs/vscode.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/queues.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/run.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/secret.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/token.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/utils.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cli/volume.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/client.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cls.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/cls.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/config.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/container_process.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/container_process.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/dict.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/dict.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/environments.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/environments.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/exception.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/experimental/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/experimental/flash.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/experimental/flash.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/experimental/ipython.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/file_io.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/file_io.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/file_pattern_matcher.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/functions.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/gpu.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/image.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/image.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/io_streams.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/io_streams.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/mount.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/mount.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/network_file_system.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/network_file_system.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/object.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/object.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/output.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/partial_function.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/partial_function.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/proxy.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/proxy.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/py.typed +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/queue.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/queue.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/retries.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/runner.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/runner.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/running_app.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/sandbox.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/sandbox.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/schedule.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/scheduler_placement.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/secret.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/secret.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/serving.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/serving.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/snapshot.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/snapshot.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/stream_type.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/token_flow.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/token_flow.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/volume.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal/volume.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/requires.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal.egg-info/top_level.txt +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/__init__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api.proto +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api_pb2.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options.proto +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options_pb2.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_proto/py.typed +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/modal_version/__main__.py +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/pyproject.toml +0 -0
- {modal-1.1.2.dev7 → modal-1.1.2.dev8}/setup.cfg +0 -0
|
@@ -71,6 +71,8 @@ from .mount import _get_client_mount, _Mount
|
|
|
71
71
|
from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
|
|
72
72
|
from .output import _get_output_manager
|
|
73
73
|
from .parallel_map import (
|
|
74
|
+
_experimental_spawn_map_async,
|
|
75
|
+
_experimental_spawn_map_sync,
|
|
74
76
|
_for_each_async,
|
|
75
77
|
_for_each_sync,
|
|
76
78
|
_map_async,
|
|
@@ -78,6 +80,7 @@ from .parallel_map import (
|
|
|
78
80
|
_map_invocation_inputplane,
|
|
79
81
|
_map_sync,
|
|
80
82
|
_spawn_map_async,
|
|
83
|
+
_spawn_map_invocation,
|
|
81
84
|
_spawn_map_sync,
|
|
82
85
|
_starmap_async,
|
|
83
86
|
_starmap_sync,
|
|
@@ -1543,6 +1546,21 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1543
1546
|
async for item in stream:
|
|
1544
1547
|
yield item
|
|
1545
1548
|
|
|
1549
|
+
@live_method
|
|
1550
|
+
async def _spawn_map(self, input_queue: _SynchronizedQueue) -> "_FunctionCall[ReturnType]":
|
|
1551
|
+
self._check_no_web_url("spawn_map")
|
|
1552
|
+
if self._is_generator:
|
|
1553
|
+
raise InvalidError("A generator function cannot be called with `.spawn_map(...)`.")
|
|
1554
|
+
|
|
1555
|
+
assert self._function_name
|
|
1556
|
+
function_call_id = await _spawn_map_invocation(
|
|
1557
|
+
self,
|
|
1558
|
+
input_queue,
|
|
1559
|
+
self.client,
|
|
1560
|
+
)
|
|
1561
|
+
fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, None)
|
|
1562
|
+
return fc
|
|
1563
|
+
|
|
1546
1564
|
async def _call_function(self, args, kwargs) -> ReturnType:
|
|
1547
1565
|
invocation: Union[_Invocation, _InputPlaneInvocation]
|
|
1548
1566
|
if self._input_plane_url:
|
|
@@ -1789,6 +1807,7 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1789
1807
|
starmap = MethodWithAio(_starmap_sync, _starmap_async, synchronizer)
|
|
1790
1808
|
for_each = MethodWithAio(_for_each_sync, _for_each_async, synchronizer)
|
|
1791
1809
|
spawn_map = MethodWithAio(_spawn_map_sync, _spawn_map_async, synchronizer)
|
|
1810
|
+
experimental_spawn_map = MethodWithAio(_experimental_spawn_map_sync, _experimental_spawn_map_async, synchronizer)
|
|
1792
1811
|
|
|
1793
1812
|
|
|
1794
1813
|
class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.1.2.
|
|
36
|
+
version: str = "1.1.2.dev8",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.1.2.
|
|
167
|
+
version: str = "1.1.2.dev8",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -405,6 +405,12 @@ class Function(
|
|
|
405
405
|
|
|
406
406
|
_map: ___map_spec[typing_extensions.Self]
|
|
407
407
|
|
|
408
|
+
class ___spawn_map_spec(typing_extensions.Protocol[ReturnType_INNER, SUPERSELF]):
|
|
409
|
+
def __call__(self, /, input_queue: modal.parallel_map.SynchronizedQueue) -> FunctionCall[ReturnType_INNER]: ...
|
|
410
|
+
async def aio(self, /, input_queue: modal.parallel_map.SynchronizedQueue) -> FunctionCall[ReturnType_INNER]: ...
|
|
411
|
+
|
|
412
|
+
_spawn_map: ___spawn_map_spec[modal._functions.ReturnType, typing_extensions.Self]
|
|
413
|
+
|
|
408
414
|
class ___call_function_spec(typing_extensions.Protocol[ReturnType_INNER, SUPERSELF]):
|
|
409
415
|
def __call__(self, /, args, kwargs) -> ReturnType_INNER: ...
|
|
410
416
|
async def aio(self, /, args, kwargs) -> ReturnType_INNER: ...
|
|
@@ -693,6 +699,33 @@ class Function(
|
|
|
693
699
|
|
|
694
700
|
spawn_map: __spawn_map_spec[typing_extensions.Self]
|
|
695
701
|
|
|
702
|
+
class __experimental_spawn_map_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
703
|
+
def __call__(self, /, *input_iterators, kwargs={}) -> modal._functions._FunctionCall:
|
|
704
|
+
"""Spawn parallel execution over a set of inputs, exiting as soon as the inputs are created (without waiting
|
|
705
|
+
for the map to complete).
|
|
706
|
+
|
|
707
|
+
Takes one iterator argument per argument in the function being mapped over.
|
|
708
|
+
|
|
709
|
+
Example:
|
|
710
|
+
```python
|
|
711
|
+
@app.function()
|
|
712
|
+
def my_func(a):
|
|
713
|
+
return a ** 2
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@app.local_entrypoint()
|
|
717
|
+
def main():
|
|
718
|
+
fc = my_func.spawn_map([1, 2, 3, 4])
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
Returns a FunctionCall object that can be used to retrieve results
|
|
722
|
+
"""
|
|
723
|
+
...
|
|
724
|
+
|
|
725
|
+
async def aio(self, /, *input_iterators, kwargs={}) -> modal._functions._FunctionCall: ...
|
|
726
|
+
|
|
727
|
+
experimental_spawn_map: __experimental_spawn_map_spec[typing_extensions.Self]
|
|
728
|
+
|
|
696
729
|
class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Object):
|
|
697
730
|
"""A reference to an executed function call.
|
|
698
731
|
|
|
@@ -260,6 +260,89 @@ class SyncInputPumper(InputPumper):
|
|
|
260
260
|
yield
|
|
261
261
|
|
|
262
262
|
|
|
263
|
+
class AsyncInputPumper(InputPumper):
|
|
264
|
+
def __init__(
|
|
265
|
+
self,
|
|
266
|
+
client: "modal.client._Client",
|
|
267
|
+
*,
|
|
268
|
+
input_queue: asyncio.Queue,
|
|
269
|
+
function: "modal.functions._Function",
|
|
270
|
+
function_call_id: str,
|
|
271
|
+
):
|
|
272
|
+
super().__init__(client, input_queue=input_queue, function=function, function_call_id=function_call_id)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
async def _spawn_map_invocation(
|
|
276
|
+
function: "modal.functions._Function", raw_input_queue: _SynchronizedQueue, client: "modal.client._Client"
|
|
277
|
+
) -> str:
|
|
278
|
+
assert client.stub
|
|
279
|
+
request = api_pb2.FunctionMapRequest(
|
|
280
|
+
function_id=function.object_id,
|
|
281
|
+
parent_input_id=current_input_id() or "",
|
|
282
|
+
function_call_type=api_pb2.FUNCTION_CALL_TYPE_MAP,
|
|
283
|
+
function_call_invocation_type=api_pb2.FUNCTION_CALL_INVOCATION_TYPE_ASYNC,
|
|
284
|
+
)
|
|
285
|
+
response: api_pb2.FunctionMapResponse = await retry_transient_errors(client.stub.FunctionMap, request)
|
|
286
|
+
function_call_id = response.function_call_id
|
|
287
|
+
|
|
288
|
+
have_all_inputs = False
|
|
289
|
+
inputs_created = 0
|
|
290
|
+
|
|
291
|
+
def set_inputs_created(set_inputs_created):
|
|
292
|
+
nonlocal inputs_created
|
|
293
|
+
assert set_inputs_created is None or set_inputs_created > inputs_created
|
|
294
|
+
inputs_created = set_inputs_created
|
|
295
|
+
|
|
296
|
+
def set_have_all_inputs():
|
|
297
|
+
nonlocal have_all_inputs
|
|
298
|
+
have_all_inputs = True
|
|
299
|
+
|
|
300
|
+
input_queue: asyncio.Queue[api_pb2.FunctionPutInputsItem | None] = asyncio.Queue()
|
|
301
|
+
input_preprocessor = InputPreprocessor(
|
|
302
|
+
client=client,
|
|
303
|
+
raw_input_queue=raw_input_queue,
|
|
304
|
+
processed_input_queue=input_queue,
|
|
305
|
+
function=function,
|
|
306
|
+
created_callback=set_inputs_created,
|
|
307
|
+
done_callback=set_have_all_inputs,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
input_pumper = AsyncInputPumper(
|
|
311
|
+
client=client,
|
|
312
|
+
input_queue=input_queue,
|
|
313
|
+
function=function,
|
|
314
|
+
function_call_id=function_call_id,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
def log_stats():
|
|
318
|
+
logger.debug(
|
|
319
|
+
f"have_all_inputs={have_all_inputs} inputs_created={inputs_created} inputs_sent={input_pumper.inputs_sent} "
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
async def log_task():
|
|
323
|
+
while True:
|
|
324
|
+
log_stats()
|
|
325
|
+
try:
|
|
326
|
+
await asyncio.sleep(10)
|
|
327
|
+
except asyncio.CancelledError:
|
|
328
|
+
# Log final stats before exiting
|
|
329
|
+
log_stats()
|
|
330
|
+
break
|
|
331
|
+
|
|
332
|
+
async def consume_generator(gen):
|
|
333
|
+
async for _ in gen:
|
|
334
|
+
pass
|
|
335
|
+
|
|
336
|
+
log_debug_stats_task = asyncio.create_task(log_task())
|
|
337
|
+
await asyncio.gather(
|
|
338
|
+
consume_generator(input_preprocessor.drain_input_generator()),
|
|
339
|
+
consume_generator(input_pumper.pump_inputs()),
|
|
340
|
+
)
|
|
341
|
+
log_debug_stats_task.cancel()
|
|
342
|
+
await log_debug_stats_task
|
|
343
|
+
return function_call_id
|
|
344
|
+
|
|
345
|
+
|
|
263
346
|
async def _map_invocation(
|
|
264
347
|
function: "modal.functions._Function",
|
|
265
348
|
raw_input_queue: _SynchronizedQueue,
|
|
@@ -1063,6 +1146,54 @@ def _map_sync(
|
|
|
1063
1146
|
)
|
|
1064
1147
|
|
|
1065
1148
|
|
|
1149
|
+
async def _experimental_spawn_map_async(self, *input_iterators, kwargs={}) -> "modal.functions._FunctionCall":
|
|
1150
|
+
async_input_gen = async_zip(*[sync_or_async_iter(it) for it in input_iterators])
|
|
1151
|
+
return await _spawn_map_helper(self, async_input_gen, kwargs)
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
async def _spawn_map_helper(
|
|
1155
|
+
self: "modal.functions.Function", async_input_gen, kwargs={}
|
|
1156
|
+
) -> "modal.functions._FunctionCall":
|
|
1157
|
+
raw_input_queue: Any = SynchronizedQueue() # type: ignore
|
|
1158
|
+
await raw_input_queue.init.aio()
|
|
1159
|
+
|
|
1160
|
+
async def feed_queue():
|
|
1161
|
+
async with aclosing(async_input_gen) as streamer:
|
|
1162
|
+
async for args in streamer:
|
|
1163
|
+
await raw_input_queue.put.aio((args, kwargs))
|
|
1164
|
+
await raw_input_queue.put.aio(None) # end-of-input sentinel
|
|
1165
|
+
|
|
1166
|
+
fc, _ = await asyncio.gather(self._spawn_map.aio(raw_input_queue), feed_queue())
|
|
1167
|
+
return fc
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
def _experimental_spawn_map_sync(self, *input_iterators, kwargs={}) -> "modal.functions._FunctionCall":
|
|
1171
|
+
"""Spawn parallel execution over a set of inputs, exiting as soon as the inputs are created (without waiting
|
|
1172
|
+
for the map to complete).
|
|
1173
|
+
|
|
1174
|
+
Takes one iterator argument per argument in the function being mapped over.
|
|
1175
|
+
|
|
1176
|
+
Example:
|
|
1177
|
+
```python
|
|
1178
|
+
@app.function()
|
|
1179
|
+
def my_func(a):
|
|
1180
|
+
return a ** 2
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
@app.local_entrypoint()
|
|
1184
|
+
def main():
|
|
1185
|
+
fc = my_func.spawn_map([1, 2, 3, 4])
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
Returns a FunctionCall object that can be used to retrieve results
|
|
1189
|
+
"""
|
|
1190
|
+
|
|
1191
|
+
return run_coroutine_in_temporary_event_loop(
|
|
1192
|
+
_experimental_spawn_map_async(self, *input_iterators, kwargs=kwargs),
|
|
1193
|
+
"You can't run Function.spawn_map() from an async function. Use Function.spawn_map.aio() instead.",
|
|
1194
|
+
)
|
|
1195
|
+
|
|
1196
|
+
|
|
1066
1197
|
async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None:
|
|
1067
1198
|
"""This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
|
|
1068
1199
|
function calls for each.
|
|
@@ -123,6 +123,22 @@ class SyncInputPumper(InputPumper):
|
|
|
123
123
|
|
|
124
124
|
def retry_inputs(self): ...
|
|
125
125
|
|
|
126
|
+
class AsyncInputPumper(InputPumper):
|
|
127
|
+
"""Reads inputs from a queue of FunctionPutInputsItems, and sends them to the server."""
|
|
128
|
+
def __init__(
|
|
129
|
+
self,
|
|
130
|
+
client: modal.client._Client,
|
|
131
|
+
*,
|
|
132
|
+
input_queue: asyncio.queues.Queue,
|
|
133
|
+
function: modal._functions._Function,
|
|
134
|
+
function_call_id: str,
|
|
135
|
+
):
|
|
136
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
137
|
+
...
|
|
138
|
+
|
|
139
|
+
async def _spawn_map_invocation(
|
|
140
|
+
function: modal._functions._Function, raw_input_queue: _SynchronizedQueue, client: modal.client._Client
|
|
141
|
+
) -> str: ...
|
|
126
142
|
def _map_invocation(
|
|
127
143
|
function: modal._functions._Function,
|
|
128
144
|
raw_input_queue: _SynchronizedQueue,
|
|
@@ -242,6 +258,32 @@ def _map_sync(
|
|
|
242
258
|
"""
|
|
243
259
|
...
|
|
244
260
|
|
|
261
|
+
async def _experimental_spawn_map_async(self, *input_iterators, kwargs={}) -> modal._functions._FunctionCall: ...
|
|
262
|
+
async def _spawn_map_helper(
|
|
263
|
+
self: modal.functions.Function, async_input_gen, kwargs={}
|
|
264
|
+
) -> modal._functions._FunctionCall: ...
|
|
265
|
+
def _experimental_spawn_map_sync(self, *input_iterators, kwargs={}) -> modal._functions._FunctionCall:
|
|
266
|
+
"""Spawn parallel execution over a set of inputs, exiting as soon as the inputs are created (without waiting
|
|
267
|
+
for the map to complete).
|
|
268
|
+
|
|
269
|
+
Takes one iterator argument per argument in the function being mapped over.
|
|
270
|
+
|
|
271
|
+
Example:
|
|
272
|
+
```python
|
|
273
|
+
@app.function()
|
|
274
|
+
def my_func(a):
|
|
275
|
+
return a ** 2
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@app.local_entrypoint()
|
|
279
|
+
def main():
|
|
280
|
+
fc = my_func.spawn_map([1, 2, 3, 4])
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Returns a FunctionCall object that can be used to retrieve results
|
|
284
|
+
"""
|
|
285
|
+
...
|
|
286
|
+
|
|
245
287
|
async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None:
|
|
246
288
|
"""This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
|
|
247
289
|
function calls for each.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|