modal 1.0.3.dev10__py3-none-any.whl → 1.2.3.dev7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- modal/__init__.py +0 -2
- modal/__main__.py +3 -4
- modal/_billing.py +80 -0
- modal/_clustered_functions.py +7 -3
- modal/_clustered_functions.pyi +15 -3
- modal/_container_entrypoint.py +51 -69
- modal/_functions.py +508 -240
- modal/_grpc_client.py +171 -0
- modal/_load_context.py +105 -0
- modal/_object.py +81 -21
- modal/_output.py +58 -45
- modal/_partial_function.py +48 -73
- modal/_pty.py +7 -3
- modal/_resolver.py +26 -46
- modal/_runtime/asgi.py +4 -3
- modal/_runtime/container_io_manager.py +358 -220
- modal/_runtime/container_io_manager.pyi +296 -101
- modal/_runtime/execution_context.py +18 -2
- modal/_runtime/execution_context.pyi +64 -7
- modal/_runtime/gpu_memory_snapshot.py +262 -57
- modal/_runtime/user_code_imports.py +28 -58
- modal/_serialization.py +90 -6
- modal/_traceback.py +42 -1
- modal/_tunnel.pyi +380 -12
- modal/_utils/async_utils.py +84 -29
- modal/_utils/auth_token_manager.py +111 -0
- modal/_utils/blob_utils.py +181 -58
- modal/_utils/deprecation.py +19 -0
- modal/_utils/function_utils.py +91 -47
- modal/_utils/grpc_utils.py +89 -66
- modal/_utils/mount_utils.py +26 -1
- modal/_utils/name_utils.py +17 -3
- modal/_utils/task_command_router_client.py +536 -0
- modal/_utils/time_utils.py +34 -6
- modal/app.py +256 -88
- modal/app.pyi +909 -92
- modal/billing.py +5 -0
- modal/builder/2025.06.txt +18 -0
- modal/builder/PREVIEW.txt +18 -0
- modal/builder/base-images.json +58 -0
- modal/cli/_download.py +19 -3
- modal/cli/_traceback.py +3 -2
- modal/cli/app.py +4 -4
- modal/cli/cluster.py +15 -7
- modal/cli/config.py +5 -3
- modal/cli/container.py +7 -6
- modal/cli/dict.py +22 -16
- modal/cli/entry_point.py +12 -5
- modal/cli/environment.py +5 -4
- modal/cli/import_refs.py +3 -3
- modal/cli/launch.py +102 -5
- modal/cli/network_file_system.py +11 -12
- modal/cli/profile.py +3 -2
- modal/cli/programs/launch_instance_ssh.py +94 -0
- modal/cli/programs/run_jupyter.py +1 -1
- modal/cli/programs/run_marimo.py +95 -0
- modal/cli/programs/vscode.py +1 -1
- modal/cli/queues.py +57 -26
- modal/cli/run.py +91 -23
- modal/cli/secret.py +48 -22
- modal/cli/token.py +7 -8
- modal/cli/utils.py +4 -7
- modal/cli/volume.py +31 -25
- modal/client.py +15 -85
- modal/client.pyi +183 -62
- modal/cloud_bucket_mount.py +5 -3
- modal/cloud_bucket_mount.pyi +197 -5
- modal/cls.py +200 -126
- modal/cls.pyi +446 -68
- modal/config.py +29 -11
- modal/container_process.py +319 -19
- modal/container_process.pyi +190 -20
- modal/dict.py +290 -71
- modal/dict.pyi +835 -83
- modal/environments.py +15 -27
- modal/environments.pyi +46 -24
- modal/exception.py +14 -2
- modal/experimental/__init__.py +194 -40
- modal/experimental/flash.py +618 -0
- modal/experimental/flash.pyi +380 -0
- modal/experimental/ipython.py +11 -7
- modal/file_io.py +29 -36
- modal/file_io.pyi +251 -53
- modal/file_pattern_matcher.py +56 -16
- modal/functions.pyi +673 -92
- modal/gpu.py +1 -1
- modal/image.py +528 -176
- modal/image.pyi +1572 -145
- modal/io_streams.py +458 -128
- modal/io_streams.pyi +433 -52
- modal/mount.py +216 -151
- modal/mount.pyi +225 -78
- modal/network_file_system.py +45 -62
- modal/network_file_system.pyi +277 -56
- modal/object.pyi +93 -17
- modal/parallel_map.py +942 -129
- modal/parallel_map.pyi +294 -15
- modal/partial_function.py +0 -2
- modal/partial_function.pyi +234 -19
- modal/proxy.py +17 -8
- modal/proxy.pyi +36 -3
- modal/queue.py +270 -65
- modal/queue.pyi +817 -57
- modal/runner.py +115 -101
- modal/runner.pyi +205 -49
- modal/sandbox.py +512 -136
- modal/sandbox.pyi +845 -111
- modal/schedule.py +1 -1
- modal/secret.py +300 -70
- modal/secret.pyi +589 -34
- modal/serving.py +7 -11
- modal/serving.pyi +7 -8
- modal/snapshot.py +11 -8
- modal/snapshot.pyi +25 -4
- modal/token_flow.py +4 -4
- modal/token_flow.pyi +28 -8
- modal/volume.py +416 -158
- modal/volume.pyi +1117 -121
- {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/METADATA +10 -9
- modal-1.2.3.dev7.dist-info/RECORD +195 -0
- modal_docs/mdmd/mdmd.py +17 -4
- modal_proto/api.proto +534 -79
- modal_proto/api_grpc.py +337 -1
- modal_proto/api_pb2.py +1522 -968
- modal_proto/api_pb2.pyi +1619 -134
- modal_proto/api_pb2_grpc.py +699 -4
- modal_proto/api_pb2_grpc.pyi +226 -14
- modal_proto/modal_api_grpc.py +175 -154
- modal_proto/sandbox_router.proto +145 -0
- modal_proto/sandbox_router_grpc.py +105 -0
- modal_proto/sandbox_router_pb2.py +149 -0
- modal_proto/sandbox_router_pb2.pyi +333 -0
- modal_proto/sandbox_router_pb2_grpc.py +203 -0
- modal_proto/sandbox_router_pb2_grpc.pyi +75 -0
- modal_proto/task_command_router.proto +144 -0
- modal_proto/task_command_router_grpc.py +105 -0
- modal_proto/task_command_router_pb2.py +149 -0
- modal_proto/task_command_router_pb2.pyi +333 -0
- modal_proto/task_command_router_pb2_grpc.py +203 -0
- modal_proto/task_command_router_pb2_grpc.pyi +75 -0
- modal_version/__init__.py +1 -1
- modal/requirements/PREVIEW.txt +0 -16
- modal/requirements/base-images.json +0 -26
- modal-1.0.3.dev10.dist-info/RECORD +0 -179
- modal_proto/modal_options_grpc.py +0 -3
- modal_proto/options.proto +0 -19
- modal_proto/options_grpc.py +0 -3
- modal_proto/options_pb2.py +0 -35
- modal_proto/options_pb2.pyi +0 -20
- modal_proto/options_pb2_grpc.py +0 -4
- modal_proto/options_pb2_grpc.pyi +0 -7
- /modal/{requirements → builder}/2023.12.312.txt +0 -0
- /modal/{requirements → builder}/2023.12.txt +0 -0
- /modal/{requirements → builder}/2024.04.txt +0 -0
- /modal/{requirements → builder}/2024.10.txt +0 -0
- /modal/{requirements → builder}/README.md +0 -0
- {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/WHEEL +0 -0
- {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/entry_points.txt +0 -0
- {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/licenses/LICENSE +0 -0
- {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/top_level.txt +0 -0
modal/cloud_bucket_mount.pyi
CHANGED
|
@@ -3,6 +3,95 @@ import modal_proto.api_pb2
|
|
|
3
3
|
import typing
|
|
4
4
|
|
|
5
5
|
class _CloudBucketMount:
|
|
6
|
+
"""Mounts a cloud bucket to your container. Currently supports AWS S3 buckets.
|
|
7
|
+
|
|
8
|
+
S3 buckets are mounted using [AWS S3 Mountpoint](https://github.com/awslabs/mountpoint-s3).
|
|
9
|
+
S3 mounts are optimized for reading large files sequentially. It does not support every file operation; consult
|
|
10
|
+
[the AWS S3 Mountpoint documentation](https://github.com/awslabs/mountpoint-s3/blob/main/doc/SEMANTICS.md)
|
|
11
|
+
for more information.
|
|
12
|
+
|
|
13
|
+
**AWS S3 Usage**
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import subprocess
|
|
17
|
+
|
|
18
|
+
app = modal.App()
|
|
19
|
+
secret = modal.Secret.from_name(
|
|
20
|
+
"aws-secret",
|
|
21
|
+
required_keys=["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
|
|
22
|
+
# Note: providing AWS_REGION can help when automatic detection of the bucket region fails.
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@app.function(
|
|
26
|
+
volumes={
|
|
27
|
+
"/my-mount": modal.CloudBucketMount(
|
|
28
|
+
bucket_name="s3-bucket-name",
|
|
29
|
+
secret=secret,
|
|
30
|
+
read_only=True
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
def f():
|
|
35
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Cloudflare R2 Usage**
|
|
39
|
+
|
|
40
|
+
Cloudflare R2 is [S3-compatible](https://developers.cloudflare.com/r2/api/s3/api/) so its setup looks
|
|
41
|
+
very similar to S3. But additionally the `bucket_endpoint_url` argument must be passed.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import subprocess
|
|
45
|
+
|
|
46
|
+
app = modal.App()
|
|
47
|
+
secret = modal.Secret.from_name(
|
|
48
|
+
"r2-secret",
|
|
49
|
+
required_keys=["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@app.function(
|
|
53
|
+
volumes={
|
|
54
|
+
"/my-mount": modal.CloudBucketMount(
|
|
55
|
+
bucket_name="my-r2-bucket",
|
|
56
|
+
bucket_endpoint_url="https://<ACCOUNT ID>.r2.cloudflarestorage.com",
|
|
57
|
+
secret=secret,
|
|
58
|
+
read_only=True
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
def f():
|
|
63
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Google GCS Usage**
|
|
67
|
+
|
|
68
|
+
Google Cloud Storage (GCS) is [S3-compatible](https://cloud.google.com/storage/docs/interoperability).
|
|
69
|
+
GCS Buckets also require a secret with Google-specific key names (see below) populated with
|
|
70
|
+
a [HMAC key](https://cloud.google.com/storage/docs/authentication/managing-hmackeys#create).
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import subprocess
|
|
74
|
+
|
|
75
|
+
app = modal.App()
|
|
76
|
+
gcp_hmac_secret = modal.Secret.from_name(
|
|
77
|
+
"gcp-secret",
|
|
78
|
+
required_keys=["GOOGLE_ACCESS_KEY_ID", "GOOGLE_ACCESS_KEY_SECRET"]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@app.function(
|
|
82
|
+
volumes={
|
|
83
|
+
"/my-mount": modal.CloudBucketMount(
|
|
84
|
+
bucket_name="my-gcs-bucket",
|
|
85
|
+
bucket_endpoint_url="https://storage.googleapis.com",
|
|
86
|
+
secret=gcp_hmac_secret,
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
def f():
|
|
91
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
92
|
+
```
|
|
93
|
+
"""
|
|
94
|
+
|
|
6
95
|
bucket_name: str
|
|
7
96
|
bucket_endpoint_url: typing.Optional[str]
|
|
8
97
|
key_prefix: typing.Optional[str]
|
|
@@ -10,6 +99,7 @@ class _CloudBucketMount:
|
|
|
10
99
|
oidc_auth_role_arn: typing.Optional[str]
|
|
11
100
|
read_only: bool
|
|
12
101
|
requester_pays: bool
|
|
102
|
+
force_path_style: bool
|
|
13
103
|
|
|
14
104
|
def __init__(
|
|
15
105
|
self,
|
|
@@ -20,15 +110,115 @@ class _CloudBucketMount:
|
|
|
20
110
|
oidc_auth_role_arn: typing.Optional[str] = None,
|
|
21
111
|
read_only: bool = False,
|
|
22
112
|
requester_pays: bool = False,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
113
|
+
force_path_style: bool = False,
|
|
114
|
+
) -> None:
|
|
115
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def __repr__(self):
|
|
119
|
+
"""Return repr(self)."""
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
def __eq__(self, other):
|
|
123
|
+
"""Return self==value."""
|
|
124
|
+
...
|
|
26
125
|
|
|
27
126
|
def cloud_bucket_mounts_to_proto(
|
|
28
|
-
mounts:
|
|
29
|
-
) -> list[modal_proto.api_pb2.CloudBucketMount]:
|
|
127
|
+
mounts: typing.Sequence[tuple[str, _CloudBucketMount]],
|
|
128
|
+
) -> list[modal_proto.api_pb2.CloudBucketMount]:
|
|
129
|
+
"""Helper function to convert `CloudBucketMount` to a list of protobufs that can be passed to the server."""
|
|
130
|
+
...
|
|
30
131
|
|
|
31
132
|
class CloudBucketMount:
|
|
133
|
+
"""Mounts a cloud bucket to your container. Currently supports AWS S3 buckets.
|
|
134
|
+
|
|
135
|
+
S3 buckets are mounted using [AWS S3 Mountpoint](https://github.com/awslabs/mountpoint-s3).
|
|
136
|
+
S3 mounts are optimized for reading large files sequentially. It does not support every file operation; consult
|
|
137
|
+
[the AWS S3 Mountpoint documentation](https://github.com/awslabs/mountpoint-s3/blob/main/doc/SEMANTICS.md)
|
|
138
|
+
for more information.
|
|
139
|
+
|
|
140
|
+
**AWS S3 Usage**
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import subprocess
|
|
144
|
+
|
|
145
|
+
app = modal.App()
|
|
146
|
+
secret = modal.Secret.from_name(
|
|
147
|
+
"aws-secret",
|
|
148
|
+
required_keys=["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
|
|
149
|
+
# Note: providing AWS_REGION can help when automatic detection of the bucket region fails.
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
@app.function(
|
|
153
|
+
volumes={
|
|
154
|
+
"/my-mount": modal.CloudBucketMount(
|
|
155
|
+
bucket_name="s3-bucket-name",
|
|
156
|
+
secret=secret,
|
|
157
|
+
read_only=True
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
def f():
|
|
162
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Cloudflare R2 Usage**
|
|
166
|
+
|
|
167
|
+
Cloudflare R2 is [S3-compatible](https://developers.cloudflare.com/r2/api/s3/api/) so its setup looks
|
|
168
|
+
very similar to S3. But additionally the `bucket_endpoint_url` argument must be passed.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
import subprocess
|
|
172
|
+
|
|
173
|
+
app = modal.App()
|
|
174
|
+
secret = modal.Secret.from_name(
|
|
175
|
+
"r2-secret",
|
|
176
|
+
required_keys=["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
@app.function(
|
|
180
|
+
volumes={
|
|
181
|
+
"/my-mount": modal.CloudBucketMount(
|
|
182
|
+
bucket_name="my-r2-bucket",
|
|
183
|
+
bucket_endpoint_url="https://<ACCOUNT ID>.r2.cloudflarestorage.com",
|
|
184
|
+
secret=secret,
|
|
185
|
+
read_only=True
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
def f():
|
|
190
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Google GCS Usage**
|
|
194
|
+
|
|
195
|
+
Google Cloud Storage (GCS) is [S3-compatible](https://cloud.google.com/storage/docs/interoperability).
|
|
196
|
+
GCS Buckets also require a secret with Google-specific key names (see below) populated with
|
|
197
|
+
a [HMAC key](https://cloud.google.com/storage/docs/authentication/managing-hmackeys#create).
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
import subprocess
|
|
201
|
+
|
|
202
|
+
app = modal.App()
|
|
203
|
+
gcp_hmac_secret = modal.Secret.from_name(
|
|
204
|
+
"gcp-secret",
|
|
205
|
+
required_keys=["GOOGLE_ACCESS_KEY_ID", "GOOGLE_ACCESS_KEY_SECRET"]
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
@app.function(
|
|
209
|
+
volumes={
|
|
210
|
+
"/my-mount": modal.CloudBucketMount(
|
|
211
|
+
bucket_name="my-gcs-bucket",
|
|
212
|
+
bucket_endpoint_url="https://storage.googleapis.com",
|
|
213
|
+
secret=gcp_hmac_secret,
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
def f():
|
|
218
|
+
subprocess.run(["ls", "/my-mount"], check=True)
|
|
219
|
+
```
|
|
220
|
+
"""
|
|
221
|
+
|
|
32
222
|
bucket_name: str
|
|
33
223
|
bucket_endpoint_url: typing.Optional[str]
|
|
34
224
|
key_prefix: typing.Optional[str]
|
|
@@ -36,6 +226,7 @@ class CloudBucketMount:
|
|
|
36
226
|
oidc_auth_role_arn: typing.Optional[str]
|
|
37
227
|
read_only: bool
|
|
38
228
|
requester_pays: bool
|
|
229
|
+
force_path_style: bool
|
|
39
230
|
|
|
40
231
|
def __init__(
|
|
41
232
|
self,
|
|
@@ -46,6 +237,7 @@ class CloudBucketMount:
|
|
|
46
237
|
oidc_auth_role_arn: typing.Optional[str] = None,
|
|
47
238
|
read_only: bool = False,
|
|
48
239
|
requester_pays: bool = False,
|
|
240
|
+
force_path_style: bool = False,
|
|
49
241
|
) -> None: ...
|
|
50
242
|
def __repr__(self): ...
|
|
51
243
|
def __eq__(self, other): ...
|