modal 1.5.4.dev22__tar.gz → 1.5.5__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.
- {modal-1.5.4.dev22 → modal-1.5.5}/PKG-INFO +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_container_entrypoint.py +4 -2
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_environments.py +14 -5
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_function_variants.py +3 -3
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_functions.py +92 -22
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_image.py +13 -10
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_logs_manager.py +191 -9
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_logs_manager.pyi +434 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_object.py +34 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_resolver.py +5 -5
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/asgi.py +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/container_io_manager.py +53 -29
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/container_io_manager.pyi +16 -10
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/user_code_imports.py +5 -5
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_serialization.py +3 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_supports_logs.py +1 -3
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/deprecation.py +29 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/function_utils.py +9 -9
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/grpc_utils.py +9 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/mount_utils.py +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_workspace.py +6 -6
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/app.py +96 -56
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/app.pyi +73 -32
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/_help.py +143 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/app.py +51 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/changelog.py +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/config.py +8 -3
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/entry_point.py +9 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/environment.py +29 -7
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/import_refs.py +9 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/launch.py +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/profile.py +4 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/run.py +35 -8
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/shell.py +2 -2
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/token.py +3 -11
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/volume.py +7 -7
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/client.py +140 -15
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/client.pyi +124 -3
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cls.py +31 -18
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cls.pyi +20 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/config.py +22 -7
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/environments.pyi +14 -2
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/exception.py +13 -2
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/experimental/__init__.py +5 -3
- modal-1.5.5/modal/experimental/flash.py +389 -0
- modal-1.5.5/modal/experimental/flash.pyi +235 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/functions.pyi +86 -10
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/object.pyi +18 -31
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/runner.py +6 -6
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/sandbox.py +126 -13
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/sandbox.pyi +108 -27
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/skills/modal/SKILL.md +2 -2
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/types.py +4 -3
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/api_grpc.py +32 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/api_pb2.py +961 -924
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/api_pb2.pyi +178 -10
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/api_pb2_grpc.py +66 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/api_pb2_grpc.pyi +20 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/modal_api_grpc.py +2 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/task_command_router_pb2.py +34 -34
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/task_command_router_pb2.pyi +20 -4
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_version/__init__.py +1 -1
- {modal-1.5.4.dev22 → modal-1.5.5}/pyproject.toml +3 -3
- modal-1.5.4.dev22/modal/experimental/flash.py +0 -814
- modal-1.5.4.dev22/modal/experimental/flash.pyi +0 -481
- {modal-1.5.4.dev22 → modal-1.5.5}/LICENSE +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/README.md +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/__main__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_billing.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_clustered_functions.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_clustered_functions.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_grpc_client.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_ipython.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_load_context.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_location.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_logs.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_output/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_output/manager.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_output/pty.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_output/rich.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_output/status.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_partial_function.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_resources.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/execution_context.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/task_lifecycle_manager.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/telemetry.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_server.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_traceback.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_tunnel.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_tunnel.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_type_manager.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/app_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/async_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/blob_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/browser_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/curl_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/display_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/docker_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/git_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/hash_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/http_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/logger.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/name_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/package_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/proxy_support.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/shell_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_utils/time_utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_vendor/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_vendor/tblib.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_vendor/version.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/_watcher.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/billing.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/billing.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/2023.12.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/2024.04.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/2024.10.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/2025.06.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/README.md +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/builder/base-images.json +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/call_graph.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/_download.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/_traceback.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/billing.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/bootstrap.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/cluster.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/container.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/curl.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/dashboard.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/dict.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/endpoint.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/image.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/logo.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/network_file_system.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/programs/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/programs/vscode.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/queues.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/secret.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/selector.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/skills.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/utils.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cli/workspace.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/container_process.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/container_process.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/dict.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/dict.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/environments.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/experimental/ipython.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/file_io.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/file_io.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/file_pattern_matcher.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/functions.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/image.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/image.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/io_streams.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/io_streams.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/mount.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/mount.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/network_file_system.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/network_file_system.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/object.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/output.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/parallel_map.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/parallel_map.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/partial_function.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/partial_function.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/proxy.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/proxy.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/py.typed +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/queue.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/queue.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/retries.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/runner.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/running_app.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/sandbox_fs.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/sandbox_fs.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/schedule.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/scheduler_placement.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/secret.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/secret.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/server.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/server.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/serving.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/serving.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/snapshot.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/snapshot.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/stream_type.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/token_flow.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/token_flow.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/volume.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/volume.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/workspace.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal/workspace.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/requires.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal.egg-info/top_level.txt +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/mdmd/types.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_docs/reference_intro.md +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/__init__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/py.typed +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/modal_version/__main__.py +0 -0
- {modal-1.5.4.dev22 → modal-1.5.5}/setup.cfg +0 -0
|
@@ -145,7 +145,7 @@ def call_function(
|
|
|
145
145
|
item_count += 1
|
|
146
146
|
|
|
147
147
|
await container_io_manager._send_outputs.aio(
|
|
148
|
-
io_context.output_items_generator_done(started_at, item_count)
|
|
148
|
+
io_context, io_context.output_items_generator_done(started_at, item_count)
|
|
149
149
|
)
|
|
150
150
|
else:
|
|
151
151
|
value = await io_context.call_function_async()
|
|
@@ -182,7 +182,9 @@ def call_function(
|
|
|
182
182
|
container_io_manager._queue_put(generator_queue, value)
|
|
183
183
|
item_count += 1
|
|
184
184
|
|
|
185
|
-
container_io_manager._send_outputs(
|
|
185
|
+
container_io_manager._send_outputs(
|
|
186
|
+
io_context, io_context.output_items_generator_done(started_at, item_count)
|
|
187
|
+
)
|
|
186
188
|
else:
|
|
187
189
|
values = io_context.call_function_sync()
|
|
188
190
|
container_io_manager.push_outputs(io_context, started_at, values)
|
|
@@ -39,6 +39,7 @@ class _EnvironmentManager:
|
|
|
39
39
|
name: str, # Name to use for the new Environment
|
|
40
40
|
*,
|
|
41
41
|
restricted: bool = False, # If True, enable RBAC restrictions on the Environment
|
|
42
|
+
default_role: str | None = None, # Default member Role for the Restricted Environment
|
|
42
43
|
experimental_options: dict[str, Any] | None = None, # Experimental options for Environment creation
|
|
43
44
|
client: _Client | None = None, # Optional client with Modal credentials
|
|
44
45
|
) -> None:
|
|
@@ -51,8 +52,11 @@ class _EnvironmentManager:
|
|
|
51
52
|
```
|
|
52
53
|
"""
|
|
53
54
|
check_environment_name(name)
|
|
55
|
+
|
|
54
56
|
client = await _Client.from_env() if client is None else client
|
|
55
57
|
request = api_pb2.EnvironmentCreateRequest(name=name, is_managed=restricted)
|
|
58
|
+
if default_role:
|
|
59
|
+
request.default_member_role_str = default_role
|
|
56
60
|
if (experimental_options or {}).get("is_public", False):
|
|
57
61
|
request.environment_type = api_pb2.ENVIRONMENT_TYPE_PUBLIC
|
|
58
62
|
await client.stub.EnvironmentCreate(request)
|
|
@@ -116,9 +120,12 @@ class _EnvironmentRolesManager:
|
|
|
116
120
|
"""mdmd:hidden"""
|
|
117
121
|
self._environment = environment
|
|
118
122
|
|
|
119
|
-
async def list(self) -> dict[Literal["users", "service_users"], dict[str, str]]:
|
|
123
|
+
async def list(self, *, exclude_default: bool = False) -> dict[Literal["users", "service_users"], dict[str, str]]:
|
|
120
124
|
"""Enumerate the Environment Role for each user and service user in the workspace.
|
|
121
125
|
|
|
126
|
+
Args:
|
|
127
|
+
exclude_default: If `True`, only include roles that are directly assigned.
|
|
128
|
+
|
|
122
129
|
**Examples:**
|
|
123
130
|
|
|
124
131
|
```python notest
|
|
@@ -137,6 +144,8 @@ class _EnvironmentRolesManager:
|
|
|
137
144
|
users: dict[str, str] = {}
|
|
138
145
|
service_users: dict[str, str] = {}
|
|
139
146
|
for principal in resp.principal_roles:
|
|
147
|
+
if exclude_default and not principal.has_role_assignment:
|
|
148
|
+
continue
|
|
140
149
|
if principal.user_id:
|
|
141
150
|
users[principal.user_name] = principal.role_str
|
|
142
151
|
elif principal.service_user_id:
|
|
@@ -252,8 +261,8 @@ class _EnvironmentMembersManager:
|
|
|
252
261
|
"""Remove the Environment Role of users and service users, reverting them to the default."""
|
|
253
262
|
deprecation_warning(
|
|
254
263
|
(2026, 7, 23),
|
|
255
|
-
"`Environment.members.remove()` is deprecated
|
|
256
|
-
"
|
|
264
|
+
"`Environment.members.remove()` is deprecated; assign a role (e.g. 'no-access') with "
|
|
265
|
+
"`Environment.roles.update()` instead.",
|
|
257
266
|
)
|
|
258
267
|
await self._environment.hydrate()
|
|
259
268
|
users = users or []
|
|
@@ -469,7 +478,7 @@ class _EnvironmentBillingManager:
|
|
|
469
478
|
elif end.tzinfo != timezone.utc:
|
|
470
479
|
raise InvalidError("Timezone-aware 'end' parameter must be in UTC.")
|
|
471
480
|
|
|
472
|
-
if not self._environment.
|
|
481
|
+
if not self._environment._is_hydrated:
|
|
473
482
|
await self._environment.hydrate()
|
|
474
483
|
|
|
475
484
|
request = api_pb2.WorkspaceBillingReportRequest(
|
|
@@ -540,7 +549,7 @@ class _EnvironmentBillingManager:
|
|
|
540
549
|
if cycle > datetime.now(timezone.utc):
|
|
541
550
|
raise InvalidError("Provided 'cycle' parameter cannot be in the future.")
|
|
542
551
|
|
|
543
|
-
if not self._environment.
|
|
552
|
+
if not self._environment._is_hydrated:
|
|
544
553
|
await self._environment.hydrate()
|
|
545
554
|
|
|
546
555
|
request = api_pb2.EnvironmentBillingSummaryRequest(environment_id=self._environment.object_id)
|
|
@@ -157,7 +157,7 @@ class _FunctionOptions:
|
|
|
157
157
|
+ list(self.secrets)
|
|
158
158
|
+ [mount.secret for _, mount in self.cloud_bucket_mounts if mount.secret]
|
|
159
159
|
)
|
|
160
|
-
return [dep for dep in all_deps if not dep.
|
|
160
|
+
return [dep for dep in all_deps if not dep._is_hydrated]
|
|
161
161
|
|
|
162
162
|
def to_proto(self) -> api_pb2.FunctionOptions:
|
|
163
163
|
"""Convert the dataclass to a FunctionOptions protobuf message."""
|
|
@@ -246,7 +246,7 @@ def _make_function_variant(
|
|
|
246
246
|
load_context: "LoadContext",
|
|
247
247
|
existing_object_id: str | None,
|
|
248
248
|
):
|
|
249
|
-
if not base_function.
|
|
249
|
+
if not base_function._is_hydrated:
|
|
250
250
|
await base_function.hydrate(load_context.client)
|
|
251
251
|
assert base_function._client and base_function._client.stub
|
|
252
252
|
|
|
@@ -290,6 +290,6 @@ def _make_function_variant(
|
|
|
290
290
|
deps=_deps,
|
|
291
291
|
load_context_overrides=base_function._load_context_overrides,
|
|
292
292
|
)
|
|
293
|
-
fun.
|
|
293
|
+
fun._source_info = base_function._source_info
|
|
294
294
|
fun._spec = base_function._spec # TODO (elias): fix - this is incorrect when using with_options
|
|
295
295
|
return fun
|
|
@@ -46,10 +46,11 @@ from ._utils.async_utils import (
|
|
|
46
46
|
warn_if_generator_is_not_consumed,
|
|
47
47
|
)
|
|
48
48
|
from ._utils.blob_utils import MAX_ASYNC_OBJECT_SIZE_BYTES, MAX_OBJECT_SIZE_BYTES
|
|
49
|
+
from ._utils.deprecation import with_deprecation_warning
|
|
49
50
|
from ._utils.function_utils import (
|
|
50
51
|
ATTEMPT_TIMEOUT_GRACE_PERIOD,
|
|
51
52
|
OUTPUTS_TIMEOUT,
|
|
52
|
-
|
|
53
|
+
FunctionSourceInfo,
|
|
53
54
|
_create_input,
|
|
54
55
|
_parse_retries,
|
|
55
56
|
_process_result,
|
|
@@ -603,7 +604,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
603
604
|
"""
|
|
604
605
|
|
|
605
606
|
# TODO: more type annotations
|
|
606
|
-
|
|
607
|
+
_source_info: FunctionSourceInfo | None
|
|
607
608
|
_serve_mounts: frozenset[_Mount] # set at load time, only by loader
|
|
608
609
|
_app: "modal.app._App | None" = None
|
|
609
610
|
# only set for InstanceServiceFunctions and bound instance methods
|
|
@@ -640,7 +641,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
640
641
|
await self.hydrate()
|
|
641
642
|
if not self._app_id:
|
|
642
643
|
raise ExecutionError("app_id should have been set during function hydration")
|
|
643
|
-
return _LogQueryData(
|
|
644
|
+
return _LogQueryData(
|
|
645
|
+
self.client,
|
|
646
|
+
self._app_id,
|
|
647
|
+
LogsFilters(function_id=self.object_id),
|
|
648
|
+
source_object_id=self.object_id,
|
|
649
|
+
)
|
|
644
650
|
|
|
645
651
|
@property
|
|
646
652
|
def logs(self) -> _FunctionLogsManager:
|
|
@@ -658,8 +664,8 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
658
664
|
return _FunctionLogsManager(self)
|
|
659
665
|
|
|
660
666
|
@staticmethod
|
|
661
|
-
def
|
|
662
|
-
info:
|
|
667
|
+
def _from_local(
|
|
668
|
+
info: FunctionSourceInfo,
|
|
663
669
|
app: "modal.app._App | None", # App here should only be None in case of Image.run_function
|
|
664
670
|
image: _Image,
|
|
665
671
|
env: dict[str, str | None] | None = None,
|
|
@@ -932,7 +938,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
932
938
|
with FunctionCreationStatus(tag) as function_creation_status:
|
|
933
939
|
timeout_secs = timeout
|
|
934
940
|
|
|
935
|
-
if app and app.
|
|
941
|
+
if app and app._is_interactive_ and not is_builder_function:
|
|
936
942
|
pty_info = get_pty_info(shell=False)
|
|
937
943
|
else:
|
|
938
944
|
pty_info = None
|
|
@@ -1105,6 +1111,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1105
1111
|
http_config=http_config,
|
|
1106
1112
|
is_server=function_definition.is_server,
|
|
1107
1113
|
routing_region=function_definition.routing_region,
|
|
1114
|
+
is_sessioned=function_definition.is_sessioned,
|
|
1108
1115
|
)
|
|
1109
1116
|
|
|
1110
1117
|
ranked_functions = []
|
|
@@ -1158,10 +1165,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1158
1165
|
# the only way to infer a LoadContext for an `@app.function`, and the App doesn't
|
|
1159
1166
|
# get its client until *after* the Function is created.
|
|
1160
1167
|
load_context = app._root_load_context if app else LoadContext.empty()
|
|
1161
|
-
obj = _Function._from_loader(
|
|
1168
|
+
obj: _Function = _Function._from_loader(
|
|
1169
|
+
_load, rep, preload=_preload, deps=_deps, load_context_overrides=load_context
|
|
1170
|
+
)
|
|
1162
1171
|
|
|
1163
1172
|
obj._raw_f = info.raw_f
|
|
1164
|
-
obj.
|
|
1173
|
+
obj._source_info = info
|
|
1165
1174
|
obj._tag = tag
|
|
1166
1175
|
obj._app = app # needed for CLI right now
|
|
1167
1176
|
obj._obj = None
|
|
@@ -1186,6 +1195,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1186
1195
|
|
|
1187
1196
|
return obj
|
|
1188
1197
|
|
|
1198
|
+
from_local = with_deprecation_warning(
|
|
1199
|
+
(2026, 8, 26),
|
|
1200
|
+
"`Function.from_local` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1201
|
+
)(_from_local)
|
|
1202
|
+
"""mdmd:hidden"""
|
|
1203
|
+
|
|
1189
1204
|
async def _update_autoscaler(
|
|
1190
1205
|
self,
|
|
1191
1206
|
*,
|
|
@@ -1378,8 +1393,16 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1378
1393
|
)
|
|
1379
1394
|
|
|
1380
1395
|
@property
|
|
1396
|
+
@with_deprecation_warning(
|
|
1397
|
+
(2026, 8, 26),
|
|
1398
|
+
"`Function.tag` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1399
|
+
)
|
|
1381
1400
|
def tag(self) -> str:
|
|
1382
1401
|
"""mdmd:hidden"""
|
|
1402
|
+
return self._tag_
|
|
1403
|
+
|
|
1404
|
+
@property
|
|
1405
|
+
def _tag_(self) -> str:
|
|
1383
1406
|
assert self._tag
|
|
1384
1407
|
return self._tag
|
|
1385
1408
|
|
|
@@ -1392,20 +1415,40 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1392
1415
|
return self._app
|
|
1393
1416
|
|
|
1394
1417
|
@property
|
|
1418
|
+
@with_deprecation_warning(
|
|
1419
|
+
(2026, 8, 26),
|
|
1420
|
+
"`Function.stub` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1421
|
+
)
|
|
1395
1422
|
def stub(self) -> "modal.app._App":
|
|
1396
1423
|
"""mdmd:hidden"""
|
|
1397
1424
|
# Deprecated soon, only for backwards compatibility
|
|
1398
1425
|
return self.app
|
|
1399
1426
|
|
|
1400
1427
|
@property
|
|
1401
|
-
|
|
1428
|
+
@with_deprecation_warning(
|
|
1429
|
+
(2026, 8, 26),
|
|
1430
|
+
"`Function.info` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1431
|
+
)
|
|
1432
|
+
def info(self) -> FunctionSourceInfo:
|
|
1402
1433
|
"""mdmd:hidden"""
|
|
1403
|
-
|
|
1404
|
-
return self._info
|
|
1434
|
+
return self._source_info_
|
|
1405
1435
|
|
|
1406
1436
|
@property
|
|
1437
|
+
def _source_info_(self) -> FunctionSourceInfo:
|
|
1438
|
+
assert self._source_info
|
|
1439
|
+
return self._source_info
|
|
1440
|
+
|
|
1441
|
+
@property
|
|
1442
|
+
@with_deprecation_warning(
|
|
1443
|
+
(2026, 8, 26),
|
|
1444
|
+
"`Function.spec` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1445
|
+
)
|
|
1407
1446
|
def spec(self) -> _FunctionSpec:
|
|
1408
1447
|
"""mdmd:hidden"""
|
|
1448
|
+
return self._spec_
|
|
1449
|
+
|
|
1450
|
+
@property
|
|
1451
|
+
def _spec_(self) -> _FunctionSpec:
|
|
1409
1452
|
assert self._spec
|
|
1410
1453
|
return self._spec
|
|
1411
1454
|
|
|
@@ -1413,13 +1456,19 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1413
1456
|
# only defined in definition scope/locally, and not for class methods at the moment
|
|
1414
1457
|
return bool(self._webhook_config and self._webhook_config.type != api_pb2.WEBHOOK_TYPE_UNSPECIFIED)
|
|
1415
1458
|
|
|
1416
|
-
def
|
|
1459
|
+
def _get_build_def(self) -> str:
|
|
1417
1460
|
"""mdmd:hidden"""
|
|
1418
1461
|
# Plaintext source and arg definition for the function, so it's part of the image
|
|
1419
1462
|
# hash. We can't use the cloudpickle hash because it's not very stable.
|
|
1420
1463
|
assert hasattr(self, "_raw_f") and hasattr(self, "_build_args") and self._raw_f is not None
|
|
1421
1464
|
return f"{inspect.getsource(self._raw_f)}\n{repr(self._build_args)}"
|
|
1422
1465
|
|
|
1466
|
+
get_build_def = with_deprecation_warning(
|
|
1467
|
+
(2026, 8, 26),
|
|
1468
|
+
"`Function.get_build_def` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1469
|
+
)(_get_build_def)
|
|
1470
|
+
"""mdmd:hidden"""
|
|
1471
|
+
|
|
1423
1472
|
# Live handle methods
|
|
1424
1473
|
|
|
1425
1474
|
def _initialize_from_empty(self):
|
|
@@ -1428,7 +1477,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1428
1477
|
self._is_generator = None
|
|
1429
1478
|
self._web_url = None
|
|
1430
1479
|
self._function_name = None
|
|
1431
|
-
self.
|
|
1480
|
+
self._source_info = None
|
|
1432
1481
|
self._serve_mounts = frozenset()
|
|
1433
1482
|
self._metadata = None
|
|
1434
1483
|
self._experimental_flash_urls = None
|
|
@@ -1560,7 +1609,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1560
1609
|
new_function._webhook_config = self._webhook_config
|
|
1561
1610
|
|
|
1562
1611
|
# Other fields not necessarily initialized
|
|
1563
|
-
if self.
|
|
1612
|
+
if self._source_info is not None:
|
|
1564
1613
|
new_function._build_args = self._build_args
|
|
1565
1614
|
new_function._is_method = self._is_method
|
|
1566
1615
|
new_function._raw_f = self._raw_f
|
|
@@ -1667,8 +1716,16 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1667
1716
|
return self._apply_dynamic_config(options, "with_batching")
|
|
1668
1717
|
|
|
1669
1718
|
@property
|
|
1719
|
+
@with_deprecation_warning(
|
|
1720
|
+
(2026, 8, 26),
|
|
1721
|
+
"`Function.is_generator` is deprecated and will be removed in `modal` version 1.6.0",
|
|
1722
|
+
)
|
|
1670
1723
|
async def is_generator(self) -> bool:
|
|
1671
1724
|
"""mdmd:hidden"""
|
|
1725
|
+
return await self._is_generator_
|
|
1726
|
+
|
|
1727
|
+
@property
|
|
1728
|
+
async def _is_generator_(self) -> bool:
|
|
1672
1729
|
# hacky: kind of like @live_method, but not hydrating if we have the value already from local source
|
|
1673
1730
|
# TODO(michael) use a common / lightweight method for handling unhydrated metadata properties
|
|
1674
1731
|
if self._is_generator is not None:
|
|
@@ -1858,12 +1915,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1858
1915
|
yield item
|
|
1859
1916
|
|
|
1860
1917
|
def _is_local(self):
|
|
1861
|
-
return self.
|
|
1918
|
+
return self._source_info is not None
|
|
1862
1919
|
|
|
1863
|
-
def
|
|
1864
|
-
if not self.
|
|
1865
|
-
raise ExecutionError("Can't get info for a function that isn't locally defined")
|
|
1866
|
-
return self.
|
|
1920
|
+
def _get_source_info(self) -> FunctionSourceInfo:
|
|
1921
|
+
if not self._source_info:
|
|
1922
|
+
raise ExecutionError("Can't get source info for a function that isn't locally defined")
|
|
1923
|
+
return self._source_info
|
|
1867
1924
|
|
|
1868
1925
|
def _get_obj(self) -> "modal.cls._Obj | None":
|
|
1869
1926
|
if not self._is_method:
|
|
@@ -1898,13 +1955,13 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1898
1955
|
)
|
|
1899
1956
|
raise ExecutionError(msg)
|
|
1900
1957
|
|
|
1901
|
-
info = self.
|
|
1958
|
+
info = self._get_source_info()
|
|
1902
1959
|
if not info.raw_f:
|
|
1903
1960
|
# Here if calling .local on a service function itself which should never happen
|
|
1904
1961
|
# TODO: check if we end up here in a container for a serialized function?
|
|
1905
1962
|
raise ExecutionError("Can't call .local on service function")
|
|
1906
1963
|
|
|
1907
|
-
if is_local() and self.
|
|
1964
|
+
if is_local() and self._spec_.volumes or self._spec_.network_file_systems:
|
|
1908
1965
|
warnings.warn(
|
|
1909
1966
|
f"The {info.function_name} function is executing locally "
|
|
1910
1967
|
+ "and will not have access to the mounted Volume or NetworkFileSystem data"
|
|
@@ -2002,12 +2059,20 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
2002
2059
|
fc._function_id = self.object_id
|
|
2003
2060
|
return fc
|
|
2004
2061
|
|
|
2062
|
+
@with_deprecation_warning(
|
|
2063
|
+
(2026, 8, 26),
|
|
2064
|
+
"`Function.get_raw_f` is deprecated and will be removed in `modal` version 1.6.0",
|
|
2065
|
+
)
|
|
2005
2066
|
def get_raw_f(self) -> Callable[..., Any]:
|
|
2006
2067
|
"""Return the inner Python object wrapped by this Modal Function.
|
|
2007
2068
|
|
|
2008
2069
|
Returns:
|
|
2009
2070
|
The original function object registered with Modal.
|
|
2010
2071
|
"""
|
|
2072
|
+
return self._raw_f_
|
|
2073
|
+
|
|
2074
|
+
@property
|
|
2075
|
+
def _raw_f_(self) -> Callable[..., Any]:
|
|
2011
2076
|
assert self._raw_f is not None
|
|
2012
2077
|
return self._raw_f
|
|
2013
2078
|
|
|
@@ -2077,7 +2142,12 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2077
2142
|
await self._hydrate_from_id_metadata()
|
|
2078
2143
|
if not self._app_id:
|
|
2079
2144
|
raise ExecutionError("app_id should have been set during function call hydration")
|
|
2080
|
-
return _LogQueryData(
|
|
2145
|
+
return _LogQueryData(
|
|
2146
|
+
self.client,
|
|
2147
|
+
self._app_id,
|
|
2148
|
+
LogsFilters(function_call_id=self.object_id),
|
|
2149
|
+
source_object_id=self.object_id,
|
|
2150
|
+
)
|
|
2081
2151
|
|
|
2082
2152
|
@property
|
|
2083
2153
|
def logs(self) -> _FunctionCallLogsManager:
|
|
@@ -41,7 +41,7 @@ from ._utils.docker_utils import (
|
|
|
41
41
|
extract_copy_command_patterns,
|
|
42
42
|
find_dockerignore_file,
|
|
43
43
|
)
|
|
44
|
-
from ._utils.function_utils import
|
|
44
|
+
from ._utils.function_utils import FunctionSourceInfo, parse_gpu_config
|
|
45
45
|
from ._utils.mount_utils import validate_only_modal_volumes, validate_volumes_by_object_id
|
|
46
46
|
from ._utils.name_utils import check_object_name
|
|
47
47
|
from .client import _Client
|
|
@@ -681,8 +681,8 @@ class _Image(_Object, type_prefix="im"):
|
|
|
681
681
|
|
|
682
682
|
if build_function:
|
|
683
683
|
build_function_id = build_function.object_id
|
|
684
|
-
globals = build_function.
|
|
685
|
-
attrs = build_function.
|
|
684
|
+
globals = build_function._get_source_info().get_globals()
|
|
685
|
+
attrs = build_function._get_source_info().get_cls_var_attrs()
|
|
686
686
|
globals = {**globals, **attrs}
|
|
687
687
|
filtered_globals = {}
|
|
688
688
|
for k, v in globals.items():
|
|
@@ -694,7 +694,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
694
694
|
# Skip unserializable values for now.
|
|
695
695
|
logger.warning(
|
|
696
696
|
f"Skipping unserializable global variable {k} for "
|
|
697
|
-
f"{build_function.
|
|
697
|
+
f"{build_function._get_source_info().function_name}. "
|
|
698
698
|
"Changes to this variable won't invalidate the image."
|
|
699
699
|
)
|
|
700
700
|
continue
|
|
@@ -704,7 +704,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
704
704
|
# TODO: better way to filter out types that don't have a stable hash?
|
|
705
705
|
build_function_globals = serialize(filtered_globals) if filtered_globals else b""
|
|
706
706
|
_build_function = api_pb2.BuildFunction(
|
|
707
|
-
definition=build_function.
|
|
707
|
+
definition=build_function._get_build_def(),
|
|
708
708
|
globals=build_function_globals,
|
|
709
709
|
input=build_function_input,
|
|
710
710
|
)
|
|
@@ -764,7 +764,10 @@ class _Image(_Object, type_prefix="im"):
|
|
|
764
764
|
if build_resp.HasField("metadata"):
|
|
765
765
|
metadata = build_resp.metadata
|
|
766
766
|
|
|
767
|
-
if result.status
|
|
767
|
+
if result.status in (
|
|
768
|
+
api_pb2.GenericResult.GENERIC_STATUS_FAILURE,
|
|
769
|
+
api_pb2.GenericResult.GENERIC_STATUS_MEMORY_MANAGER_EVICTION,
|
|
770
|
+
):
|
|
768
771
|
if result.exception:
|
|
769
772
|
raise ImageBuildError(
|
|
770
773
|
f"Image build for {image_id} failed with the exception:\n{result.exception}", image_id
|
|
@@ -2751,9 +2754,9 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2751
2754
|
# It may be possible to support lambdas eventually, but for now we don't handle them well, so reject quickly
|
|
2752
2755
|
raise InvalidError("Image.run_function does not support lambda functions.")
|
|
2753
2756
|
|
|
2754
|
-
info =
|
|
2757
|
+
info = FunctionSourceInfo(raw_f)
|
|
2755
2758
|
|
|
2756
|
-
function = _Function.
|
|
2759
|
+
function = _Function._from_local(
|
|
2757
2760
|
info,
|
|
2758
2761
|
app=None,
|
|
2759
2762
|
image=self,
|
|
@@ -2935,7 +2938,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2935
2938
|
try:
|
|
2936
2939
|
yield
|
|
2937
2940
|
except Exception as exc:
|
|
2938
|
-
if not self.
|
|
2941
|
+
if not self._is_hydrated:
|
|
2939
2942
|
# Might be hydrated later (if it's the container's used image)
|
|
2940
2943
|
self.inside_exceptions.append(exc)
|
|
2941
2944
|
elif env_image_id == self.object_id:
|
|
@@ -3048,7 +3051,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
3048
3051
|
"""mdmd:hidden"""
|
|
3049
3052
|
# Image inherits hydrate() from Object but can't be hydrated on demand
|
|
3050
3053
|
# Overriding the method lets us hide it from the docs and raise a better error message
|
|
3051
|
-
if not self.
|
|
3054
|
+
if not self._is_hydrated:
|
|
3052
3055
|
raise ExecutionError(
|
|
3053
3056
|
"Images cannot currently be hydrated on demand; you can build an Image by running an App that uses it."
|
|
3054
3057
|
)
|