modal 1.0.6.dev7__tar.gz → 1.0.6.dev9__tar.gz
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-1.0.6.dev7 → modal-1.0.6.dev9}/PKG-INFO +1 -1
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/blob_utils.py +22 -9
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/function_utils.py +9 -2
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/client.pyi +2 -2
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/functions.pyi +6 -6
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/image.py +1 -2
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/base-images.json +4 -4
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api.proto +2 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api_pb2.py +494 -494
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api_pb2.pyi +7 -1
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_version/__init__.py +1 -1
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/LICENSE +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/README.md +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/__main__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_clustered_functions.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_clustered_functions.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_functions.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_ipython.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_location.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_object.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_output.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_partial_function.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_pty.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_resolver.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_resources.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_serialization.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_traceback.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_tunnel.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_tunnel.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_type_manager.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/logger.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/_watcher.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/app.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/app.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/call_graph.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/_download.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/_traceback.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/app.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/cluster.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/config.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/container.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/dict.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/entry_point.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/environment.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/import_refs.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/launch.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/profile.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/queues.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/run.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/secret.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/token.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/utils.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cli/volume.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/client.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cls.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/cls.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/config.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/container_process.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/container_process.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/dict.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/dict.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/environments.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/environments.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/exception.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/experimental/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/experimental/ipython.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/file_io.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/file_io.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/functions.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/gpu.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/image.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/io_streams.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/io_streams.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/mount.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/mount.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/network_file_system.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/network_file_system.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/object.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/object.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/output.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/parallel_map.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/parallel_map.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/partial_function.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/partial_function.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/proxy.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/proxy.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/py.typed +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/queue.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/queue.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/requirements/README.md +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/retries.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/runner.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/runner.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/running_app.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/sandbox.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/sandbox.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/schedule.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/scheduler_placement.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/secret.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/secret.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/serving.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/serving.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/snapshot.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/snapshot.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/stream_type.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/token_flow.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/token_flow.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/volume.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal/volume.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/requires.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/__init__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options.proto +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_proto/py.typed +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/modal_version/__main__.py +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/pyproject.toml +0 -0
- {modal-1.0.6.dev7 → modal-1.0.6.dev9}/setup.cfg +0 -0
|
@@ -188,16 +188,23 @@ def get_content_length(data: BinaryIO) -> int:
|
|
|
188
188
|
return content_length - pos
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
async def _blob_upload_with_fallback(items, blob_ids, callback):
|
|
191
|
+
async def _blob_upload_with_fallback(items, blob_ids: list[str], callback) -> tuple[str, bool, int]:
|
|
192
|
+
r2_latency_ms = 0
|
|
193
|
+
r2_failed = False
|
|
192
194
|
for idx, (item, blob_id) in enumerate(zip(items, blob_ids)):
|
|
193
195
|
# We want to default to R2 95% of the time and S3 5% of the time.
|
|
194
196
|
# To ensure the failure path is continuously exercised.
|
|
195
197
|
if idx == 0 and len(items) > 1 and random.random() > HEALTHY_R2_UPLOAD_PERCENTAGE:
|
|
196
198
|
continue
|
|
197
199
|
try:
|
|
200
|
+
init_time = time.monotonic_ns()
|
|
198
201
|
await callback(item)
|
|
199
|
-
|
|
202
|
+
if blob_id.endswith(":r2"):
|
|
203
|
+
r2_latency_ms = (time.monotonic_ns() - init_time) // 1_000_000
|
|
204
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
200
205
|
except Exception as _:
|
|
206
|
+
if blob_id.endswith(":r2"):
|
|
207
|
+
r2_failed = True
|
|
201
208
|
# Ignore all errors except the last one, since we're out of fallback options.
|
|
202
209
|
if idx == len(items) - 1:
|
|
203
210
|
raise
|
|
@@ -206,7 +213,7 @@ async def _blob_upload_with_fallback(items, blob_ids, callback):
|
|
|
206
213
|
|
|
207
214
|
async def _blob_upload(
|
|
208
215
|
upload_hashes: UploadHashes, data: Union[bytes, BinaryIO], stub, progress_report_cb: Optional[Callable] = None
|
|
209
|
-
) -> str:
|
|
216
|
+
) -> tuple[str, bool, int]:
|
|
210
217
|
if isinstance(data, bytes):
|
|
211
218
|
data = BytesIO(data)
|
|
212
219
|
|
|
@@ -232,7 +239,7 @@ async def _blob_upload(
|
|
|
232
239
|
progress_report_cb=progress_report_cb,
|
|
233
240
|
)
|
|
234
241
|
|
|
235
|
-
blob_id = await _blob_upload_with_fallback(
|
|
242
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload_with_fallback(
|
|
236
243
|
resp.multiparts.items,
|
|
237
244
|
resp.blob_ids,
|
|
238
245
|
upload_multipart_upload,
|
|
@@ -252,7 +259,7 @@ async def _blob_upload(
|
|
|
252
259
|
content_md5_b64=upload_hashes.md5_base64,
|
|
253
260
|
)
|
|
254
261
|
|
|
255
|
-
blob_id = await _blob_upload_with_fallback(
|
|
262
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload_with_fallback(
|
|
256
263
|
resp.upload_urls.items,
|
|
257
264
|
resp.blob_ids,
|
|
258
265
|
upload_to_s3_url,
|
|
@@ -261,10 +268,10 @@ async def _blob_upload(
|
|
|
261
268
|
if progress_report_cb:
|
|
262
269
|
progress_report_cb(complete=True)
|
|
263
270
|
|
|
264
|
-
return blob_id
|
|
271
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
265
272
|
|
|
266
273
|
|
|
267
|
-
async def
|
|
274
|
+
async def blob_upload_with_r2_failure_info(payload: bytes, stub: ModalClientModal) -> tuple[str, bool, int]:
|
|
268
275
|
size_mib = len(payload) / 1024 / 1024
|
|
269
276
|
logger.debug(f"Uploading large blob of size {size_mib:.2f} MiB")
|
|
270
277
|
t0 = time.time()
|
|
@@ -272,12 +279,17 @@ async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
|
|
272
279
|
logger.warning("Blob uploading string, not bytes - auto-encoding as utf8")
|
|
273
280
|
payload = payload.encode("utf8")
|
|
274
281
|
upload_hashes = get_upload_hashes(payload)
|
|
275
|
-
blob_id = await _blob_upload(upload_hashes, payload, stub)
|
|
282
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload(upload_hashes, payload, stub)
|
|
276
283
|
dur_s = max(time.time() - t0, 0.001) # avoid division by zero
|
|
277
284
|
throughput_mib_s = (size_mib) / dur_s
|
|
278
285
|
logger.debug(
|
|
279
286
|
f"Uploaded large blob of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s, total {dur_s:.2f}s). {blob_id}"
|
|
280
287
|
)
|
|
288
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
|
292
|
+
blob_id, _, _ = await blob_upload_with_r2_failure_info(payload, stub)
|
|
281
293
|
return blob_id
|
|
282
294
|
|
|
283
295
|
|
|
@@ -289,7 +301,8 @@ async def blob_upload_file(
|
|
|
289
301
|
md5_hex: Optional[str] = None,
|
|
290
302
|
) -> str:
|
|
291
303
|
upload_hashes = get_upload_hashes(file_obj, sha256_hex=sha256_hex, md5_hex=md5_hex)
|
|
292
|
-
|
|
304
|
+
blob_id, _, _ = await _blob_upload(upload_hashes, file_obj, stub, progress_report_cb)
|
|
305
|
+
return blob_id
|
|
293
306
|
|
|
294
307
|
|
|
295
308
|
@retry(n_attempts=5, base_delay=0.1, timeout=None)
|
|
@@ -32,7 +32,12 @@ from ..exception import (
|
|
|
32
32
|
RemoteError,
|
|
33
33
|
)
|
|
34
34
|
from ..mount import ROOT_DIR, _is_modal_path, _Mount
|
|
35
|
-
from .blob_utils import
|
|
35
|
+
from .blob_utils import (
|
|
36
|
+
MAX_ASYNC_OBJECT_SIZE_BYTES,
|
|
37
|
+
MAX_OBJECT_SIZE_BYTES,
|
|
38
|
+
blob_download,
|
|
39
|
+
blob_upload_with_r2_failure_info,
|
|
40
|
+
)
|
|
36
41
|
from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
|
|
37
42
|
|
|
38
43
|
|
|
@@ -544,7 +549,7 @@ async def _create_input(
|
|
|
544
549
|
args_serialized = serialize((args, kwargs))
|
|
545
550
|
|
|
546
551
|
if should_upload(len(args_serialized), function_call_invocation_type):
|
|
547
|
-
args_blob_id = await
|
|
552
|
+
args_blob_id, r2_failed, r2_latency_ms = await blob_upload_with_r2_failure_info(args_serialized, stub)
|
|
548
553
|
return api_pb2.FunctionPutInputsItem(
|
|
549
554
|
input=api_pb2.FunctionInput(
|
|
550
555
|
args_blob_id=args_blob_id,
|
|
@@ -552,6 +557,8 @@ async def _create_input(
|
|
|
552
557
|
method_name=method_name,
|
|
553
558
|
),
|
|
554
559
|
idx=idx,
|
|
560
|
+
r2_failed=r2_failed,
|
|
561
|
+
r2_latency_ms=r2_latency_ms,
|
|
555
562
|
)
|
|
556
563
|
else:
|
|
557
564
|
return api_pb2.FunctionPutInputsItem(
|
|
@@ -31,7 +31,7 @@ class _Client:
|
|
|
31
31
|
server_url: str,
|
|
32
32
|
client_type: int,
|
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
|
34
|
-
version: str = "1.0.6.
|
|
34
|
+
version: str = "1.0.6.dev9",
|
|
35
35
|
):
|
|
36
36
|
"""mdmd:hidden
|
|
37
37
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -160,7 +160,7 @@ class Client:
|
|
|
160
160
|
server_url: str,
|
|
161
161
|
client_type: int,
|
|
162
162
|
credentials: typing.Optional[tuple[str, str]],
|
|
163
|
-
version: str = "1.0.6.
|
|
163
|
+
version: str = "1.0.6.dev9",
|
|
164
164
|
):
|
|
165
165
|
"""mdmd:hidden
|
|
166
166
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -428,7 +428,7 @@ class Function(
|
|
|
428
428
|
|
|
429
429
|
_call_generator: ___call_generator_spec[typing_extensions.Self]
|
|
430
430
|
|
|
431
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
431
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
432
432
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
433
433
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
434
434
|
...
|
|
@@ -437,7 +437,7 @@ class Function(
|
|
|
437
437
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
438
438
|
...
|
|
439
439
|
|
|
440
|
-
remote: __remote_spec[modal._functions.
|
|
440
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
441
441
|
|
|
442
442
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
443
443
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -464,7 +464,7 @@ class Function(
|
|
|
464
464
|
"""
|
|
465
465
|
...
|
|
466
466
|
|
|
467
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
467
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
468
468
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
469
469
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
470
470
|
|
|
@@ -488,7 +488,7 @@ class Function(
|
|
|
488
488
|
...
|
|
489
489
|
|
|
490
490
|
_experimental_spawn: ___experimental_spawn_spec[
|
|
491
|
-
modal._functions.
|
|
491
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
|
492
492
|
]
|
|
493
493
|
|
|
494
494
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
|
|
@@ -497,7 +497,7 @@ class Function(
|
|
|
497
497
|
|
|
498
498
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
|
|
499
499
|
|
|
500
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
500
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
501
501
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
502
502
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
503
503
|
|
|
@@ -518,7 +518,7 @@ class Function(
|
|
|
518
518
|
"""
|
|
519
519
|
...
|
|
520
520
|
|
|
521
|
-
spawn: __spawn_spec[modal._functions.
|
|
521
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
522
522
|
|
|
523
523
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
524
524
|
"""Return the inner Python object wrapped by this Modal Function."""
|
|
@@ -1450,8 +1450,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
1450
1450
|
python_version = "3.9" # Backcompat for old hardcoded default param
|
|
1451
1451
|
validated_python_version = _validate_python_version(python_version, version)
|
|
1452
1452
|
micromamba_version = _base_image_config("micromamba", version)
|
|
1453
|
-
|
|
1454
|
-
tag = f"mambaorg/micromamba:{micromamba_version}-{debian_codename}-slim"
|
|
1453
|
+
tag = f"mambaorg/micromamba:{micromamba_version}"
|
|
1455
1454
|
setup_commands = [
|
|
1456
1455
|
'SHELL ["/usr/local/bin/_dockerfile_shell.sh"]',
|
|
1457
1456
|
"ENV MAMBA_DOCKERFILE_ACTIVATE=1",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
]
|
|
35
35
|
},
|
|
36
36
|
"micromamba": {
|
|
37
|
-
"PREVIEW": "2.1.1",
|
|
38
|
-
"2024.10": "1.5.10",
|
|
39
|
-
"2024.04": "1.5.8",
|
|
40
|
-
"2023.12": "1.3.1"
|
|
37
|
+
"PREVIEW": "2.1.1-debian12-slim",
|
|
38
|
+
"2024.10": "1.5.10-bookworm-slim",
|
|
39
|
+
"2024.04": "1.5.8-bookworm-slim",
|
|
40
|
+
"2023.12": "1.3.1-bullseye-slim"
|
|
41
41
|
},
|
|
42
42
|
"package_tools": {
|
|
43
43
|
"PREVIEW": "pip wheel uv",
|