modal 0.67.5__py3-none-any.whl → 0.67.7__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/_utils/function_utils.py +3 -0
- modal/app.py +37 -26
- modal/app.pyi +2 -2
- modal/client.pyi +2 -2
- modal/functions.pyi +6 -6
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/METADATA +1 -1
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/RECORD +12 -12
- modal_version/_version_generated.py +1 -1
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/LICENSE +0 -0
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/WHEEL +0 -0
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/entry_points.txt +0 -0
- {modal-0.67.5.dist-info → modal-0.67.7.dist-info}/top_level.txt +0 -0
modal/_utils/function_utils.py
CHANGED
@@ -133,6 +133,9 @@ class FunctionInfo:
|
|
133
133
|
elif f is None and user_cls:
|
134
134
|
# "service function" for running all methods of a class
|
135
135
|
self.function_name = f"{user_cls.__name__}.*"
|
136
|
+
elif f and user_cls:
|
137
|
+
# Method may be defined on superclass of the wrapped class
|
138
|
+
self.function_name = f"{user_cls.__name__}.{f.__name__}"
|
136
139
|
else:
|
137
140
|
self.function_name = f.__qualname__
|
138
141
|
|
modal/app.py
CHANGED
@@ -313,23 +313,6 @@ class _App:
|
|
313
313
|
if not isinstance(value, _Object):
|
314
314
|
raise InvalidError(f"App attribute `{key}` with value {value!r} is not a valid Modal object")
|
315
315
|
|
316
|
-
def _add_object(self, tag, obj):
|
317
|
-
# TODO(erikbern): replace this with _add_function and _add_class
|
318
|
-
if self._running_app:
|
319
|
-
# If this is inside a container, then objects can be defined after app initialization.
|
320
|
-
# So we may have to initialize objects once they get bound to the app.
|
321
|
-
if tag in self._running_app.tag_to_object_id:
|
322
|
-
object_id: str = self._running_app.tag_to_object_id[tag]
|
323
|
-
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
324
|
-
obj._hydrate(object_id, self._client, metadata)
|
325
|
-
|
326
|
-
if isinstance(obj, _Function):
|
327
|
-
self._functions[tag] = obj
|
328
|
-
elif isinstance(obj, _Cls):
|
329
|
-
self._classes[tag] = obj
|
330
|
-
else:
|
331
|
-
raise RuntimeError(f"Expected `obj` to be a _Function or _Cls (got {type(obj)}")
|
332
|
-
|
333
316
|
def __getitem__(self, tag: str):
|
334
317
|
deprecation_error((2024, 3, 25), _app_attr_error)
|
335
318
|
|
@@ -481,10 +464,29 @@ class _App:
|
|
481
464
|
if function.tag in self._classes:
|
482
465
|
logger.warning(f"Warning: tag {function.tag} exists but is overridden by function")
|
483
466
|
|
484
|
-
self.
|
467
|
+
if self._running_app:
|
468
|
+
# If this is inside a container, then objects can be defined after app initialization.
|
469
|
+
# So we may have to initialize objects once they get bound to the app.
|
470
|
+
if function.tag in self._running_app.tag_to_object_id:
|
471
|
+
object_id: str = self._running_app.tag_to_object_id[function.tag]
|
472
|
+
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
473
|
+
function._hydrate(object_id, self._client, metadata)
|
474
|
+
|
475
|
+
self._functions[function.tag] = function
|
485
476
|
if is_web_endpoint:
|
486
477
|
self._web_endpoints.append(function.tag)
|
487
478
|
|
479
|
+
def _add_class(self, tag: str, cls: _Cls):
|
480
|
+
if self._running_app:
|
481
|
+
# If this is inside a container, then objects can be defined after app initialization.
|
482
|
+
# So we may have to initialize objects once they get bound to the app.
|
483
|
+
if tag in self._running_app.tag_to_object_id:
|
484
|
+
object_id: str = self._running_app.tag_to_object_id[tag]
|
485
|
+
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
486
|
+
cls._hydrate(object_id, self._client, metadata)
|
487
|
+
|
488
|
+
self._classes[tag] = cls
|
489
|
+
|
488
490
|
def _init_container(self, client: _Client, running_app: RunningApp):
|
489
491
|
self._app_id = running_app.app_id
|
490
492
|
self._running_app = running_app
|
@@ -935,7 +937,7 @@ class _App:
|
|
935
937
|
cls: _Cls = _Cls.from_local(user_cls, self, cls_func)
|
936
938
|
|
937
939
|
tag: str = user_cls.__name__
|
938
|
-
self.
|
940
|
+
self._add_class(tag, cls)
|
939
941
|
return cls # type: ignore # a _Cls instance "simulates" being the user provided class
|
940
942
|
|
941
943
|
return wrapper
|
@@ -1022,16 +1024,25 @@ class _App:
|
|
1022
1024
|
bar.remote()
|
1023
1025
|
```
|
1024
1026
|
"""
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1027
|
+
for tag, function in other_app._functions.items():
|
1028
|
+
existing_function = self._functions.get(tag)
|
1029
|
+
if existing_function and existing_function != function:
|
1030
|
+
logger.warning(
|
1031
|
+
f"Named app function {tag} with existing value {existing_function} is being "
|
1032
|
+
f"overwritten by a different function {function}"
|
1033
|
+
)
|
1034
|
+
|
1035
|
+
self._add_function(function, False) # TODO(erikbern): webhook config?
|
1036
|
+
|
1037
|
+
for tag, cls in other_app._classes.items():
|
1038
|
+
existing_cls = self._classes.get(tag)
|
1039
|
+
if existing_cls and existing_cls != cls:
|
1029
1040
|
logger.warning(
|
1030
|
-
f"Named app
|
1031
|
-
f"overwritten by a different
|
1041
|
+
f"Named app class {tag} with existing value {existing_cls} is being "
|
1042
|
+
f"overwritten by a different class {cls}"
|
1032
1043
|
)
|
1033
1044
|
|
1034
|
-
self.
|
1045
|
+
self._add_class(tag, cls)
|
1035
1046
|
|
1036
1047
|
async def _logs(self, client: Optional[_Client] = None) -> AsyncGenerator[str, None]:
|
1037
1048
|
"""Stream logs from the app.
|
modal/app.pyi
CHANGED
@@ -114,7 +114,6 @@ class _App:
|
|
114
114
|
) -> _App: ...
|
115
115
|
def set_description(self, description: str): ...
|
116
116
|
def _validate_blueprint_value(self, key: str, value: typing.Any): ...
|
117
|
-
def _add_object(self, tag, obj): ...
|
118
117
|
def __getitem__(self, tag: str): ...
|
119
118
|
def __setitem__(self, tag: str, obj: modal.object._Object): ...
|
120
119
|
def __getattr__(self, tag: str): ...
|
@@ -137,6 +136,7 @@ class _App:
|
|
137
136
|
def _get_default_image(self): ...
|
138
137
|
def _get_watch_mounts(self): ...
|
139
138
|
def _add_function(self, function: modal.functions._Function, is_web_endpoint: bool): ...
|
139
|
+
def _add_class(self, tag: str, cls: modal.cls._Cls): ...
|
140
140
|
def _init_container(self, client: modal.client._Client, running_app: modal.running_app.RunningApp): ...
|
141
141
|
@property
|
142
142
|
def registered_functions(self) -> typing.Dict[str, modal.functions._Function]: ...
|
@@ -321,7 +321,6 @@ class App:
|
|
321
321
|
|
322
322
|
def set_description(self, description: str): ...
|
323
323
|
def _validate_blueprint_value(self, key: str, value: typing.Any): ...
|
324
|
-
def _add_object(self, tag, obj): ...
|
325
324
|
def __getitem__(self, tag: str): ...
|
326
325
|
def __setitem__(self, tag: str, obj: modal.object.Object): ...
|
327
326
|
def __getattr__(self, tag: str): ...
|
@@ -363,6 +362,7 @@ class App:
|
|
363
362
|
def _get_default_image(self): ...
|
364
363
|
def _get_watch_mounts(self): ...
|
365
364
|
def _add_function(self, function: modal.functions.Function, is_web_endpoint: bool): ...
|
365
|
+
def _add_class(self, tag: str, cls: modal.cls.Cls): ...
|
366
366
|
def _init_container(self, client: modal.client.Client, running_app: modal.running_app.RunningApp): ...
|
367
367
|
@property
|
368
368
|
def registered_functions(self) -> typing.Dict[str, modal.functions.Function]: ...
|
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[typing.Tuple[str, str]],
|
34
|
-
version: str = "0.67.
|
34
|
+
version: str = "0.67.7",
|
35
35
|
): ...
|
36
36
|
def is_closed(self) -> bool: ...
|
37
37
|
@property
|
@@ -90,7 +90,7 @@ class Client:
|
|
90
90
|
server_url: str,
|
91
91
|
client_type: int,
|
92
92
|
credentials: typing.Optional[typing.Tuple[str, str]],
|
93
|
-
version: str = "0.67.
|
93
|
+
version: str = "0.67.7",
|
94
94
|
): ...
|
95
95
|
def is_closed(self) -> bool: ...
|
96
96
|
@property
|
modal/functions.pyi
CHANGED
@@ -436,11 +436,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
|
|
436
436
|
|
437
437
|
_call_generator_nowait: ___call_generator_nowait_spec
|
438
438
|
|
439
|
-
class __remote_spec(typing_extensions.Protocol[
|
439
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
440
440
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
441
441
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
442
442
|
|
443
|
-
remote: __remote_spec[
|
443
|
+
remote: __remote_spec[P, ReturnType]
|
444
444
|
|
445
445
|
class __remote_gen_spec(typing_extensions.Protocol):
|
446
446
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -452,17 +452,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
|
|
452
452
|
def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
|
453
453
|
def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
|
454
454
|
|
455
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
455
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
456
456
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
457
457
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
458
458
|
|
459
|
-
_experimental_spawn: ___experimental_spawn_spec[
|
459
|
+
_experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
|
460
460
|
|
461
|
-
class __spawn_spec(typing_extensions.Protocol[
|
461
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
462
462
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
463
463
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
464
464
|
|
465
|
-
spawn: __spawn_spec[
|
465
|
+
spawn: __spawn_spec[P, ReturnType]
|
466
466
|
|
467
467
|
def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
|
468
468
|
|
@@ -15,11 +15,11 @@ modal/_traceback.py,sha256=1yNp1Dqq4qRIQp8idDp5PEqjwH4eA8MNI0FhFkCOFgo,4408
|
|
15
15
|
modal/_tunnel.py,sha256=BC9Fbvr9xvE3UMp5t8rn4ek-jXu2uwU778cKPMJfTtM,6290
|
16
16
|
modal/_tunnel.pyi,sha256=SA_Q0UGB-D9skFjv6CqlTnCEWU67a2xJxfwVdXtar3Y,1259
|
17
17
|
modal/_watcher.py,sha256=STlDe73R7IS33a_GMW2HnDc3hCDKLdsBfMxRpVh-flA,3581
|
18
|
-
modal/app.py,sha256=
|
19
|
-
modal/app.pyi,sha256=
|
18
|
+
modal/app.py,sha256=J2vcc3MDUnawxgEe-WXvfISPGLLcdCPlCqnYk9TeP2I,46114
|
19
|
+
modal/app.pyi,sha256=AWJVT92FaRN7DvSA5tD5w3_E-_PJeEPXTAf8rcwxR60,25312
|
20
20
|
modal/call_graph.py,sha256=l-Wi6vM8aosCdHTWegcCyGeVJGFdZ_fzlCmbRVPBXFI,2593
|
21
21
|
modal/client.py,sha256=4SpWb4n0nolITR36kADZl1tYLOg6avukmzZU56UQjCo,16385
|
22
|
-
modal/client.pyi,sha256=
|
22
|
+
modal/client.pyi,sha256=oX4k-6SBendqT1YJ3mOiGxMu2hUSrl-2E4pDclWro6I,7370
|
23
23
|
modal/cloud_bucket_mount.py,sha256=eWQhCtMIczpokjfTZEgNBCGO_s5ft46PqTSLfKBykq4,5748
|
24
24
|
modal/cloud_bucket_mount.pyi,sha256=tTF7M4FR9bTA30cFkz8qq3ZTlFL19NHU_36e_5GgAGA,1424
|
25
25
|
modal/cls.py,sha256=v3Uad6nTpHNwkAZ04KlQY3jZGgntKt5Onz6DusFRtg8,24706
|
@@ -34,7 +34,7 @@ modal/environments.pyi,sha256=oScvFAclF55-tL9UioLIL_SPBwgy_9O-BBvJ-PLbRgY,3542
|
|
34
34
|
modal/exception.py,sha256=K-czk1oK8wFvK8snWrytXSByo2WNb9SJAlgBVPGWZBs,6417
|
35
35
|
modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
|
36
36
|
modal/functions.py,sha256=Gfr-IsAeH0uIHCSfVYNWSzjnnrN33LPY3Ui4S6c6Pvo,66953
|
37
|
-
modal/functions.pyi,sha256=
|
37
|
+
modal/functions.pyi,sha256=1pFjUQBZx__UGaqJadYoMycQdlVb4jTex307VREzpQA,24375
|
38
38
|
modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
|
39
39
|
modal/image.py,sha256=DoubwAD9ebYNIEO3GJWbtAaJl_ZRW4K0tpIJdS9CZAg,79551
|
40
40
|
modal/image.pyi,sha256=3rfae_E0KuNHqdi5j33nHXp_7P3tTkt7QKH5cXYczUc,24672
|
@@ -83,7 +83,7 @@ modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
|
83
83
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
84
84
|
modal/_utils/async_utils.py,sha256=LInaa9xOl256MwXPtFlgmgk9iS2OEJGF15BCyi_O0hE,24994
|
85
85
|
modal/_utils/blob_utils.py,sha256=pAY22w0oVc6ujGfI7La7HPUMOf42FehIapuhSDeeqEs,15835
|
86
|
-
modal/_utils/function_utils.py,sha256
|
86
|
+
modal/_utils/function_utils.py,sha256=-rqOuLS77IJ9QIQ8_CbQ_yiRBgfn59pnIQaPisI_n2o,24644
|
87
87
|
modal/_utils/grpc_testing.py,sha256=LOzWygTdHINzV-o_Ajbl7sOFbUQFoonP0iKpsJjA_nc,8301
|
88
88
|
modal/_utils/grpc_utils.py,sha256=tM1Q32VOU2WG733IfVHTLZdiyCe8Ga0f0Dx0iDLLy_8,7724
|
89
89
|
modal/_utils/hash_utils.py,sha256=HefF7zPQPxFxyx3fpz-AdSm4QsHZNNvgL9-iQHY-_F4,1790
|
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
159
159
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
160
160
|
modal_version/__init__.py,sha256=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
|
161
161
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
162
|
-
modal_version/_version_generated.py,sha256=
|
163
|
-
modal-0.67.
|
164
|
-
modal-0.67.
|
165
|
-
modal-0.67.
|
166
|
-
modal-0.67.
|
167
|
-
modal-0.67.
|
168
|
-
modal-0.67.
|
162
|
+
modal_version/_version_generated.py,sha256=2urHEXqwYQx-GEaj2QGwfa-He9pNAWXWIc9xMcryLt8,148
|
163
|
+
modal-0.67.7.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
164
|
+
modal-0.67.7.dist-info/METADATA,sha256=ZrYiBib8zhzx2pQy3G_NLDJrRE7AaqjpprGR80iirfo,2328
|
165
|
+
modal-0.67.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
166
|
+
modal-0.67.7.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
167
|
+
modal-0.67.7.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
168
|
+
modal-0.67.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|