modal 0.73.146__py3-none-any.whl → 0.73.148__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 +8 -6
- modal/_partial_function.py +394 -266
- modal/_runtime/user_code_imports.py +2 -2
- modal/app.py +22 -22
- modal/client.pyi +2 -2
- modal/cls.py +11 -7
- modal/experimental/__init__.py +6 -35
- modal/partial_function.py +1 -1
- modal/partial_function.pyi +82 -39
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/METADATA +1 -1
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/RECORD +16 -16
- modal_version/_version_generated.py +1 -1
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/LICENSE +0 -0
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/WHEEL +0 -0
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/entry_points.txt +0 -0
- {modal-0.73.146.dist-info → modal-0.73.148.dist-info}/top_level.txt +0 -0
@@ -150,8 +150,8 @@ class ImportedClass(Service):
|
|
150
150
|
# Check this property before we turn it into a method (overriden by webhooks)
|
151
151
|
is_async = get_is_async(user_func)
|
152
152
|
# Use the function definition for whether this is a generator (overriden by webhooks)
|
153
|
-
is_generator = partial.is_generator
|
154
|
-
webhook_config = partial.webhook_config
|
153
|
+
is_generator = partial.params.is_generator
|
154
|
+
webhook_config = partial.params.webhook_config
|
155
155
|
|
156
156
|
bound_func = user_func.__get__(self.user_cls_instance)
|
157
157
|
|
modal/app.py
CHANGED
@@ -652,7 +652,7 @@ class _App:
|
|
652
652
|
|
653
653
|
if isinstance(f, _PartialFunction):
|
654
654
|
# typically for @function-wrapped @web_endpoint, @asgi_app, or @batched
|
655
|
-
f.
|
655
|
+
f.registered = True
|
656
656
|
|
657
657
|
# but we don't support @app.function wrapping a method.
|
658
658
|
if is_method_fn(f.raw_f.__qualname__):
|
@@ -670,17 +670,17 @@ class _App:
|
|
670
670
|
"```\n"
|
671
671
|
)
|
672
672
|
i6pn_enabled = i6pn or (f.flags & _PartialFunctionFlags.CLUSTERED)
|
673
|
-
cluster_size = f.cluster_size # Experimental: Clustered functions
|
673
|
+
cluster_size = f.params.cluster_size # Experimental: Clustered functions
|
674
674
|
|
675
675
|
info = FunctionInfo(f.raw_f, serialized=serialized, name_override=name)
|
676
676
|
raw_f = f.raw_f
|
677
|
-
webhook_config = f.webhook_config
|
678
|
-
is_generator = f.is_generator
|
679
|
-
batch_max_size = f.batch_max_size
|
680
|
-
batch_wait_ms = f.batch_wait_ms
|
681
|
-
if f.
|
682
|
-
max_concurrent_inputs = f.max_concurrent_inputs
|
683
|
-
target_concurrent_inputs = f.target_concurrent_inputs
|
677
|
+
webhook_config = f.params.webhook_config
|
678
|
+
is_generator = f.params.is_generator
|
679
|
+
batch_max_size = f.params.batch_max_size
|
680
|
+
batch_wait_ms = f.params.batch_wait_ms
|
681
|
+
if f.flags & _PartialFunctionFlags.CONCURRENT:
|
682
|
+
max_concurrent_inputs = f.params.max_concurrent_inputs
|
683
|
+
target_concurrent_inputs = f.params.target_concurrent_inputs
|
684
684
|
else:
|
685
685
|
max_concurrent_inputs = allow_concurrent_inputs
|
686
686
|
target_concurrent_inputs = None
|
@@ -857,11 +857,11 @@ class _App:
|
|
857
857
|
def wrapper(wrapped_cls: Union[CLS_T, _PartialFunction]) -> CLS_T:
|
858
858
|
# Check if the decorated object is a class
|
859
859
|
if isinstance(wrapped_cls, _PartialFunction):
|
860
|
-
wrapped_cls.
|
861
|
-
user_cls = wrapped_cls.
|
862
|
-
if wrapped_cls.
|
863
|
-
max_concurrent_inputs = wrapped_cls.max_concurrent_inputs
|
864
|
-
target_concurrent_inputs = wrapped_cls.target_concurrent_inputs
|
860
|
+
wrapped_cls.registered = True
|
861
|
+
user_cls = wrapped_cls.user_cls
|
862
|
+
if wrapped_cls.flags & _PartialFunctionFlags.CONCURRENT:
|
863
|
+
max_concurrent_inputs = wrapped_cls.params.max_concurrent_inputs
|
864
|
+
target_concurrent_inputs = wrapped_cls.params.target_concurrent_inputs
|
865
865
|
else:
|
866
866
|
max_concurrent_inputs = allow_concurrent_inputs
|
867
867
|
target_concurrent_inputs = None
|
@@ -876,13 +876,13 @@ class _App:
|
|
876
876
|
if batch_functions:
|
877
877
|
if len(batch_functions) > 1:
|
878
878
|
raise InvalidError(f"Modal class {user_cls.__name__} can only have one batched function.")
|
879
|
-
if len(_find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.
|
879
|
+
if len(_find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.interface_flags())) > 1:
|
880
880
|
raise InvalidError(
|
881
881
|
f"Modal class {user_cls.__name__} with a modal batched function cannot have other modal methods." # noqa
|
882
882
|
)
|
883
883
|
batch_function = next(iter(batch_functions.values()))
|
884
|
-
batch_max_size = batch_function.batch_max_size
|
885
|
-
batch_wait_ms = batch_function.batch_wait_ms
|
884
|
+
batch_max_size = batch_function.params.batch_max_size
|
885
|
+
batch_wait_ms = batch_function.params.batch_wait_ms
|
886
886
|
else:
|
887
887
|
batch_max_size = None
|
888
888
|
batch_wait_ms = None
|
@@ -893,11 +893,11 @@ class _App:
|
|
893
893
|
):
|
894
894
|
raise InvalidError("A class must have `enable_memory_snapshot=True` to use `snap=True` on its methods.")
|
895
895
|
|
896
|
-
for method in _find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
896
|
+
for method in _find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.CONCURRENT).values():
|
897
|
+
method.registered = True # Avoid warning about not registering the method (hacky!)
|
898
|
+
raise InvalidError(
|
899
|
+
"The `@modal.concurrent` decorator cannot be used on methods; decorate the class instead."
|
900
|
+
)
|
901
901
|
|
902
902
|
info = FunctionInfo(None, serialized=serialized, user_cls=user_cls)
|
903
903
|
|
modal/client.pyi
CHANGED
@@ -31,7 +31,7 @@ class _Client:
|
|
31
31
|
server_url: str,
|
32
32
|
client_type: int,
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
34
|
-
version: str = "0.73.
|
34
|
+
version: str = "0.73.148",
|
35
35
|
): ...
|
36
36
|
def is_closed(self) -> bool: ...
|
37
37
|
@property
|
@@ -93,7 +93,7 @@ class Client:
|
|
93
93
|
server_url: str,
|
94
94
|
client_type: int,
|
95
95
|
credentials: typing.Optional[tuple[str, str]],
|
96
|
-
version: str = "0.73.
|
96
|
+
version: str = "0.73.148",
|
97
97
|
): ...
|
98
98
|
def is_closed(self) -> bool: ...
|
99
99
|
@property
|
modal/cls.py
CHANGED
@@ -225,7 +225,7 @@ class _Obj:
|
|
225
225
|
|
226
226
|
# user cls instances are only created locally, so we have all partial functions available
|
227
227
|
instance_methods = {}
|
228
|
-
for method_name in _find_partial_methods_for_user_cls(self._user_cls, _PartialFunctionFlags.
|
228
|
+
for method_name in _find_partial_methods_for_user_cls(self._user_cls, _PartialFunctionFlags.interface_flags()):
|
229
229
|
instance_methods[method_name] = getattr(self, method_name)
|
230
230
|
|
231
231
|
user_cls_instance._modal_functions = instance_methods
|
@@ -475,22 +475,26 @@ class _Cls(_Object, type_prefix="cs"):
|
|
475
475
|
_Cls.validate_construction_mechanism(user_cls)
|
476
476
|
|
477
477
|
method_partials: dict[str, _PartialFunction] = _find_partial_methods_for_user_cls(
|
478
|
-
user_cls, _PartialFunctionFlags.
|
478
|
+
user_cls, _PartialFunctionFlags.interface_flags()
|
479
479
|
)
|
480
480
|
|
481
481
|
for method_name, partial_function in method_partials.items():
|
482
|
-
if partial_function.webhook_config is not None:
|
482
|
+
if partial_function.params.webhook_config is not None:
|
483
483
|
full_name = f"{user_cls.__name__}.{method_name}"
|
484
484
|
app._web_endpoints.append(full_name)
|
485
|
-
partial_function.
|
485
|
+
partial_function.registered = True
|
486
486
|
|
487
487
|
# Disable the warning that lifecycle methods are not wrapped
|
488
|
-
for partial_function in _find_partial_methods_for_user_cls(
|
489
|
-
|
488
|
+
for partial_function in _find_partial_methods_for_user_cls(
|
489
|
+
user_cls, ~_PartialFunctionFlags.interface_flags()
|
490
|
+
).values():
|
491
|
+
partial_function.registered = True
|
490
492
|
|
491
493
|
# Get all callables
|
492
494
|
callables: dict[str, Callable] = {
|
493
|
-
k: pf.raw_f
|
495
|
+
k: pf.raw_f
|
496
|
+
for k, pf in _find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.all()).items()
|
497
|
+
if pf.raw_f is not None # Should be true for _find_partial_methods output, but hard to annotate
|
494
498
|
}
|
495
499
|
|
496
500
|
def _deps() -> list[_Function]:
|
modal/experimental/__init__.py
CHANGED
@@ -2,16 +2,15 @@
|
|
2
2
|
import os
|
3
3
|
from dataclasses import dataclass
|
4
4
|
from pathlib import Path
|
5
|
-
from typing import
|
5
|
+
from typing import Literal, Optional, Union
|
6
6
|
|
7
7
|
from modal_proto import api_pb2
|
8
8
|
|
9
9
|
from .._clustered_functions import ClusterInfo, get_cluster_info as _get_cluster_info
|
10
|
-
from .._functions import _Function
|
11
10
|
from .._object import _get_environment_name
|
12
|
-
from .._partial_function import
|
11
|
+
from .._partial_function import _clustered
|
13
12
|
from .._runtime.container_io_manager import _ContainerIOManager
|
14
|
-
from .._utils.async_utils import synchronizer
|
13
|
+
from .._utils.async_utils import synchronize_api, synchronizer
|
15
14
|
from ..client import _Client
|
16
15
|
from ..exception import InvalidError
|
17
16
|
from ..image import DockerfileSpec, ImageBuilderVersion, _Image, _ImageRegistryConfig
|
@@ -38,41 +37,13 @@ def set_local_input_concurrency(concurrency: int):
|
|
38
37
|
_ContainerIOManager.set_input_concurrency(concurrency)
|
39
38
|
|
40
39
|
|
41
|
-
def clustered(size: int, broadcast: bool = True):
|
42
|
-
"""Provision clusters of colocated and networked containers for the Function.
|
43
|
-
|
44
|
-
Parameters:
|
45
|
-
size: int
|
46
|
-
Number of containers spun up to handle each input.
|
47
|
-
broadcast: bool = True
|
48
|
-
If True, inputs will be sent simultaneously to each container. Otherwise,
|
49
|
-
inputs will be sent only to the rank-0 container, which is responsible for
|
50
|
-
delegating to the workers.
|
51
|
-
"""
|
52
|
-
|
53
|
-
assert broadcast, "broadcast=False has not been implemented yet!"
|
54
|
-
|
55
|
-
if size <= 0:
|
56
|
-
raise ValueError("cluster size must be greater than 0")
|
57
|
-
|
58
|
-
def wrapper(raw_f: Callable[..., Any]) -> _PartialFunction:
|
59
|
-
if isinstance(raw_f, _Function):
|
60
|
-
raw_f = raw_f.get_raw_f()
|
61
|
-
raise InvalidError(
|
62
|
-
f"Applying decorators for {raw_f} in the wrong order!\nUsage:\n\n"
|
63
|
-
"@app.function()\n@modal.clustered()\ndef clustered_function():\n ..."
|
64
|
-
)
|
65
|
-
return _PartialFunction(
|
66
|
-
raw_f, _PartialFunctionFlags.FUNCTION | _PartialFunctionFlags.CLUSTERED, cluster_size=size
|
67
|
-
)
|
68
|
-
|
69
|
-
return wrapper
|
70
|
-
|
71
|
-
|
72
40
|
def get_cluster_info() -> ClusterInfo:
|
73
41
|
return _get_cluster_info()
|
74
42
|
|
75
43
|
|
44
|
+
clustered = synchronize_api(_clustered, target_module=__name__)
|
45
|
+
|
46
|
+
|
76
47
|
@dataclass
|
77
48
|
class AppInfo:
|
78
49
|
app_id: str
|
modal/partial_function.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# Copyright Modal Labs 2025
|
2
|
-
from modal._utils.async_utils import synchronize_api
|
3
2
|
|
4
3
|
from ._partial_function import (
|
5
4
|
_asgi_app,
|
@@ -15,6 +14,7 @@ from ._partial_function import (
|
|
15
14
|
_web_server,
|
16
15
|
_wsgi_app,
|
17
16
|
)
|
17
|
+
from ._utils.async_utils import synchronize_api
|
18
18
|
|
19
19
|
# The only reason these are wrapped is to get translated type stubs, they
|
20
20
|
# don't actually run any async code as of 2025-02-04:
|
modal/partial_function.pyi
CHANGED
@@ -1,41 +1,37 @@
|
|
1
1
|
import collections.abc
|
2
2
|
import modal._partial_function
|
3
3
|
import modal.functions
|
4
|
-
import modal_proto.api_pb2
|
5
4
|
import typing
|
5
|
+
import typing_extensions
|
6
6
|
|
7
7
|
class PartialFunction(
|
8
8
|
typing.Generic[
|
9
9
|
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.OriginalReturnType
|
10
10
|
]
|
11
11
|
):
|
12
|
-
raw_f: collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType]
|
12
|
+
raw_f: typing.Optional[collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType]]
|
13
|
+
user_cls: typing.Optional[type]
|
13
14
|
flags: modal._partial_function._PartialFunctionFlags
|
14
|
-
|
15
|
-
|
16
|
-
batch_max_size: typing.Optional[int]
|
17
|
-
batch_wait_ms: typing.Optional[int]
|
18
|
-
force_build: bool
|
19
|
-
cluster_size: typing.Optional[int]
|
20
|
-
build_timeout: typing.Optional[int]
|
21
|
-
max_concurrent_inputs: typing.Optional[int]
|
22
|
-
target_concurrent_inputs: typing.Optional[int]
|
15
|
+
params: modal._partial_function._PartialFunctionParams
|
16
|
+
registered: bool
|
23
17
|
|
24
18
|
def __init__(
|
25
19
|
self,
|
26
|
-
|
20
|
+
obj: typing.Union[
|
21
|
+
collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType], type
|
22
|
+
],
|
27
23
|
flags: modal._partial_function._PartialFunctionFlags,
|
28
|
-
|
29
|
-
webhook_config: typing.Optional[modal_proto.api_pb2.WebhookConfig] = None,
|
30
|
-
is_generator: typing.Optional[bool] = None,
|
31
|
-
batch_max_size: typing.Optional[int] = None,
|
32
|
-
batch_wait_ms: typing.Optional[int] = None,
|
33
|
-
cluster_size: typing.Optional[int] = None,
|
34
|
-
force_build: bool = False,
|
35
|
-
build_timeout: typing.Optional[int] = None,
|
36
|
-
max_concurrent_inputs: typing.Optional[int] = None,
|
37
|
-
target_concurrent_inputs: typing.Optional[int] = None,
|
24
|
+
params: modal._partial_function._PartialFunctionParams,
|
38
25
|
): ...
|
26
|
+
def stack(
|
27
|
+
self,
|
28
|
+
flags: modal._partial_function._PartialFunctionFlags,
|
29
|
+
params: modal._partial_function._PartialFunctionParams,
|
30
|
+
) -> typing_extensions.Self: ...
|
31
|
+
def validate_flag_composition(self) -> None: ...
|
32
|
+
def validate_obj_compatibility(
|
33
|
+
self, decorator_name: str, require_sync: bool = False, require_nullary: bool = False
|
34
|
+
) -> None: ...
|
39
35
|
def _get_raw_f(self) -> collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType]: ...
|
40
36
|
def _is_web_endpoint(self) -> bool: ...
|
41
37
|
def __get__(
|
@@ -44,7 +40,6 @@ class PartialFunction(
|
|
44
40
|
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.OriginalReturnType
|
45
41
|
]: ...
|
46
42
|
def __del__(self): ...
|
47
|
-
def add_flags(self, flags) -> PartialFunction: ...
|
48
43
|
|
49
44
|
def method(
|
50
45
|
_warn_parentheses_missing=None, *, is_generator: typing.Optional[bool] = None
|
@@ -58,7 +53,14 @@ def web_endpoint(
|
|
58
53
|
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
59
54
|
requires_proxy_auth: bool = False,
|
60
55
|
) -> collections.abc.Callable[
|
61
|
-
[
|
56
|
+
[
|
57
|
+
typing.Union[
|
58
|
+
PartialFunction[
|
59
|
+
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType
|
60
|
+
],
|
61
|
+
collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType],
|
62
|
+
]
|
63
|
+
],
|
62
64
|
PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
|
63
65
|
]: ...
|
64
66
|
def fastapi_endpoint(
|
@@ -70,7 +72,14 @@ def fastapi_endpoint(
|
|
70
72
|
docs: bool = False,
|
71
73
|
requires_proxy_auth: bool = False,
|
72
74
|
) -> collections.abc.Callable[
|
73
|
-
[
|
75
|
+
[
|
76
|
+
typing.Union[
|
77
|
+
PartialFunction[
|
78
|
+
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType
|
79
|
+
],
|
80
|
+
collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType],
|
81
|
+
]
|
82
|
+
],
|
74
83
|
PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
|
75
84
|
]: ...
|
76
85
|
def asgi_app(
|
@@ -79,14 +88,32 @@ def asgi_app(
|
|
79
88
|
label: typing.Optional[str] = None,
|
80
89
|
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
81
90
|
requires_proxy_auth: bool = False,
|
82
|
-
) -> collections.abc.Callable[
|
91
|
+
) -> collections.abc.Callable[
|
92
|
+
[
|
93
|
+
typing.Union[
|
94
|
+
PartialFunction,
|
95
|
+
collections.abc.Callable[[], typing.Any],
|
96
|
+
collections.abc.Callable[[typing.Any], typing.Any],
|
97
|
+
]
|
98
|
+
],
|
99
|
+
PartialFunction,
|
100
|
+
]: ...
|
83
101
|
def wsgi_app(
|
84
102
|
_warn_parentheses_missing=None,
|
85
103
|
*,
|
86
104
|
label: typing.Optional[str] = None,
|
87
105
|
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
88
106
|
requires_proxy_auth: bool = False,
|
89
|
-
) -> collections.abc.Callable[
|
107
|
+
) -> collections.abc.Callable[
|
108
|
+
[
|
109
|
+
typing.Union[
|
110
|
+
PartialFunction,
|
111
|
+
collections.abc.Callable[[], typing.Any],
|
112
|
+
collections.abc.Callable[[typing.Any], typing.Any],
|
113
|
+
]
|
114
|
+
],
|
115
|
+
PartialFunction,
|
116
|
+
]: ...
|
90
117
|
def web_server(
|
91
118
|
port: int,
|
92
119
|
*,
|
@@ -94,36 +121,52 @@ def web_server(
|
|
94
121
|
label: typing.Optional[str] = None,
|
95
122
|
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
96
123
|
requires_proxy_auth: bool = False,
|
97
|
-
) -> collections.abc.Callable[
|
124
|
+
) -> collections.abc.Callable[
|
125
|
+
[
|
126
|
+
typing.Union[
|
127
|
+
PartialFunction,
|
128
|
+
collections.abc.Callable[[], typing.Any],
|
129
|
+
collections.abc.Callable[[typing.Any], typing.Any],
|
130
|
+
]
|
131
|
+
],
|
132
|
+
PartialFunction,
|
133
|
+
]: ...
|
98
134
|
def build(
|
99
135
|
_warn_parentheses_missing=None, *, force: bool = False, timeout: int = 86400
|
100
136
|
) -> collections.abc.Callable[
|
101
|
-
[typing.Union[collections.abc.Callable[[typing.Any], typing.Any]
|
137
|
+
[typing.Union[PartialFunction, collections.abc.Callable[[typing.Any], typing.Any]]], PartialFunction
|
102
138
|
]: ...
|
103
139
|
def enter(
|
104
140
|
_warn_parentheses_missing=None, *, snap: bool = False
|
105
141
|
) -> collections.abc.Callable[
|
106
|
-
[typing.Union[collections.abc.Callable[[typing.Any], typing.Any]
|
142
|
+
[typing.Union[PartialFunction, collections.abc.Callable[[typing.Any], typing.Any]]], PartialFunction
|
107
143
|
]: ...
|
108
144
|
def exit(
|
109
145
|
_warn_parentheses_missing=None,
|
146
|
+
) -> collections.abc.Callable[[collections.abc.Callable[[typing.Any], typing.Any]], PartialFunction]: ...
|
147
|
+
def batched(
|
148
|
+
_warn_parentheses_missing=None, *, max_batch_size: int, wait_ms: int
|
110
149
|
) -> collections.abc.Callable[
|
111
150
|
[
|
112
151
|
typing.Union[
|
113
|
-
|
114
|
-
|
115
|
-
typing.Any,
|
152
|
+
PartialFunction[
|
153
|
+
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType
|
116
154
|
],
|
117
|
-
collections.abc.Callable[
|
155
|
+
collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType],
|
118
156
|
]
|
119
157
|
],
|
120
|
-
PartialFunction,
|
158
|
+
PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
|
121
159
|
]: ...
|
122
|
-
def batched(
|
123
|
-
_warn_parentheses_missing=None, *, max_batch_size: int, wait_ms: int
|
124
|
-
) -> collections.abc.Callable[[collections.abc.Callable[..., typing.Any]], PartialFunction]: ...
|
125
160
|
def concurrent(
|
126
161
|
_warn_parentheses_missing=None, *, max_inputs: int, target_inputs: typing.Optional[int] = None
|
127
162
|
) -> collections.abc.Callable[
|
128
|
-
[
|
163
|
+
[
|
164
|
+
typing.Union[
|
165
|
+
PartialFunction[
|
166
|
+
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType
|
167
|
+
],
|
168
|
+
collections.abc.Callable[modal._partial_function.P, modal._partial_function.ReturnType],
|
169
|
+
]
|
170
|
+
],
|
171
|
+
PartialFunction[modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.ReturnType],
|
129
172
|
]: ...
|
@@ -3,12 +3,12 @@ modal/__main__.py,sha256=CgIjP8m1xJjjd4AXc-delmR6LdBCZclw2A_V38CFIio,2870
|
|
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=XyqJPvzX0YMqviIIz-9bsD6HMrPsboU4A1yfgTloTSA,29302
|
6
|
-
modal/_functions.py,sha256=
|
6
|
+
modal/_functions.py,sha256=nUyiCOYcuY_jXJhY5-haHFIUQleCmjh8z6GgXgo5MRY,73556
|
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=JBIECWdfpRKCaCxVWZbC3Q1kF5Whk_EKvY9f4Y6AFyg,11446
|
10
10
|
modal/_output.py,sha256=Z0nngPh2mKHMQc4MQ92YjVPc3ewOLa3I4dFBlL9nvQY,25656
|
11
|
-
modal/_partial_function.py,sha256=
|
11
|
+
modal/_partial_function.py,sha256=fsHktCBncN2pj_BwSe0eqUn-fo8emZnnCg5YK5mOBuM,39570
|
12
12
|
modal/_proxy_tunnel.py,sha256=gnKyCfmVB7x2d1A6c-JDysNIP3kEFxmXzhcXhPrzPn0,1906
|
13
13
|
modal/_pty.py,sha256=JZfPDDpzqICZqtyPI_oMJf_9w-p_lLNuzHhwhodUXio,1329
|
14
14
|
modal/_resolver.py,sha256=RtoXoYzSllPlFu0D1vel_FWiEmDO7RyToiC2bxeN8ZY,6917
|
@@ -19,14 +19,14 @@ modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
|
19
19
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
20
20
|
modal/_type_manager.py,sha256=SvDvX9JK1jLp8TA_psLd-hNYPALlG9KtSOmlbHqdtQE,8284
|
21
21
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
22
|
-
modal/app.py,sha256=
|
22
|
+
modal/app.py,sha256=w00bV9cjABAsS2ExE7zb1jY6Q_snXYmdKa3xRFg8iXA,47428
|
23
23
|
modal/app.pyi,sha256=pUEqciyGZ446sc_QoG8XcQ_oc6oU-U4dqjkxjhgOX98,26968
|
24
24
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
25
25
|
modal/client.py,sha256=j9D3hNis1lfhnz9lVFGgJgowbH3PaGUzNKgHPWYG778,15372
|
26
|
-
modal/client.pyi,sha256=
|
26
|
+
modal/client.pyi,sha256=mMEPgjcIyzVWg-sdPiS4Xg6JpoC5OjNBEmIbLmqn6Ok,7661
|
27
27
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
28
28
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
29
|
-
modal/cls.py,sha256=
|
29
|
+
modal/cls.py,sha256=6MZYzhOcsCG7uWKk_zv_Q7fDcn5dkmK0M4QVRrpfF3Q,31769
|
30
30
|
modal/cls.pyi,sha256=ZJUwtRaQBGlM6tphvnv49FHBVDSgttMdD_LnYyRSKJM,10302
|
31
31
|
modal/config.py,sha256=Zx7YsllgIJzMRKeIkaGSLLtMFV4kTUvGxpptnmqlP1U,11623
|
32
32
|
modal/container_process.py,sha256=vvyK3DVPUMsuqvkKdUiQ49cDLF9JawGrxpglLk5vfgI,6208
|
@@ -55,8 +55,8 @@ modal/object.pyi,sha256=kyJkRQcVv3ct7zSAxvvXcuhBVeH914v80uSlqeS7cA4,5632
|
|
55
55
|
modal/output.py,sha256=q4T9uHduunj4NwY-YSwkHGgjZlCXMuJbfQ5UFaAGRAc,1968
|
56
56
|
modal/parallel_map.py,sha256=2d30AM43g8SazkhGbbP1t2sACa4NRqeZrw3JEAqqZDg,33867
|
57
57
|
modal/parallel_map.pyi,sha256=mEenHruPiZDq3ucV_6RM8ctc0c_Qpqra5MBagXeHiiQ,5708
|
58
|
-
modal/partial_function.py,sha256=
|
59
|
-
modal/partial_function.pyi,sha256
|
58
|
+
modal/partial_function.py,sha256=SwuAAj2wj4SO6F6nkSnwNZrczEmm9w9YdlQTHh6hr04,1195
|
59
|
+
modal/partial_function.pyi,sha256=NFWz1aCAs2B3-GnPf1cTatWRZOLnYpFKCnjP_X9iNRs,6411
|
60
60
|
modal/proxy.py,sha256=NrOevrWxG3G7-zlyRzG6BcIvop7AWLeyahZxitbBaOk,1418
|
61
61
|
modal/proxy.pyi,sha256=1OEKIVUyC-xb7fHMzngakQso0nTsK60TVhXtlcMj6Wk,390
|
62
62
|
modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -89,7 +89,7 @@ modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7J
|
|
89
89
|
modal/_runtime/execution_context.pyi,sha256=wQZwMNADExkeNdB9yKX0PPojovxlFHbap3441wAsiMY,634
|
90
90
|
modal/_runtime/gpu_memory_snapshot.py,sha256=tA3m1d1cwnmHpvpCeN_WijDd6n8byn7LWlpicbIxiOI,3144
|
91
91
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
92
|
-
modal/_runtime/user_code_imports.py,sha256=
|
92
|
+
modal/_runtime/user_code_imports.py,sha256=Q3EXhRObBvBWwUrrXI3wfVPSlGqNr5UtchFjMWeoVS0,14828
|
93
93
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
94
94
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
95
95
|
modal/_utils/async_utils.py,sha256=b2TJyKY1Hq7df7M-fo3qlFM95mGdo3dCuqRPPcV5hsE,27445
|
@@ -137,7 +137,7 @@ modal/cli/volume.py,sha256=c2IuVNO2yJVaXmZkRh3xwQmznlRTgFoJr_BIzzqtVv0,10251
|
|
137
137
|
modal/cli/programs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
138
138
|
modal/cli/programs/run_jupyter.py,sha256=MX6YQ6zRyRk1xo8tYZFiGam0p5KETwax81L6TpaS9I0,2778
|
139
139
|
modal/cli/programs/vscode.py,sha256=kfvhZQ4bJwtVm3MgC1V7AlygZOlKT1a33alr_uwrewA,3473
|
140
|
-
modal/experimental/__init__.py,sha256=
|
140
|
+
modal/experimental/__init__.py,sha256=7qlR4P4U1_sfPdiX8mhSzHR5scbS96QVxeKFnsIcpS4,6457
|
141
141
|
modal/experimental/ipython.py,sha256=epLUZeDSdE226TH_tU3igRKCiVuQi99mUOrIJ4SemOE,2792
|
142
142
|
modal/requirements/2023.12.312.txt,sha256=zWWUVgVQ92GXBKNYYr2-5vn9rlnXcmkqlwlX5u1eTYw,400
|
143
143
|
modal/requirements/2023.12.txt,sha256=OjsbXFkCSdkzzryZP82Q73osr5wxQ6EUzmGcK7twfkA,502
|
@@ -170,10 +170,10 @@ 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=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
172
172
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
173
|
-
modal_version/_version_generated.py,sha256=
|
174
|
-
modal-0.73.
|
175
|
-
modal-0.73.
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
173
|
+
modal_version/_version_generated.py,sha256=nzFQHmuRs46mrfpDMjMlOZqG-WUOmD7XQgKYT_4bcSQ,150
|
174
|
+
modal-0.73.148.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
175
|
+
modal-0.73.148.dist-info/METADATA,sha256=7cfZ8raRL3PwJoKUpglIOKEiGcmBB0rkUu2ijhjasOo,2453
|
176
|
+
modal-0.73.148.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
177
|
+
modal-0.73.148.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
178
|
+
modal-0.73.148.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
179
|
+
modal-0.73.148.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|