modal 0.66.43__py3-none-any.whl → 0.66.45__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/cli/launch.py +6 -4
- modal/client.pyi +2 -2
- modal/functions.pyi +6 -6
- modal/io_streams.py +40 -33
- modal/io_streams.pyi +13 -13
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/METADATA +1 -1
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/RECORD +12 -12
- modal_version/_version_generated.py +1 -1
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/LICENSE +0 -0
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/WHEEL +0 -0
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/entry_points.txt +0 -0
- {modal-0.66.43.dist-info → modal-0.66.45.dist-info}/top_level.txt +0 -0
modal/cli/launch.py
CHANGED
@@ -25,7 +25,7 @@ launch_cli = Typer(
|
|
25
25
|
)
|
26
26
|
|
27
27
|
|
28
|
-
def _launch_program(name: str, filename: str, args: Dict[str, Any]) -> None:
|
28
|
+
def _launch_program(name: str, filename: str, detach: bool, args: Dict[str, Any]) -> None:
|
29
29
|
os.environ["MODAL_LAUNCH_ARGS"] = json.dumps(args)
|
30
30
|
|
31
31
|
program_path = str(Path(__file__).parent / "programs" / filename)
|
@@ -37,7 +37,7 @@ def _launch_program(name: str, filename: str, args: Dict[str, Any]) -> None:
|
|
37
37
|
func = entrypoint.info.raw_f
|
38
38
|
isasync = inspect.iscoroutinefunction(func)
|
39
39
|
with enable_output():
|
40
|
-
with run_app(app):
|
40
|
+
with run_app(app, detach=detach):
|
41
41
|
try:
|
42
42
|
if isasync:
|
43
43
|
asyncio.run(func())
|
@@ -57,6 +57,7 @@ def jupyter(
|
|
57
57
|
add_python: Optional[str] = "3.11",
|
58
58
|
mount: Optional[str] = None, # Create a `modal.Mount` from a local directory.
|
59
59
|
volume: Optional[str] = None, # Attach a persisted `modal.Volume` by name (creating if missing).
|
60
|
+
detach: bool = False, # Run the app in "detached" mode to persist after local client disconnects
|
60
61
|
):
|
61
62
|
args = {
|
62
63
|
"cpu": cpu,
|
@@ -68,7 +69,7 @@ def jupyter(
|
|
68
69
|
"mount": mount,
|
69
70
|
"volume": volume,
|
70
71
|
}
|
71
|
-
_launch_program("jupyter", "run_jupyter.py", args)
|
72
|
+
_launch_program("jupyter", "run_jupyter.py", detach, args)
|
72
73
|
|
73
74
|
|
74
75
|
@launch_cli.command(name="vscode", help="Start Visual Studio Code on Modal.")
|
@@ -79,6 +80,7 @@ def vscode(
|
|
79
80
|
timeout: int = 3600,
|
80
81
|
mount: Optional[str] = None, # Create a `modal.Mount` from a local directory.
|
81
82
|
volume: Optional[str] = None, # Attach a persisted `modal.Volume` by name (creating if missing).
|
83
|
+
detach: bool = False, # Run the app in "detached" mode to persist after local client disconnects
|
82
84
|
):
|
83
85
|
args = {
|
84
86
|
"cpu": cpu,
|
@@ -88,4 +90,4 @@ def vscode(
|
|
88
90
|
"mount": mount,
|
89
91
|
"volume": volume,
|
90
92
|
}
|
91
|
-
_launch_program("vscode", "vscode.py", args)
|
93
|
+
_launch_program("vscode", "vscode.py", detach, args)
|
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.66.
|
34
|
+
version: str = "0.66.45",
|
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.66.
|
93
|
+
version: str = "0.66.45",
|
94
94
|
): ...
|
95
95
|
def is_closed(self) -> bool: ...
|
96
96
|
@property
|
modal/functions.pyi
CHANGED
@@ -446,11 +446,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
|
|
446
446
|
|
447
447
|
_call_generator_nowait: ___call_generator_nowait_spec
|
448
448
|
|
449
|
-
class __remote_spec(typing_extensions.Protocol[
|
449
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
450
450
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
451
451
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
|
452
452
|
|
453
|
-
remote: __remote_spec[
|
453
|
+
remote: __remote_spec[ReturnType, P]
|
454
454
|
|
455
455
|
class __remote_gen_spec(typing_extensions.Protocol):
|
456
456
|
def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
|
@@ -462,17 +462,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
|
|
462
462
|
def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
|
463
463
|
def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
|
464
464
|
|
465
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
465
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
466
466
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
467
467
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
468
468
|
|
469
|
-
_experimental_spawn: ___experimental_spawn_spec[
|
469
|
+
_experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
|
470
470
|
|
471
|
-
class __spawn_spec(typing_extensions.Protocol[
|
471
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
472
472
|
def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
473
473
|
async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
|
474
474
|
|
475
|
-
spawn: __spawn_spec[
|
475
|
+
spawn: __spawn_spec[ReturnType, P]
|
476
476
|
|
477
477
|
def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
|
478
478
|
|
modal/io_streams.py
CHANGED
@@ -66,9 +66,10 @@ T = TypeVar("T", str, bytes)
|
|
66
66
|
|
67
67
|
|
68
68
|
class _StreamReader(Generic[T]):
|
69
|
-
"""
|
69
|
+
"""Retrieve logs from a stream (`stdout` or `stderr`).
|
70
70
|
|
71
|
-
As an asynchronous iterable, the object supports the async for
|
71
|
+
As an asynchronous iterable, the object supports the `for` and `async for`
|
72
|
+
statements. Just loop over the object to read in chunks.
|
72
73
|
|
73
74
|
**Usage**
|
74
75
|
|
@@ -140,12 +141,12 @@ class _StreamReader(Generic[T]):
|
|
140
141
|
self._consume_container_process_task = asyncio.create_task(self._consume_container_process_stream())
|
141
142
|
|
142
143
|
@property
|
143
|
-
def file_descriptor(self):
|
144
|
+
def file_descriptor(self) -> int:
|
145
|
+
"""Possible values are `1` for stdout and `2` for stderr."""
|
144
146
|
return self._file_descriptor
|
145
147
|
|
146
148
|
async def read(self) -> T:
|
147
|
-
"""Fetch
|
148
|
-
return an empty string.
|
149
|
+
"""Fetch the entire contents of the stream until EOF.
|
149
150
|
|
150
151
|
**Usage**
|
151
152
|
|
@@ -157,7 +158,6 @@ class _StreamReader(Generic[T]):
|
|
157
158
|
|
158
159
|
print(sandbox.stdout.read())
|
159
160
|
```
|
160
|
-
|
161
161
|
"""
|
162
162
|
data_str = ""
|
163
163
|
data_bytes = b""
|
@@ -175,9 +175,7 @@ class _StreamReader(Generic[T]):
|
|
175
175
|
return cast(T, data_bytes)
|
176
176
|
|
177
177
|
async def _consume_container_process_stream(self):
|
178
|
-
"""
|
179
|
-
Consumes the container process stream and stores the messages in the buffer.
|
180
|
-
"""
|
178
|
+
"""Consume the container process stream and store messages in the buffer."""
|
181
179
|
if self._stream_type == StreamType.DEVNULL:
|
182
180
|
return
|
183
181
|
|
@@ -211,9 +209,7 @@ class _StreamReader(Generic[T]):
|
|
211
209
|
raise exc
|
212
210
|
|
213
211
|
async def _stream_container_process(self) -> AsyncGenerator[Tuple[Optional[bytes], str], None]:
|
214
|
-
"""
|
215
|
-
Streams the container process buffer to the reader.
|
216
|
-
"""
|
212
|
+
"""Streams the container process buffer to the reader."""
|
217
213
|
entry_id = 0
|
218
214
|
if self._last_entry_id:
|
219
215
|
entry_id = int(self._last_entry_id) + 1
|
@@ -232,8 +228,7 @@ class _StreamReader(Generic[T]):
|
|
232
228
|
entry_id += 1
|
233
229
|
|
234
230
|
async def _get_logs(self) -> AsyncGenerator[Optional[bytes], None]:
|
235
|
-
"""
|
236
|
-
Streams sandbox or process logs from the server to the reader.
|
231
|
+
"""Streams sandbox or process logs from the server to the reader.
|
237
232
|
|
238
233
|
Logs returned by this method may contain partial or multiple lines at a time.
|
239
234
|
|
@@ -278,9 +273,7 @@ class _StreamReader(Generic[T]):
|
|
278
273
|
raise
|
279
274
|
|
280
275
|
async def _get_logs_by_line(self) -> AsyncGenerator[Optional[bytes], None]:
|
281
|
-
"""
|
282
|
-
Processes logs from the server and yields complete lines only.
|
283
|
-
"""
|
276
|
+
"""Process logs from the server and yield complete lines only."""
|
284
277
|
async for message in self._get_logs():
|
285
278
|
if message is None:
|
286
279
|
if self._line_buffer:
|
@@ -325,7 +318,8 @@ MAX_BUFFER_SIZE = 2 * 1024 * 1024
|
|
325
318
|
class _StreamWriter:
|
326
319
|
"""Provides an interface to buffer and write logs to a sandbox or container process stream (`stdin`)."""
|
327
320
|
|
328
|
-
def __init__(self, object_id: str, object_type: Literal["sandbox", "container_process"], client: _Client):
|
321
|
+
def __init__(self, object_id: str, object_type: Literal["sandbox", "container_process"], client: _Client) -> None:
|
322
|
+
"""mdmd:hidden"""
|
329
323
|
self._index = 1
|
330
324
|
self._object_id = object_id
|
331
325
|
self._object_type = object_type
|
@@ -333,17 +327,16 @@ class _StreamWriter:
|
|
333
327
|
self._is_closed = False
|
334
328
|
self._buffer = bytearray()
|
335
329
|
|
336
|
-
def
|
337
|
-
"""mdmd:hidden"""
|
330
|
+
def _get_next_index(self) -> int:
|
338
331
|
index = self._index
|
339
332
|
self._index += 1
|
340
333
|
return index
|
341
334
|
|
342
|
-
def write(self, data: Union[bytes, bytearray, memoryview, str]):
|
343
|
-
"""
|
344
|
-
Writes data to stream's internal buffer, but does not drain/flush the write.
|
335
|
+
def write(self, data: Union[bytes, bytearray, memoryview, str]) -> None:
|
336
|
+
"""Write data to the stream but does not send it immediately.
|
345
337
|
|
346
|
-
This
|
338
|
+
This is non-blocking and queues the data to an internal buffer. Must be
|
339
|
+
used along with the `drain()` method, which flushes the buffer.
|
347
340
|
|
348
341
|
**Usage**
|
349
342
|
|
@@ -375,22 +368,36 @@ class _StreamWriter:
|
|
375
368
|
else:
|
376
369
|
raise TypeError(f"data argument must be a bytes-like object, not {type(data).__name__}")
|
377
370
|
|
378
|
-
def write_eof(self):
|
379
|
-
"""
|
380
|
-
Closes the write end of the stream after the buffered write data is drained.
|
381
|
-
If the process was blocked on input, it will become unblocked after `write_eof()`.
|
371
|
+
def write_eof(self) -> None:
|
372
|
+
"""Close the write end of the stream after the buffered data is drained.
|
382
373
|
|
383
|
-
|
374
|
+
If the process was blocked on input, it will become unblocked after
|
375
|
+
`write_eof()`. This method needs to be used along with the `drain()`
|
376
|
+
method, which flushes the EOF to the process.
|
384
377
|
"""
|
385
378
|
self._is_closed = True
|
386
379
|
|
387
|
-
async def drain(self):
|
388
|
-
"""
|
389
|
-
|
380
|
+
async def drain(self) -> None:
|
381
|
+
"""Flush the write buffer and send data to the running process.
|
382
|
+
|
383
|
+
This is a flow control method that blocks until data is sent. It returns
|
384
|
+
when it is appropriate to continue writing data to the stream.
|
385
|
+
|
386
|
+
**Usage**
|
387
|
+
|
388
|
+
```python
|
389
|
+
# Synchronous
|
390
|
+
writer.write(data)
|
391
|
+
writer.drain()
|
392
|
+
|
393
|
+
# Async
|
394
|
+
writer.write(data)
|
395
|
+
await writer.drain.aio()
|
396
|
+
```
|
390
397
|
"""
|
391
398
|
data = bytes(self._buffer)
|
392
399
|
self._buffer.clear()
|
393
|
-
index = self.
|
400
|
+
index = self._get_next_index()
|
394
401
|
|
395
402
|
try:
|
396
403
|
if self._object_type == "sandbox":
|
modal/io_streams.pyi
CHANGED
@@ -26,7 +26,7 @@ class _StreamReader(typing.Generic[T]):
|
|
26
26
|
by_line: bool = False,
|
27
27
|
) -> None: ...
|
28
28
|
@property
|
29
|
-
def file_descriptor(self): ...
|
29
|
+
def file_descriptor(self) -> int: ...
|
30
30
|
async def read(self) -> T: ...
|
31
31
|
async def _consume_container_process_stream(self): ...
|
32
32
|
def _stream_container_process(self) -> typing.AsyncGenerator[typing.Tuple[typing.Optional[bytes], str], None]: ...
|
@@ -38,11 +38,11 @@ class _StreamReader(typing.Generic[T]):
|
|
38
38
|
class _StreamWriter:
|
39
39
|
def __init__(
|
40
40
|
self, object_id: str, object_type: typing.Literal["sandbox", "container_process"], client: modal.client._Client
|
41
|
-
): ...
|
42
|
-
def
|
43
|
-
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]): ...
|
44
|
-
def write_eof(self): ...
|
45
|
-
async def drain(self): ...
|
41
|
+
) -> None: ...
|
42
|
+
def _get_next_index(self) -> int: ...
|
43
|
+
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None: ...
|
44
|
+
def write_eof(self) -> None: ...
|
45
|
+
async def drain(self) -> None: ...
|
46
46
|
|
47
47
|
T_INNER = typing.TypeVar("T_INNER", covariant=True)
|
48
48
|
|
@@ -60,7 +60,7 @@ class StreamReader(typing.Generic[T]):
|
|
60
60
|
by_line: bool = False,
|
61
61
|
) -> None: ...
|
62
62
|
@property
|
63
|
-
def file_descriptor(self): ...
|
63
|
+
def file_descriptor(self) -> int: ...
|
64
64
|
|
65
65
|
class __read_spec(typing_extensions.Protocol[T_INNER]):
|
66
66
|
def __call__(self) -> T_INNER: ...
|
@@ -100,13 +100,13 @@ class StreamReader(typing.Generic[T]):
|
|
100
100
|
class StreamWriter:
|
101
101
|
def __init__(
|
102
102
|
self, object_id: str, object_type: typing.Literal["sandbox", "container_process"], client: modal.client.Client
|
103
|
-
): ...
|
104
|
-
def
|
105
|
-
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]): ...
|
106
|
-
def write_eof(self): ...
|
103
|
+
) -> None: ...
|
104
|
+
def _get_next_index(self) -> int: ...
|
105
|
+
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None: ...
|
106
|
+
def write_eof(self) -> None: ...
|
107
107
|
|
108
108
|
class __drain_spec(typing_extensions.Protocol):
|
109
|
-
def __call__(self): ...
|
110
|
-
async def aio(self): ...
|
109
|
+
def __call__(self) -> None: ...
|
110
|
+
async def aio(self) -> None: ...
|
111
111
|
|
112
112
|
drain: __drain_spec
|
@@ -19,7 +19,7 @@ modal/app.py,sha256=QEBK8qYSrux36oi3iS3msBQmcUOS1r4s2nengzzynjQ,44658
|
|
19
19
|
modal/app.pyi,sha256=wHwBIDqkUb2CQzYVhxZafJ8xZ17TZ-8y-cRyOeZsEm0,25182
|
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=ff5IGJxJXwH0-8hhT2-74k9Md0GGmQlcmloXCqdI2bo,7372
|
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=apKnBOHKYEpBiMC8mRvHtCDJl1g0vP0tG1r8mUZ1yH0,24684
|
@@ -34,12 +34,12 @@ 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=BxccB-3a1migZQ6JA6iiHZJQ7WQ-jYpmg9DEZoTxzcc,71639
|
37
|
-
modal/functions.pyi,sha256=
|
37
|
+
modal/functions.pyi,sha256=5JGM4Mhpm674Ia7h3OTsPBmZA32goyOs2oBCCUG8A3I,24800
|
38
38
|
modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
|
39
39
|
modal/image.py,sha256=j-NH8pLWk4jd5UOGD4y6W7DHWoeb3rG_VR7zPLSqj-Q,78927
|
40
40
|
modal/image.pyi,sha256=QEjjnl4ZSmqt7toHww5ZbhL2Re5qaFGgH7qADcJS_vA,24493
|
41
|
-
modal/io_streams.py,sha256=
|
42
|
-
modal/io_streams.pyi,sha256=
|
41
|
+
modal/io_streams.py,sha256=XUsNsxRzDrhkjyb2Hx0hugCoOEz266SHQF8wP-VgsfY,14582
|
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
45
|
modal/network_file_system.py,sha256=P_LsILecyda1SRHU76Hk4Lq3M1HSx9shFJbaLThzw0U,14071
|
@@ -109,7 +109,7 @@ modal/cli/dict.py,sha256=lIEl6uxygFt3omC-oF6tHUxnFjVhy4d0InC_kZrlkvM,4454
|
|
109
109
|
modal/cli/entry_point.py,sha256=aaNxFAqZcmtSjwzkYIA_Ba9CkL4cL4_i2gy5VjoXxkM,4228
|
110
110
|
modal/cli/environment.py,sha256=eq8Rixbo8u-nJPvtGwW4-I1lXZPnevsFEv65WlSxFXY,4362
|
111
111
|
modal/cli/import_refs.py,sha256=0sYZLcgcnor_CECq-7yX3WBs1W55nz5y65sbysxxKzY,9267
|
112
|
-
modal/cli/launch.py,sha256=
|
112
|
+
modal/cli/launch.py,sha256=FgZ0L-e3dLl9vRJ_IVHfSRUzCbmdyS8-u_abC42tTDo,2941
|
113
113
|
modal/cli/network_file_system.py,sha256=p_o3wu8rh2tjHXJYrjaad__pD8hv93ypeDtfSY2fSEU,7527
|
114
114
|
modal/cli/profile.py,sha256=s4jCYHwriOorEFCKxeGZoSWX8rXTR_hDTNFZhOA565s,3109
|
115
115
|
modal/cli/queues.py,sha256=mJ44A319sPIrysH3A0HCIz4Or0jFey6miiuQKZoEQxo,4493
|
@@ -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=UnAuHBPuPSstqgdCOx0SBVdfhpeJnMlY_oxEbu44Izg,470
|
161
161
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
162
|
-
modal_version/_version_generated.py,sha256=
|
163
|
-
modal-0.66.
|
164
|
-
modal-0.66.
|
165
|
-
modal-0.66.
|
166
|
-
modal-0.66.
|
167
|
-
modal-0.66.
|
168
|
-
modal-0.66.
|
162
|
+
modal_version/_version_generated.py,sha256=UXFAH4OKxboSSDBrr37s5UWM3WNwZ-Q4bjX-tfF7Hj0,149
|
163
|
+
modal-0.66.45.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
164
|
+
modal-0.66.45.dist-info/METADATA,sha256=sxLqxkKCOBQaGBvhzaKx-RB1ybImrlmY0lJdeOJYGDQ,2329
|
165
|
+
modal-0.66.45.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
166
|
+
modal-0.66.45.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
167
|
+
modal-0.66.45.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
168
|
+
modal-0.66.45.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|