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.

Files changed (160) hide show
  1. modal/__init__.py +0 -2
  2. modal/__main__.py +3 -4
  3. modal/_billing.py +80 -0
  4. modal/_clustered_functions.py +7 -3
  5. modal/_clustered_functions.pyi +15 -3
  6. modal/_container_entrypoint.py +51 -69
  7. modal/_functions.py +508 -240
  8. modal/_grpc_client.py +171 -0
  9. modal/_load_context.py +105 -0
  10. modal/_object.py +81 -21
  11. modal/_output.py +58 -45
  12. modal/_partial_function.py +48 -73
  13. modal/_pty.py +7 -3
  14. modal/_resolver.py +26 -46
  15. modal/_runtime/asgi.py +4 -3
  16. modal/_runtime/container_io_manager.py +358 -220
  17. modal/_runtime/container_io_manager.pyi +296 -101
  18. modal/_runtime/execution_context.py +18 -2
  19. modal/_runtime/execution_context.pyi +64 -7
  20. modal/_runtime/gpu_memory_snapshot.py +262 -57
  21. modal/_runtime/user_code_imports.py +28 -58
  22. modal/_serialization.py +90 -6
  23. modal/_traceback.py +42 -1
  24. modal/_tunnel.pyi +380 -12
  25. modal/_utils/async_utils.py +84 -29
  26. modal/_utils/auth_token_manager.py +111 -0
  27. modal/_utils/blob_utils.py +181 -58
  28. modal/_utils/deprecation.py +19 -0
  29. modal/_utils/function_utils.py +91 -47
  30. modal/_utils/grpc_utils.py +89 -66
  31. modal/_utils/mount_utils.py +26 -1
  32. modal/_utils/name_utils.py +17 -3
  33. modal/_utils/task_command_router_client.py +536 -0
  34. modal/_utils/time_utils.py +34 -6
  35. modal/app.py +256 -88
  36. modal/app.pyi +909 -92
  37. modal/billing.py +5 -0
  38. modal/builder/2025.06.txt +18 -0
  39. modal/builder/PREVIEW.txt +18 -0
  40. modal/builder/base-images.json +58 -0
  41. modal/cli/_download.py +19 -3
  42. modal/cli/_traceback.py +3 -2
  43. modal/cli/app.py +4 -4
  44. modal/cli/cluster.py +15 -7
  45. modal/cli/config.py +5 -3
  46. modal/cli/container.py +7 -6
  47. modal/cli/dict.py +22 -16
  48. modal/cli/entry_point.py +12 -5
  49. modal/cli/environment.py +5 -4
  50. modal/cli/import_refs.py +3 -3
  51. modal/cli/launch.py +102 -5
  52. modal/cli/network_file_system.py +11 -12
  53. modal/cli/profile.py +3 -2
  54. modal/cli/programs/launch_instance_ssh.py +94 -0
  55. modal/cli/programs/run_jupyter.py +1 -1
  56. modal/cli/programs/run_marimo.py +95 -0
  57. modal/cli/programs/vscode.py +1 -1
  58. modal/cli/queues.py +57 -26
  59. modal/cli/run.py +91 -23
  60. modal/cli/secret.py +48 -22
  61. modal/cli/token.py +7 -8
  62. modal/cli/utils.py +4 -7
  63. modal/cli/volume.py +31 -25
  64. modal/client.py +15 -85
  65. modal/client.pyi +183 -62
  66. modal/cloud_bucket_mount.py +5 -3
  67. modal/cloud_bucket_mount.pyi +197 -5
  68. modal/cls.py +200 -126
  69. modal/cls.pyi +446 -68
  70. modal/config.py +29 -11
  71. modal/container_process.py +319 -19
  72. modal/container_process.pyi +190 -20
  73. modal/dict.py +290 -71
  74. modal/dict.pyi +835 -83
  75. modal/environments.py +15 -27
  76. modal/environments.pyi +46 -24
  77. modal/exception.py +14 -2
  78. modal/experimental/__init__.py +194 -40
  79. modal/experimental/flash.py +618 -0
  80. modal/experimental/flash.pyi +380 -0
  81. modal/experimental/ipython.py +11 -7
  82. modal/file_io.py +29 -36
  83. modal/file_io.pyi +251 -53
  84. modal/file_pattern_matcher.py +56 -16
  85. modal/functions.pyi +673 -92
  86. modal/gpu.py +1 -1
  87. modal/image.py +528 -176
  88. modal/image.pyi +1572 -145
  89. modal/io_streams.py +458 -128
  90. modal/io_streams.pyi +433 -52
  91. modal/mount.py +216 -151
  92. modal/mount.pyi +225 -78
  93. modal/network_file_system.py +45 -62
  94. modal/network_file_system.pyi +277 -56
  95. modal/object.pyi +93 -17
  96. modal/parallel_map.py +942 -129
  97. modal/parallel_map.pyi +294 -15
  98. modal/partial_function.py +0 -2
  99. modal/partial_function.pyi +234 -19
  100. modal/proxy.py +17 -8
  101. modal/proxy.pyi +36 -3
  102. modal/queue.py +270 -65
  103. modal/queue.pyi +817 -57
  104. modal/runner.py +115 -101
  105. modal/runner.pyi +205 -49
  106. modal/sandbox.py +512 -136
  107. modal/sandbox.pyi +845 -111
  108. modal/schedule.py +1 -1
  109. modal/secret.py +300 -70
  110. modal/secret.pyi +589 -34
  111. modal/serving.py +7 -11
  112. modal/serving.pyi +7 -8
  113. modal/snapshot.py +11 -8
  114. modal/snapshot.pyi +25 -4
  115. modal/token_flow.py +4 -4
  116. modal/token_flow.pyi +28 -8
  117. modal/volume.py +416 -158
  118. modal/volume.pyi +1117 -121
  119. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/METADATA +10 -9
  120. modal-1.2.3.dev7.dist-info/RECORD +195 -0
  121. modal_docs/mdmd/mdmd.py +17 -4
  122. modal_proto/api.proto +534 -79
  123. modal_proto/api_grpc.py +337 -1
  124. modal_proto/api_pb2.py +1522 -968
  125. modal_proto/api_pb2.pyi +1619 -134
  126. modal_proto/api_pb2_grpc.py +699 -4
  127. modal_proto/api_pb2_grpc.pyi +226 -14
  128. modal_proto/modal_api_grpc.py +175 -154
  129. modal_proto/sandbox_router.proto +145 -0
  130. modal_proto/sandbox_router_grpc.py +105 -0
  131. modal_proto/sandbox_router_pb2.py +149 -0
  132. modal_proto/sandbox_router_pb2.pyi +333 -0
  133. modal_proto/sandbox_router_pb2_grpc.py +203 -0
  134. modal_proto/sandbox_router_pb2_grpc.pyi +75 -0
  135. modal_proto/task_command_router.proto +144 -0
  136. modal_proto/task_command_router_grpc.py +105 -0
  137. modal_proto/task_command_router_pb2.py +149 -0
  138. modal_proto/task_command_router_pb2.pyi +333 -0
  139. modal_proto/task_command_router_pb2_grpc.py +203 -0
  140. modal_proto/task_command_router_pb2_grpc.pyi +75 -0
  141. modal_version/__init__.py +1 -1
  142. modal/requirements/PREVIEW.txt +0 -16
  143. modal/requirements/base-images.json +0 -26
  144. modal-1.0.3.dev10.dist-info/RECORD +0 -179
  145. modal_proto/modal_options_grpc.py +0 -3
  146. modal_proto/options.proto +0 -19
  147. modal_proto/options_grpc.py +0 -3
  148. modal_proto/options_pb2.py +0 -35
  149. modal_proto/options_pb2.pyi +0 -20
  150. modal_proto/options_pb2_grpc.py +0 -4
  151. modal_proto/options_pb2_grpc.pyi +0 -7
  152. /modal/{requirements → builder}/2023.12.312.txt +0 -0
  153. /modal/{requirements → builder}/2023.12.txt +0 -0
  154. /modal/{requirements → builder}/2024.04.txt +0 -0
  155. /modal/{requirements → builder}/2024.10.txt +0 -0
  156. /modal/{requirements → builder}/README.md +0 -0
  157. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/WHEEL +0 -0
  158. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/entry_points.txt +0 -0
  159. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/licenses/LICENSE +0 -0
  160. {modal-1.0.3.dev10.dist-info → modal-1.2.3.dev7.dist-info}/top_level.txt +0 -0
@@ -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
- ) -> None: ...
24
- def __repr__(self): ...
25
- def __eq__(self, other): ...
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: list[tuple[str, _CloudBucketMount]],
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): ...