modal 1.2.1.dev7__py3-none-any.whl → 1.2.1.dev8__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.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- modal/app.py +89 -53
- modal/app.pyi +48 -18
- modal/client.pyi +2 -2
- modal/cls.py +5 -12
- modal/runner.py +20 -30
- modal/runner.pyi +40 -24
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/METADATA +1 -1
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/RECORD +13 -13
- modal_version/__init__.py +1 -1
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/WHEEL +0 -0
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/entry_points.txt +0 -0
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/licenses/LICENSE +0 -0
- {modal-1.2.1.dev7.dist-info → modal-1.2.1.dev8.dist-info}/top_level.txt +0 -0
modal/app.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import inspect
|
|
3
3
|
import typing
|
|
4
4
|
from collections.abc import AsyncGenerator, Collection, Coroutine, Mapping, Sequence
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
from pathlib import PurePosixPath
|
|
6
7
|
from textwrap import dedent
|
|
7
8
|
from typing import (
|
|
@@ -114,6 +115,22 @@ class _FunctionDecoratorType:
|
|
|
114
115
|
def __call__(self, func): ...
|
|
115
116
|
|
|
116
117
|
|
|
118
|
+
@dataclass()
|
|
119
|
+
class _LocalAppState:
|
|
120
|
+
"""All state for apps that's part of the local/definition state"""
|
|
121
|
+
|
|
122
|
+
functions: dict[str, _Function]
|
|
123
|
+
classes: dict[str, _Cls]
|
|
124
|
+
image_default: Optional[_Image]
|
|
125
|
+
web_endpoints: list[str] # Used by the CLI
|
|
126
|
+
local_entrypoints: dict[str, _LocalEntrypoint]
|
|
127
|
+
tags: dict[str, str]
|
|
128
|
+
|
|
129
|
+
include_source_default: bool
|
|
130
|
+
secrets_default: Sequence[_Secret]
|
|
131
|
+
volumes_default: dict[Union[str, PurePosixPath], _Volume]
|
|
132
|
+
|
|
133
|
+
|
|
117
134
|
class _App:
|
|
118
135
|
"""A Modal App is a group of functions and classes that are deployed together.
|
|
119
136
|
|
|
@@ -151,23 +168,21 @@ class _App:
|
|
|
151
168
|
|
|
152
169
|
_name: Optional[str]
|
|
153
170
|
_description: Optional[str]
|
|
154
|
-
_tags: dict[str, str]
|
|
155
|
-
|
|
156
|
-
_functions: dict[str, _Function]
|
|
157
|
-
_classes: dict[str, _Cls]
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
_secrets: Sequence[_Secret]
|
|
161
|
-
_volumes: dict[Union[str, PurePosixPath], _Volume]
|
|
162
|
-
_web_endpoints: list[str] # Used by the CLI
|
|
163
|
-
_local_entrypoints: dict[str, _LocalEntrypoint]
|
|
172
|
+
_local_state_attr: Optional[_LocalAppState] = None
|
|
164
173
|
|
|
165
174
|
# Running apps only (container apps or running local)
|
|
166
175
|
_app_id: Optional[str] # Kept after app finishes
|
|
167
176
|
_running_app: Optional[RunningApp] # Various app info
|
|
168
177
|
_client: Optional[_Client]
|
|
169
178
|
|
|
170
|
-
|
|
179
|
+
@property
|
|
180
|
+
def _local_state(self) -> _LocalAppState:
|
|
181
|
+
"""For internal use only. Do not use this property directly."""
|
|
182
|
+
|
|
183
|
+
if self._local_state_attr is None:
|
|
184
|
+
raise AttributeError("Local state is not initialized - app is not locally available")
|
|
185
|
+
return self._local_state_attr
|
|
171
186
|
|
|
172
187
|
def __init__(
|
|
173
188
|
self,
|
|
@@ -196,8 +211,6 @@ class _App:
|
|
|
196
211
|
|
|
197
212
|
self._name = name
|
|
198
213
|
self._description = name
|
|
199
|
-
self._tags = tags or {}
|
|
200
|
-
self._include_source_default = include_source
|
|
201
214
|
|
|
202
215
|
check_sequence(secrets, _Secret, "`secrets=` has to be a list or tuple of `modal.Secret` objects")
|
|
203
216
|
validate_volumes(volumes)
|
|
@@ -205,16 +218,24 @@ class _App:
|
|
|
205
218
|
if image is not None and not isinstance(image, _Image):
|
|
206
219
|
raise InvalidError("`image=` has to be a `modal.Image` object")
|
|
207
220
|
|
|
208
|
-
self.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
self._local_state_attr = _LocalAppState(
|
|
222
|
+
functions={},
|
|
223
|
+
classes={},
|
|
224
|
+
image_default=image,
|
|
225
|
+
secrets_default=secrets,
|
|
226
|
+
volumes_default=volumes,
|
|
227
|
+
include_source_default=include_source,
|
|
228
|
+
web_endpoints=[],
|
|
229
|
+
local_entrypoints={},
|
|
230
|
+
tags=tags or {},
|
|
231
|
+
)
|
|
215
232
|
|
|
233
|
+
# Running apps only
|
|
216
234
|
self._app_id = None
|
|
217
235
|
self._running_app = None # Set inside container, OR during the time an app is running locally
|
|
236
|
+
|
|
237
|
+
# Client is special - needed to be set just before the app is "hydrated" or running at the latest
|
|
238
|
+
# Guaranteed to be set for running apps, but also needed to actually *hydrate* the app and make it running
|
|
218
239
|
self._client = None
|
|
219
240
|
|
|
220
241
|
# Register this app. This is used to look up the app in the container, when we can't get it from the function
|
|
@@ -283,7 +304,8 @@ class _App:
|
|
|
283
304
|
|
|
284
305
|
response = await retry_transient_errors(client.stub.AppGetOrCreate, request)
|
|
285
306
|
|
|
286
|
-
app = _App(name)
|
|
307
|
+
app = _App(name) # TODO: this should probably be a distinct constructor, possibly even a distinct type
|
|
308
|
+
app._local_state_attr = None # this is not a locally defined App, so no local state
|
|
287
309
|
app._app_id = response.app_id
|
|
288
310
|
app._client = client
|
|
289
311
|
app._running_app = RunningApp(response.app_id, interactive=False)
|
|
@@ -310,18 +332,19 @@ class _App:
|
|
|
310
332
|
App that is retrieved via `modal.App.lookup`. It is likely to be deprecated in the future.
|
|
311
333
|
|
|
312
334
|
"""
|
|
313
|
-
return self.
|
|
335
|
+
return self._local_state.image_default
|
|
314
336
|
|
|
315
337
|
@image.setter
|
|
316
338
|
def image(self, value):
|
|
317
339
|
"""mdmd:hidden"""
|
|
318
|
-
self.
|
|
340
|
+
self._local_state.image_default = value
|
|
319
341
|
|
|
320
342
|
def _uncreate_all_objects(self):
|
|
321
343
|
# TODO(erikbern): this doesn't unhydrate objects that aren't tagged
|
|
322
|
-
|
|
344
|
+
local_state = self._local_state
|
|
345
|
+
for obj in local_state.functions.values():
|
|
323
346
|
obj._unhydrate()
|
|
324
|
-
for obj in
|
|
347
|
+
for obj in local_state.classes.values():
|
|
325
348
|
obj._unhydrate()
|
|
326
349
|
|
|
327
350
|
@asynccontextmanager
|
|
@@ -457,8 +480,9 @@ class _App:
|
|
|
457
480
|
return self
|
|
458
481
|
|
|
459
482
|
def _get_default_image(self):
|
|
460
|
-
|
|
461
|
-
|
|
483
|
+
local_state = self._local_state
|
|
484
|
+
if local_state.image_default:
|
|
485
|
+
return local_state.image_default
|
|
462
486
|
else:
|
|
463
487
|
return _default_image
|
|
464
488
|
|
|
@@ -473,7 +497,8 @@ class _App:
|
|
|
473
497
|
return [m for m in all_mounts if m.is_local()]
|
|
474
498
|
|
|
475
499
|
def _add_function(self, function: _Function, is_web_endpoint: bool):
|
|
476
|
-
|
|
500
|
+
local_state = self._local_state
|
|
501
|
+
if old_function := local_state.functions.get(function.tag, None):
|
|
477
502
|
if old_function is function:
|
|
478
503
|
return # already added the same exact instance, ignore
|
|
479
504
|
|
|
@@ -484,7 +509,7 @@ class _App:
|
|
|
484
509
|
f"[{old_function._info.module_name}].{old_function._info.function_name}"
|
|
485
510
|
f" with new function [{function._info.module_name}].{function._info.function_name}"
|
|
486
511
|
)
|
|
487
|
-
if function.tag in
|
|
512
|
+
if function.tag in local_state.classes:
|
|
488
513
|
logger.warning(f"Warning: tag {function.tag} exists but is overridden by function")
|
|
489
514
|
|
|
490
515
|
if self._running_app:
|
|
@@ -495,9 +520,9 @@ class _App:
|
|
|
495
520
|
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
|
496
521
|
function._hydrate(object_id, self._client, metadata)
|
|
497
522
|
|
|
498
|
-
|
|
523
|
+
local_state.functions[function.tag] = function
|
|
499
524
|
if is_web_endpoint:
|
|
500
|
-
|
|
525
|
+
local_state.web_endpoints.append(function.tag)
|
|
501
526
|
|
|
502
527
|
def _add_class(self, tag: str, cls: _Cls):
|
|
503
528
|
if self._running_app:
|
|
@@ -508,7 +533,7 @@ class _App:
|
|
|
508
533
|
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
|
509
534
|
cls._hydrate(object_id, self._client, metadata)
|
|
510
535
|
|
|
511
|
-
self.
|
|
536
|
+
self._local_state.classes[tag] = cls
|
|
512
537
|
|
|
513
538
|
def _init_container(self, client: _Client, running_app: RunningApp):
|
|
514
539
|
self._app_id = running_app.app_id
|
|
@@ -516,18 +541,18 @@ class _App:
|
|
|
516
541
|
self._client = client
|
|
517
542
|
|
|
518
543
|
_App._container_app = self
|
|
519
|
-
|
|
544
|
+
local_state = self._local_state
|
|
520
545
|
# Hydrate function objects
|
|
521
546
|
for tag, object_id in running_app.function_ids.items():
|
|
522
|
-
if tag in
|
|
523
|
-
obj =
|
|
547
|
+
if tag in local_state.functions:
|
|
548
|
+
obj = local_state.functions[tag]
|
|
524
549
|
handle_metadata = running_app.object_handle_metadata[object_id]
|
|
525
550
|
obj._hydrate(object_id, client, handle_metadata)
|
|
526
551
|
|
|
527
552
|
# Hydrate class objects
|
|
528
553
|
for tag, object_id in running_app.class_ids.items():
|
|
529
|
-
if tag in
|
|
530
|
-
obj =
|
|
554
|
+
if tag in local_state.classes:
|
|
555
|
+
obj = local_state.classes[tag]
|
|
531
556
|
handle_metadata = running_app.object_handle_metadata[object_id]
|
|
532
557
|
obj._hydrate(object_id, client, handle_metadata)
|
|
533
558
|
|
|
@@ -541,7 +566,7 @@ class _App:
|
|
|
541
566
|
This method is likely to be deprecated in the future in favor of a different
|
|
542
567
|
approach for retrieving the layout of a deployed App.
|
|
543
568
|
"""
|
|
544
|
-
return self.
|
|
569
|
+
return self._local_state.functions
|
|
545
570
|
|
|
546
571
|
@property
|
|
547
572
|
def registered_classes(self) -> dict[str, _Cls]:
|
|
@@ -553,7 +578,7 @@ class _App:
|
|
|
553
578
|
This method is likely to be deprecated in the future in favor of a different
|
|
554
579
|
approach for retrieving the layout of a deployed App.
|
|
555
580
|
"""
|
|
556
|
-
return self.
|
|
581
|
+
return self._local_state.classes
|
|
557
582
|
|
|
558
583
|
@property
|
|
559
584
|
def registered_entrypoints(self) -> dict[str, _LocalEntrypoint]:
|
|
@@ -564,7 +589,7 @@ class _App:
|
|
|
564
589
|
expected to work when a deplyoed App has been retrieved via `modal.App.lookup`.
|
|
565
590
|
This method is likely to be deprecated in the future.
|
|
566
591
|
"""
|
|
567
|
-
return self.
|
|
592
|
+
return self._local_state.local_entrypoints
|
|
568
593
|
|
|
569
594
|
@property
|
|
570
595
|
def registered_web_endpoints(self) -> list[str]:
|
|
@@ -576,7 +601,7 @@ class _App:
|
|
|
576
601
|
This method is likely to be deprecated in the future in favor of a different
|
|
577
602
|
approach for retrieving the layout of a deployed App.
|
|
578
603
|
"""
|
|
579
|
-
return self.
|
|
604
|
+
return self._local_state.web_endpoints
|
|
580
605
|
|
|
581
606
|
def local_entrypoint(
|
|
582
607
|
self, _warn_parentheses_missing: Any = None, *, name: Optional[str] = None
|
|
@@ -637,10 +662,11 @@ class _App:
|
|
|
637
662
|
def wrapped(raw_f: Callable[..., Any]) -> _LocalEntrypoint:
|
|
638
663
|
info = FunctionInfo(raw_f)
|
|
639
664
|
tag = name if name is not None else raw_f.__qualname__
|
|
640
|
-
|
|
665
|
+
local_state = self._local_state
|
|
666
|
+
if tag in local_state.local_entrypoints:
|
|
641
667
|
# TODO: get rid of this limitation.
|
|
642
668
|
raise InvalidError(f"Duplicate local entrypoint name: {tag}. Local entrypoint names must be unique.")
|
|
643
|
-
entrypoint =
|
|
669
|
+
entrypoint = local_state.local_entrypoints[tag] = _LocalEntrypoint(info, self)
|
|
644
670
|
return entrypoint
|
|
645
671
|
|
|
646
672
|
return wrapped
|
|
@@ -732,7 +758,8 @@ class _App:
|
|
|
732
758
|
secrets = secrets or []
|
|
733
759
|
if env:
|
|
734
760
|
secrets = [*secrets, _Secret.from_dict(env)]
|
|
735
|
-
|
|
761
|
+
local_state = self._local_state
|
|
762
|
+
secrets = [*local_state.secrets_default, *secrets]
|
|
736
763
|
|
|
737
764
|
def wrapped(
|
|
738
765
|
f: Union[_PartialFunction, Callable[..., Any], None],
|
|
@@ -840,7 +867,7 @@ class _App:
|
|
|
840
867
|
is_generator=is_generator,
|
|
841
868
|
gpu=gpu,
|
|
842
869
|
network_file_systems=network_file_systems,
|
|
843
|
-
volumes={**
|
|
870
|
+
volumes={**local_state.volumes_default, **volumes},
|
|
844
871
|
cpu=cpu,
|
|
845
872
|
memory=memory,
|
|
846
873
|
ephemeral_disk=ephemeral_disk,
|
|
@@ -866,7 +893,7 @@ class _App:
|
|
|
866
893
|
i6pn_enabled=i6pn_enabled,
|
|
867
894
|
cluster_size=cluster_size, # Experimental: Clustered functions
|
|
868
895
|
rdma=rdma,
|
|
869
|
-
include_source=include_source if include_source is not None else
|
|
896
|
+
include_source=include_source if include_source is not None else local_state.include_source_default,
|
|
870
897
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
871
898
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
872
899
|
restrict_output=_experimental_restrict_output,
|
|
@@ -963,6 +990,7 @@ class _App:
|
|
|
963
990
|
secrets = [*secrets, _Secret.from_dict(env)]
|
|
964
991
|
|
|
965
992
|
def wrapper(wrapped_cls: Union[CLS_T, _PartialFunction]) -> CLS_T:
|
|
993
|
+
local_state = self._local_state
|
|
966
994
|
# Check if the decorated object is a class
|
|
967
995
|
if isinstance(wrapped_cls, _PartialFunction):
|
|
968
996
|
wrapped_cls.registered = True
|
|
@@ -1029,10 +1057,10 @@ class _App:
|
|
|
1029
1057
|
info,
|
|
1030
1058
|
app=self,
|
|
1031
1059
|
image=image or self._get_default_image(),
|
|
1032
|
-
secrets=[*
|
|
1060
|
+
secrets=[*local_state.secrets_default, *secrets],
|
|
1033
1061
|
gpu=gpu,
|
|
1034
1062
|
network_file_systems=network_file_systems,
|
|
1035
|
-
volumes={**
|
|
1063
|
+
volumes={**local_state.volumes_default, **volumes},
|
|
1036
1064
|
cpu=cpu,
|
|
1037
1065
|
memory=memory,
|
|
1038
1066
|
ephemeral_disk=ephemeral_disk,
|
|
@@ -1057,7 +1085,7 @@ class _App:
|
|
|
1057
1085
|
i6pn_enabled=i6pn_enabled,
|
|
1058
1086
|
cluster_size=cluster_size,
|
|
1059
1087
|
rdma=rdma,
|
|
1060
|
-
include_source=include_source if include_source is not None else
|
|
1088
|
+
include_source=include_source if include_source is not None else local_state.include_source_default,
|
|
1061
1089
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
1062
1090
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
1063
1091
|
_experimental_custom_scaling_factor=_experimental_custom_scaling_factor,
|
|
@@ -1067,6 +1095,11 @@ class _App:
|
|
|
1067
1095
|
self._add_function(cls_func, is_web_endpoint=False)
|
|
1068
1096
|
|
|
1069
1097
|
cls: _Cls = _Cls.from_local(user_cls, self, cls_func)
|
|
1098
|
+
for method_name, partial_function in cls._method_partials.items():
|
|
1099
|
+
if partial_function.params.webhook_config is not None:
|
|
1100
|
+
full_name = f"{user_cls.__name__}.{method_name}"
|
|
1101
|
+
local_state.web_endpoints.append(full_name)
|
|
1102
|
+
partial_function.registered = True
|
|
1070
1103
|
|
|
1071
1104
|
tag: str = user_cls.__name__
|
|
1072
1105
|
self._add_class(tag, cls)
|
|
@@ -1102,11 +1135,14 @@ class _App:
|
|
|
1102
1135
|
(with this App's tags taking precedence in the case of conflicts).
|
|
1103
1136
|
|
|
1104
1137
|
"""
|
|
1105
|
-
|
|
1138
|
+
other_app_local_state = other_app._local_state
|
|
1139
|
+
this_local_state = self._local_state
|
|
1140
|
+
|
|
1141
|
+
for tag, function in other_app_local_state.functions.items():
|
|
1106
1142
|
self._add_function(function, False) # TODO(erikbern): webhook config?
|
|
1107
1143
|
|
|
1108
|
-
for tag, cls in
|
|
1109
|
-
existing_cls =
|
|
1144
|
+
for tag, cls in other_app_local_state.classes.items():
|
|
1145
|
+
existing_cls = this_local_state.classes.get(tag)
|
|
1110
1146
|
if existing_cls and existing_cls != cls:
|
|
1111
1147
|
logger.warning(
|
|
1112
1148
|
f"Named app class {tag} with existing value {existing_cls} is being "
|
|
@@ -1116,7 +1152,7 @@ class _App:
|
|
|
1116
1152
|
self._add_class(tag, cls)
|
|
1117
1153
|
|
|
1118
1154
|
if inherit_tags:
|
|
1119
|
-
|
|
1155
|
+
this_local_state.tags = {**other_app_local_state.tags, **this_local_state.tags}
|
|
1120
1156
|
|
|
1121
1157
|
return self
|
|
1122
1158
|
|
|
@@ -1132,7 +1168,7 @@ class _App:
|
|
|
1132
1168
|
|
|
1133
1169
|
"""
|
|
1134
1170
|
# Note that we are requiring the App to be "running" before we set the tags.
|
|
1135
|
-
# Alternatively, we could hold onto the tags (i.e. in `self.
|
|
1171
|
+
# Alternatively, we could hold onto the tags (i.e. in `self._local_state.tags`) and then pass
|
|
1136
1172
|
# then up when AppPublish gets called. I'm not certain we want to support it, though.
|
|
1137
1173
|
# It might not be obvious to users that `.set_tags()` is eager and has immediate effect
|
|
1138
1174
|
# when the App is running, but lazy (and potentially ignored) otherwise. There would be
|
modal/app.pyi
CHANGED
|
@@ -74,6 +74,42 @@ class _FunctionDecoratorType:
|
|
|
74
74
|
self, func: collections.abc.Callable[P, ReturnType]
|
|
75
75
|
) -> modal.functions.Function[P, ReturnType, ReturnType]: ...
|
|
76
76
|
|
|
77
|
+
class _LocalAppState:
|
|
78
|
+
"""All state for apps that's part of the local/definition state"""
|
|
79
|
+
|
|
80
|
+
functions: dict[str, modal._functions._Function]
|
|
81
|
+
classes: dict[str, modal.cls._Cls]
|
|
82
|
+
image_default: typing.Optional[modal.image._Image]
|
|
83
|
+
web_endpoints: list[str]
|
|
84
|
+
local_entrypoints: dict[str, _LocalEntrypoint]
|
|
85
|
+
tags: dict[str, str]
|
|
86
|
+
include_source_default: bool
|
|
87
|
+
secrets_default: collections.abc.Sequence[modal.secret._Secret]
|
|
88
|
+
volumes_default: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
|
|
89
|
+
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
functions: dict[str, modal._functions._Function],
|
|
93
|
+
classes: dict[str, modal.cls._Cls],
|
|
94
|
+
image_default: typing.Optional[modal.image._Image],
|
|
95
|
+
web_endpoints: list[str],
|
|
96
|
+
local_entrypoints: dict[str, _LocalEntrypoint],
|
|
97
|
+
tags: dict[str, str],
|
|
98
|
+
include_source_default: bool,
|
|
99
|
+
secrets_default: collections.abc.Sequence[modal.secret._Secret],
|
|
100
|
+
volumes_default: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume],
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
def __repr__(self):
|
|
106
|
+
"""Return repr(self)."""
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
def __eq__(self, other):
|
|
110
|
+
"""Return self==value."""
|
|
111
|
+
...
|
|
112
|
+
|
|
77
113
|
class _App:
|
|
78
114
|
"""A Modal App is a group of functions and classes that are deployed together.
|
|
79
115
|
|
|
@@ -110,18 +146,15 @@ class _App:
|
|
|
110
146
|
_container_app: typing.ClassVar[typing.Optional[_App]]
|
|
111
147
|
_name: typing.Optional[str]
|
|
112
148
|
_description: typing.Optional[str]
|
|
113
|
-
|
|
114
|
-
_functions: dict[str, modal._functions._Function]
|
|
115
|
-
_classes: dict[str, modal.cls._Cls]
|
|
116
|
-
_image: typing.Optional[modal.image._Image]
|
|
117
|
-
_secrets: collections.abc.Sequence[modal.secret._Secret]
|
|
118
|
-
_volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
|
|
119
|
-
_web_endpoints: list[str]
|
|
120
|
-
_local_entrypoints: dict[str, _LocalEntrypoint]
|
|
149
|
+
_local_state_attr: typing.Optional[_LocalAppState]
|
|
121
150
|
_app_id: typing.Optional[str]
|
|
122
151
|
_running_app: typing.Optional[modal.running_app.RunningApp]
|
|
123
152
|
_client: typing.Optional[modal.client._Client]
|
|
124
|
-
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def _local_state(self) -> _LocalAppState:
|
|
156
|
+
"""For internal use only. Do not use this property directly."""
|
|
157
|
+
...
|
|
125
158
|
|
|
126
159
|
def __init__(
|
|
127
160
|
self,
|
|
@@ -630,18 +663,10 @@ class App:
|
|
|
630
663
|
_container_app: typing.ClassVar[typing.Optional[App]]
|
|
631
664
|
_name: typing.Optional[str]
|
|
632
665
|
_description: typing.Optional[str]
|
|
633
|
-
|
|
634
|
-
_functions: dict[str, modal.functions.Function]
|
|
635
|
-
_classes: dict[str, modal.cls.Cls]
|
|
636
|
-
_image: typing.Optional[modal.image.Image]
|
|
637
|
-
_secrets: collections.abc.Sequence[modal.secret.Secret]
|
|
638
|
-
_volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume]
|
|
639
|
-
_web_endpoints: list[str]
|
|
640
|
-
_local_entrypoints: dict[str, LocalEntrypoint]
|
|
666
|
+
_local_state_attr: typing.Optional[_LocalAppState]
|
|
641
667
|
_app_id: typing.Optional[str]
|
|
642
668
|
_running_app: typing.Optional[modal.running_app.RunningApp]
|
|
643
669
|
_client: typing.Optional[modal.client.Client]
|
|
644
|
-
_include_source_default: typing.Optional[bool]
|
|
645
670
|
|
|
646
671
|
def __init__(
|
|
647
672
|
self,
|
|
@@ -664,6 +689,11 @@ class App:
|
|
|
664
689
|
"""
|
|
665
690
|
...
|
|
666
691
|
|
|
692
|
+
@property
|
|
693
|
+
def _local_state(self) -> _LocalAppState:
|
|
694
|
+
"""For internal use only. Do not use this property directly."""
|
|
695
|
+
...
|
|
696
|
+
|
|
667
697
|
@property
|
|
668
698
|
def name(self) -> typing.Optional[str]:
|
|
669
699
|
"""The user-provided name of the App."""
|
modal/client.pyi
CHANGED
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.2.1.
|
|
36
|
+
version: str = "1.2.1.dev8",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.2.1.
|
|
167
|
+
version: str = "1.2.1.dev8",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
modal/cls.py
CHANGED
|
@@ -577,22 +577,15 @@ More information on class parameterization can be found here: https://modal.com/
|
|
|
577
577
|
# validate signature
|
|
578
578
|
_Cls.validate_construction_mechanism(user_cls)
|
|
579
579
|
|
|
580
|
-
method_partials: dict[str, _PartialFunction] = _find_partial_methods_for_user_cls(
|
|
581
|
-
user_cls, _PartialFunctionFlags.interface_flags()
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
for method_name, partial_function in method_partials.items():
|
|
585
|
-
if partial_function.params.webhook_config is not None:
|
|
586
|
-
full_name = f"{user_cls.__name__}.{method_name}"
|
|
587
|
-
app._web_endpoints.append(full_name)
|
|
588
|
-
partial_function.registered = True
|
|
589
|
-
|
|
590
580
|
# Disable the warning that lifecycle methods are not wrapped
|
|
591
|
-
|
|
581
|
+
lifecycle_method_partials = _find_partial_methods_for_user_cls(
|
|
592
582
|
user_cls, ~_PartialFunctionFlags.interface_flags()
|
|
593
|
-
)
|
|
583
|
+
)
|
|
584
|
+
for partial_function in lifecycle_method_partials.values():
|
|
594
585
|
partial_function.registered = True
|
|
595
586
|
|
|
587
|
+
method_partials = _find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.interface_flags())
|
|
588
|
+
|
|
596
589
|
# Get all callables
|
|
597
590
|
callables: dict[str, Callable] = {
|
|
598
591
|
k: pf.raw_f
|
modal/runner.py
CHANGED
|
@@ -43,9 +43,7 @@ from .secret import _Secret
|
|
|
43
43
|
from .stream_type import StreamType
|
|
44
44
|
|
|
45
45
|
if TYPE_CHECKING:
|
|
46
|
-
|
|
47
|
-
else:
|
|
48
|
-
_App = TypeVar("_App")
|
|
46
|
+
import modal.app
|
|
49
47
|
|
|
50
48
|
|
|
51
49
|
V = TypeVar("V")
|
|
@@ -126,12 +124,11 @@ async def _init_local_app_from_name(
|
|
|
126
124
|
async def _create_all_objects(
|
|
127
125
|
client: _Client,
|
|
128
126
|
running_app: RunningApp,
|
|
129
|
-
|
|
130
|
-
classes: dict[str, _Cls],
|
|
127
|
+
local_app_state: "modal.app._LocalAppState",
|
|
131
128
|
environment_name: str,
|
|
132
129
|
) -> None:
|
|
133
130
|
"""Create objects that have been defined but not created on the server."""
|
|
134
|
-
indexed_objects: dict[str, _Object] = {**functions, **classes}
|
|
131
|
+
indexed_objects: dict[str, _Object] = {**local_app_state.functions, **local_app_state.classes}
|
|
135
132
|
resolver = Resolver(
|
|
136
133
|
client,
|
|
137
134
|
environment_name=environment_name,
|
|
@@ -182,21 +179,19 @@ async def _publish_app(
|
|
|
182
179
|
client: _Client,
|
|
183
180
|
running_app: RunningApp,
|
|
184
181
|
app_state: int, # api_pb2.AppState.value
|
|
185
|
-
|
|
186
|
-
classes: dict[str, _Cls],
|
|
182
|
+
app_local_state: "modal.app._LocalAppState",
|
|
187
183
|
name: str = "",
|
|
188
|
-
tags: dict[str, str] = {}, # Additional App metadata
|
|
189
184
|
deployment_tag: str = "", # Only relevant for deployments
|
|
190
185
|
commit_info: Optional[api_pb2.CommitInfo] = None, # Git commit information
|
|
191
186
|
) -> tuple[str, list[api_pb2.Warning]]:
|
|
192
187
|
"""Wrapper for AppPublish RPC."""
|
|
193
|
-
|
|
188
|
+
functions = app_local_state.functions
|
|
194
189
|
definition_ids = {obj.object_id: obj._get_metadata().definition_id for obj in functions.values()} # type: ignore
|
|
195
190
|
|
|
196
191
|
request = api_pb2.AppPublishRequest(
|
|
197
192
|
app_id=running_app.app_id,
|
|
198
193
|
name=name,
|
|
199
|
-
tags=tags,
|
|
194
|
+
tags=app_local_state.tags,
|
|
200
195
|
deployment_tag=deployment_tag,
|
|
201
196
|
commit_info=commit_info,
|
|
202
197
|
app_state=app_state, # type: ignore : should be a api_pb2.AppState.value
|
|
@@ -260,13 +255,13 @@ async def _status_based_disconnect(client: _Client, app_id: str, exc_info: Optio
|
|
|
260
255
|
|
|
261
256
|
@asynccontextmanager
|
|
262
257
|
async def _run_app(
|
|
263
|
-
app: _App,
|
|
258
|
+
app: "modal.app._App",
|
|
264
259
|
*,
|
|
265
260
|
client: Optional[_Client] = None,
|
|
266
261
|
detach: bool = False,
|
|
267
262
|
environment_name: Optional[str] = None,
|
|
268
263
|
interactive: bool = False,
|
|
269
|
-
) -> AsyncGenerator[_App, None]:
|
|
264
|
+
) -> AsyncGenerator["modal.app._App", None]:
|
|
270
265
|
"""mdmd:hidden"""
|
|
271
266
|
if environment_name is None:
|
|
272
267
|
environment_name = typing.cast(str, config.get("environment"))
|
|
@@ -338,12 +333,13 @@ async def _run_app(
|
|
|
338
333
|
get_app_logs_loop(client, output_mgr, app_id=running_app.app_id, app_logs_url=running_app.app_logs_url)
|
|
339
334
|
)
|
|
340
335
|
|
|
336
|
+
local_app_state = app._local_state
|
|
341
337
|
try:
|
|
342
338
|
# Create all members
|
|
343
|
-
await _create_all_objects(client, running_app,
|
|
339
|
+
await _create_all_objects(client, running_app, local_app_state, environment_name)
|
|
344
340
|
|
|
345
341
|
# Publish the app
|
|
346
|
-
await _publish_app(client, running_app, app_state,
|
|
342
|
+
await _publish_app(client, running_app, app_state, local_app_state)
|
|
347
343
|
except asyncio.CancelledError as e:
|
|
348
344
|
# this typically happens on sigint/ctrl-C during setup (the KeyboardInterrupt happens in the main thread)
|
|
349
345
|
if output_mgr := _get_output_manager():
|
|
@@ -440,7 +436,7 @@ async def _run_app(
|
|
|
440
436
|
|
|
441
437
|
|
|
442
438
|
async def _serve_update(
|
|
443
|
-
app: _App,
|
|
439
|
+
app: "modal.app._App",
|
|
444
440
|
existing_app_id: str,
|
|
445
441
|
is_ready: Event,
|
|
446
442
|
environment_name: str,
|
|
@@ -450,13 +446,12 @@ async def _serve_update(
|
|
|
450
446
|
client = await _Client.from_env()
|
|
451
447
|
try:
|
|
452
448
|
running_app: RunningApp = await _init_local_app_existing(client, existing_app_id, environment_name)
|
|
453
|
-
|
|
449
|
+
local_app_state = app._local_state
|
|
454
450
|
# Create objects
|
|
455
451
|
await _create_all_objects(
|
|
456
452
|
client,
|
|
457
453
|
running_app,
|
|
458
|
-
|
|
459
|
-
app._classes,
|
|
454
|
+
local_app_state,
|
|
460
455
|
environment_name,
|
|
461
456
|
)
|
|
462
457
|
|
|
@@ -465,9 +460,7 @@ async def _serve_update(
|
|
|
465
460
|
client,
|
|
466
461
|
running_app,
|
|
467
462
|
app_state=api_pb2.APP_STATE_UNSPECIFIED,
|
|
468
|
-
|
|
469
|
-
classes=app._classes,
|
|
470
|
-
tags=app._tags,
|
|
463
|
+
app_local_state=local_app_state,
|
|
471
464
|
)
|
|
472
465
|
|
|
473
466
|
# Communicate to the parent process
|
|
@@ -488,7 +481,7 @@ class DeployResult:
|
|
|
488
481
|
|
|
489
482
|
|
|
490
483
|
async def _deploy_app(
|
|
491
|
-
app: _App,
|
|
484
|
+
app: "modal.app._App",
|
|
492
485
|
name: Optional[str] = None,
|
|
493
486
|
namespace: Any = None, # mdmd:line-hidden
|
|
494
487
|
client: Optional[_Client] = None,
|
|
@@ -546,8 +539,7 @@ async def _deploy_app(
|
|
|
546
539
|
await _create_all_objects(
|
|
547
540
|
client,
|
|
548
541
|
running_app,
|
|
549
|
-
app.
|
|
550
|
-
app._classes,
|
|
542
|
+
app._local_state,
|
|
551
543
|
environment_name=environment_name,
|
|
552
544
|
)
|
|
553
545
|
|
|
@@ -560,11 +552,9 @@ async def _deploy_app(
|
|
|
560
552
|
app_url, warnings = await _publish_app(
|
|
561
553
|
client,
|
|
562
554
|
running_app,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
classes=app._classes,
|
|
555
|
+
api_pb2.APP_STATE_DEPLOYED,
|
|
556
|
+
app._local_state,
|
|
566
557
|
name=name,
|
|
567
|
-
tags=app._tags,
|
|
568
558
|
deployment_tag=tag,
|
|
569
559
|
commit_info=commit_info,
|
|
570
560
|
)
|
|
@@ -586,7 +576,7 @@ async def _deploy_app(
|
|
|
586
576
|
|
|
587
577
|
|
|
588
578
|
async def _interactive_shell(
|
|
589
|
-
_app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: Any
|
|
579
|
+
_app: "modal.app._App", cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: Any
|
|
590
580
|
) -> None:
|
|
591
581
|
"""Run an interactive shell (like `bash`) within the image for this app.
|
|
592
582
|
|
modal/runner.pyi
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import modal.
|
|
1
|
+
import modal.app
|
|
2
2
|
import modal.client
|
|
3
|
-
import modal.cls
|
|
4
3
|
import modal.running_app
|
|
5
4
|
import modal_proto.api_pb2
|
|
6
5
|
import multiprocessing.synchronize
|
|
@@ -8,8 +7,6 @@ import synchronicity.combined_types
|
|
|
8
7
|
import typing
|
|
9
8
|
import typing_extensions
|
|
10
9
|
|
|
11
|
-
_App = typing.TypeVar("_App")
|
|
12
|
-
|
|
13
10
|
V = typing.TypeVar("V")
|
|
14
11
|
|
|
15
12
|
async def _heartbeat(client: modal.client._Client, app_id: str) -> None: ...
|
|
@@ -29,8 +26,7 @@ async def _init_local_app_from_name(
|
|
|
29
26
|
async def _create_all_objects(
|
|
30
27
|
client: modal.client._Client,
|
|
31
28
|
running_app: modal.running_app.RunningApp,
|
|
32
|
-
|
|
33
|
-
classes: dict[str, modal.cls._Cls],
|
|
29
|
+
local_app_state: modal.app._LocalAppState,
|
|
34
30
|
environment_name: str,
|
|
35
31
|
) -> None:
|
|
36
32
|
"""Create objects that have been defined but not created on the server."""
|
|
@@ -40,10 +36,8 @@ async def _publish_app(
|
|
|
40
36
|
client: modal.client._Client,
|
|
41
37
|
running_app: modal.running_app.RunningApp,
|
|
42
38
|
app_state: int,
|
|
43
|
-
|
|
44
|
-
classes: dict[str, modal.cls._Cls],
|
|
39
|
+
app_local_state: modal.app._LocalAppState,
|
|
45
40
|
name: str = "",
|
|
46
|
-
tags: dict[str, str] = {},
|
|
47
41
|
deployment_tag: str = "",
|
|
48
42
|
commit_info: typing.Optional[modal_proto.api_pb2.CommitInfo] = None,
|
|
49
43
|
) -> tuple[str, list[modal_proto.api_pb2.Warning]]:
|
|
@@ -66,18 +60,18 @@ async def _status_based_disconnect(
|
|
|
66
60
|
...
|
|
67
61
|
|
|
68
62
|
def _run_app(
|
|
69
|
-
app: _App,
|
|
63
|
+
app: modal.app._App,
|
|
70
64
|
*,
|
|
71
65
|
client: typing.Optional[modal.client._Client] = None,
|
|
72
66
|
detach: bool = False,
|
|
73
67
|
environment_name: typing.Optional[str] = None,
|
|
74
68
|
interactive: bool = False,
|
|
75
|
-
) -> typing.AsyncContextManager[_App]:
|
|
69
|
+
) -> typing.AsyncContextManager[modal.app._App]:
|
|
76
70
|
"""mdmd:hidden"""
|
|
77
71
|
...
|
|
78
72
|
|
|
79
73
|
async def _serve_update(
|
|
80
|
-
app: _App, existing_app_id: str, is_ready: multiprocessing.synchronize.Event, environment_name: str
|
|
74
|
+
app: modal.app._App, existing_app_id: str, is_ready: multiprocessing.synchronize.Event, environment_name: str
|
|
81
75
|
) -> None:
|
|
82
76
|
"""mdmd:hidden"""
|
|
83
77
|
...
|
|
@@ -115,7 +109,7 @@ class DeployResult:
|
|
|
115
109
|
...
|
|
116
110
|
|
|
117
111
|
async def _deploy_app(
|
|
118
|
-
app: _App,
|
|
112
|
+
app: modal.app._App,
|
|
119
113
|
name: typing.Optional[str] = None,
|
|
120
114
|
namespace: typing.Any = None,
|
|
121
115
|
client: typing.Optional[modal.client._Client] = None,
|
|
@@ -129,7 +123,7 @@ async def _deploy_app(
|
|
|
129
123
|
...
|
|
130
124
|
|
|
131
125
|
async def _interactive_shell(
|
|
132
|
-
_app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
|
|
126
|
+
_app: modal.app._App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
|
|
133
127
|
) -> None:
|
|
134
128
|
"""Run an interactive shell (like `bash`) within the image for this app.
|
|
135
129
|
|
|
@@ -159,26 +153,26 @@ class __run_app_spec(typing_extensions.Protocol):
|
|
|
159
153
|
def __call__(
|
|
160
154
|
self,
|
|
161
155
|
/,
|
|
162
|
-
app:
|
|
156
|
+
app: modal.app.App,
|
|
163
157
|
*,
|
|
164
158
|
client: typing.Optional[modal.client.Client] = None,
|
|
165
159
|
detach: bool = False,
|
|
166
160
|
environment_name: typing.Optional[str] = None,
|
|
167
161
|
interactive: bool = False,
|
|
168
|
-
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[
|
|
162
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[modal.app.App]:
|
|
169
163
|
"""mdmd:hidden"""
|
|
170
164
|
...
|
|
171
165
|
|
|
172
166
|
def aio(
|
|
173
167
|
self,
|
|
174
168
|
/,
|
|
175
|
-
app:
|
|
169
|
+
app: modal.app.App,
|
|
176
170
|
*,
|
|
177
171
|
client: typing.Optional[modal.client.Client] = None,
|
|
178
172
|
detach: bool = False,
|
|
179
173
|
environment_name: typing.Optional[str] = None,
|
|
180
174
|
interactive: bool = False,
|
|
181
|
-
) -> typing.AsyncContextManager[
|
|
175
|
+
) -> typing.AsyncContextManager[modal.app.App]:
|
|
182
176
|
"""mdmd:hidden"""
|
|
183
177
|
...
|
|
184
178
|
|
|
@@ -186,13 +180,23 @@ run_app: __run_app_spec
|
|
|
186
180
|
|
|
187
181
|
class __serve_update_spec(typing_extensions.Protocol):
|
|
188
182
|
def __call__(
|
|
189
|
-
self,
|
|
183
|
+
self,
|
|
184
|
+
/,
|
|
185
|
+
app: modal.app.App,
|
|
186
|
+
existing_app_id: str,
|
|
187
|
+
is_ready: multiprocessing.synchronize.Event,
|
|
188
|
+
environment_name: str,
|
|
190
189
|
) -> None:
|
|
191
190
|
"""mdmd:hidden"""
|
|
192
191
|
...
|
|
193
192
|
|
|
194
193
|
async def aio(
|
|
195
|
-
self,
|
|
194
|
+
self,
|
|
195
|
+
/,
|
|
196
|
+
app: modal.app.App,
|
|
197
|
+
existing_app_id: str,
|
|
198
|
+
is_ready: multiprocessing.synchronize.Event,
|
|
199
|
+
environment_name: str,
|
|
196
200
|
) -> None:
|
|
197
201
|
"""mdmd:hidden"""
|
|
198
202
|
...
|
|
@@ -203,7 +207,7 @@ class __deploy_app_spec(typing_extensions.Protocol):
|
|
|
203
207
|
def __call__(
|
|
204
208
|
self,
|
|
205
209
|
/,
|
|
206
|
-
app:
|
|
210
|
+
app: modal.app.App,
|
|
207
211
|
name: typing.Optional[str] = None,
|
|
208
212
|
namespace: typing.Any = None,
|
|
209
213
|
client: typing.Optional[modal.client.Client] = None,
|
|
@@ -219,7 +223,7 @@ class __deploy_app_spec(typing_extensions.Protocol):
|
|
|
219
223
|
async def aio(
|
|
220
224
|
self,
|
|
221
225
|
/,
|
|
222
|
-
app:
|
|
226
|
+
app: modal.app.App,
|
|
223
227
|
name: typing.Optional[str] = None,
|
|
224
228
|
namespace: typing.Any = None,
|
|
225
229
|
client: typing.Optional[modal.client.Client] = None,
|
|
@@ -236,7 +240,13 @@ deploy_app: __deploy_app_spec
|
|
|
236
240
|
|
|
237
241
|
class __interactive_shell_spec(typing_extensions.Protocol):
|
|
238
242
|
def __call__(
|
|
239
|
-
self,
|
|
243
|
+
self,
|
|
244
|
+
/,
|
|
245
|
+
_app: modal.app.App,
|
|
246
|
+
cmds: list[str],
|
|
247
|
+
environment_name: str = "",
|
|
248
|
+
pty: bool = True,
|
|
249
|
+
**kwargs: typing.Any,
|
|
240
250
|
) -> None:
|
|
241
251
|
"""Run an interactive shell (like `bash`) within the image for this app.
|
|
242
252
|
|
|
@@ -263,7 +273,13 @@ class __interactive_shell_spec(typing_extensions.Protocol):
|
|
|
263
273
|
...
|
|
264
274
|
|
|
265
275
|
async def aio(
|
|
266
|
-
self,
|
|
276
|
+
self,
|
|
277
|
+
/,
|
|
278
|
+
_app: modal.app.App,
|
|
279
|
+
cmds: list[str],
|
|
280
|
+
environment_name: str = "",
|
|
281
|
+
pty: bool = True,
|
|
282
|
+
**kwargs: typing.Any,
|
|
267
283
|
) -> None:
|
|
268
284
|
"""Run an interactive shell (like `bash`) within the image for this app.
|
|
269
285
|
|
|
@@ -19,15 +19,15 @@ modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
|
|
19
19
|
modal/_tunnel.pyi,sha256=rvC7USR2BcKkbZIeCJXwf7-UfGE-LPLjKsGNiK7Lxa4,13366
|
|
20
20
|
modal/_type_manager.py,sha256=DWjgmjYJuOagw2erin506UUbG2H5UzZCFEekS-7hmfA,9087
|
|
21
21
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
|
22
|
-
modal/app.py,sha256=
|
|
23
|
-
modal/app.pyi,sha256=
|
|
22
|
+
modal/app.py,sha256=tXbc6EO7ZCxphspVuqIOHOr-OKqL7De8vChDTYEAElg,54516
|
|
23
|
+
modal/app.pyi,sha256=AUV5Rp8qQrZJTP2waoKHFY7rYgsXNMYibMcCAQKuSeo,50544
|
|
24
24
|
modal/billing.py,sha256=zmQ3bcCJlwa4KD1IA_QgdWpm1pn13c-7qfy79iEauYI,195
|
|
25
25
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
|
26
26
|
modal/client.py,sha256=kyAIVB3Ay-XKJizQ_1ufUFB__EagV0MLmHJpyYyJ7J0,18636
|
|
27
|
-
modal/client.pyi,sha256=
|
|
27
|
+
modal/client.pyi,sha256=xJmCcXA-PosLDtwke2D3FfNQrdt1jVNJ_jGodXMBA8Y,15829
|
|
28
28
|
modal/cloud_bucket_mount.py,sha256=I2GRXYhOWLIz2kJZjXu75jAm9EJkBNcutGc6jR2ReUw,5928
|
|
29
29
|
modal/cloud_bucket_mount.pyi,sha256=VuUOipMIHqFXMkD-3g2bsoqpSxV5qswlFHDOqPQzYAo,7405
|
|
30
|
-
modal/cls.py,sha256=
|
|
30
|
+
modal/cls.py,sha256=ZxzivE3fNci4-A5uyBYNAzXMXtdqDg3gnYvgbdy5fhg,40384
|
|
31
31
|
modal/cls.pyi,sha256=jJsDPFoqzM4ht-V-e-xEJKJ5TINLF0fYtoBm_UeAW5Y,27281
|
|
32
32
|
modal/config.py,sha256=ZvQtKR4vACdvV-sDI-CtGepUGNMpQucwhgkGZ3k6gc0,12869
|
|
33
33
|
modal/container_process.py,sha256=Mutkl7sg_WR5zP4oJiWSC-3UdYRqp0zdKi1shZbi-bk,6996
|
|
@@ -64,8 +64,8 @@ modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
64
64
|
modal/queue.py,sha256=aaH3SNWeh_HjEyVUtFiN345v0GJFoucJ6aNDrDggWZQ,25775
|
|
65
65
|
modal/queue.pyi,sha256=mFu7GFFVFNLU9VZshnfekEsb-ABgpjdhJ07KXHvdv3A,37256
|
|
66
66
|
modal/retries.py,sha256=IvNLDM0f_GLUDD5VgEDoN09C88yoxSrCquinAuxT1Sc,5205
|
|
67
|
-
modal/runner.py,sha256=
|
|
68
|
-
modal/runner.pyi,sha256=
|
|
67
|
+
modal/runner.py,sha256=b_oG8LU8pT3NByfhwLJfYJ0RdNbnlBd-Zcds-J1JRYU,25197
|
|
68
|
+
modal/runner.pyi,sha256=DV3Z7h0owgRyOu9W5KU5O3UbRftX99KGrZQId91fpsU,8671
|
|
69
69
|
modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
|
|
70
70
|
modal/sandbox.py,sha256=R1WOFDTmg_SiG7NIEbzQMeTYHwLvX9r3j9lpINhIufc,45970
|
|
71
71
|
modal/sandbox.pyi,sha256=elVE1xEy_ZhD009oNPnCwlZi4tK-RUb1qAoxkVteG9E,50713
|
|
@@ -155,7 +155,7 @@ modal/experimental/__init__.py,sha256=9gkVuDmu3m4TlKoU3MzEtTOemUSs8EEOWba40s7Aa0
|
|
|
155
155
|
modal/experimental/flash.py,sha256=C4sef08rARYFllsgtqukFmYL18SZW0_JpMS0BejDcUs,28552
|
|
156
156
|
modal/experimental/flash.pyi,sha256=vV_OQhtdrPn8SW0XrBK-aLLHHIvxAzLzwFbWrke-m74,15463
|
|
157
157
|
modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
|
|
158
|
-
modal-1.2.1.
|
|
158
|
+
modal-1.2.1.dev8.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
159
159
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
|
160
160
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
|
161
161
|
modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
|
|
@@ -183,10 +183,10 @@ modal_proto/task_command_router_pb2.py,sha256=_pD2ZpU0bNzhwBdzmLoLyLtAtftI_Agxwn
|
|
|
183
183
|
modal_proto/task_command_router_pb2.pyi,sha256=EyDgXPLr7alqjXYERV8w_MPuO404x0uCppmSkrfE9IE,14589
|
|
184
184
|
modal_proto/task_command_router_pb2_grpc.py,sha256=uEQ0HdrCp8v-9bB5yIic9muA8spCShLHY6Bz9cCgOUE,10114
|
|
185
185
|
modal_proto/task_command_router_pb2_grpc.pyi,sha256=s3Yxsrawdj4nr8vqQqsAxyX6ilWaGbdECy425KKbLIA,3301
|
|
186
|
-
modal_version/__init__.py,sha256=
|
|
186
|
+
modal_version/__init__.py,sha256=BGT-zG4jbs-VPlDeSA13G_diAPSM3dNIBl_5lJOh-4w,120
|
|
187
187
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
|
188
|
-
modal-1.2.1.
|
|
189
|
-
modal-1.2.1.
|
|
190
|
-
modal-1.2.1.
|
|
191
|
-
modal-1.2.1.
|
|
192
|
-
modal-1.2.1.
|
|
188
|
+
modal-1.2.1.dev8.dist-info/METADATA,sha256=gfahBhON2zAnVUbV8XvOE3cuXb3nukFnV9mOuVwiWBs,2483
|
|
189
|
+
modal-1.2.1.dev8.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
190
|
+
modal-1.2.1.dev8.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
|
191
|
+
modal-1.2.1.dev8.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
|
192
|
+
modal-1.2.1.dev8.dist-info/RECORD,,
|
modal_version/__init__.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|