modal 1.0.5.dev1__py3-none-any.whl → 1.0.5.dev3__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/_clustered_functions.pyi +13 -3
- modal/_functions.py +44 -35
- modal/_runtime/container_io_manager.pyi +222 -40
- modal/_runtime/execution_context.pyi +60 -6
- modal/_tunnel.pyi +380 -12
- modal/_utils/function_utils.py +3 -3
- modal/app.pyi +658 -48
- modal/client.pyi +224 -28
- modal/cloud_bucket_mount.pyi +192 -4
- modal/cls.pyi +442 -35
- modal/container_process.pyi +103 -14
- modal/dict.pyi +453 -51
- modal/environments.pyi +41 -9
- modal/exception.py +4 -0
- modal/file_io.pyi +236 -45
- modal/functions.pyi +571 -65
- modal/image.pyi +1256 -74
- modal/io_streams.pyi +342 -39
- modal/mount.pyi +261 -31
- modal/network_file_system.pyi +307 -26
- modal/object.pyi +48 -9
- modal/parallel_map.py +38 -6
- modal/parallel_map.pyi +155 -15
- modal/partial_function.pyi +255 -14
- modal/proxy.pyi +28 -3
- modal/queue.pyi +447 -30
- modal/runner.pyi +160 -22
- modal/sandbox.pyi +310 -50
- modal/secret.pyi +164 -15
- modal/snapshot.pyi +25 -4
- modal/token_flow.pyi +28 -8
- modal/volume.pyi +649 -59
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/METADATA +1 -1
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/RECORD +39 -39
- modal_version/__init__.py +1 -1
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/WHEEL +0 -0
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/entry_points.txt +0 -0
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/licenses/LICENSE +0 -0
- {modal-1.0.5.dev1.dist-info → modal-1.0.5.dev3.dist-info}/top_level.txt +0 -0
modal/io_streams.pyi
CHANGED
@@ -14,6 +14,27 @@ def _container_process_logs_iterator(
|
|
14
14
|
T = typing.TypeVar("T")
|
15
15
|
|
16
16
|
class _StreamReader(typing.Generic[T]):
|
17
|
+
"""Retrieve logs from a stream (`stdout` or `stderr`).
|
18
|
+
|
19
|
+
As an asynchronous iterable, the object supports the `for` and `async for`
|
20
|
+
statements. Just loop over the object to read in chunks.
|
21
|
+
|
22
|
+
**Usage**
|
23
|
+
|
24
|
+
```python fixture:running_app
|
25
|
+
from modal import Sandbox
|
26
|
+
|
27
|
+
sandbox = Sandbox.create(
|
28
|
+
"bash",
|
29
|
+
"-c",
|
30
|
+
"for i in $(seq 1 10); do echo foo; sleep 0.1; done",
|
31
|
+
app=running_app,
|
32
|
+
)
|
33
|
+
for message in sandbox.stdout:
|
34
|
+
print(f"Message: {message}")
|
35
|
+
```
|
36
|
+
"""
|
37
|
+
|
17
38
|
_stream: typing.Optional[collections.abc.AsyncGenerator[typing.Optional[bytes], None]]
|
18
39
|
|
19
40
|
def __init__(
|
@@ -25,34 +46,159 @@ class _StreamReader(typing.Generic[T]):
|
|
25
46
|
stream_type: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
26
47
|
text: bool = True,
|
27
48
|
by_line: bool = False,
|
28
|
-
) -> None:
|
49
|
+
) -> None:
|
50
|
+
"""mdmd:hidden"""
|
51
|
+
...
|
52
|
+
|
29
53
|
@property
|
30
|
-
def file_descriptor(self) -> int:
|
31
|
-
|
32
|
-
|
33
|
-
|
54
|
+
def file_descriptor(self) -> int:
|
55
|
+
"""Possible values are `1` for stdout and `2` for stderr."""
|
56
|
+
...
|
57
|
+
|
58
|
+
async def read(self) -> T:
|
59
|
+
"""Fetch the entire contents of the stream until EOF.
|
60
|
+
|
61
|
+
**Usage**
|
62
|
+
|
63
|
+
```python fixture:running_app
|
64
|
+
from modal import Sandbox
|
65
|
+
|
66
|
+
sandbox = Sandbox.create("echo", "hello", app=running_app)
|
67
|
+
sandbox.wait()
|
68
|
+
|
69
|
+
print(sandbox.stdout.read())
|
70
|
+
```
|
71
|
+
"""
|
72
|
+
...
|
73
|
+
|
74
|
+
async def _consume_container_process_stream(self):
|
75
|
+
"""Consume the container process stream and store messages in the buffer."""
|
76
|
+
...
|
77
|
+
|
78
|
+
def _stream_container_process(self) -> collections.abc.AsyncGenerator[tuple[typing.Optional[bytes], str], None]:
|
79
|
+
"""Streams the container process buffer to the reader."""
|
80
|
+
...
|
81
|
+
|
34
82
|
def _get_logs(
|
35
83
|
self, skip_empty_messages: bool = True
|
36
|
-
) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
84
|
+
) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
85
|
+
"""Streams sandbox or process logs from the server to the reader.
|
86
|
+
|
87
|
+
Logs returned by this method may contain partial or multiple lines at a time.
|
88
|
+
|
89
|
+
When the stream receives an EOF, it yields None. Once an EOF is received,
|
90
|
+
subsequent invocations will not yield logs.
|
91
|
+
"""
|
92
|
+
...
|
93
|
+
|
94
|
+
def _get_logs_by_line(self) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
95
|
+
"""Process logs from the server and yield complete lines only."""
|
96
|
+
...
|
97
|
+
|
98
|
+
def __aiter__(self) -> collections.abc.AsyncIterator[T]:
|
99
|
+
"""mdmd:hidden"""
|
100
|
+
...
|
101
|
+
|
102
|
+
async def __anext__(self) -> T:
|
103
|
+
"""mdmd:hidden"""
|
104
|
+
...
|
105
|
+
|
106
|
+
async def aclose(self):
|
107
|
+
"""mdmd:hidden"""
|
108
|
+
...
|
41
109
|
|
42
110
|
class _StreamWriter:
|
111
|
+
"""Provides an interface to buffer and write logs to a sandbox or container process stream (`stdin`)."""
|
43
112
|
def __init__(
|
44
113
|
self, object_id: str, object_type: typing.Literal["sandbox", "container_process"], client: modal.client._Client
|
45
|
-
) -> None:
|
114
|
+
) -> None:
|
115
|
+
"""mdmd:hidden"""
|
116
|
+
...
|
117
|
+
|
46
118
|
def _get_next_index(self) -> int: ...
|
47
|
-
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None:
|
48
|
-
|
49
|
-
|
119
|
+
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None:
|
120
|
+
"""Write data to the stream but does not send it immediately.
|
121
|
+
|
122
|
+
This is non-blocking and queues the data to an internal buffer. Must be
|
123
|
+
used along with the `drain()` method, which flushes the buffer.
|
124
|
+
|
125
|
+
**Usage**
|
126
|
+
|
127
|
+
```python fixture:running_app
|
128
|
+
from modal import Sandbox
|
129
|
+
|
130
|
+
sandbox = Sandbox.create(
|
131
|
+
"bash",
|
132
|
+
"-c",
|
133
|
+
"while read line; do echo $line; done",
|
134
|
+
app=running_app,
|
135
|
+
)
|
136
|
+
sandbox.stdin.write(b"foo\n")
|
137
|
+
sandbox.stdin.write(b"bar\n")
|
138
|
+
sandbox.stdin.write_eof()
|
139
|
+
|
140
|
+
sandbox.stdin.drain()
|
141
|
+
sandbox.wait()
|
142
|
+
```
|
143
|
+
"""
|
144
|
+
...
|
145
|
+
|
146
|
+
def write_eof(self) -> None:
|
147
|
+
"""Close the write end of the stream after the buffered data is drained.
|
148
|
+
|
149
|
+
If the process was blocked on input, it will become unblocked after
|
150
|
+
`write_eof()`. This method needs to be used along with the `drain()`
|
151
|
+
method, which flushes the EOF to the process.
|
152
|
+
"""
|
153
|
+
...
|
154
|
+
|
155
|
+
async def drain(self) -> None:
|
156
|
+
"""Flush the write buffer and send data to the running process.
|
157
|
+
|
158
|
+
This is a flow control method that blocks until data is sent. It returns
|
159
|
+
when it is appropriate to continue writing data to the stream.
|
160
|
+
|
161
|
+
**Usage**
|
162
|
+
|
163
|
+
```python notest
|
164
|
+
writer.write(data)
|
165
|
+
writer.drain()
|
166
|
+
```
|
167
|
+
|
168
|
+
Async usage:
|
169
|
+
```python notest
|
170
|
+
writer.write(data) # not a blocking operation
|
171
|
+
await writer.drain.aio()
|
172
|
+
```
|
173
|
+
"""
|
174
|
+
...
|
50
175
|
|
51
176
|
T_INNER = typing.TypeVar("T_INNER", covariant=True)
|
52
177
|
|
53
178
|
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
54
179
|
|
55
180
|
class StreamReader(typing.Generic[T]):
|
181
|
+
"""Retrieve logs from a stream (`stdout` or `stderr`).
|
182
|
+
|
183
|
+
As an asynchronous iterable, the object supports the `for` and `async for`
|
184
|
+
statements. Just loop over the object to read in chunks.
|
185
|
+
|
186
|
+
**Usage**
|
187
|
+
|
188
|
+
```python fixture:running_app
|
189
|
+
from modal import Sandbox
|
190
|
+
|
191
|
+
sandbox = Sandbox.create(
|
192
|
+
"bash",
|
193
|
+
"-c",
|
194
|
+
"for i in $(seq 1 10); do echo foo; sleep 0.1; done",
|
195
|
+
app=running_app,
|
196
|
+
)
|
197
|
+
for message in sandbox.stdout:
|
198
|
+
print(f"Message: {message}")
|
199
|
+
```
|
200
|
+
"""
|
201
|
+
|
56
202
|
_stream: typing.Optional[collections.abc.AsyncGenerator[typing.Optional[bytes], None]]
|
57
203
|
|
58
204
|
def __init__(
|
@@ -64,61 +210,218 @@ class StreamReader(typing.Generic[T]):
|
|
64
210
|
stream_type: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
65
211
|
text: bool = True,
|
66
212
|
by_line: bool = False,
|
67
|
-
) -> None:
|
213
|
+
) -> None:
|
214
|
+
"""mdmd:hidden"""
|
215
|
+
...
|
216
|
+
|
68
217
|
@property
|
69
|
-
def file_descriptor(self) -> int:
|
218
|
+
def file_descriptor(self) -> int:
|
219
|
+
"""Possible values are `1` for stdout and `2` for stderr."""
|
220
|
+
...
|
70
221
|
|
71
222
|
class __read_spec(typing_extensions.Protocol[T_INNER, SUPERSELF]):
|
72
|
-
def __call__(self, /) -> T_INNER:
|
73
|
-
|
223
|
+
def __call__(self, /) -> T_INNER:
|
224
|
+
"""Fetch the entire contents of the stream until EOF.
|
225
|
+
|
226
|
+
**Usage**
|
227
|
+
|
228
|
+
```python fixture:running_app
|
229
|
+
from modal import Sandbox
|
230
|
+
|
231
|
+
sandbox = Sandbox.create("echo", "hello", app=running_app)
|
232
|
+
sandbox.wait()
|
233
|
+
|
234
|
+
print(sandbox.stdout.read())
|
235
|
+
```
|
236
|
+
"""
|
237
|
+
...
|
238
|
+
|
239
|
+
async def aio(self, /) -> T_INNER:
|
240
|
+
"""Fetch the entire contents of the stream until EOF.
|
241
|
+
|
242
|
+
**Usage**
|
243
|
+
|
244
|
+
```python fixture:running_app
|
245
|
+
from modal import Sandbox
|
246
|
+
|
247
|
+
sandbox = Sandbox.create("echo", "hello", app=running_app)
|
248
|
+
sandbox.wait()
|
249
|
+
|
250
|
+
print(sandbox.stdout.read())
|
251
|
+
```
|
252
|
+
"""
|
253
|
+
...
|
74
254
|
|
75
255
|
read: __read_spec[T, typing_extensions.Self]
|
76
256
|
|
77
257
|
class ___consume_container_process_stream_spec(typing_extensions.Protocol[SUPERSELF]):
|
78
|
-
def __call__(self, /):
|
79
|
-
|
258
|
+
def __call__(self, /):
|
259
|
+
"""Consume the container process stream and store messages in the buffer."""
|
260
|
+
...
|
261
|
+
|
262
|
+
async def aio(self, /):
|
263
|
+
"""Consume the container process stream and store messages in the buffer."""
|
264
|
+
...
|
80
265
|
|
81
266
|
_consume_container_process_stream: ___consume_container_process_stream_spec[typing_extensions.Self]
|
82
267
|
|
83
268
|
class ___stream_container_process_spec(typing_extensions.Protocol[SUPERSELF]):
|
84
|
-
def __call__(self, /) -> typing.Generator[tuple[typing.Optional[bytes], str], None, None]:
|
85
|
-
|
269
|
+
def __call__(self, /) -> typing.Generator[tuple[typing.Optional[bytes], str], None, None]:
|
270
|
+
"""Streams the container process buffer to the reader."""
|
271
|
+
...
|
272
|
+
|
273
|
+
def aio(self, /) -> collections.abc.AsyncGenerator[tuple[typing.Optional[bytes], str], None]:
|
274
|
+
"""Streams the container process buffer to the reader."""
|
275
|
+
...
|
86
276
|
|
87
277
|
_stream_container_process: ___stream_container_process_spec[typing_extensions.Self]
|
88
278
|
|
89
279
|
class ___get_logs_spec(typing_extensions.Protocol[SUPERSELF]):
|
90
|
-
def __call__(
|
91
|
-
|
92
|
-
|
280
|
+
def __call__(self, /, skip_empty_messages: bool = True) -> typing.Generator[typing.Optional[bytes], None, None]:
|
281
|
+
"""Streams sandbox or process logs from the server to the reader.
|
282
|
+
|
283
|
+
Logs returned by this method may contain partial or multiple lines at a time.
|
284
|
+
|
285
|
+
When the stream receives an EOF, it yields None. Once an EOF is received,
|
286
|
+
subsequent invocations will not yield logs.
|
287
|
+
"""
|
288
|
+
...
|
289
|
+
|
93
290
|
def aio(
|
94
291
|
self, /, skip_empty_messages: bool = True
|
95
|
-
) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
292
|
+
) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
293
|
+
"""Streams sandbox or process logs from the server to the reader.
|
294
|
+
|
295
|
+
Logs returned by this method may contain partial or multiple lines at a time.
|
296
|
+
|
297
|
+
When the stream receives an EOF, it yields None. Once an EOF is received,
|
298
|
+
subsequent invocations will not yield logs.
|
299
|
+
"""
|
300
|
+
...
|
96
301
|
|
97
302
|
_get_logs: ___get_logs_spec[typing_extensions.Self]
|
98
303
|
|
99
304
|
class ___get_logs_by_line_spec(typing_extensions.Protocol[SUPERSELF]):
|
100
|
-
def __call__(self, /) -> typing.Generator[typing.Optional[bytes], None, None]:
|
101
|
-
|
305
|
+
def __call__(self, /) -> typing.Generator[typing.Optional[bytes], None, None]:
|
306
|
+
"""Process logs from the server and yield complete lines only."""
|
307
|
+
...
|
308
|
+
|
309
|
+
def aio(self, /) -> collections.abc.AsyncGenerator[typing.Optional[bytes], None]:
|
310
|
+
"""Process logs from the server and yield complete lines only."""
|
311
|
+
...
|
102
312
|
|
103
313
|
_get_logs_by_line: ___get_logs_by_line_spec[typing_extensions.Self]
|
104
314
|
|
105
|
-
def __iter__(self) -> typing.Iterator[T]:
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def
|
110
|
-
|
315
|
+
def __iter__(self) -> typing.Iterator[T]:
|
316
|
+
"""mdmd:hidden"""
|
317
|
+
...
|
318
|
+
|
319
|
+
def __aiter__(self) -> collections.abc.AsyncIterator[T]:
|
320
|
+
"""mdmd:hidden"""
|
321
|
+
...
|
322
|
+
|
323
|
+
def __next__(self) -> T:
|
324
|
+
"""mdmd:hidden"""
|
325
|
+
...
|
326
|
+
|
327
|
+
async def __anext__(self) -> T:
|
328
|
+
"""mdmd:hidden"""
|
329
|
+
...
|
330
|
+
|
331
|
+
def close(self):
|
332
|
+
"""mdmd:hidden"""
|
333
|
+
...
|
334
|
+
|
335
|
+
async def aclose(self):
|
336
|
+
"""mdmd:hidden"""
|
337
|
+
...
|
111
338
|
|
112
339
|
class StreamWriter:
|
340
|
+
"""Provides an interface to buffer and write logs to a sandbox or container process stream (`stdin`)."""
|
113
341
|
def __init__(
|
114
342
|
self, object_id: str, object_type: typing.Literal["sandbox", "container_process"], client: modal.client.Client
|
115
|
-
) -> None:
|
343
|
+
) -> None:
|
344
|
+
"""mdmd:hidden"""
|
345
|
+
...
|
346
|
+
|
116
347
|
def _get_next_index(self) -> int: ...
|
117
|
-
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None:
|
118
|
-
|
348
|
+
def write(self, data: typing.Union[bytes, bytearray, memoryview, str]) -> None:
|
349
|
+
"""Write data to the stream but does not send it immediately.
|
350
|
+
|
351
|
+
This is non-blocking and queues the data to an internal buffer. Must be
|
352
|
+
used along with the `drain()` method, which flushes the buffer.
|
353
|
+
|
354
|
+
**Usage**
|
355
|
+
|
356
|
+
```python fixture:running_app
|
357
|
+
from modal import Sandbox
|
358
|
+
|
359
|
+
sandbox = Sandbox.create(
|
360
|
+
"bash",
|
361
|
+
"-c",
|
362
|
+
"while read line; do echo $line; done",
|
363
|
+
app=running_app,
|
364
|
+
)
|
365
|
+
sandbox.stdin.write(b"foo\n")
|
366
|
+
sandbox.stdin.write(b"bar\n")
|
367
|
+
sandbox.stdin.write_eof()
|
368
|
+
|
369
|
+
sandbox.stdin.drain()
|
370
|
+
sandbox.wait()
|
371
|
+
```
|
372
|
+
"""
|
373
|
+
...
|
374
|
+
|
375
|
+
def write_eof(self) -> None:
|
376
|
+
"""Close the write end of the stream after the buffered data is drained.
|
377
|
+
|
378
|
+
If the process was blocked on input, it will become unblocked after
|
379
|
+
`write_eof()`. This method needs to be used along with the `drain()`
|
380
|
+
method, which flushes the EOF to the process.
|
381
|
+
"""
|
382
|
+
...
|
119
383
|
|
120
384
|
class __drain_spec(typing_extensions.Protocol[SUPERSELF]):
|
121
|
-
def __call__(self, /) -> None:
|
122
|
-
|
385
|
+
def __call__(self, /) -> None:
|
386
|
+
"""Flush the write buffer and send data to the running process.
|
387
|
+
|
388
|
+
This is a flow control method that blocks until data is sent. It returns
|
389
|
+
when it is appropriate to continue writing data to the stream.
|
390
|
+
|
391
|
+
**Usage**
|
392
|
+
|
393
|
+
```python notest
|
394
|
+
writer.write(data)
|
395
|
+
writer.drain()
|
396
|
+
```
|
397
|
+
|
398
|
+
Async usage:
|
399
|
+
```python notest
|
400
|
+
writer.write(data) # not a blocking operation
|
401
|
+
await writer.drain.aio()
|
402
|
+
```
|
403
|
+
"""
|
404
|
+
...
|
405
|
+
|
406
|
+
async def aio(self, /) -> None:
|
407
|
+
"""Flush the write buffer and send data to the running process.
|
408
|
+
|
409
|
+
This is a flow control method that blocks until data is sent. It returns
|
410
|
+
when it is appropriate to continue writing data to the stream.
|
411
|
+
|
412
|
+
**Usage**
|
413
|
+
|
414
|
+
```python notest
|
415
|
+
writer.write(data)
|
416
|
+
writer.drain()
|
417
|
+
```
|
418
|
+
|
419
|
+
Async usage:
|
420
|
+
```python notest
|
421
|
+
writer.write(data) # not a blocking operation
|
422
|
+
await writer.drain.aio()
|
423
|
+
```
|
424
|
+
"""
|
425
|
+
...
|
123
426
|
|
124
427
|
drain: __drain_spec[typing_extensions.Self]
|