modal 0.67.0__py3-none-any.whl → 0.67.22__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.py +2 -2
- modal/_clustered_functions.pyi +2 -2
- modal/_container_entrypoint.py +5 -4
- modal/_output.py +29 -28
- modal/_pty.py +2 -2
- modal/_resolver.py +6 -5
- modal/_resources.py +3 -3
- modal/_runtime/asgi.py +46 -6
- modal/_runtime/container_io_manager.py +22 -26
- modal/_runtime/execution_context.py +2 -2
- modal/_runtime/telemetry.py +1 -2
- modal/_runtime/user_code_imports.py +12 -14
- modal/_serialization.py +3 -7
- modal/_traceback.py +5 -5
- modal/_tunnel.py +5 -4
- modal/_tunnel.pyi +2 -2
- modal/_utils/async_utils.py +53 -17
- modal/_utils/blob_utils.py +22 -7
- modal/_utils/function_utils.py +14 -10
- modal/_utils/grpc_testing.py +7 -6
- modal/_utils/grpc_utils.py +2 -3
- modal/_utils/hash_utils.py +2 -2
- modal/_utils/mount_utils.py +5 -4
- modal/_utils/package_utils.py +2 -3
- modal/_utils/pattern_matcher.py +6 -6
- modal/_utils/rand_pb_testing.py +3 -3
- modal/_utils/shell_utils.py +2 -1
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +8 -7
- modal/app.py +81 -69
- modal/app.pyi +104 -99
- modal/call_graph.py +6 -6
- modal/cli/_download.py +3 -2
- modal/cli/_traceback.py +4 -4
- modal/cli/app.py +4 -4
- modal/cli/container.py +4 -4
- modal/cli/dict.py +1 -1
- modal/cli/environment.py +2 -3
- modal/cli/import_refs.py +1 -1
- modal/cli/launch.py +2 -2
- modal/cli/network_file_system.py +1 -1
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +2 -2
- modal/cli/programs/vscode.py +3 -3
- modal/cli/queues.py +1 -1
- modal/cli/run.py +6 -6
- modal/cli/secret.py +3 -3
- modal/cli/utils.py +2 -1
- modal/cli/volume.py +3 -3
- modal/client.py +6 -11
- modal/client.pyi +18 -27
- modal/cloud_bucket_mount.py +3 -3
- modal/cloud_bucket_mount.pyi +2 -2
- modal/cls.py +32 -32
- modal/cls.pyi +35 -34
- modal/config.py +3 -2
- modal/container_process.py +6 -2
- modal/dict.py +6 -3
- modal/dict.pyi +10 -9
- modal/environments.py +3 -3
- modal/environments.pyi +3 -3
- modal/exception.py +2 -3
- modal/functions.py +111 -40
- modal/functions.pyi +71 -48
- modal/image.py +46 -49
- modal/image.pyi +102 -101
- modal/io_streams.py +20 -12
- modal/io_streams.pyi +24 -14
- modal/mount.py +24 -24
- modal/mount.pyi +28 -29
- modal/network_file_system.py +14 -11
- modal/network_file_system.pyi +12 -11
- modal/object.py +9 -8
- modal/object.pyi +47 -34
- modal/output.py +2 -1
- modal/parallel_map.py +4 -4
- modal/partial_function.py +10 -14
- modal/partial_function.pyi +17 -18
- modal/queue.py +11 -8
- modal/queue.pyi +23 -22
- modal/retries.py +38 -0
- modal/runner.py +8 -7
- modal/runner.pyi +8 -14
- modal/running_app.py +3 -3
- modal/sandbox.py +20 -13
- modal/sandbox.pyi +73 -72
- modal/scheduler_placement.py +2 -1
- modal/secret.py +7 -7
- modal/secret.pyi +12 -12
- modal/serving.py +4 -3
- modal/serving.pyi +5 -4
- modal/token_flow.py +3 -2
- modal/token_flow.pyi +3 -3
- modal/volume.py +16 -23
- modal/volume.pyi +17 -16
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/METADATA +2 -2
- modal-0.67.22.dist-info/RECORD +168 -0
- modal_docs/mdmd/signatures.py +1 -2
- modal_global_objects/mounts/python_standalone.py +1 -1
- modal_proto/api.proto +13 -0
- modal_proto/api_grpc.py +16 -0
- modal_proto/api_pb2.py +241 -221
- modal_proto/api_pb2.pyi +41 -0
- modal_proto/api_pb2_grpc.py +33 -0
- modal_proto/api_pb2_grpc.pyi +10 -0
- modal_proto/modal_api_grpc.py +1 -0
- modal_version/_version_generated.py +1 -1
- modal-0.67.0.dist-info/RECORD +0 -168
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/LICENSE +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/WHEEL +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/entry_points.txt +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/top_level.txt +0 -0
modal/image.pyi
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import google.protobuf.message
|
2
3
|
import modal.client
|
3
4
|
import modal.cloud_bucket_mount
|
@@ -29,9 +30,9 @@ def _get_modal_requirements_path(
|
|
29
30
|
) -> str: ...
|
30
31
|
def _get_modal_requirements_command(version: typing.Literal["2023.12", "2024.04", "2024.10"]) -> str: ...
|
31
32
|
def _flatten_str_args(
|
32
|
-
function_name: str, arg_name: str, args:
|
33
|
-
) ->
|
34
|
-
def _validate_packages(packages:
|
33
|
+
function_name: str, arg_name: str, args: collections.abc.Sequence[typing.Union[str, list[str]]]
|
34
|
+
) -> list[str]: ...
|
35
|
+
def _validate_packages(packages: list[str]) -> bool: ...
|
35
36
|
def _warn_invalid_packages(old_command: str) -> None: ...
|
36
37
|
def _make_pip_install_args(
|
37
38
|
find_links: typing.Optional[str] = None,
|
@@ -49,10 +50,10 @@ class _ImageRegistryConfig:
|
|
49
50
|
def get_proto(self) -> modal_proto.api_pb2.ImageRegistryConfig: ...
|
50
51
|
|
51
52
|
class DockerfileSpec:
|
52
|
-
commands:
|
53
|
-
context_files:
|
53
|
+
commands: list[str]
|
54
|
+
context_files: dict[str, str]
|
54
55
|
|
55
|
-
def __init__(self, commands:
|
56
|
+
def __init__(self, commands: list[str], context_files: dict[str, str]) -> None: ...
|
56
57
|
def __repr__(self): ...
|
57
58
|
def __eq__(self, other): ...
|
58
59
|
|
@@ -62,9 +63,9 @@ async def _image_await_build_result(
|
|
62
63
|
|
63
64
|
class _Image(modal.object._Object):
|
64
65
|
force_build: bool
|
65
|
-
inside_exceptions:
|
66
|
-
_serve_mounts:
|
67
|
-
_deferred_mounts:
|
66
|
+
inside_exceptions: list[Exception]
|
67
|
+
_serve_mounts: frozenset[modal.mount._Mount]
|
68
|
+
_deferred_mounts: collections.abc.Sequence[modal.mount._Mount]
|
68
69
|
_metadata: typing.Optional[modal_proto.api_pb2.ImageMetadata]
|
69
70
|
|
70
71
|
def _initialize_from_empty(self): ...
|
@@ -77,11 +78,11 @@ class _Image(modal.object._Object):
|
|
77
78
|
@staticmethod
|
78
79
|
def _from_args(
|
79
80
|
*,
|
80
|
-
base_images: typing.Optional[
|
81
|
+
base_images: typing.Optional[dict[str, _Image]] = None,
|
81
82
|
dockerfile_function: typing.Optional[
|
82
83
|
typing.Callable[[typing.Literal["2023.12", "2024.04", "2024.10"]], DockerfileSpec]
|
83
84
|
] = None,
|
84
|
-
secrets: typing.Optional[
|
85
|
+
secrets: typing.Optional[collections.abc.Sequence[modal.secret._Secret]] = None,
|
85
86
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
86
87
|
build_function: typing.Optional[modal.functions._Function] = None,
|
87
88
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
@@ -94,7 +95,7 @@ class _Image(modal.object._Object):
|
|
94
95
|
def extend(
|
95
96
|
self,
|
96
97
|
*,
|
97
|
-
secrets: typing.Optional[
|
98
|
+
secrets: typing.Optional[collections.abc.Sequence[modal.secret._Secret]] = None,
|
98
99
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
99
100
|
build_function: typing.Optional[modal.functions._Function] = None,
|
100
101
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
@@ -120,14 +121,14 @@ class _Image(modal.object._Object):
|
|
120
121
|
) -> _Image: ...
|
121
122
|
def pip_install(
|
122
123
|
self,
|
123
|
-
*packages: typing.Union[str,
|
124
|
+
*packages: typing.Union[str, list[str]],
|
124
125
|
find_links: typing.Optional[str] = None,
|
125
126
|
index_url: typing.Optional[str] = None,
|
126
127
|
extra_index_url: typing.Optional[str] = None,
|
127
128
|
pre: bool = False,
|
128
129
|
extra_options: str = "",
|
129
130
|
force_build: bool = False,
|
130
|
-
secrets:
|
131
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
131
132
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
132
133
|
) -> _Image: ...
|
133
134
|
def pip_install_private_repos(
|
@@ -140,7 +141,7 @@ class _Image(modal.object._Object):
|
|
140
141
|
pre: bool = False,
|
141
142
|
extra_options: str = "",
|
142
143
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
143
|
-
secrets:
|
144
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
144
145
|
force_build: bool = False,
|
145
146
|
) -> _Image: ...
|
146
147
|
def pip_install_from_requirements(
|
@@ -153,13 +154,13 @@ class _Image(modal.object._Object):
|
|
153
154
|
pre: bool = False,
|
154
155
|
extra_options: str = "",
|
155
156
|
force_build: bool = False,
|
156
|
-
secrets:
|
157
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
157
158
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
158
159
|
) -> _Image: ...
|
159
160
|
def pip_install_from_pyproject(
|
160
161
|
self,
|
161
162
|
pyproject_toml: str,
|
162
|
-
optional_dependencies:
|
163
|
+
optional_dependencies: list[str] = [],
|
163
164
|
*,
|
164
165
|
find_links: typing.Optional[str] = None,
|
165
166
|
index_url: typing.Optional[str] = None,
|
@@ -167,7 +168,7 @@ class _Image(modal.object._Object):
|
|
167
168
|
pre: bool = False,
|
168
169
|
extra_options: str = "",
|
169
170
|
force_build: bool = False,
|
170
|
-
secrets:
|
171
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
171
172
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
172
173
|
) -> _Image: ...
|
173
174
|
def poetry_install_from_file(
|
@@ -177,28 +178,28 @@ class _Image(modal.object._Object):
|
|
177
178
|
ignore_lockfile: bool = False,
|
178
179
|
old_installer: bool = False,
|
179
180
|
force_build: bool = False,
|
180
|
-
with_:
|
181
|
-
without:
|
182
|
-
only:
|
181
|
+
with_: list[str] = [],
|
182
|
+
without: list[str] = [],
|
183
|
+
only: list[str] = [],
|
183
184
|
*,
|
184
|
-
secrets:
|
185
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
185
186
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
186
187
|
) -> _Image: ...
|
187
188
|
def dockerfile_commands(
|
188
189
|
self,
|
189
|
-
*dockerfile_commands: typing.Union[str,
|
190
|
-
context_files:
|
191
|
-
secrets:
|
190
|
+
*dockerfile_commands: typing.Union[str, list[str]],
|
191
|
+
context_files: dict[str, str] = {},
|
192
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
192
193
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
193
194
|
context_mount: typing.Optional[modal.mount._Mount] = None,
|
194
195
|
force_build: bool = False,
|
195
196
|
) -> _Image: ...
|
196
|
-
def entrypoint(self, entrypoint_commands:
|
197
|
-
def shell(self, shell_commands:
|
197
|
+
def entrypoint(self, entrypoint_commands: list[str]) -> _Image: ...
|
198
|
+
def shell(self, shell_commands: list[str]) -> _Image: ...
|
198
199
|
def run_commands(
|
199
200
|
self,
|
200
|
-
*commands: typing.Union[str,
|
201
|
-
secrets:
|
201
|
+
*commands: typing.Union[str, list[str]],
|
202
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
202
203
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
203
204
|
force_build: bool = False,
|
204
205
|
) -> _Image: ...
|
@@ -206,10 +207,10 @@ class _Image(modal.object._Object):
|
|
206
207
|
def conda(python_version: typing.Optional[str] = None, force_build: bool = False): ...
|
207
208
|
def conda_install(
|
208
209
|
self,
|
209
|
-
*packages: typing.Union[str,
|
210
|
-
channels:
|
210
|
+
*packages: typing.Union[str, list[str]],
|
211
|
+
channels: list[str] = [],
|
211
212
|
force_build: bool = False,
|
212
|
-
secrets:
|
213
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
213
214
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
214
215
|
): ...
|
215
216
|
def conda_update_from_environment(
|
@@ -217,33 +218,33 @@ class _Image(modal.object._Object):
|
|
217
218
|
environment_yml: str,
|
218
219
|
force_build: bool = False,
|
219
220
|
*,
|
220
|
-
secrets:
|
221
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
221
222
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
222
223
|
): ...
|
223
224
|
@staticmethod
|
224
225
|
def micromamba(python_version: typing.Optional[str] = None, force_build: bool = False) -> _Image: ...
|
225
226
|
def micromamba_install(
|
226
227
|
self,
|
227
|
-
*packages: typing.Union[str,
|
228
|
+
*packages: typing.Union[str, list[str]],
|
228
229
|
spec_file: typing.Optional[str] = None,
|
229
|
-
channels:
|
230
|
+
channels: list[str] = [],
|
230
231
|
force_build: bool = False,
|
231
|
-
secrets:
|
232
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
232
233
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
233
234
|
) -> _Image: ...
|
234
235
|
@staticmethod
|
235
236
|
def _registry_setup_commands(
|
236
237
|
tag: str,
|
237
238
|
builder_version: typing.Literal["2023.12", "2024.04", "2024.10"],
|
238
|
-
setup_commands:
|
239
|
+
setup_commands: list[str],
|
239
240
|
add_python: typing.Optional[str] = None,
|
240
|
-
) ->
|
241
|
+
) -> list[str]: ...
|
241
242
|
@staticmethod
|
242
243
|
def from_registry(
|
243
244
|
tag: str,
|
244
245
|
*,
|
245
246
|
secret: typing.Optional[modal.secret._Secret] = None,
|
246
|
-
setup_dockerfile_commands:
|
247
|
+
setup_dockerfile_commands: list[str] = [],
|
247
248
|
force_build: bool = False,
|
248
249
|
add_python: typing.Optional[str] = None,
|
249
250
|
**kwargs,
|
@@ -253,7 +254,7 @@ class _Image(modal.object._Object):
|
|
253
254
|
tag: str,
|
254
255
|
secret: typing.Optional[modal.secret._Secret] = None,
|
255
256
|
*,
|
256
|
-
setup_dockerfile_commands:
|
257
|
+
setup_dockerfile_commands: list[str] = [],
|
257
258
|
force_build: bool = False,
|
258
259
|
add_python: typing.Optional[str] = None,
|
259
260
|
**kwargs,
|
@@ -263,7 +264,7 @@ class _Image(modal.object._Object):
|
|
263
264
|
tag: str,
|
264
265
|
secret: typing.Optional[modal.secret._Secret] = None,
|
265
266
|
*,
|
266
|
-
setup_dockerfile_commands:
|
267
|
+
setup_dockerfile_commands: list[str] = [],
|
267
268
|
force_build: bool = False,
|
268
269
|
add_python: typing.Optional[str] = None,
|
269
270
|
**kwargs,
|
@@ -274,7 +275,7 @@ class _Image(modal.object._Object):
|
|
274
275
|
context_mount: typing.Optional[modal.mount._Mount] = None,
|
275
276
|
force_build: bool = False,
|
276
277
|
*,
|
277
|
-
secrets:
|
278
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
278
279
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
279
280
|
add_python: typing.Optional[str] = None,
|
280
281
|
) -> _Image: ...
|
@@ -282,24 +283,24 @@ class _Image(modal.object._Object):
|
|
282
283
|
def debian_slim(python_version: typing.Optional[str] = None, force_build: bool = False) -> _Image: ...
|
283
284
|
def apt_install(
|
284
285
|
self,
|
285
|
-
*packages: typing.Union[str,
|
286
|
+
*packages: typing.Union[str, list[str]],
|
286
287
|
force_build: bool = False,
|
287
|
-
secrets:
|
288
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
288
289
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
289
290
|
) -> _Image: ...
|
290
291
|
def run_function(
|
291
292
|
self,
|
292
293
|
raw_f: typing.Callable[..., typing.Any],
|
293
|
-
secrets:
|
294
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
294
295
|
gpu: typing.Union[
|
295
|
-
None, bool, str, modal.gpu._GPUConfig,
|
296
|
+
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
296
297
|
] = None,
|
297
|
-
mounts:
|
298
|
-
volumes:
|
298
|
+
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
299
|
+
volumes: dict[
|
299
300
|
typing.Union[str, pathlib.PurePosixPath],
|
300
301
|
typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
|
301
302
|
] = {},
|
302
|
-
network_file_systems:
|
303
|
+
network_file_systems: dict[
|
303
304
|
typing.Union[str, pathlib.PurePosixPath], modal.network_file_system._NetworkFileSystem
|
304
305
|
] = {},
|
305
306
|
cpu: typing.Optional[float] = None,
|
@@ -307,20 +308,20 @@ class _Image(modal.object._Object):
|
|
307
308
|
timeout: typing.Optional[int] = 3600,
|
308
309
|
force_build: bool = False,
|
309
310
|
cloud: typing.Optional[str] = None,
|
310
|
-
region: typing.Union[str,
|
311
|
-
args:
|
312
|
-
kwargs:
|
311
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
312
|
+
args: collections.abc.Sequence[typing.Any] = (),
|
313
|
+
kwargs: dict[str, typing.Any] = {},
|
313
314
|
) -> _Image: ...
|
314
|
-
def env(self, vars:
|
315
|
+
def env(self, vars: dict[str, str]) -> _Image: ...
|
315
316
|
def workdir(self, path: typing.Union[str, pathlib.PurePosixPath]) -> _Image: ...
|
316
317
|
def imports(self): ...
|
317
318
|
def _logs(self) -> typing.AsyncGenerator[str, None]: ...
|
318
319
|
|
319
320
|
class Image(modal.object.Object):
|
320
321
|
force_build: bool
|
321
|
-
inside_exceptions:
|
322
|
-
_serve_mounts:
|
323
|
-
_deferred_mounts:
|
322
|
+
inside_exceptions: list[Exception]
|
323
|
+
_serve_mounts: frozenset[modal.mount.Mount]
|
324
|
+
_deferred_mounts: collections.abc.Sequence[modal.mount.Mount]
|
324
325
|
_metadata: typing.Optional[modal_proto.api_pb2.ImageMetadata]
|
325
326
|
|
326
327
|
def __init__(self, *args, **kwargs): ...
|
@@ -334,11 +335,11 @@ class Image(modal.object.Object):
|
|
334
335
|
@staticmethod
|
335
336
|
def _from_args(
|
336
337
|
*,
|
337
|
-
base_images: typing.Optional[
|
338
|
+
base_images: typing.Optional[dict[str, Image]] = None,
|
338
339
|
dockerfile_function: typing.Optional[
|
339
340
|
typing.Callable[[typing.Literal["2023.12", "2024.04", "2024.10"]], DockerfileSpec]
|
340
341
|
] = None,
|
341
|
-
secrets: typing.Optional[
|
342
|
+
secrets: typing.Optional[collections.abc.Sequence[modal.secret.Secret]] = None,
|
342
343
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
343
344
|
build_function: typing.Optional[modal.functions.Function] = None,
|
344
345
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
@@ -351,7 +352,7 @@ class Image(modal.object.Object):
|
|
351
352
|
def extend(
|
352
353
|
self,
|
353
354
|
*,
|
354
|
-
secrets: typing.Optional[
|
355
|
+
secrets: typing.Optional[collections.abc.Sequence[modal.secret.Secret]] = None,
|
355
356
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
356
357
|
build_function: typing.Optional[modal.functions.Function] = None,
|
357
358
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
@@ -377,14 +378,14 @@ class Image(modal.object.Object):
|
|
377
378
|
) -> Image: ...
|
378
379
|
def pip_install(
|
379
380
|
self,
|
380
|
-
*packages: typing.Union[str,
|
381
|
+
*packages: typing.Union[str, list[str]],
|
381
382
|
find_links: typing.Optional[str] = None,
|
382
383
|
index_url: typing.Optional[str] = None,
|
383
384
|
extra_index_url: typing.Optional[str] = None,
|
384
385
|
pre: bool = False,
|
385
386
|
extra_options: str = "",
|
386
387
|
force_build: bool = False,
|
387
|
-
secrets:
|
388
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
388
389
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
389
390
|
) -> Image: ...
|
390
391
|
def pip_install_private_repos(
|
@@ -397,7 +398,7 @@ class Image(modal.object.Object):
|
|
397
398
|
pre: bool = False,
|
398
399
|
extra_options: str = "",
|
399
400
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
400
|
-
secrets:
|
401
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
401
402
|
force_build: bool = False,
|
402
403
|
) -> Image: ...
|
403
404
|
def pip_install_from_requirements(
|
@@ -410,13 +411,13 @@ class Image(modal.object.Object):
|
|
410
411
|
pre: bool = False,
|
411
412
|
extra_options: str = "",
|
412
413
|
force_build: bool = False,
|
413
|
-
secrets:
|
414
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
414
415
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
415
416
|
) -> Image: ...
|
416
417
|
def pip_install_from_pyproject(
|
417
418
|
self,
|
418
419
|
pyproject_toml: str,
|
419
|
-
optional_dependencies:
|
420
|
+
optional_dependencies: list[str] = [],
|
420
421
|
*,
|
421
422
|
find_links: typing.Optional[str] = None,
|
422
423
|
index_url: typing.Optional[str] = None,
|
@@ -424,7 +425,7 @@ class Image(modal.object.Object):
|
|
424
425
|
pre: bool = False,
|
425
426
|
extra_options: str = "",
|
426
427
|
force_build: bool = False,
|
427
|
-
secrets:
|
428
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
428
429
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
429
430
|
) -> Image: ...
|
430
431
|
def poetry_install_from_file(
|
@@ -434,28 +435,28 @@ class Image(modal.object.Object):
|
|
434
435
|
ignore_lockfile: bool = False,
|
435
436
|
old_installer: bool = False,
|
436
437
|
force_build: bool = False,
|
437
|
-
with_:
|
438
|
-
without:
|
439
|
-
only:
|
438
|
+
with_: list[str] = [],
|
439
|
+
without: list[str] = [],
|
440
|
+
only: list[str] = [],
|
440
441
|
*,
|
441
|
-
secrets:
|
442
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
442
443
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
443
444
|
) -> Image: ...
|
444
445
|
def dockerfile_commands(
|
445
446
|
self,
|
446
|
-
*dockerfile_commands: typing.Union[str,
|
447
|
-
context_files:
|
448
|
-
secrets:
|
447
|
+
*dockerfile_commands: typing.Union[str, list[str]],
|
448
|
+
context_files: dict[str, str] = {},
|
449
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
449
450
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
450
451
|
context_mount: typing.Optional[modal.mount.Mount] = None,
|
451
452
|
force_build: bool = False,
|
452
453
|
) -> Image: ...
|
453
|
-
def entrypoint(self, entrypoint_commands:
|
454
|
-
def shell(self, shell_commands:
|
454
|
+
def entrypoint(self, entrypoint_commands: list[str]) -> Image: ...
|
455
|
+
def shell(self, shell_commands: list[str]) -> Image: ...
|
455
456
|
def run_commands(
|
456
457
|
self,
|
457
|
-
*commands: typing.Union[str,
|
458
|
-
secrets:
|
458
|
+
*commands: typing.Union[str, list[str]],
|
459
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
459
460
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
460
461
|
force_build: bool = False,
|
461
462
|
) -> Image: ...
|
@@ -463,10 +464,10 @@ class Image(modal.object.Object):
|
|
463
464
|
def conda(python_version: typing.Optional[str] = None, force_build: bool = False): ...
|
464
465
|
def conda_install(
|
465
466
|
self,
|
466
|
-
*packages: typing.Union[str,
|
467
|
-
channels:
|
467
|
+
*packages: typing.Union[str, list[str]],
|
468
|
+
channels: list[str] = [],
|
468
469
|
force_build: bool = False,
|
469
|
-
secrets:
|
470
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
470
471
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
471
472
|
): ...
|
472
473
|
def conda_update_from_environment(
|
@@ -474,33 +475,33 @@ class Image(modal.object.Object):
|
|
474
475
|
environment_yml: str,
|
475
476
|
force_build: bool = False,
|
476
477
|
*,
|
477
|
-
secrets:
|
478
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
478
479
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
479
480
|
): ...
|
480
481
|
@staticmethod
|
481
482
|
def micromamba(python_version: typing.Optional[str] = None, force_build: bool = False) -> Image: ...
|
482
483
|
def micromamba_install(
|
483
484
|
self,
|
484
|
-
*packages: typing.Union[str,
|
485
|
+
*packages: typing.Union[str, list[str]],
|
485
486
|
spec_file: typing.Optional[str] = None,
|
486
|
-
channels:
|
487
|
+
channels: list[str] = [],
|
487
488
|
force_build: bool = False,
|
488
|
-
secrets:
|
489
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
489
490
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
490
491
|
) -> Image: ...
|
491
492
|
@staticmethod
|
492
493
|
def _registry_setup_commands(
|
493
494
|
tag: str,
|
494
495
|
builder_version: typing.Literal["2023.12", "2024.04", "2024.10"],
|
495
|
-
setup_commands:
|
496
|
+
setup_commands: list[str],
|
496
497
|
add_python: typing.Optional[str] = None,
|
497
|
-
) ->
|
498
|
+
) -> list[str]: ...
|
498
499
|
@staticmethod
|
499
500
|
def from_registry(
|
500
501
|
tag: str,
|
501
502
|
*,
|
502
503
|
secret: typing.Optional[modal.secret.Secret] = None,
|
503
|
-
setup_dockerfile_commands:
|
504
|
+
setup_dockerfile_commands: list[str] = [],
|
504
505
|
force_build: bool = False,
|
505
506
|
add_python: typing.Optional[str] = None,
|
506
507
|
**kwargs,
|
@@ -510,7 +511,7 @@ class Image(modal.object.Object):
|
|
510
511
|
tag: str,
|
511
512
|
secret: typing.Optional[modal.secret.Secret] = None,
|
512
513
|
*,
|
513
|
-
setup_dockerfile_commands:
|
514
|
+
setup_dockerfile_commands: list[str] = [],
|
514
515
|
force_build: bool = False,
|
515
516
|
add_python: typing.Optional[str] = None,
|
516
517
|
**kwargs,
|
@@ -520,7 +521,7 @@ class Image(modal.object.Object):
|
|
520
521
|
tag: str,
|
521
522
|
secret: typing.Optional[modal.secret.Secret] = None,
|
522
523
|
*,
|
523
|
-
setup_dockerfile_commands:
|
524
|
+
setup_dockerfile_commands: list[str] = [],
|
524
525
|
force_build: bool = False,
|
525
526
|
add_python: typing.Optional[str] = None,
|
526
527
|
**kwargs,
|
@@ -531,7 +532,7 @@ class Image(modal.object.Object):
|
|
531
532
|
context_mount: typing.Optional[modal.mount.Mount] = None,
|
532
533
|
force_build: bool = False,
|
533
534
|
*,
|
534
|
-
secrets:
|
535
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
535
536
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
536
537
|
add_python: typing.Optional[str] = None,
|
537
538
|
) -> Image: ...
|
@@ -539,24 +540,24 @@ class Image(modal.object.Object):
|
|
539
540
|
def debian_slim(python_version: typing.Optional[str] = None, force_build: bool = False) -> Image: ...
|
540
541
|
def apt_install(
|
541
542
|
self,
|
542
|
-
*packages: typing.Union[str,
|
543
|
+
*packages: typing.Union[str, list[str]],
|
543
544
|
force_build: bool = False,
|
544
|
-
secrets:
|
545
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
545
546
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
546
547
|
) -> Image: ...
|
547
548
|
def run_function(
|
548
549
|
self,
|
549
550
|
raw_f: typing.Callable[..., typing.Any],
|
550
|
-
secrets:
|
551
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
551
552
|
gpu: typing.Union[
|
552
|
-
None, bool, str, modal.gpu._GPUConfig,
|
553
|
+
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
553
554
|
] = None,
|
554
|
-
mounts:
|
555
|
-
volumes:
|
555
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
556
|
+
volumes: dict[
|
556
557
|
typing.Union[str, pathlib.PurePosixPath],
|
557
558
|
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
558
559
|
] = {},
|
559
|
-
network_file_systems:
|
560
|
+
network_file_systems: dict[
|
560
561
|
typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
|
561
562
|
] = {},
|
562
563
|
cpu: typing.Optional[float] = None,
|
@@ -564,11 +565,11 @@ class Image(modal.object.Object):
|
|
564
565
|
timeout: typing.Optional[int] = 3600,
|
565
566
|
force_build: bool = False,
|
566
567
|
cloud: typing.Optional[str] = None,
|
567
|
-
region: typing.Union[str,
|
568
|
-
args:
|
569
|
-
kwargs:
|
568
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
569
|
+
args: collections.abc.Sequence[typing.Any] = (),
|
570
|
+
kwargs: dict[str, typing.Any] = {},
|
570
571
|
) -> Image: ...
|
571
|
-
def env(self, vars:
|
572
|
+
def env(self, vars: dict[str, str]) -> Image: ...
|
572
573
|
def workdir(self, path: typing.Union[str, pathlib.PurePosixPath]) -> Image: ...
|
573
574
|
def imports(self): ...
|
574
575
|
|
@@ -578,4 +579,4 @@ class Image(modal.object.Object):
|
|
578
579
|
|
579
580
|
_logs: ___logs_spec
|
580
581
|
|
581
|
-
SUPPORTED_PYTHON_SERIES:
|
582
|
+
SUPPORTED_PYTHON_SERIES: dict[typing.Literal["2023.12", "2024.04", "2024.10"], list[str]]
|
modal/io_streams.py
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
# Copyright Modal Labs 2022
|
2
2
|
import asyncio
|
3
|
+
from collections.abc import AsyncGenerator, AsyncIterator
|
3
4
|
from typing import (
|
4
5
|
TYPE_CHECKING,
|
5
|
-
AsyncGenerator,
|
6
|
-
AsyncIterator,
|
7
6
|
Generic,
|
8
|
-
List,
|
9
7
|
Literal,
|
10
8
|
Optional,
|
11
|
-
Tuple,
|
12
9
|
TypeVar,
|
13
10
|
Union,
|
14
11
|
cast,
|
@@ -31,7 +28,7 @@ if TYPE_CHECKING:
|
|
31
28
|
|
32
29
|
async def _sandbox_logs_iterator(
|
33
30
|
sandbox_id: str, file_descriptor: "api_pb2.FileDescriptor.ValueType", last_entry_id: str, client: _Client
|
34
|
-
) -> AsyncGenerator[
|
31
|
+
) -> AsyncGenerator[tuple[Optional[bytes], str], None]:
|
35
32
|
req = api_pb2.SandboxGetLogsRequest(
|
36
33
|
sandbox_id=sandbox_id,
|
37
34
|
file_descriptor=file_descriptor,
|
@@ -137,7 +134,7 @@ class _StreamReader(Generic[T]):
|
|
137
134
|
# Container process streams need to be consumed as they are produced,
|
138
135
|
# otherwise the process will block. Use a buffer to store the stream
|
139
136
|
# until the client consumes it.
|
140
|
-
self._container_process_buffer:
|
137
|
+
self._container_process_buffer: list[Optional[bytes]] = []
|
141
138
|
self._consume_container_process_task = asyncio.create_task(self._consume_container_process_stream())
|
142
139
|
|
143
140
|
@property
|
@@ -208,7 +205,7 @@ class _StreamReader(Generic[T]):
|
|
208
205
|
break
|
209
206
|
raise exc
|
210
207
|
|
211
|
-
async def _stream_container_process(self) -> AsyncGenerator[
|
208
|
+
async def _stream_container_process(self) -> AsyncGenerator[tuple[Optional[bytes], str], None]:
|
212
209
|
"""Streams the container process buffer to the reader."""
|
213
210
|
entry_id = 0
|
214
211
|
if self._last_entry_id:
|
@@ -227,7 +224,7 @@ class _StreamReader(Generic[T]):
|
|
227
224
|
|
228
225
|
entry_id += 1
|
229
226
|
|
230
|
-
async def _get_logs(self) -> AsyncGenerator[Optional[bytes], None]:
|
227
|
+
async def _get_logs(self, skip_empty_messages: bool = True) -> AsyncGenerator[Optional[bytes], None]:
|
231
228
|
"""Streams sandbox or process logs from the server to the reader.
|
232
229
|
|
233
230
|
Logs returned by this method may contain partial or multiple lines at a time.
|
@@ -256,6 +253,11 @@ class _StreamReader(Generic[T]):
|
|
256
253
|
|
257
254
|
async for message, entry_id in iterator:
|
258
255
|
self._last_entry_id = entry_id
|
256
|
+
# Empty messages are sent when the process boots up. Don't yield them unless
|
257
|
+
# we're using the empty message to signal process liveness.
|
258
|
+
if skip_empty_messages and message == b"":
|
259
|
+
continue
|
260
|
+
|
259
261
|
yield message
|
260
262
|
if message is None:
|
261
263
|
completed = True
|
@@ -311,6 +313,11 @@ class _StreamReader(Generic[T]):
|
|
311
313
|
else:
|
312
314
|
return cast(T, value)
|
313
315
|
|
316
|
+
async def aclose(self):
|
317
|
+
"""mdmd:hidden"""
|
318
|
+
if self._stream:
|
319
|
+
await self._stream.aclose()
|
320
|
+
|
314
321
|
|
315
322
|
MAX_BUFFER_SIZE = 2 * 1024 * 1024
|
316
323
|
|
@@ -385,13 +392,14 @@ class _StreamWriter:
|
|
385
392
|
|
386
393
|
**Usage**
|
387
394
|
|
388
|
-
```python
|
389
|
-
# Synchronous
|
395
|
+
```python notest
|
390
396
|
writer.write(data)
|
391
397
|
writer.drain()
|
398
|
+
```
|
392
399
|
|
393
|
-
|
394
|
-
|
400
|
+
Async usage:
|
401
|
+
```python notest
|
402
|
+
writer.write(data) # not a blocking operation
|
395
403
|
await writer.drain.aio()
|
396
404
|
```
|
397
405
|
"""
|