modal 0.67.1__py3-none-any.whl → 0.67.6__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/_runtime/asgi.py +39 -0
- modal/_tunnel.py +1 -1
- modal/_utils/async_utils.py +40 -0
- modal/app.py +39 -28
- modal/app.pyi +2 -2
- modal/client.pyi +2 -2
- modal/cls.py +2 -2
- modal/dict.py +2 -0
- modal/functions.py +2 -2
- modal/functions.pyi +6 -6
- modal/image.py +1 -1
- modal/io_streams.py +5 -4
- modal/network_file_system.py +7 -5
- modal/queue.py +2 -0
- modal/volume.py +8 -5
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/METADATA +1 -1
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/RECORD +22 -22
- modal_version/_version_generated.py +1 -1
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/LICENSE +0 -0
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/WHEEL +0 -0
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/entry_points.txt +0 -0
- {modal-0.67.1.dist-info → modal-0.67.6.dist-info}/top_level.txt +0 -0
modal/_runtime/asgi.py
CHANGED
@@ -280,9 +280,48 @@ def wait_for_web_server(host: str, port: int, *, timeout: float) -> None:
|
|
280
280
|
) from ex
|
281
281
|
|
282
282
|
|
283
|
+
def _add_forwarded_for_header(scope):
|
284
|
+
# we strip X-Forwarded-For headers from the scope
|
285
|
+
# but we can add it back from the ASGI scope
|
286
|
+
# https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
|
287
|
+
|
288
|
+
# X-Forwarded-For headers is a comma separated list of IP addresses
|
289
|
+
# there may be multiple X-Forwarded-For headers
|
290
|
+
# we want to prepend the client IP to the first one
|
291
|
+
# but only if it doesn't exist in one of the headers already
|
292
|
+
|
293
|
+
first_x_forwarded_for_idx = None
|
294
|
+
if "headers" in scope and "client" in scope:
|
295
|
+
client_host = scope["client"][0]
|
296
|
+
|
297
|
+
for idx, header in enumerate(scope["headers"]):
|
298
|
+
if header[0] == b"X-Forwarded-For":
|
299
|
+
if first_x_forwarded_for_idx is None:
|
300
|
+
first_x_forwarded_for_idx = idx
|
301
|
+
values = header[1].decode().split(", ")
|
302
|
+
|
303
|
+
if client_host in values:
|
304
|
+
# we already have the client IP in this header
|
305
|
+
# return early
|
306
|
+
return scope
|
307
|
+
|
308
|
+
if first_x_forwarded_for_idx is not None:
|
309
|
+
# we have X-Forwarded-For headers but they don't have the client IP
|
310
|
+
# we need to prepend the client IP to the first one
|
311
|
+
values = [client_host] + scope["headers"][first_x_forwarded_for_idx][1].decode().split(", ")
|
312
|
+
scope["headers"][first_x_forwarded_for_idx] = (b"X-Forwarded-For", ", ".join(values).encode())
|
313
|
+
else:
|
314
|
+
# we don't have X-Forwarded-For headers, we need to add one
|
315
|
+
scope["headers"].append((b"X-Forwarded-For", client_host.encode()))
|
316
|
+
|
317
|
+
return scope
|
318
|
+
|
319
|
+
|
283
320
|
async def _proxy_http_request(session: aiohttp.ClientSession, scope, receive, send) -> None:
|
284
321
|
proxy_response: aiohttp.ClientResponse
|
285
322
|
|
323
|
+
scope = _add_forwarded_for_header(scope)
|
324
|
+
|
286
325
|
async def request_generator() -> AsyncGenerator[bytes, None]:
|
287
326
|
while True:
|
288
327
|
message = await receive()
|
modal/_tunnel.py
CHANGED
modal/_utils/async_utils.py
CHANGED
@@ -573,6 +573,46 @@ STOP_SENTINEL = StopSentinelType()
|
|
573
573
|
|
574
574
|
|
575
575
|
async def async_merge(*generators: AsyncGenerator[T, None]) -> AsyncGenerator[T, None]:
|
576
|
+
"""
|
577
|
+
Asynchronously merges multiple async generators into a single async generator.
|
578
|
+
|
579
|
+
This function takes multiple async generators and yields their values in the order
|
580
|
+
they are produced. If any generator raises an exception, the exception is propagated.
|
581
|
+
|
582
|
+
Args:
|
583
|
+
*generators: One or more async generators to be merged.
|
584
|
+
|
585
|
+
Yields:
|
586
|
+
The values produced by the input async generators.
|
587
|
+
|
588
|
+
Raises:
|
589
|
+
Exception: If any of the input generators raises an exception, it is propagated.
|
590
|
+
|
591
|
+
Usage:
|
592
|
+
```python
|
593
|
+
import asyncio
|
594
|
+
from modal._utils.async_utils import async_merge
|
595
|
+
|
596
|
+
async def gen1():
|
597
|
+
yield 1
|
598
|
+
yield 2
|
599
|
+
|
600
|
+
async def gen2():
|
601
|
+
yield "a"
|
602
|
+
yield "b"
|
603
|
+
|
604
|
+
async def example():
|
605
|
+
values = set()
|
606
|
+
async for value in async_merge(gen1(), gen2()):
|
607
|
+
values.add(value)
|
608
|
+
|
609
|
+
return values
|
610
|
+
|
611
|
+
# Output could be: {1, "a", 2, "b"} (order may vary)
|
612
|
+
values = asyncio.run(example())
|
613
|
+
assert values == {1, "a", 2, "b"}
|
614
|
+
```
|
615
|
+
"""
|
576
616
|
queue: asyncio.Queue[Union[ValueWrapper[T], ExceptionWrapper]] = asyncio.Queue(maxsize=len(generators) * 10)
|
577
617
|
|
578
618
|
async def producer(generator: AsyncGenerator[T, None]):
|
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
|
|
@@ -401,14 +384,14 @@ class _App:
|
|
401
384
|
|
402
385
|
**Example**
|
403
386
|
|
404
|
-
```python
|
387
|
+
```python notest
|
405
388
|
with app.run():
|
406
389
|
some_modal_function.remote()
|
407
390
|
```
|
408
391
|
|
409
392
|
To enable output printing, use `modal.enable_output()`:
|
410
393
|
|
411
|
-
```python
|
394
|
+
```python notest
|
412
395
|
with modal.enable_output():
|
413
396
|
with app.run():
|
414
397
|
some_modal_function.remote()
|
@@ -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.6",
|
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.6",
|
94
94
|
): ...
|
95
95
|
def is_closed(self) -> bool: ...
|
96
96
|
@property
|
modal/cls.py
CHANGED
@@ -154,7 +154,7 @@ class _Obj:
|
|
154
154
|
Note that all Modal methods and web endpoints of a class share the same set
|
155
155
|
of containers and the warm_pool_size affects that common container pool.
|
156
156
|
|
157
|
-
```python
|
157
|
+
```python notest
|
158
158
|
# Usage on a parametrized function.
|
159
159
|
Model = modal.Cls.lookup("my-app", "Model")
|
160
160
|
Model("fine-tuned-model").keep_warm(2)
|
@@ -524,7 +524,7 @@ class _Cls(_Object, type_prefix="cs"):
|
|
524
524
|
In contrast to `modal.Cls.from_name`, this is an eager method
|
525
525
|
that will hydrate the local object with metadata from Modal servers.
|
526
526
|
|
527
|
-
```python
|
527
|
+
```python notest
|
528
528
|
Class = modal.Cls.lookup("other-app", "Class")
|
529
529
|
obj = Class()
|
530
530
|
```
|
modal/dict.py
CHANGED
modal/functions.py
CHANGED
@@ -997,7 +997,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
997
997
|
Please exercise care when using this advanced feature!
|
998
998
|
Setting and forgetting a warm pool on functions can lead to increased costs.
|
999
999
|
|
1000
|
-
```python
|
1000
|
+
```python notest
|
1001
1001
|
# Usage on a regular function.
|
1002
1002
|
f = modal.Function.lookup("my-app", "function")
|
1003
1003
|
f.keep_warm(2)
|
@@ -1076,7 +1076,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1076
1076
|
In contrast to `modal.Function.from_name`, this is an eager method
|
1077
1077
|
that will hydrate the local object with metadata from Modal servers.
|
1078
1078
|
|
1079
|
-
```python
|
1079
|
+
```python notest
|
1080
1080
|
f = modal.Function.lookup("other-app", "function")
|
1081
1081
|
```
|
1082
1082
|
"""
|
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
|
|
modal/image.py
CHANGED
@@ -375,7 +375,7 @@ class _Image(_Object, type_prefix="im"):
|
|
375
375
|
"\n"
|
376
376
|
"Run `image.add_local_*` commands last in your image build to avoid rebuilding images with every local "
|
377
377
|
"file change. Modal will then add these files to containers on startup instead, saving build time.\n"
|
378
|
-
"If you need to run other build steps after adding local files, set `copy=True` to copy the files"
|
378
|
+
"If you need to run other build steps after adding local files, set `copy=True` to copy the files "
|
379
379
|
"directly into the image, at the expense of some added build time.\n"
|
380
380
|
"\n"
|
381
381
|
"Example:\n"
|
modal/io_streams.py
CHANGED
@@ -385,13 +385,14 @@ class _StreamWriter:
|
|
385
385
|
|
386
386
|
**Usage**
|
387
387
|
|
388
|
-
```python
|
389
|
-
# Synchronous
|
388
|
+
```python notest
|
390
389
|
writer.write(data)
|
391
390
|
writer.drain()
|
391
|
+
```
|
392
392
|
|
393
|
-
|
394
|
-
|
393
|
+
Async usage:
|
394
|
+
```python notest
|
395
|
+
writer.write(data) # not a blocking operation
|
395
396
|
await writer.drain.aio()
|
396
397
|
```
|
397
398
|
"""
|
modal/network_file_system.py
CHANGED
@@ -152,11 +152,13 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
152
152
|
|
153
153
|
Usage:
|
154
154
|
```python
|
155
|
-
with NetworkFileSystem.ephemeral() as nfs:
|
156
|
-
assert nfs.listdir() == []
|
155
|
+
with modal.NetworkFileSystem.ephemeral() as nfs:
|
156
|
+
assert nfs.listdir("/") == []
|
157
|
+
```
|
157
158
|
|
158
|
-
|
159
|
-
|
159
|
+
```python notest
|
160
|
+
async with modal.NetworkFileSystem.ephemeral() as nfs:
|
161
|
+
assert await nfs.listdir("/") == []
|
160
162
|
```
|
161
163
|
"""
|
162
164
|
if client is None:
|
@@ -184,7 +186,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
184
186
|
In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
|
185
187
|
that will hydrate the local object with metadata from Modal servers.
|
186
188
|
|
187
|
-
```python
|
189
|
+
```python notest
|
188
190
|
nfs = modal.NetworkFileSystem.lookup("my-nfs")
|
189
191
|
print(nfs.listdir("/"))
|
190
192
|
```
|
modal/queue.py
CHANGED
modal/volume.py
CHANGED
@@ -200,11 +200,14 @@ class _Volume(_Object, type_prefix="vo"):
|
|
200
200
|
|
201
201
|
Usage:
|
202
202
|
```python
|
203
|
-
|
204
|
-
|
203
|
+
import modal
|
204
|
+
with modal.Volume.ephemeral() as vol:
|
205
|
+
assert vol.listdir("/") == []
|
206
|
+
```
|
205
207
|
|
206
|
-
|
207
|
-
|
208
|
+
```python notest
|
209
|
+
async with modal.Volume.ephemeral() as vol:
|
210
|
+
assert await vol.listdir("/") == []
|
208
211
|
```
|
209
212
|
"""
|
210
213
|
if client is None:
|
@@ -234,7 +237,7 @@ class _Volume(_Object, type_prefix="vo"):
|
|
234
237
|
In contrast to `modal.Volume.from_name`, this is an eager method
|
235
238
|
that will hydrate the local object with metadata from Modal servers.
|
236
239
|
|
237
|
-
```python
|
240
|
+
```python notest
|
238
241
|
vol = modal.Volume.lookup("my-volume")
|
239
242
|
print(vol.listdir("/"))
|
240
243
|
```
|
@@ -12,37 +12,37 @@ modal/_resolver.py,sha256=s2YSLnpZbwUQHLs2ahltvEVDMLRYyIagdTcWr2-qkeA,6760
|
|
12
12
|
modal/_resources.py,sha256=zTCcXvmG1erERnTvUcN0r4IjjwVEs4N8fs7OnkpvbJQ,1740
|
13
13
|
modal/_serialization.py,sha256=b1X44hDP7WDTX3iz3HrPyFJJz51a69luq5Tyhnm1fK0,18762
|
14
14
|
modal/_traceback.py,sha256=1yNp1Dqq4qRIQp8idDp5PEqjwH4eA8MNI0FhFkCOFgo,4408
|
15
|
-
modal/_tunnel.py,sha256=
|
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=hJ4icHlSyz3LcVDSF0myB0Zi5G2mVoMS4Vr4uqiQKJY,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
|
-
modal/cls.py,sha256=
|
25
|
+
modal/cls.py,sha256=v3Uad6nTpHNwkAZ04KlQY3jZGgntKt5Onz6DusFRtg8,24706
|
26
26
|
modal/cls.pyi,sha256=eVQ3QQC2XwGe2rvYFvjQ57d8ToBXbpI6M-9_YyVQkbo,8214
|
27
27
|
modal/config.py,sha256=bij_YRIynxQtwDmS73BNMR9YZf6CHcqbFYdfRqDrWV0,10929
|
28
28
|
modal/container_process.py,sha256=c_jBPtyPeSxbIcbLfs_FzTrt-1eErtRSnsfxkDozFoY,5589
|
29
29
|
modal/container_process.pyi,sha256=k2kClwaSzz11eci1pzFZgCm-ptXapHAyHTOENorlazA,2594
|
30
|
-
modal/dict.py,sha256=
|
30
|
+
modal/dict.py,sha256=ncy0q21IU2PqZa4CpFfPfNIMWpOLwKvdU40xZhxCemc,12608
|
31
31
|
modal/dict.pyi,sha256=4Rh5HNzXk99hotPUzoj1kYOHNlEgndZFfA-hlmBtBIc,7223
|
32
32
|
modal/environments.py,sha256=KwKdrWfSnz2XF5eYXZyd0kdac1x1PVw2uxPYsGy8cys,6517
|
33
33
|
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
|
-
modal/functions.py,sha256=
|
37
|
-
modal/functions.pyi,sha256=
|
36
|
+
modal/functions.py,sha256=Gfr-IsAeH0uIHCSfVYNWSzjnnrN33LPY3Ui4S6c6Pvo,66953
|
37
|
+
modal/functions.pyi,sha256=1pFjUQBZx__UGaqJadYoMycQdlVb4jTex307VREzpQA,24375
|
38
38
|
modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
|
39
|
-
modal/image.py,sha256=
|
39
|
+
modal/image.py,sha256=DoubwAD9ebYNIEO3GJWbtAaJl_ZRW4K0tpIJdS9CZAg,79551
|
40
40
|
modal/image.pyi,sha256=3rfae_E0KuNHqdi5j33nHXp_7P3tTkt7QKH5cXYczUc,24672
|
41
|
-
modal/io_streams.py,sha256=
|
41
|
+
modal/io_streams.py,sha256=AAY-qcISGCIMp-F6SwX6vhZWJv7Sg_KudDBW0rMfc-E,14637
|
42
42
|
modal/io_streams.pyi,sha256=WJmSI1WvZITUNBO7mnIuJgYdSKdbLaHk10V4GbttAVw,4452
|
43
43
|
modal/mount.py,sha256=QZ4nabpbNU9tjLIPCq86rlHor9CXzADMkhJWBYfKKgg,27750
|
44
44
|
modal/mount.pyi,sha256=nywUmeUELLY2OEnAc1NNBHmSxuEylTWBzkh6nuXkkuc,9965
|
45
|
-
modal/network_file_system.py,sha256=
|
45
|
+
modal/network_file_system.py,sha256=xCQDM8aajiGydGVm8BaJo0yTgsceHNMmAfG5D3L3d_I,14133
|
46
46
|
modal/network_file_system.pyi,sha256=XLyUnDx55ExbJcF_xlKxRax_r06XTvSsQh-a-_EyCOU,7239
|
47
47
|
modal/object.py,sha256=Qgee_lQJY_583YsGIVrSNuDF_gJA_qmTAeVTVI1tf-g,9637
|
48
48
|
modal/object.pyi,sha256=uGGD5A2B_mj8jxLfFiHama5wzCcBS_GNvPSKsIfsCO0,8518
|
@@ -54,7 +54,7 @@ modal/partial_function.pyi,sha256=BqKN7It5QLxS2yhhhDX0RgI8EyNMPBD6Duk21kN_fvA,89
|
|
54
54
|
modal/proxy.py,sha256=ZrOsuQP7dSZFq1OrIxalNnt0Zvsnp1h86Th679sSL40,1417
|
55
55
|
modal/proxy.pyi,sha256=UvygdOYneLTuoDY6hVaMNCyZ947Tmx93IdLjErUqkvM,368
|
56
56
|
modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
-
modal/queue.py,sha256=
|
57
|
+
modal/queue.py,sha256=WdiU0eiBtQx3tOk-QojyScieHZRkIqaXWQdJwCMlDCc,18375
|
58
58
|
modal/queue.pyi,sha256=t5yhDqXRtexy7AVraCexPyT6Xo3QA_H5OxVe_JLzTps,9999
|
59
59
|
modal/retries.py,sha256=z4dYXdksUcjkefM3vGLkhCQ_m_TUPLJgC4uSYDzWSOU,3750
|
60
60
|
modal/runner.py,sha256=Yx8SdnxGzHIlqMxhIQiBukF12yj7wh-c6jWwy8w76u8,24081
|
@@ -71,17 +71,17 @@ modal/serving.pyi,sha256=0KWUH5rdYnihSv1XB8bK9GokzpfzrCq8Sf6nYlUvQI8,1689
|
|
71
71
|
modal/stream_type.py,sha256=A6320qoAAWhEfwOCZfGtymQTu5AfLfJXXgARqooTPvY,417
|
72
72
|
modal/token_flow.py,sha256=lsVpJACut76AeJLw44vJKMSlpcqp8wcvxdUOoX6CIOc,6754
|
73
73
|
modal/token_flow.pyi,sha256=qEYP7grgqSA440w7kBREU9Ezeo_NxCT67OciIPgDzcc,1958
|
74
|
-
modal/volume.py,sha256=
|
74
|
+
modal/volume.py,sha256=uq1hyHXRdCG10rbIDWq6B9mveeJlOE5mXWKUaynhN4o,29384
|
75
75
|
modal/volume.pyi,sha256=3lB6wiC75u3o44cwJVqDsmvR4wsP2JXSxJrVXi9KrK4,11127
|
76
76
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
77
|
-
modal/_runtime/asgi.py,sha256=
|
77
|
+
modal/_runtime/asgi.py,sha256=69X60gSg6AnH8dZlMC1C5eWkC0nypewbHbzAcy9-_gg,21523
|
78
78
|
modal/_runtime/container_io_manager.py,sha256=qFxBdmOh6Vz_Jc9HW27yM-Wt6rOvhMi1yHUW1CzCneg,44146
|
79
79
|
modal/_runtime/execution_context.py,sha256=cXEVY4wEK-oZJVJptyj1ZplZvVQ1HDzFsyHxhaY4o8M,2718
|
80
80
|
modal/_runtime/telemetry.py,sha256=3NbrfwYH6mvDckzdTppymmda2lQKX2oHGc2JwdFZdUc,5191
|
81
81
|
modal/_runtime/user_code_imports.py,sha256=2COhqA77zwbP__-DWiDHEScHM-Go3CmI-AlKvT_oBOU,14545
|
82
82
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
83
83
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
84
|
-
modal/_utils/async_utils.py,sha256=
|
84
|
+
modal/_utils/async_utils.py,sha256=LInaa9xOl256MwXPtFlgmgk9iS2OEJGF15BCyi_O0hE,24994
|
85
85
|
modal/_utils/blob_utils.py,sha256=pAY22w0oVc6ujGfI7La7HPUMOf42FehIapuhSDeeqEs,15835
|
86
86
|
modal/_utils/function_utils.py,sha256=28mxgg_-7JF1DDiNnp3iNVsFQkOzMFjORsetdvZZTHU,24475
|
87
87
|
modal/_utils/grpc_testing.py,sha256=LOzWygTdHINzV-o_Ajbl7sOFbUQFoonP0iKpsJjA_nc,8301
|
@@ -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=w1TBMXGTDLGjMZ9q-CYFNmAgzYtrFjHKc0nUcuwOGEg,148
|
163
|
+
modal-0.67.6.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
164
|
+
modal-0.67.6.dist-info/METADATA,sha256=gEvosk6PchWUcuXAFRrWJcWX8J3vWX6bd9G_55uJ88o,2328
|
165
|
+
modal-0.67.6.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
166
|
+
modal-0.67.6.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
167
|
+
modal-0.67.6.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
168
|
+
modal-0.67.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|