modal 0.74.47__py3-none-any.whl → 0.74.49__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/_functions.py +35 -5
- modal/_utils/async_utils.py +13 -0
- modal/_utils/logger.py +16 -7
- modal/client.pyi +2 -2
- modal/config.py +6 -0
- modal/functions.pyi +18 -8
- modal/parallel_map.py +55 -1
- modal/parallel_map.pyi +2 -0
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/METADATA +1 -1
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/RECORD +18 -18
- modal_proto/api.proto +1 -0
- modal_proto/api_pb2.py +488 -488
- modal_proto/api_pb2.pyi +4 -1
- modal_version/_version_generated.py +1 -1
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/WHEEL +0 -0
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/entry_points.txt +0 -0
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/licenses/LICENSE +0 -0
- {modal-0.74.47.dist-info → modal-0.74.49.dist-info}/top_level.txt +0 -0
modal/_functions.py
CHANGED
@@ -55,7 +55,7 @@ from ._utils.function_utils import (
|
|
55
55
|
get_include_source_mode,
|
56
56
|
is_async,
|
57
57
|
)
|
58
|
-
from ._utils.grpc_utils import retry_transient_errors
|
58
|
+
from ._utils.grpc_utils import RetryWarningMessage, retry_transient_errors
|
59
59
|
from ._utils.mount_utils import validate_network_file_systems, validate_volumes
|
60
60
|
from .call_graph import InputInfo, _reconstruct_call_graph
|
61
61
|
from .client import _Client
|
@@ -80,6 +80,8 @@ from .parallel_map import (
|
|
80
80
|
_map_async,
|
81
81
|
_map_invocation,
|
82
82
|
_map_sync,
|
83
|
+
_spawn_map_async,
|
84
|
+
_spawn_map_sync,
|
83
85
|
_starmap_async,
|
84
86
|
_starmap_sync,
|
85
87
|
_SynchronizedQueue,
|
@@ -134,6 +136,7 @@ class _Invocation:
|
|
134
136
|
*,
|
135
137
|
client: _Client,
|
136
138
|
function_call_invocation_type: "api_pb2.FunctionCallInvocationType.ValueType",
|
139
|
+
from_spawn_map: bool = False,
|
137
140
|
) -> "_Invocation":
|
138
141
|
assert client.stub
|
139
142
|
function_id = function.object_id
|
@@ -146,9 +149,26 @@ class _Invocation:
|
|
146
149
|
pipelined_inputs=[item],
|
147
150
|
function_call_invocation_type=function_call_invocation_type,
|
148
151
|
)
|
149
|
-
response = await retry_transient_errors(client.stub.FunctionMap, request)
|
150
|
-
function_call_id = response.function_call_id
|
151
152
|
|
153
|
+
if from_spawn_map:
|
154
|
+
request.from_spawn_map = True
|
155
|
+
response = await retry_transient_errors(
|
156
|
+
client.stub.FunctionMap,
|
157
|
+
request,
|
158
|
+
max_retries=None,
|
159
|
+
max_delay=30.0,
|
160
|
+
retry_warning_message=RetryWarningMessage(
|
161
|
+
message="Warning: `.spawn_map(...)` for function `{self._function_name}` is waiting to create"
|
162
|
+
"more function calls. This may be due to hitting rate limits or function backlog limits.",
|
163
|
+
warning_interval=10,
|
164
|
+
errors_to_warn_for=[Status.RESOURCE_EXHAUSTED],
|
165
|
+
),
|
166
|
+
additional_status_codes=[Status.RESOURCE_EXHAUSTED],
|
167
|
+
)
|
168
|
+
else:
|
169
|
+
response = await retry_transient_errors(client.stub.FunctionMap, request)
|
170
|
+
|
171
|
+
function_call_id = response.function_call_id
|
152
172
|
if response.pipelined_inputs:
|
153
173
|
assert len(response.pipelined_inputs) == 1
|
154
174
|
input = response.pipelined_inputs[0]
|
@@ -1396,10 +1416,19 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1396
1416
|
return await invocation.run_function()
|
1397
1417
|
|
1398
1418
|
async def _call_function_nowait(
|
1399
|
-
self,
|
1419
|
+
self,
|
1420
|
+
args,
|
1421
|
+
kwargs,
|
1422
|
+
function_call_invocation_type: "api_pb2.FunctionCallInvocationType.ValueType",
|
1423
|
+
from_spawn_map: bool = False,
|
1400
1424
|
) -> _Invocation:
|
1401
1425
|
return await _Invocation.create(
|
1402
|
-
self,
|
1426
|
+
self,
|
1427
|
+
args,
|
1428
|
+
kwargs,
|
1429
|
+
client=self.client,
|
1430
|
+
function_call_invocation_type=function_call_invocation_type,
|
1431
|
+
from_spawn_map=from_spawn_map,
|
1403
1432
|
)
|
1404
1433
|
|
1405
1434
|
@warn_if_generator_is_not_consumed()
|
@@ -1603,6 +1632,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1603
1632
|
map = MethodWithAio(_map_sync, _map_async, synchronizer)
|
1604
1633
|
starmap = MethodWithAio(_starmap_sync, _starmap_async, synchronizer)
|
1605
1634
|
for_each = MethodWithAio(_for_each_sync, _for_each_async, synchronizer)
|
1635
|
+
spawn_map = MethodWithAio(_spawn_map_sync, _spawn_map_async, synchronizer)
|
1606
1636
|
|
1607
1637
|
|
1608
1638
|
class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
modal/_utils/async_utils.py
CHANGED
@@ -432,6 +432,19 @@ def warn_if_generator_is_not_consumed(function_name: Optional[str] = None):
|
|
432
432
|
return decorator
|
433
433
|
|
434
434
|
|
435
|
+
def run_coroutine_in_temporary_event_loop(coro: typing.Coroutine[None, None, T], nested_async_message: str) -> T:
|
436
|
+
"""Compatibility function to run an async coroutine in a temporary event loop.
|
437
|
+
|
438
|
+
This is needed for compatibility with the async implementation of Function.spawn_map. The future plan is
|
439
|
+
to have separate implementations so there is no issue with nested event loops.
|
440
|
+
"""
|
441
|
+
try:
|
442
|
+
with Runner() as runner:
|
443
|
+
return runner.run(coro)
|
444
|
+
except NestedEventLoops:
|
445
|
+
raise InvalidError(nested_async_message)
|
446
|
+
|
447
|
+
|
435
448
|
class AsyncOrSyncIterable:
|
436
449
|
"""Compatibility class for non-synchronicity wrapped async iterables to get
|
437
450
|
both async and sync interfaces in the same way that synchronicity does (but on the main thread)
|
modal/_utils/logger.py
CHANGED
@@ -4,33 +4,42 @@ import os
|
|
4
4
|
|
5
5
|
|
6
6
|
def configure_logger(logger: logging.Logger, log_level: str, log_format: str):
|
7
|
+
from modal.config import config
|
8
|
+
|
7
9
|
ch = logging.StreamHandler()
|
8
10
|
log_level_numeric = logging.getLevelName(log_level.upper())
|
9
11
|
logger.setLevel(log_level_numeric)
|
10
12
|
ch.setLevel(log_level_numeric)
|
11
|
-
|
13
|
+
datefmt = "%Y-%m-%dT%H:%M:%S%z"
|
12
14
|
if log_format.upper() == "JSON":
|
13
15
|
# This is primarily for modal internal use.
|
14
16
|
# pythonjsonlogger is already installed in the environment.
|
15
17
|
from pythonjsonlogger import jsonlogger
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
if not (log_format_pattern := config.get("log_pattern")):
|
20
|
+
log_format_pattern = (
|
19
21
|
"%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] "
|
20
22
|
"[dd.service=%(dd.service)s dd.env=%(dd.env)s dd.version=%(dd.version)s dd.trace_id=%(dd.trace_id)s "
|
21
23
|
"dd.span_id=%(dd.span_id)s] "
|
22
24
|
"- %(message)s"
|
23
|
-
)
|
24
|
-
datefmt="%Y-%m-%dT%H:%M:%S%z",
|
25
|
-
)
|
25
|
+
)
|
26
26
|
|
27
|
+
json_formatter = jsonlogger.JsonFormatter(
|
28
|
+
fmt=log_format_pattern,
|
29
|
+
datefmt=datefmt,
|
30
|
+
)
|
27
31
|
ch.setFormatter(json_formatter)
|
28
32
|
else:
|
29
|
-
|
33
|
+
if not (log_format_pattern := config.get("log_pattern")):
|
34
|
+
# TODO: use `%(name)s` instead of `modal-client` as soon as we unify the loggers we use
|
35
|
+
log_format_pattern = "[modal-client] %(asctime)s %(message)s"
|
36
|
+
|
37
|
+
ch.setFormatter(logging.Formatter(log_format_pattern, datefmt=datefmt))
|
30
38
|
|
31
39
|
logger.addHandler(ch)
|
32
40
|
|
33
41
|
|
42
|
+
# TODO: remove this distinct logger in favor of the one in modal.config?
|
34
43
|
log_level = os.environ.get("MODAL_LOGLEVEL", "WARNING")
|
35
44
|
log_format = os.environ.get("MODAL_LOG_FORMAT", "STRING")
|
36
45
|
|
modal/client.pyi
CHANGED
@@ -27,7 +27,7 @@ class _Client:
|
|
27
27
|
_snapshotted: bool
|
28
28
|
|
29
29
|
def __init__(
|
30
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.74.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.74.49"
|
31
31
|
): ...
|
32
32
|
def is_closed(self) -> bool: ...
|
33
33
|
@property
|
@@ -85,7 +85,7 @@ class Client:
|
|
85
85
|
_snapshotted: bool
|
86
86
|
|
87
87
|
def __init__(
|
88
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.74.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.74.49"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
modal/config.py
CHANGED
@@ -70,6 +70,11 @@ Other possible configuration options are:
|
|
70
70
|
* `traceback` (in the .toml file) / `MODAL_TRACEBACK` (as an env var).
|
71
71
|
Defaults to False. Enables printing full tracebacks on unexpected CLI
|
72
72
|
errors, which can be useful for debugging client issues.
|
73
|
+
* `log_pattern` (in the .toml file) / MODAL_LOG_PATTERN` (as an env var).
|
74
|
+
Defaults to "[modal-client] %(asctime)s %(message)s"
|
75
|
+
The log formatting pattern that will be used by the modal client itself.
|
76
|
+
See https://docs.python.org/3/library/logging.html#logrecord-attributes for available
|
77
|
+
log attributes.
|
73
78
|
|
74
79
|
Meta-configuration
|
75
80
|
------------------
|
@@ -216,6 +221,7 @@ class _Setting(typing.NamedTuple):
|
|
216
221
|
_SETTINGS = {
|
217
222
|
"loglevel": _Setting("WARNING", lambda s: s.upper()),
|
218
223
|
"log_format": _Setting("STRING", lambda s: s.upper()),
|
224
|
+
"log_pattern": _Setting(), # optional override of the formatting pattern
|
219
225
|
"server_url": _Setting("https://api.modal.com"),
|
220
226
|
"token_id": _Setting(),
|
221
227
|
"token_secret": _Setting(),
|
modal/functions.pyi
CHANGED
@@ -201,8 +201,12 @@ class Function(
|
|
201
201
|
_call_function: ___call_function_spec[modal._functions.ReturnType, typing_extensions.Self]
|
202
202
|
|
203
203
|
class ___call_function_nowait_spec(typing_extensions.Protocol[SUPERSELF]):
|
204
|
-
def __call__(
|
205
|
-
|
204
|
+
def __call__(
|
205
|
+
self, args, kwargs, function_call_invocation_type: int, from_spawn_map: bool = False
|
206
|
+
) -> modal._functions._Invocation: ...
|
207
|
+
async def aio(
|
208
|
+
self, args, kwargs, function_call_invocation_type: int, from_spawn_map: bool = False
|
209
|
+
) -> modal._functions._Invocation: ...
|
206
210
|
|
207
211
|
_call_function_nowait: ___call_function_nowait_spec[typing_extensions.Self]
|
208
212
|
|
@@ -218,11 +222,11 @@ class Function(
|
|
218
222
|
|
219
223
|
_call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
|
220
224
|
|
221
|
-
class __remote_spec(typing_extensions.Protocol[
|
225
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
222
226
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
223
227
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
224
228
|
|
225
|
-
remote: __remote_spec[modal._functions.
|
229
|
+
remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
226
230
|
|
227
231
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
228
232
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -237,19 +241,19 @@ class Function(
|
|
237
241
|
self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
|
238
242
|
) -> modal._functions.OriginalReturnType: ...
|
239
243
|
|
240
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
244
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
241
245
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
242
246
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
243
247
|
|
244
248
|
_experimental_spawn: ___experimental_spawn_spec[
|
245
|
-
modal._functions.
|
249
|
+
modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
|
246
250
|
]
|
247
251
|
|
248
|
-
class __spawn_spec(typing_extensions.Protocol[
|
252
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
|
249
253
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
250
254
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
251
255
|
|
252
|
-
spawn: __spawn_spec[modal._functions.
|
256
|
+
spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
|
253
257
|
|
254
258
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
|
255
259
|
|
@@ -307,6 +311,12 @@ class Function(
|
|
307
311
|
|
308
312
|
for_each: __for_each_spec[typing_extensions.Self]
|
309
313
|
|
314
|
+
class __spawn_map_spec(typing_extensions.Protocol[SUPERSELF]):
|
315
|
+
def __call__(self, *input_iterators, kwargs={}) -> None: ...
|
316
|
+
async def aio(self, *input_iterators, kwargs={}) -> None: ...
|
317
|
+
|
318
|
+
spawn_map: __spawn_map_spec[typing_extensions.Self]
|
319
|
+
|
310
320
|
class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Object):
|
311
321
|
_is_generator: bool
|
312
322
|
|
modal/parallel_map.py
CHANGED
@@ -13,10 +13,12 @@ from modal._utils.async_utils import (
|
|
13
13
|
AsyncOrSyncIterable,
|
14
14
|
TimestampPriorityQueue,
|
15
15
|
aclosing,
|
16
|
+
async_map,
|
16
17
|
async_map_ordered,
|
17
18
|
async_merge,
|
18
19
|
async_zip,
|
19
20
|
queue_batch_iterator,
|
21
|
+
run_coroutine_in_temporary_event_loop,
|
20
22
|
sync_or_async_iter,
|
21
23
|
synchronize_api,
|
22
24
|
synchronizer,
|
@@ -480,8 +482,60 @@ async def _map_async(
|
|
480
482
|
yield output
|
481
483
|
|
482
484
|
|
485
|
+
async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None:
|
486
|
+
"""mdmd:hidden
|
487
|
+
This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
|
488
|
+
function calls for each.
|
489
|
+
"""
|
490
|
+
|
491
|
+
def _call_with_args(args):
|
492
|
+
"""
|
493
|
+
Returns co-routine that invokes a function with the given arguments.
|
494
|
+
|
495
|
+
On RESOURCE_EXHAUSTED, it will retry indefinitely with exponential backoff up to 30 seconds. Every 10 retriable
|
496
|
+
errors, log a warning that the function call is waiting to be created.
|
497
|
+
"""
|
498
|
+
|
499
|
+
return self._call_function_nowait.aio(
|
500
|
+
args, kwargs, api_pb2.FUNCTION_CALL_INVOCATION_TYPE_ASYNC, from_spawn_map=True
|
501
|
+
)
|
502
|
+
|
503
|
+
input_gen = async_zip(*[sync_or_async_iter(it) for it in input_iterators])
|
504
|
+
|
505
|
+
# TODO(gongy): Can improve this by creating async_foreach method which foregoes async_merge.
|
506
|
+
async for _ in async_map(input_gen, _call_with_args, concurrency=256):
|
507
|
+
pass
|
508
|
+
|
509
|
+
|
510
|
+
def _spawn_map_sync(self, *input_iterators, kwargs={}) -> None:
|
511
|
+
"""Spawn parallel execution over a set of inputs, exiting as soon as the inputs are created (without waiting
|
512
|
+
for the map to complete).
|
513
|
+
|
514
|
+
Takes one iterator argument per argument in the function being mapped over.
|
515
|
+
|
516
|
+
Example:
|
517
|
+
```python
|
518
|
+
@app.function()
|
519
|
+
def my_func(a):
|
520
|
+
return a ** 2
|
521
|
+
|
522
|
+
|
523
|
+
@app.local_entrypoint()
|
524
|
+
def main():
|
525
|
+
my_func.spawn_map([1, 2, 3, 4])
|
526
|
+
```
|
527
|
+
|
528
|
+
Programmatic retrieval of results will be supported in a future update.
|
529
|
+
"""
|
530
|
+
|
531
|
+
return run_coroutine_in_temporary_event_loop(
|
532
|
+
_spawn_map_async(self, *input_iterators, kwargs=kwargs),
|
533
|
+
"You can't run Function.spawn_map() from an async function. Use Function.map.aio() instead.",
|
534
|
+
)
|
535
|
+
|
536
|
+
|
483
537
|
def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
|
484
|
-
"""Execute function for all inputs, ignoring outputs.
|
538
|
+
"""Execute function for all inputs, ignoring outputs. Waits for completion of the inputs.
|
485
539
|
|
486
540
|
Convenient alias for `.map()` in cases where the function just needs to be called.
|
487
541
|
as the caller doesn't have to consume the generator to process the inputs.
|
modal/parallel_map.pyi
CHANGED
@@ -65,6 +65,8 @@ def _map_async(
|
|
65
65
|
order_outputs: bool = True,
|
66
66
|
return_exceptions: bool = False,
|
67
67
|
) -> typing.AsyncGenerator[typing.Any, None]: ...
|
68
|
+
async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None: ...
|
69
|
+
def _spawn_map_sync(self, *input_iterators, kwargs={}) -> None: ...
|
68
70
|
def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
|
69
71
|
async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
|
70
72
|
def _starmap_async(
|
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=sTJcc9EbDuCKSwg3tL6ZckFw9WWdlkXW8mId1IvJCNc,2846
|
|
3
3
|
modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
|
4
4
|
modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
|
5
5
|
modal/_container_entrypoint.py,sha256=2Zx9O_EMJg0H77EdnC2vGKs6uFMWwbP1NLFf-qYmWmU,28962
|
6
|
-
modal/_functions.py,sha256=
|
6
|
+
modal/_functions.py,sha256=3Nx7snIerJEqcyCRGMTr3MReWklMpURItVz-o5qX7tE,77262
|
7
7
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
8
8
|
modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
|
9
9
|
modal/_object.py,sha256=6ve4sI2nRAnjPCuAXdSoUplaXfzC9MqRlF_ZLULwwy0,11472
|
@@ -22,12 +22,12 @@ modal/app.py,sha256=r-9vVU1lrR1CWtJEo60fuaianvxY_oOXZyv1Qx1DEkI,51231
|
|
22
22
|
modal/app.pyi,sha256=0QNtnUpAFbOPcbwCt119ge7OmoBqMFw5SajLgdE5eOw,28600
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=U-YKSw0n7J1ZLREt9cbEJCtmHe5YoPKFxl0xlkan2yc,15565
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=aMgJftZr5pTStBb0n4tz8sgLrlKIaRZdrBMMEh9rFVg,7593
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
28
28
|
modal/cls.py,sha256=aHoMEWMZUN7bOezs3tRPxzS1FP3gTxZBORVjbPmtxyg,35338
|
29
29
|
modal/cls.pyi,sha256=B--Y4xEOo3GRE3QiiFdIE8jnIKEeBcOtwAbXvg2Z8H4,12012
|
30
|
-
modal/config.py,sha256=
|
30
|
+
modal/config.py,sha256=_2KU5jG-vZQ4vDLYQ83r4aQdnjnN00TY12DtSJMGYsA,12617
|
31
31
|
modal/container_process.py,sha256=vvyK3DVPUMsuqvkKdUiQ49cDLF9JawGrxpglLk5vfgI,6208
|
32
32
|
modal/container_process.pyi,sha256=bXs2KHe7nxVuLAm6RRBqXCvDKelANGX9gFY8qIuZYDs,2898
|
33
33
|
modal/dict.py,sha256=7NJVI05hisF9gTuJMYestH9X0LIOaE9PPqbCeYtwSRs,13365
|
@@ -39,7 +39,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
39
39
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
40
40
|
modal/file_pattern_matcher.py,sha256=trosX-Bp7dOubudN1bLLhRAoidWy1TcoaR4Pv8CedWw,6497
|
41
41
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
42
|
-
modal/functions.pyi,sha256=
|
42
|
+
modal/functions.pyi,sha256=N0vF8PfDKQLsWEKjtr0oWU6Ls6a07hj_1G8Bj2grdvk,16010
|
43
43
|
modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
|
44
44
|
modal/image.py,sha256=ZCghS6l1O7pezXcdMHk6RoJpW3qWszfWGJTW38lNXaU,92797
|
45
45
|
modal/image.pyi,sha256=ddbegF532pDLiVANOJdtJiYoDbbF3mAFrsCiyvIu7jU,25632
|
@@ -52,8 +52,8 @@ modal/network_file_system.pyi,sha256=C_ZiXmpdkTObapVhAPlRmB4ofmM2D7SdKlUCZVg-1IQ
|
|
52
52
|
modal/object.py,sha256=bTeskuY8JFrESjU4_UL_nTwYlBQdOLmVaOX3X6EMxsg,164
|
53
53
|
modal/object.pyi,sha256=kyJkRQcVv3ct7zSAxvvXcuhBVeH914v80uSlqeS7cA4,5632
|
54
54
|
modal/output.py,sha256=q4T9uHduunj4NwY-YSwkHGgjZlCXMuJbfQ5UFaAGRAc,1968
|
55
|
-
modal/parallel_map.py,sha256=
|
56
|
-
modal/parallel_map.pyi,sha256=
|
55
|
+
modal/parallel_map.py,sha256=UAqwhlsMQzhVtc9b2xzwH0__T3auN5tPX0h8a9ZHIMA,35737
|
56
|
+
modal/parallel_map.pyi,sha256=bLh_D57e5KOIkmP4WW-C_rMSzfxRUNfdtpNJKj4jWA4,5865
|
57
57
|
modal/partial_function.py,sha256=SwuAAj2wj4SO6F6nkSnwNZrczEmm9w9YdlQTHh6hr04,1195
|
58
58
|
modal/partial_function.pyi,sha256=NFWz1aCAs2B3-GnPf1cTatWRZOLnYpFKCnjP_X9iNRs,6411
|
59
59
|
modal/proxy.py,sha256=XEjIHzZvbD3UW4YWyDzbDuNFq6hDUxyPPxupl2qwULY,1429
|
@@ -91,7 +91,7 @@ modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5
|
|
91
91
|
modal/_runtime/user_code_imports.py,sha256=78wJyleqY2RVibqcpbDQyfWVBVT9BjyHPeoV9WdwV5Y,17720
|
92
92
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
93
93
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
94
|
-
modal/_utils/async_utils.py,sha256=
|
94
|
+
modal/_utils/async_utils.py,sha256=zjdtdA54zvNL_RuREmN5NWFhhiRcNh8z0jT2rBc5RgY,28001
|
95
95
|
modal/_utils/blob_utils.py,sha256=IexC2Jbtqp_Tkmy62ayfgzTYte0UPCNufB_v-DO21g8,18585
|
96
96
|
modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
|
97
97
|
modal/_utils/deprecation.py,sha256=EXP1beU4pmEqEzWMLw6E3kUfNfpmNA_VOp6i0EHi93g,4856
|
@@ -103,7 +103,7 @@ modal/_utils/grpc_utils.py,sha256=VmVHEFxEWXNLrgYwLk0vFwwls8g97Pg6B4RGz_5RA1w,92
|
|
103
103
|
modal/_utils/hash_utils.py,sha256=zg3J6OGxTFGSFri1qQ12giDz90lWk8bzaxCTUCRtiX4,3034
|
104
104
|
modal/_utils/http_utils.py,sha256=yeTFsXYr0rYMEhB7vBP7audG9Uc7OLhzKBANFDZWVt0,2451
|
105
105
|
modal/_utils/jwt_utils.py,sha256=fxH9plyrbAemTbjSsQtzIdDXE9QXxvMC4DiUZ16G0aA,1360
|
106
|
-
modal/_utils/logger.py,sha256=
|
106
|
+
modal/_utils/logger.py,sha256=NgbMKFT9chYYt_TU01DdIior5ByYr2gZtrWIk1SFRLc,1782
|
107
107
|
modal/_utils/mount_utils.py,sha256=gGCgIlWwYiJbUtgFY2GJcWYismYvazbMAeUOgf7NhFQ,3205
|
108
108
|
modal/_utils/name_utils.py,sha256=TW1iyJedvDNPEJ5UVp93u8xuD5J2gQL_CUt1mgov_aI,1939
|
109
109
|
modal/_utils/package_utils.py,sha256=LcL2olGN4xaUzu2Tbv-C-Ft9Qp6bsLxEfETOAVd-mjU,2073
|
@@ -145,7 +145,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
|
|
145
145
|
modal/requirements/PREVIEW.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddRo,296
|
146
146
|
modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
|
147
147
|
modal/requirements/base-images.json,sha256=57vMSqzMbLBxw5tFWSaMiIkkVEps4JfX5PAtXGnkS4U,740
|
148
|
-
modal-0.74.
|
148
|
+
modal-0.74.49.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
149
149
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
150
150
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
151
151
|
modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
|
@@ -153,10 +153,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
|
|
153
153
|
modal_docs/mdmd/mdmd.py,sha256=Irx49MCCTlBOP4FBdLR--JrpA3-WhsVeriq0LGgsRic,6232
|
154
154
|
modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
|
155
155
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
156
|
-
modal_proto/api.proto,sha256=
|
156
|
+
modal_proto/api.proto,sha256=r1eiUMvVau4QqFmHrZD5nfQ67d-enn3O83HtGndkuos,94253
|
157
157
|
modal_proto/api_grpc.py,sha256=kTSfs9yI_YtxkPuATpSQ1_Nvd7TtjK03H61RupX1bpM,114421
|
158
|
-
modal_proto/api_pb2.py,sha256=
|
159
|
-
modal_proto/api_pb2.pyi,sha256=
|
158
|
+
modal_proto/api_pb2.py,sha256=xJ2zpxvjBC3RI1_GXVcin9upB3SpkN5lh2xIZbvZU9Y,332430
|
159
|
+
modal_proto/api_pb2.pyi,sha256=HZ2gYP9m94RcGz-cjWfusEkCq05Z5oyzPB1SvE3yE0Q,452052
|
160
160
|
modal_proto/api_pb2_grpc.py,sha256=-KPQMzXmTYwgF23_tGpODCVK79iOdV1sRsw5mN-byMw,247448
|
161
161
|
modal_proto/api_pb2_grpc.pyi,sha256=ls1qcby7goTrlE6BluSWpo73cW_ajvh3rOe41azMBWM,57929
|
162
162
|
modal_proto/modal_api_grpc.py,sha256=X-sgFt2CYE5cahn41gc0oDNfK0sWIOs7AlmHUWKMB1k,15234
|
@@ -170,9 +170,9 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
170
170
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
171
171
|
modal_version/__init__.py,sha256=m94xZNWIjH8oUtJk4l9xfovzDJede2o7X-q0MHVECtM,470
|
172
172
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
173
|
-
modal_version/_version_generated.py,sha256
|
174
|
-
modal-0.74.
|
175
|
-
modal-0.74.
|
176
|
-
modal-0.74.
|
177
|
-
modal-0.74.
|
178
|
-
modal-0.74.
|
173
|
+
modal_version/_version_generated.py,sha256=-h2evheb0h6ZeCRd4OY4P-xlD3f4lAxmMFdV25T_ZpM,149
|
174
|
+
modal-0.74.49.dist-info/METADATA,sha256=WVM_5pHEfZr-wAqhPek3gvwIZMAWoKWpdeUjIw-Bveo,2451
|
175
|
+
modal-0.74.49.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
176
|
+
modal-0.74.49.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
177
|
+
modal-0.74.49.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
178
|
+
modal-0.74.49.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
@@ -1673,6 +1673,7 @@ message FunctionMapRequest {
|
|
1673
1673
|
FunctionCallType function_call_type = 4;
|
1674
1674
|
repeated FunctionPutInputsItem pipelined_inputs = 5;
|
1675
1675
|
FunctionCallInvocationType function_call_invocation_type = 6;
|
1676
|
+
bool from_spawn_map = 7;
|
1676
1677
|
}
|
1677
1678
|
|
1678
1679
|
message FunctionMapResponse {
|