modal 0.62.115__py3-none-any.whl → 0.72.13__py3-none-any.whl
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/__init__.py +13 -9
- modal/__main__.py +41 -3
- modal/_clustered_functions.py +80 -0
- modal/_clustered_functions.pyi +22 -0
- modal/_container_entrypoint.py +402 -398
- modal/_ipython.py +3 -13
- modal/_location.py +17 -10
- modal/_output.py +243 -99
- modal/_pty.py +2 -2
- modal/_resolver.py +55 -60
- modal/_resources.py +26 -7
- modal/_runtime/__init__.py +1 -0
- modal/_runtime/asgi.py +519 -0
- modal/_runtime/container_io_manager.py +1025 -0
- modal/{execution_context.py → _runtime/execution_context.py} +11 -2
- modal/_runtime/telemetry.py +169 -0
- modal/_runtime/user_code_imports.py +356 -0
- modal/_serialization.py +123 -6
- modal/_traceback.py +47 -187
- modal/_tunnel.py +50 -14
- modal/_tunnel.pyi +19 -36
- modal/_utils/app_utils.py +3 -17
- modal/_utils/async_utils.py +386 -104
- modal/_utils/blob_utils.py +157 -186
- modal/_utils/bytes_io_segment_payload.py +97 -0
- modal/_utils/deprecation.py +89 -0
- modal/_utils/docker_utils.py +98 -0
- modal/_utils/function_utils.py +299 -98
- modal/_utils/grpc_testing.py +47 -34
- modal/_utils/grpc_utils.py +54 -21
- modal/_utils/hash_utils.py +51 -10
- modal/_utils/http_utils.py +39 -9
- modal/_utils/logger.py +2 -1
- modal/_utils/mount_utils.py +34 -16
- modal/_utils/name_utils.py +58 -0
- modal/_utils/package_utils.py +14 -1
- modal/_utils/pattern_utils.py +205 -0
- modal/_utils/rand_pb_testing.py +3 -3
- modal/_utils/shell_utils.py +15 -49
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +12 -10
- modal/app.py +561 -323
- modal/app.pyi +474 -262
- modal/call_graph.py +7 -6
- modal/cli/_download.py +22 -6
- modal/cli/_traceback.py +200 -0
- modal/cli/app.py +203 -42
- modal/cli/config.py +12 -5
- modal/cli/container.py +61 -13
- modal/cli/dict.py +128 -0
- modal/cli/entry_point.py +26 -13
- modal/cli/environment.py +40 -9
- modal/cli/import_refs.py +21 -48
- modal/cli/launch.py +28 -14
- modal/cli/network_file_system.py +57 -21
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +34 -9
- modal/cli/programs/vscode.py +58 -8
- modal/cli/queues.py +131 -0
- modal/cli/run.py +199 -96
- modal/cli/secret.py +5 -4
- modal/cli/token.py +7 -2
- modal/cli/utils.py +74 -8
- modal/cli/volume.py +97 -56
- modal/client.py +248 -144
- modal/client.pyi +156 -124
- modal/cloud_bucket_mount.py +43 -30
- modal/cloud_bucket_mount.pyi +32 -25
- modal/cls.py +528 -141
- modal/cls.pyi +189 -145
- modal/config.py +32 -15
- modal/container_process.py +177 -0
- modal/container_process.pyi +82 -0
- modal/dict.py +50 -54
- modal/dict.pyi +120 -164
- modal/environments.py +106 -5
- modal/environments.pyi +77 -25
- modal/exception.py +30 -43
- modal/experimental.py +62 -2
- modal/file_io.py +537 -0
- modal/file_io.pyi +235 -0
- modal/file_pattern_matcher.py +196 -0
- modal/functions.py +846 -428
- modal/functions.pyi +446 -387
- modal/gpu.py +57 -44
- modal/image.py +943 -417
- modal/image.pyi +584 -245
- modal/io_streams.py +434 -0
- modal/io_streams.pyi +122 -0
- modal/mount.py +223 -90
- modal/mount.pyi +241 -243
- modal/network_file_system.py +85 -86
- modal/network_file_system.pyi +151 -110
- modal/object.py +66 -36
- modal/object.pyi +166 -143
- modal/output.py +63 -0
- modal/parallel_map.py +73 -47
- modal/parallel_map.pyi +51 -63
- modal/partial_function.py +272 -107
- modal/partial_function.pyi +219 -120
- modal/proxy.py +15 -12
- modal/proxy.pyi +3 -8
- modal/queue.py +96 -72
- modal/queue.pyi +210 -135
- modal/requirements/2024.04.txt +2 -1
- modal/requirements/2024.10.txt +16 -0
- modal/requirements/README.md +21 -0
- modal/requirements/base-images.json +22 -0
- modal/retries.py +45 -4
- modal/runner.py +325 -203
- modal/runner.pyi +124 -110
- modal/running_app.py +27 -4
- modal/sandbox.py +509 -231
- modal/sandbox.pyi +396 -169
- modal/schedule.py +2 -2
- modal/scheduler_placement.py +20 -3
- modal/secret.py +41 -25
- modal/secret.pyi +62 -42
- modal/serving.py +39 -49
- modal/serving.pyi +37 -43
- modal/stream_type.py +15 -0
- modal/token_flow.py +5 -3
- modal/token_flow.pyi +37 -32
- modal/volume.py +123 -137
- modal/volume.pyi +228 -221
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
- modal-0.72.13.dist-info/RECORD +174 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/top_level.txt +0 -1
- modal_docs/gen_reference_docs.py +3 -1
- modal_docs/mdmd/mdmd.py +0 -1
- modal_docs/mdmd/signatures.py +1 -2
- modal_global_objects/images/base_images.py +28 -0
- modal_global_objects/mounts/python_standalone.py +2 -2
- modal_proto/__init__.py +1 -1
- modal_proto/api.proto +1231 -531
- modal_proto/api_grpc.py +750 -430
- modal_proto/api_pb2.py +2102 -1176
- modal_proto/api_pb2.pyi +8859 -0
- modal_proto/api_pb2_grpc.py +1329 -675
- modal_proto/api_pb2_grpc.pyi +1416 -0
- modal_proto/modal_api_grpc.py +149 -0
- modal_proto/modal_options_grpc.py +3 -0
- modal_proto/options_pb2.pyi +20 -0
- modal_proto/options_pb2_grpc.pyi +7 -0
- modal_proto/py.typed +0 -0
- modal_version/__init__.py +1 -1
- modal_version/_version_generated.py +2 -2
- modal/_asgi.py +0 -370
- modal/_container_exec.py +0 -128
- modal/_container_io_manager.py +0 -646
- modal/_container_io_manager.pyi +0 -412
- modal/_sandbox_shell.py +0 -49
- modal/app_utils.py +0 -20
- modal/app_utils.pyi +0 -17
- modal/execution_context.pyi +0 -37
- modal/shared_volume.py +0 -23
- modal/shared_volume.pyi +0 -24
- modal-0.62.115.dist-info/RECORD +0 -207
- modal_global_objects/images/conda.py +0 -15
- modal_global_objects/images/debian_slim.py +0 -15
- modal_global_objects/images/micromamba.py +0 -15
- test/__init__.py +0 -1
- test/aio_test.py +0 -12
- test/async_utils_test.py +0 -279
- test/blob_test.py +0 -67
- test/cli_imports_test.py +0 -149
- test/cli_test.py +0 -674
- test/client_test.py +0 -203
- test/cloud_bucket_mount_test.py +0 -22
- test/cls_test.py +0 -636
- test/config_test.py +0 -149
- test/conftest.py +0 -1485
- test/container_app_test.py +0 -50
- test/container_test.py +0 -1405
- test/cpu_test.py +0 -23
- test/decorator_test.py +0 -85
- test/deprecation_test.py +0 -34
- test/dict_test.py +0 -51
- test/e2e_test.py +0 -68
- test/error_test.py +0 -7
- test/function_serialization_test.py +0 -32
- test/function_test.py +0 -791
- test/function_utils_test.py +0 -101
- test/gpu_test.py +0 -159
- test/grpc_utils_test.py +0 -82
- test/helpers.py +0 -47
- test/image_test.py +0 -814
- test/live_reload_test.py +0 -80
- test/lookup_test.py +0 -70
- test/mdmd_test.py +0 -329
- test/mount_test.py +0 -162
- test/mounted_files_test.py +0 -327
- test/network_file_system_test.py +0 -188
- test/notebook_test.py +0 -66
- test/object_test.py +0 -41
- test/package_utils_test.py +0 -25
- test/queue_test.py +0 -115
- test/resolver_test.py +0 -59
- test/retries_test.py +0 -67
- test/runner_test.py +0 -85
- test/sandbox_test.py +0 -191
- test/schedule_test.py +0 -15
- test/scheduler_placement_test.py +0 -57
- test/secret_test.py +0 -89
- test/serialization_test.py +0 -50
- test/stub_composition_test.py +0 -10
- test/stub_test.py +0 -361
- test/test_asgi_wrapper.py +0 -234
- test/token_flow_test.py +0 -18
- test/traceback_test.py +0 -135
- test/tunnel_test.py +0 -29
- test/utils_test.py +0 -88
- test/version_test.py +0 -14
- test/volume_test.py +0 -397
- test/watcher_test.py +0 -58
- test/webhook_test.py +0 -145
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
modal/parallel_map.py
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
# Copyright Modal Labs 2024
|
2
2
|
import asyncio
|
3
|
+
import time
|
3
4
|
import typing
|
4
5
|
from dataclasses import dataclass
|
5
|
-
from typing import Any, Callable,
|
6
|
+
from typing import Any, Callable, Optional
|
6
7
|
|
7
|
-
from
|
8
|
-
from grpclib import Status
|
8
|
+
from grpclib import GRPCError, Status
|
9
9
|
|
10
|
+
from modal._runtime.execution_context import current_input_id
|
10
11
|
from modal._utils.async_utils import (
|
11
|
-
|
12
|
+
AsyncOrSyncIterable,
|
13
|
+
aclosing,
|
14
|
+
async_map_ordered,
|
15
|
+
async_merge,
|
16
|
+
async_zip,
|
12
17
|
queue_batch_iterator,
|
18
|
+
sync_or_async_iter,
|
13
19
|
synchronize_api,
|
14
20
|
synchronizer,
|
15
21
|
warn_if_generator_is_not_consumed,
|
@@ -23,7 +29,6 @@ from modal._utils.function_utils import (
|
|
23
29
|
)
|
24
30
|
from modal._utils.grpc_utils import retry_transient_errors
|
25
31
|
from modal.config import logger
|
26
|
-
from modal.execution_context import current_input_id
|
27
32
|
from modal_proto import api_pb2
|
28
33
|
|
29
34
|
if typing.TYPE_CHECKING:
|
@@ -59,9 +64,12 @@ class _OutputValue:
|
|
59
64
|
|
60
65
|
MAP_INVOCATION_CHUNK_SIZE = 49
|
61
66
|
|
67
|
+
if typing.TYPE_CHECKING:
|
68
|
+
import modal.functions
|
69
|
+
|
62
70
|
|
63
71
|
async def _map_invocation(
|
64
|
-
|
72
|
+
function: "modal.functions._Function",
|
65
73
|
raw_input_queue: _SynchronizedQueue,
|
66
74
|
client: "modal.client._Client",
|
67
75
|
order_outputs: bool,
|
@@ -70,7 +78,7 @@ async def _map_invocation(
|
|
70
78
|
):
|
71
79
|
assert client.stub
|
72
80
|
request = api_pb2.FunctionMapRequest(
|
73
|
-
function_id=
|
81
|
+
function_id=function.object_id,
|
74
82
|
parent_input_id=current_input_id() or "",
|
75
83
|
function_call_type=api_pb2.FUNCTION_CALL_TYPE_MAP,
|
76
84
|
return_exceptions=return_exceptions,
|
@@ -87,8 +95,8 @@ async def _map_invocation(
|
|
87
95
|
if count_update_callback is not None:
|
88
96
|
count_update_callback(num_outputs, num_inputs)
|
89
97
|
|
90
|
-
pending_outputs:
|
91
|
-
completed_outputs:
|
98
|
+
pending_outputs: dict[str, int] = {} # Map input_id -> next expected gen_index value
|
99
|
+
completed_outputs: set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
|
92
100
|
|
93
101
|
input_queue: asyncio.Queue = asyncio.Queue()
|
94
102
|
|
@@ -97,23 +105,20 @@ async def _map_invocation(
|
|
97
105
|
idx = num_inputs
|
98
106
|
num_inputs += 1
|
99
107
|
(args, kwargs) = argskwargs
|
100
|
-
return await _create_input(args, kwargs, client, idx)
|
108
|
+
return await _create_input(args, kwargs, client, idx=idx, method_name=function._use_method_name)
|
101
109
|
|
102
110
|
async def input_iter():
|
103
111
|
while 1:
|
104
112
|
raw_input = await raw_input_queue.get()
|
105
113
|
if raw_input is None: # end of input sentinel
|
106
|
-
|
114
|
+
break
|
107
115
|
yield raw_input # args, kwargs
|
108
116
|
|
109
117
|
async def drain_input_generator():
|
110
118
|
# Parallelize uploading blobs
|
111
|
-
|
112
|
-
create_input,
|
113
|
-
|
114
|
-
task_limit=BLOB_MAX_PARALLELISM,
|
115
|
-
)
|
116
|
-
async with proto_input_stream.stream() as streamer:
|
119
|
+
async with aclosing(
|
120
|
+
async_map_ordered(input_iter(), create_input, concurrency=BLOB_MAX_PARALLELISM)
|
121
|
+
) as streamer:
|
117
122
|
async for item in streamer:
|
118
123
|
await input_queue.put(item)
|
119
124
|
|
@@ -126,23 +131,36 @@ async def _map_invocation(
|
|
126
131
|
nonlocal have_all_inputs, num_inputs
|
127
132
|
async for items in queue_batch_iterator(input_queue, MAP_INVOCATION_CHUNK_SIZE):
|
128
133
|
request = api_pb2.FunctionPutInputsRequest(
|
129
|
-
function_id=
|
134
|
+
function_id=function.object_id, inputs=items, function_call_id=function_call_id
|
130
135
|
)
|
131
136
|
logger.debug(
|
132
137
|
f"Pushing {len(items)} inputs to server. Num queued inputs awaiting push is {input_queue.qsize()}."
|
133
138
|
)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
while True:
|
140
|
+
try:
|
141
|
+
resp = await retry_transient_errors(
|
142
|
+
client.stub.FunctionPutInputs,
|
143
|
+
request,
|
144
|
+
# with 8 retries we log the warning below about every 30 secondswhich isn't too spammy.
|
145
|
+
max_retries=8,
|
146
|
+
max_delay=15,
|
147
|
+
additional_status_codes=[Status.RESOURCE_EXHAUSTED],
|
148
|
+
)
|
149
|
+
break
|
150
|
+
except GRPCError as err:
|
151
|
+
if err.status != Status.RESOURCE_EXHAUSTED:
|
152
|
+
raise err
|
153
|
+
logger.warning(
|
154
|
+
"Warning: map progress is limited. Common bottlenecks "
|
155
|
+
"include slow iteration over results, or function backlogs."
|
156
|
+
)
|
157
|
+
|
141
158
|
count_update()
|
142
159
|
for item in resp.inputs:
|
143
160
|
pending_outputs.setdefault(item.input_id, 0)
|
144
161
|
logger.debug(
|
145
|
-
f"Successfully pushed {len(items)} inputs to server.
|
162
|
+
f"Successfully pushed {len(items)} inputs to server. "
|
163
|
+
f"Num queued inputs awaiting push is {input_queue.qsize()}."
|
146
164
|
)
|
147
165
|
|
148
166
|
have_all_inputs = True
|
@@ -158,6 +176,7 @@ async def _map_invocation(
|
|
158
176
|
timeout=OUTPUTS_TIMEOUT,
|
159
177
|
last_entry_id=last_entry_id,
|
160
178
|
clear_on_success=False,
|
179
|
+
requested_at=time.time(),
|
161
180
|
)
|
162
181
|
response = await retry_transient_errors(
|
163
182
|
client.stub.FunctionGetOutputs,
|
@@ -183,8 +202,9 @@ async def _map_invocation(
|
|
183
202
|
async def get_all_outputs_and_clean_up():
|
184
203
|
assert client.stub
|
185
204
|
try:
|
186
|
-
async
|
187
|
-
|
205
|
+
async with aclosing(get_all_outputs()) as output_items:
|
206
|
+
async for item in output_items:
|
207
|
+
yield item
|
188
208
|
finally:
|
189
209
|
# "ack" that we have all outputs we are interested in and let backend clear results
|
190
210
|
request = api_pb2.FunctionGetOutputsRequest(
|
@@ -192,10 +212,11 @@ async def _map_invocation(
|
|
192
212
|
timeout=0,
|
193
213
|
last_entry_id="0-0",
|
194
214
|
clear_on_success=True,
|
215
|
+
requested_at=time.time(),
|
195
216
|
)
|
196
217
|
await retry_transient_errors(client.stub.FunctionGetOutputs, request)
|
197
218
|
|
198
|
-
async def fetch_output(item: api_pb2.FunctionGetOutputsItem) ->
|
219
|
+
async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> tuple[int, Any]:
|
199
220
|
try:
|
200
221
|
output = await _process_result(item.result, item.data_format, client.stub, client)
|
201
222
|
except Exception as e:
|
@@ -206,14 +227,13 @@ async def _map_invocation(
|
|
206
227
|
return (item.idx, output)
|
207
228
|
|
208
229
|
async def poll_outputs():
|
209
|
-
outputs = stream.iterate(get_all_outputs_and_clean_up())
|
210
|
-
outputs_fetched = outputs | pipe.map(fetch_output, ordered=True, task_limit=BLOB_MAX_PARALLELISM) # type: ignore
|
211
|
-
|
212
230
|
# map to store out-of-order outputs received
|
213
231
|
received_outputs = {}
|
214
232
|
output_idx = 0
|
215
233
|
|
216
|
-
async with
|
234
|
+
async with aclosing(
|
235
|
+
async_map_ordered(get_all_outputs_and_clean_up(), fetch_output, concurrency=BLOB_MAX_PARALLELISM)
|
236
|
+
) as streamer:
|
217
237
|
async for idx, output in streamer:
|
218
238
|
count_update()
|
219
239
|
if not order_outputs:
|
@@ -228,9 +248,7 @@ async def _map_invocation(
|
|
228
248
|
|
229
249
|
assert len(received_outputs) == 0
|
230
250
|
|
231
|
-
|
232
|
-
|
233
|
-
async with response_gen.stream() as streamer:
|
251
|
+
async with aclosing(async_merge(drain_input_generator(), pump_inputs(), poll_outputs())) as streamer:
|
234
252
|
async for response in streamer:
|
235
253
|
if response is not None:
|
236
254
|
yield response.value
|
@@ -243,7 +261,7 @@ def _map_sync(
|
|
243
261
|
kwargs={}, # any extra keyword arguments for the function
|
244
262
|
order_outputs: bool = True, # return outputs in order
|
245
263
|
return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
|
246
|
-
) ->
|
264
|
+
) -> AsyncOrSyncIterable:
|
247
265
|
"""Parallel map over a set of inputs.
|
248
266
|
|
249
267
|
Takes one iterator argument per argument in the function being mapped over.
|
@@ -281,11 +299,14 @@ def _map_sync(
|
|
281
299
|
```
|
282
300
|
"""
|
283
301
|
|
284
|
-
return
|
302
|
+
return AsyncOrSyncIterable(
|
285
303
|
_map_async(
|
286
304
|
self, *input_iterators, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
|
287
305
|
),
|
288
|
-
nested_async_message=
|
306
|
+
nested_async_message=(
|
307
|
+
"You can't iter(Function.map()) or Function.for_each() from an async function. "
|
308
|
+
"Use async for ... Function.map.aio() or Function.for_each.aio() instead."
|
309
|
+
),
|
289
310
|
)
|
290
311
|
|
291
312
|
|
@@ -314,7 +335,7 @@ async def _map_async(
|
|
314
335
|
|
315
336
|
async def feed_queue():
|
316
337
|
# This runs in a main thread event loop, so it doesn't block the synchronizer loop
|
317
|
-
async with
|
338
|
+
async with aclosing(async_zip(*[sync_or_async_iter(it) for it in input_iterators])) as streamer:
|
318
339
|
async for args in streamer:
|
319
340
|
await raw_input_queue.put.aio((args, kwargs))
|
320
341
|
await raw_input_queue.put.aio(None) # end-of-input sentinel
|
@@ -322,11 +343,13 @@ async def _map_async(
|
|
322
343
|
feed_input_task = asyncio.create_task(feed_queue())
|
323
344
|
|
324
345
|
try:
|
325
|
-
# note that `map()` and `map.aio()` are not synchronicity-wrapped, since
|
346
|
+
# note that `map()` and `map.aio()` are not synchronicity-wrapped, since
|
347
|
+
# they accept executable code in the form of
|
326
348
|
# iterators that we don't want to run inside the synchronicity thread.
|
327
349
|
# Instead, we delegate to `._map()` with a safer Queue as input
|
328
|
-
async
|
329
|
-
|
350
|
+
async with aclosing(self._map.aio(raw_input_queue, order_outputs, return_exceptions)) as map_output_stream:
|
351
|
+
async for output in map_output_stream:
|
352
|
+
yield output
|
330
353
|
finally:
|
331
354
|
feed_input_task.cancel() # should only be needed in case of exceptions
|
332
355
|
|
@@ -363,7 +386,7 @@ async def _starmap_async(
|
|
363
386
|
|
364
387
|
async def feed_queue():
|
365
388
|
# This runs in a main thread event loop, so it doesn't block the synchronizer loop
|
366
|
-
async with
|
389
|
+
async with aclosing(sync_or_async_iter(input_iterator)) as streamer:
|
367
390
|
async for args in streamer:
|
368
391
|
await raw_input_queue.put.aio((args, kwargs))
|
369
392
|
await raw_input_queue.put.aio(None) # end-of-input sentinel
|
@@ -383,7 +406,7 @@ def _starmap_sync(
|
|
383
406
|
kwargs={},
|
384
407
|
order_outputs: bool = True,
|
385
408
|
return_exceptions: bool = False,
|
386
|
-
) ->
|
409
|
+
) -> AsyncOrSyncIterable:
|
387
410
|
"""Like `map`, but spreads arguments over multiple function arguments.
|
388
411
|
|
389
412
|
Assumes every input is a sequence (e.g. a tuple).
|
@@ -400,9 +423,12 @@ def _starmap_sync(
|
|
400
423
|
assert list(my_func.starmap([(1, 2), (3, 4)])) == [3, 7]
|
401
424
|
```
|
402
425
|
"""
|
403
|
-
return
|
426
|
+
return AsyncOrSyncIterable(
|
404
427
|
_starmap_async(
|
405
428
|
self, input_iterator, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
|
406
429
|
),
|
407
|
-
nested_async_message=
|
430
|
+
nested_async_message=(
|
431
|
+
"You can't run Function.map() or Function.for_each() from an async function. "
|
432
|
+
"Use Function.map.aio()/Function.for_each.aio() instead."
|
433
|
+
),
|
408
434
|
)
|
modal/parallel_map.pyi
CHANGED
@@ -1,87 +1,75 @@
|
|
1
1
|
import modal._utils.async_utils
|
2
2
|
import modal.client
|
3
|
+
import modal.functions
|
3
4
|
import typing
|
4
5
|
import typing_extensions
|
5
6
|
|
6
7
|
class _SynchronizedQueue:
|
7
|
-
async def init(self):
|
8
|
-
|
9
|
-
|
10
|
-
async def put(self, item):
|
11
|
-
...
|
12
|
-
|
13
|
-
async def get(self):
|
14
|
-
...
|
15
|
-
|
8
|
+
async def init(self): ...
|
9
|
+
async def put(self, item): ...
|
10
|
+
async def get(self): ...
|
16
11
|
|
17
12
|
class SynchronizedQueue:
|
18
|
-
def __init__(self, /, *args, **kwargs):
|
19
|
-
...
|
13
|
+
def __init__(self, /, *args, **kwargs): ...
|
20
14
|
|
21
15
|
class __init_spec(typing_extensions.Protocol):
|
22
|
-
def __call__(self):
|
23
|
-
|
24
|
-
|
25
|
-
async def aio(self, *args, **kwargs):
|
26
|
-
...
|
16
|
+
def __call__(self): ...
|
17
|
+
async def aio(self): ...
|
27
18
|
|
28
19
|
init: __init_spec
|
29
20
|
|
30
21
|
class __put_spec(typing_extensions.Protocol):
|
31
|
-
def __call__(self, item):
|
32
|
-
|
33
|
-
|
34
|
-
async def aio(self, *args, **kwargs):
|
35
|
-
...
|
22
|
+
def __call__(self, item): ...
|
23
|
+
async def aio(self, item): ...
|
36
24
|
|
37
25
|
put: __put_spec
|
38
26
|
|
39
27
|
class __get_spec(typing_extensions.Protocol):
|
40
|
-
def __call__(self):
|
41
|
-
|
42
|
-
|
43
|
-
async def aio(self, *args, **kwargs):
|
44
|
-
...
|
28
|
+
def __call__(self): ...
|
29
|
+
async def aio(self): ...
|
45
30
|
|
46
31
|
get: __get_spec
|
47
32
|
|
48
|
-
|
49
33
|
class _OutputValue:
|
50
34
|
value: typing.Any
|
51
35
|
|
52
|
-
def __init__(self, value: typing.Any) -> None:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
36
|
+
def __init__(self, value: typing.Any) -> None: ...
|
37
|
+
def __repr__(self): ...
|
38
|
+
def __eq__(self, other): ...
|
39
|
+
|
40
|
+
def _map_invocation(
|
41
|
+
function: modal.functions._Function,
|
42
|
+
raw_input_queue: _SynchronizedQueue,
|
43
|
+
client: modal.client._Client,
|
44
|
+
order_outputs: bool,
|
45
|
+
return_exceptions: bool,
|
46
|
+
count_update_callback: typing.Optional[typing.Callable[[int, int], None]],
|
47
|
+
): ...
|
48
|
+
def _map_sync(
|
49
|
+
self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
|
50
|
+
) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
|
51
|
+
def _map_async(
|
52
|
+
self,
|
53
|
+
*input_iterators: typing.Union[typing.Iterable[typing.Any], typing.AsyncIterable[typing.Any]],
|
54
|
+
kwargs={},
|
55
|
+
order_outputs: bool = True,
|
56
|
+
return_exceptions: bool = False,
|
57
|
+
) -> typing.AsyncGenerator[typing.Any, None]: ...
|
58
|
+
def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
|
59
|
+
async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
|
60
|
+
def _starmap_async(
|
61
|
+
self,
|
62
|
+
input_iterator: typing.Union[
|
63
|
+
typing.Iterable[typing.Sequence[typing.Any]], typing.AsyncIterable[typing.Sequence[typing.Any]]
|
64
|
+
],
|
65
|
+
kwargs={},
|
66
|
+
order_outputs: bool = True,
|
67
|
+
return_exceptions: bool = False,
|
68
|
+
) -> typing.AsyncIterable[typing.Any]: ...
|
69
|
+
def _starmap_sync(
|
70
|
+
self,
|
71
|
+
input_iterator: typing.Iterable[typing.Sequence[typing.Any]],
|
72
|
+
kwargs={},
|
73
|
+
order_outputs: bool = True,
|
74
|
+
return_exceptions: bool = False,
|
75
|
+
) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
|