modal 0.70.3__py3-none-any.whl → 0.70.4__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/_container_entrypoint.py +14 -13
- modal/_runtime/container_io_manager.py +1 -6
- modal/app.py +10 -8
- modal/app.pyi +6 -2
- modal/client.pyi +2 -2
- modal/runner.py +0 -3
- modal/running_app.py +0 -8
- modal/sandbox.py +3 -3
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/METADATA +1 -1
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/RECORD +15 -15
- modal_version/_version_generated.py +2 -2
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/LICENSE +0 -0
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/WHEEL +0 -0
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/entry_points.txt +0 -0
- {modal-0.70.3.dist-info → modal-0.70.4.dist-info}/top_level.txt +0 -0
modal/_container_entrypoint.py
CHANGED
@@ -337,14 +337,17 @@ def call_function(
|
|
337
337
|
signal.signal(signal.SIGUSR1, usr1_handler) # reset signal handler
|
338
338
|
|
339
339
|
|
340
|
-
def get_active_app_fallback(function_def: api_pb2.Function) ->
|
340
|
+
def get_active_app_fallback(function_def: api_pb2.Function) -> _App:
|
341
341
|
# This branch is reached in the special case that the imported function/class is:
|
342
342
|
# 1) not serialized, and
|
343
343
|
# 2) isn't a FunctionHandle - i.e, not decorated at definition time
|
344
344
|
# Look at all instantiated apps - if there is only one with the indicated name, use that one
|
345
345
|
app_name: Optional[str] = function_def.app_name or None # coalesce protobuf field to None
|
346
346
|
matching_apps = _App._all_apps.get(app_name, [])
|
347
|
-
|
347
|
+
if len(matching_apps) == 1:
|
348
|
+
active_app: _App = matching_apps[0]
|
349
|
+
return active_app
|
350
|
+
|
348
351
|
if len(matching_apps) > 1:
|
349
352
|
if app_name is not None:
|
350
353
|
warning_sub_message = f"app with the same name ('{app_name}')"
|
@@ -354,12 +357,10 @@ def get_active_app_fallback(function_def: api_pb2.Function) -> Optional[_App]:
|
|
354
357
|
f"You have more than one {warning_sub_message}. "
|
355
358
|
"It's recommended to name all your Apps uniquely when using multiple apps"
|
356
359
|
)
|
357
|
-
elif len(matching_apps) == 1:
|
358
|
-
(active_app,) = matching_apps
|
359
|
-
# there could also technically be zero found apps, but that should probably never be an
|
360
|
-
# issue since that would mean user won't use is_inside or other function handles anyway
|
361
360
|
|
362
|
-
|
361
|
+
# If we don't have an active app, create one on the fly
|
362
|
+
# The app object is used to carry the app layout etc
|
363
|
+
return _App()
|
363
364
|
|
364
365
|
|
365
366
|
def call_lifecycle_functions(
|
@@ -403,7 +404,7 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
|
|
403
404
|
# This is a bit weird but we need both the blocking and async versions of ContainerIOManager.
|
404
405
|
# At some point, we should fix that by having built-in support for running "user code"
|
405
406
|
container_io_manager = ContainerIOManager(container_args, client)
|
406
|
-
active_app:
|
407
|
+
active_app: _App
|
407
408
|
service: Service
|
408
409
|
function_def = container_args.function_def
|
409
410
|
is_auto_snapshot: bool = function_def.is_auto_snapshot
|
@@ -450,8 +451,9 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
|
|
450
451
|
)
|
451
452
|
|
452
453
|
# If the cls/function decorator was applied in local scope, but the app is global, we can look it up
|
453
|
-
|
454
|
-
|
454
|
+
if service.app is not None:
|
455
|
+
active_app = service.app
|
456
|
+
else:
|
455
457
|
# if the app can't be inferred by the imported function, use name-based fallback
|
456
458
|
active_app = get_active_app_fallback(function_def)
|
457
459
|
|
@@ -468,9 +470,8 @@ def main(container_args: api_pb2.ContainerArguments, client: Client):
|
|
468
470
|
|
469
471
|
# Initialize objects on the app.
|
470
472
|
# This is basically only functions and classes - anything else is deprecated and will be unsupported soon
|
471
|
-
|
472
|
-
|
473
|
-
app._init_container(client, container_app)
|
473
|
+
app: App = synchronizer._translate_out(active_app)
|
474
|
+
app._init_container(client, container_app)
|
474
475
|
|
475
476
|
# Hydrate all function dependencies.
|
476
477
|
# TODO(erikbern): we an remove this once we
|
@@ -457,12 +457,7 @@ class _ContainerIOManager:
|
|
457
457
|
resp = await retry_transient_errors(self._client.stub.AppGetLayout, req)
|
458
458
|
app_layout = resp.app_layout
|
459
459
|
|
460
|
-
return running_app_from_layout(
|
461
|
-
self.app_id,
|
462
|
-
app_layout,
|
463
|
-
self._client,
|
464
|
-
environment_name=self._environment_name,
|
465
|
-
)
|
460
|
+
return running_app_from_layout(self.app_id, app_layout)
|
466
461
|
|
467
462
|
async def get_serialized_function(self) -> tuple[Optional[Any], Optional[Callable[..., Any]]]:
|
468
463
|
# Fetch the serialized function definition
|
modal/app.py
CHANGED
@@ -168,7 +168,7 @@ class _App:
|
|
168
168
|
"""
|
169
169
|
|
170
170
|
_all_apps: ClassVar[dict[Optional[str], list["_App"]]] = {}
|
171
|
-
_container_app: ClassVar[Optional[
|
171
|
+
_container_app: ClassVar[Optional["_App"]] = None
|
172
172
|
|
173
173
|
_name: Optional[str]
|
174
174
|
_description: Optional[str]
|
@@ -294,12 +294,7 @@ class _App:
|
|
294
294
|
app = _App(name)
|
295
295
|
app._app_id = response.app_id
|
296
296
|
app._client = client
|
297
|
-
app._running_app = RunningApp(
|
298
|
-
response.app_id,
|
299
|
-
client=client,
|
300
|
-
environment_name=environment_name,
|
301
|
-
interactive=False,
|
302
|
-
)
|
297
|
+
app._running_app = RunningApp(response.app_id, interactive=False)
|
303
298
|
return app
|
304
299
|
|
305
300
|
def set_description(self, description: str):
|
@@ -488,7 +483,7 @@ class _App:
|
|
488
483
|
self._running_app = running_app
|
489
484
|
self._client = client
|
490
485
|
|
491
|
-
_App._container_app =
|
486
|
+
_App._container_app = self
|
492
487
|
|
493
488
|
# Hydrate function objects
|
494
489
|
for tag, object_id in running_app.function_ids.items():
|
@@ -1047,6 +1042,13 @@ class _App:
|
|
1047
1042
|
if log.data:
|
1048
1043
|
yield log.data
|
1049
1044
|
|
1045
|
+
@classmethod
|
1046
|
+
def container_app(cls) -> Optional["_App"]:
|
1047
|
+
"""Returns the `App` running inside a container.
|
1048
|
+
|
1049
|
+
This will return `None` outside of a Modal container."""
|
1050
|
+
return cls._container_app
|
1051
|
+
|
1050
1052
|
@classmethod
|
1051
1053
|
def _reset_container_app(cls):
|
1052
1054
|
"""Only used for tests."""
|
modal/app.pyi
CHANGED
@@ -73,7 +73,7 @@ class _FunctionDecoratorType:
|
|
73
73
|
|
74
74
|
class _App:
|
75
75
|
_all_apps: typing.ClassVar[dict[typing.Optional[str], list[_App]]]
|
76
|
-
_container_app: typing.ClassVar[typing.Optional[
|
76
|
+
_container_app: typing.ClassVar[typing.Optional[_App]]
|
77
77
|
_name: typing.Optional[str]
|
78
78
|
_description: typing.Optional[str]
|
79
79
|
_functions: dict[str, modal.functions._Function]
|
@@ -266,11 +266,13 @@ class _App:
|
|
266
266
|
self, client: typing.Optional[modal.client._Client] = None
|
267
267
|
) -> collections.abc.AsyncGenerator[str, None]: ...
|
268
268
|
@classmethod
|
269
|
+
def container_app(cls) -> typing.Optional[_App]: ...
|
270
|
+
@classmethod
|
269
271
|
def _reset_container_app(cls): ...
|
270
272
|
|
271
273
|
class App:
|
272
274
|
_all_apps: typing.ClassVar[dict[typing.Optional[str], list[App]]]
|
273
|
-
_container_app: typing.ClassVar[typing.Optional[
|
275
|
+
_container_app: typing.ClassVar[typing.Optional[App]]
|
274
276
|
_name: typing.Optional[str]
|
275
277
|
_description: typing.Optional[str]
|
276
278
|
_functions: dict[str, modal.functions.Function]
|
@@ -530,6 +532,8 @@ class App:
|
|
530
532
|
|
531
533
|
_logs: ___logs_spec
|
532
534
|
|
535
|
+
@classmethod
|
536
|
+
def container_app(cls) -> typing.Optional[App]: ...
|
533
537
|
@classmethod
|
534
538
|
def _reset_container_app(cls): ...
|
535
539
|
|
modal/client.pyi
CHANGED
@@ -26,7 +26,7 @@ class _Client:
|
|
26
26
|
_stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
|
27
27
|
|
28
28
|
def __init__(
|
29
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.70.
|
29
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.70.4"
|
30
30
|
): ...
|
31
31
|
def is_closed(self) -> bool: ...
|
32
32
|
@property
|
@@ -81,7 +81,7 @@ class Client:
|
|
81
81
|
_stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
|
82
82
|
|
83
83
|
def __init__(
|
84
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.70.
|
84
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.70.4"
|
85
85
|
): ...
|
86
86
|
def is_closed(self) -> bool: ...
|
87
87
|
@property
|
modal/runner.py
CHANGED
@@ -64,7 +64,6 @@ async def _init_local_app_existing(client: _Client, existing_app_id: str, enviro
|
|
64
64
|
return running_app_from_layout(
|
65
65
|
existing_app_id,
|
66
66
|
obj_resp.app_layout,
|
67
|
-
client,
|
68
67
|
app_page_url=app_page_url,
|
69
68
|
)
|
70
69
|
|
@@ -89,10 +88,8 @@ async def _init_local_app_new(
|
|
89
88
|
logger.debug(f"Created new app with id {app_resp.app_id}")
|
90
89
|
return RunningApp(
|
91
90
|
app_resp.app_id,
|
92
|
-
client=client,
|
93
91
|
app_page_url=app_resp.app_page_url,
|
94
92
|
app_logs_url=app_resp.app_logs_url,
|
95
|
-
environment_name=environment_name,
|
96
93
|
interactive=interactive,
|
97
94
|
)
|
98
95
|
|
modal/running_app.py
CHANGED
@@ -7,14 +7,10 @@ from google.protobuf.message import Message
|
|
7
7
|
from modal._utils.grpc_utils import get_proto_oneof
|
8
8
|
from modal_proto import api_pb2
|
9
9
|
|
10
|
-
from .client import _Client
|
11
|
-
|
12
10
|
|
13
11
|
@dataclass
|
14
12
|
class RunningApp:
|
15
13
|
app_id: str
|
16
|
-
client: _Client
|
17
|
-
environment_name: Optional[str] = None
|
18
14
|
app_page_url: Optional[str] = None
|
19
15
|
app_logs_url: Optional[str] = None
|
20
16
|
function_ids: dict[str, str] = field(default_factory=dict)
|
@@ -26,8 +22,6 @@ class RunningApp:
|
|
26
22
|
def running_app_from_layout(
|
27
23
|
app_id: str,
|
28
24
|
app_layout: api_pb2.AppLayout,
|
29
|
-
client: _Client,
|
30
|
-
environment_name: Optional[str] = None,
|
31
25
|
app_page_url: Optional[str] = None,
|
32
26
|
) -> RunningApp:
|
33
27
|
object_handle_metadata = {}
|
@@ -37,8 +31,6 @@ def running_app_from_layout(
|
|
37
31
|
|
38
32
|
return RunningApp(
|
39
33
|
app_id,
|
40
|
-
client,
|
41
|
-
environment_name=environment_name,
|
42
34
|
function_ids=dict(app_layout.function_ids),
|
43
35
|
class_ids=dict(app_layout.class_ids),
|
44
36
|
object_handle_metadata=object_handle_metadata,
|
modal/sandbox.py
CHANGED
@@ -276,9 +276,9 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
276
276
|
|
277
277
|
app_id = app.app_id
|
278
278
|
app_client = app._client
|
279
|
-
elif _App.
|
280
|
-
app_id =
|
281
|
-
app_client =
|
279
|
+
elif (container_app := _App.container_app()) is not None:
|
280
|
+
app_id = container_app.app_id
|
281
|
+
app_client = container_app._client
|
282
282
|
else:
|
283
283
|
arglist = ", ".join(repr(s) for s in entrypoint_args)
|
284
284
|
deprecation_error(
|
@@ -2,7 +2,7 @@ modal/__init__.py,sha256=3NJLLHb0TRc2tc68kf8NHzORx38GbtbZvPEWDWrQ6N4,2234
|
|
2
2
|
modal/__main__.py,sha256=scYhGFqh8OJcVDo-VOxIT6CCwxOgzgflYWMnIZiMRqE,2871
|
3
3
|
modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
|
4
4
|
modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
|
5
|
-
modal/_container_entrypoint.py,sha256=
|
5
|
+
modal/_container_entrypoint.py,sha256=d4Mgwkv93Kvt92msYSNGyhH4QXhrt08wosz4WfDp0Aw,28830
|
6
6
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
7
7
|
modal/_location.py,sha256=S3lSxIU3h9HkWpkJ3Pwo0pqjIOSB1fjeSgUsY3x7eec,1202
|
8
8
|
modal/_output.py,sha256=0fWX_KQwhER--U81ys16CL-pA5A-LN20C0EZjElKGJQ,25410
|
@@ -15,11 +15,11 @@ modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
|
|
15
15
|
modal/_tunnel.py,sha256=o-jJhS4vQ6-XswDhHcJWGMZZmD03SC0e9i8fEu1JTjo,6310
|
16
16
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
17
17
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
18
|
-
modal/app.py,sha256=
|
19
|
-
modal/app.pyi,sha256=
|
18
|
+
modal/app.py,sha256=LhAdfXUfqcVvmqTC8HM-LxMlGWCW2U8Xuhb6URyj9RI,45577
|
19
|
+
modal/app.pyi,sha256=ojqaDubpV6wdhqewMe2T_AKt2RPXSG4nySZu8_lHpvc,25292
|
20
20
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
21
21
|
modal/client.py,sha256=JAnd4-GCN093BwkvOFAK5a6iy5ycxofjpUncMxlrIMw,15253
|
22
|
-
modal/client.pyi,sha256=
|
22
|
+
modal/client.pyi,sha256=tK1--wDx9xNyIcEiYHIHtti3ZVkYOuTVjeZXSRT1-HY,7278
|
23
23
|
modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
|
24
24
|
modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
|
25
25
|
modal/cls.py,sha256=3hjb0JcoPjxKZNeK22f5rR43bZRBjoRI7_EMZXY7YrE,31172
|
@@ -60,10 +60,10 @@ modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
60
|
modal/queue.py,sha256=zMUQtdAyqZzBg-2iAo3c3G54HLP7TEWfVhiQXLjewb4,18556
|
61
61
|
modal/queue.pyi,sha256=gGV97pWelSSYqMV9Bl4ys3mSP7q82fS71oqSWeAwyDE,9818
|
62
62
|
modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
|
63
|
-
modal/runner.py,sha256=
|
63
|
+
modal/runner.py,sha256=mhqgRdjD5cUDpBQIokiX7OCfVblpGV6aWmZ-WvWJgGg,24114
|
64
64
|
modal/runner.pyi,sha256=YmP4EOCNjjkwSIPi2Gl6hF_ji_ytkxz9dw3iB9KXaOI,5275
|
65
|
-
modal/running_app.py,sha256=
|
66
|
-
modal/sandbox.py,sha256=
|
65
|
+
modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
|
66
|
+
modal/sandbox.py,sha256=_r-Cj5L6BE5tOzwIUxGP99BH9EsCTupQSV3jcP61aZM,28115
|
67
67
|
modal/sandbox.pyi,sha256=k8_vHjN3oigxSCF13Cm2HfcSHuliGuSb8ryd3CGqwoA,19815
|
68
68
|
modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
|
69
69
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
@@ -78,7 +78,7 @@ modal/volume.py,sha256=T-pLxCYqmqRO6OolpAXlPxomMu0RWjti2e4kUpaj2cQ,29229
|
|
78
78
|
modal/volume.pyi,sha256=eekb2dnAAwFK_NO9ciAOOTthl8NP1iAmMFrCGgjDA2k,11100
|
79
79
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
80
80
|
modal/_runtime/asgi.py,sha256=Mjs859pSgOmtZL-YmEsSKN557v1A2Ax_5-ERgPfj55E,21920
|
81
|
-
modal/_runtime/container_io_manager.py,sha256=
|
81
|
+
modal/_runtime/container_io_manager.py,sha256=HgDLjE78yy1P7WZTmsEVDf89YnFFWG63Ddes8uYLVDY,43764
|
82
82
|
modal/_runtime/execution_context.py,sha256=E6ofm6j1POXGPxS841X3V7JU6NheVb8OkQc7JpLq4Kg,2712
|
83
83
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
84
84
|
modal/_runtime/user_code_imports.py,sha256=n4CQOojzSdf0jwSKSy6MEnVX3IWl3t3Dq54-x9VS2Ds,14663
|
@@ -165,10 +165,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
165
165
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
166
166
|
modal_version/__init__.py,sha256=N9Kh4DrM2649_INTJG4Lp3NKdux7cxGuiDtXpq_hkFY,470
|
167
167
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
168
|
-
modal_version/_version_generated.py,sha256=
|
169
|
-
modal-0.70.
|
170
|
-
modal-0.70.
|
171
|
-
modal-0.70.
|
172
|
-
modal-0.70.
|
173
|
-
modal-0.70.
|
174
|
-
modal-0.70.
|
168
|
+
modal_version/_version_generated.py,sha256=ZMPi8R_MjME99Sf5PLcfgOuAzbE-RYxPuF4CSKV1_vg,148
|
169
|
+
modal-0.70.4.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
170
|
+
modal-0.70.4.dist-info/METADATA,sha256=cQc9rstYeBi9SeZxjUL12d2OZjHF2UAua4d8C4acz3Y,2328
|
171
|
+
modal-0.70.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
172
|
+
modal-0.70.4.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
173
|
+
modal-0.70.4.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
174
|
+
modal-0.70.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|