modal 1.2.1.dev7__tar.gz → 1.2.1.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.2.1.dev7 → modal-1.2.1.dev9}/PKG-INFO +1 -1
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/app.py +89 -53
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/app.pyi +48 -18
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/client.pyi +2 -2
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cls.py +5 -12
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/runner.py +24 -33
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/runner.pyi +40 -24
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_version/__init__.py +1 -1
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/LICENSE +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/README.md +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/__main__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_billing.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_clustered_functions.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_functions.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_ipython.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_location.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_object.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_output.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_partial_function.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_pty.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_resolver.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_resources.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_serialization.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_traceback.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_tunnel.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_tunnel.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_type_manager.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/async_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/logger.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/_watcher.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/billing.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/2025.06.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/README.md +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/builder/base-images.json +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/call_graph.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/_download.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/_traceback.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/app.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/cluster.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/config.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/container.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/dict.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/entry_point.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/environment.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/import_refs.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/launch.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/profile.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/programs/launch_instance_ssh.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/programs/run_marimo.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/queues.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/run.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/secret.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/token.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/utils.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cli/volume.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/client.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/cls.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/config.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/container_process.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/container_process.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/dict.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/dict.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/environments.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/environments.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/exception.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/experimental/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/experimental/flash.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/experimental/flash.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/experimental/ipython.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/file_io.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/file_io.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/functions.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/functions.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/gpu.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/image.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/image.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/io_streams.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/io_streams.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/mount.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/mount.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/network_file_system.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/network_file_system.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/object.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/object.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/output.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/parallel_map.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/parallel_map.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/partial_function.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/partial_function.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/proxy.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/proxy.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/py.typed +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/queue.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/queue.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/retries.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/running_app.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/sandbox.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/sandbox.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/schedule.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/scheduler_placement.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/secret.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/secret.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/serving.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/serving.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/snapshot.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/snapshot.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/stream_type.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/token_flow.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/token_flow.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/volume.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal/volume.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/requires.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/__init__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api.proto +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api_pb2.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/py.typed +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router.proto +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router_pb2.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router_pb2.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/modal_version/__main__.py +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/pyproject.toml +0 -0
- {modal-1.2.1.dev7 → modal-1.2.1.dev9}/setup.cfg +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import inspect
|
|
3
3
|
import typing
|
|
4
4
|
from collections.abc import AsyncGenerator, Collection, Coroutine, Mapping, Sequence
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
from pathlib import PurePosixPath
|
|
6
7
|
from textwrap import dedent
|
|
7
8
|
from typing import (
|
|
@@ -114,6 +115,22 @@ class _FunctionDecoratorType:
|
|
|
114
115
|
def __call__(self, func): ...
|
|
115
116
|
|
|
116
117
|
|
|
118
|
+
@dataclass()
|
|
119
|
+
class _LocalAppState:
|
|
120
|
+
"""All state for apps that's part of the local/definition state"""
|
|
121
|
+
|
|
122
|
+
functions: dict[str, _Function]
|
|
123
|
+
classes: dict[str, _Cls]
|
|
124
|
+
image_default: Optional[_Image]
|
|
125
|
+
web_endpoints: list[str] # Used by the CLI
|
|
126
|
+
local_entrypoints: dict[str, _LocalEntrypoint]
|
|
127
|
+
tags: dict[str, str]
|
|
128
|
+
|
|
129
|
+
include_source_default: bool
|
|
130
|
+
secrets_default: Sequence[_Secret]
|
|
131
|
+
volumes_default: dict[Union[str, PurePosixPath], _Volume]
|
|
132
|
+
|
|
133
|
+
|
|
117
134
|
class _App:
|
|
118
135
|
"""A Modal App is a group of functions and classes that are deployed together.
|
|
119
136
|
|
|
@@ -151,23 +168,21 @@ class _App:
|
|
|
151
168
|
|
|
152
169
|
_name: Optional[str]
|
|
153
170
|
_description: Optional[str]
|
|
154
|
-
_tags: dict[str, str]
|
|
155
|
-
|
|
156
|
-
_functions: dict[str, _Function]
|
|
157
|
-
_classes: dict[str, _Cls]
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
_secrets: Sequence[_Secret]
|
|
161
|
-
_volumes: dict[Union[str, PurePosixPath], _Volume]
|
|
162
|
-
_web_endpoints: list[str] # Used by the CLI
|
|
163
|
-
_local_entrypoints: dict[str, _LocalEntrypoint]
|
|
172
|
+
_local_state_attr: Optional[_LocalAppState] = None
|
|
164
173
|
|
|
165
174
|
# Running apps only (container apps or running local)
|
|
166
175
|
_app_id: Optional[str] # Kept after app finishes
|
|
167
176
|
_running_app: Optional[RunningApp] # Various app info
|
|
168
177
|
_client: Optional[_Client]
|
|
169
178
|
|
|
170
|
-
|
|
179
|
+
@property
|
|
180
|
+
def _local_state(self) -> _LocalAppState:
|
|
181
|
+
"""For internal use only. Do not use this property directly."""
|
|
182
|
+
|
|
183
|
+
if self._local_state_attr is None:
|
|
184
|
+
raise AttributeError("Local state is not initialized - app is not locally available")
|
|
185
|
+
return self._local_state_attr
|
|
171
186
|
|
|
172
187
|
def __init__(
|
|
173
188
|
self,
|
|
@@ -196,8 +211,6 @@ class _App:
|
|
|
196
211
|
|
|
197
212
|
self._name = name
|
|
198
213
|
self._description = name
|
|
199
|
-
self._tags = tags or {}
|
|
200
|
-
self._include_source_default = include_source
|
|
201
214
|
|
|
202
215
|
check_sequence(secrets, _Secret, "`secrets=` has to be a list or tuple of `modal.Secret` objects")
|
|
203
216
|
validate_volumes(volumes)
|
|
@@ -205,16 +218,24 @@ class _App:
|
|
|
205
218
|
if image is not None and not isinstance(image, _Image):
|
|
206
219
|
raise InvalidError("`image=` has to be a `modal.Image` object")
|
|
207
220
|
|
|
208
|
-
self.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
self._local_state_attr = _LocalAppState(
|
|
222
|
+
functions={},
|
|
223
|
+
classes={},
|
|
224
|
+
image_default=image,
|
|
225
|
+
secrets_default=secrets,
|
|
226
|
+
volumes_default=volumes,
|
|
227
|
+
include_source_default=include_source,
|
|
228
|
+
web_endpoints=[],
|
|
229
|
+
local_entrypoints={},
|
|
230
|
+
tags=tags or {},
|
|
231
|
+
)
|
|
215
232
|
|
|
233
|
+
# Running apps only
|
|
216
234
|
self._app_id = None
|
|
217
235
|
self._running_app = None # Set inside container, OR during the time an app is running locally
|
|
236
|
+
|
|
237
|
+
# Client is special - needed to be set just before the app is "hydrated" or running at the latest
|
|
238
|
+
# Guaranteed to be set for running apps, but also needed to actually *hydrate* the app and make it running
|
|
218
239
|
self._client = None
|
|
219
240
|
|
|
220
241
|
# Register this app. This is used to look up the app in the container, when we can't get it from the function
|
|
@@ -283,7 +304,8 @@ class _App:
|
|
|
283
304
|
|
|
284
305
|
response = await retry_transient_errors(client.stub.AppGetOrCreate, request)
|
|
285
306
|
|
|
286
|
-
app = _App(name)
|
|
307
|
+
app = _App(name) # TODO: this should probably be a distinct constructor, possibly even a distinct type
|
|
308
|
+
app._local_state_attr = None # this is not a locally defined App, so no local state
|
|
287
309
|
app._app_id = response.app_id
|
|
288
310
|
app._client = client
|
|
289
311
|
app._running_app = RunningApp(response.app_id, interactive=False)
|
|
@@ -310,18 +332,19 @@ class _App:
|
|
|
310
332
|
App that is retrieved via `modal.App.lookup`. It is likely to be deprecated in the future.
|
|
311
333
|
|
|
312
334
|
"""
|
|
313
|
-
return self.
|
|
335
|
+
return self._local_state.image_default
|
|
314
336
|
|
|
315
337
|
@image.setter
|
|
316
338
|
def image(self, value):
|
|
317
339
|
"""mdmd:hidden"""
|
|
318
|
-
self.
|
|
340
|
+
self._local_state.image_default = value
|
|
319
341
|
|
|
320
342
|
def _uncreate_all_objects(self):
|
|
321
343
|
# TODO(erikbern): this doesn't unhydrate objects that aren't tagged
|
|
322
|
-
|
|
344
|
+
local_state = self._local_state
|
|
345
|
+
for obj in local_state.functions.values():
|
|
323
346
|
obj._unhydrate()
|
|
324
|
-
for obj in
|
|
347
|
+
for obj in local_state.classes.values():
|
|
325
348
|
obj._unhydrate()
|
|
326
349
|
|
|
327
350
|
@asynccontextmanager
|
|
@@ -457,8 +480,9 @@ class _App:
|
|
|
457
480
|
return self
|
|
458
481
|
|
|
459
482
|
def _get_default_image(self):
|
|
460
|
-
|
|
461
|
-
|
|
483
|
+
local_state = self._local_state
|
|
484
|
+
if local_state.image_default:
|
|
485
|
+
return local_state.image_default
|
|
462
486
|
else:
|
|
463
487
|
return _default_image
|
|
464
488
|
|
|
@@ -473,7 +497,8 @@ class _App:
|
|
|
473
497
|
return [m for m in all_mounts if m.is_local()]
|
|
474
498
|
|
|
475
499
|
def _add_function(self, function: _Function, is_web_endpoint: bool):
|
|
476
|
-
|
|
500
|
+
local_state = self._local_state
|
|
501
|
+
if old_function := local_state.functions.get(function.tag, None):
|
|
477
502
|
if old_function is function:
|
|
478
503
|
return # already added the same exact instance, ignore
|
|
479
504
|
|
|
@@ -484,7 +509,7 @@ class _App:
|
|
|
484
509
|
f"[{old_function._info.module_name}].{old_function._info.function_name}"
|
|
485
510
|
f" with new function [{function._info.module_name}].{function._info.function_name}"
|
|
486
511
|
)
|
|
487
|
-
if function.tag in
|
|
512
|
+
if function.tag in local_state.classes:
|
|
488
513
|
logger.warning(f"Warning: tag {function.tag} exists but is overridden by function")
|
|
489
514
|
|
|
490
515
|
if self._running_app:
|
|
@@ -495,9 +520,9 @@ class _App:
|
|
|
495
520
|
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
|
496
521
|
function._hydrate(object_id, self._client, metadata)
|
|
497
522
|
|
|
498
|
-
|
|
523
|
+
local_state.functions[function.tag] = function
|
|
499
524
|
if is_web_endpoint:
|
|
500
|
-
|
|
525
|
+
local_state.web_endpoints.append(function.tag)
|
|
501
526
|
|
|
502
527
|
def _add_class(self, tag: str, cls: _Cls):
|
|
503
528
|
if self._running_app:
|
|
@@ -508,7 +533,7 @@ class _App:
|
|
|
508
533
|
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
|
509
534
|
cls._hydrate(object_id, self._client, metadata)
|
|
510
535
|
|
|
511
|
-
self.
|
|
536
|
+
self._local_state.classes[tag] = cls
|
|
512
537
|
|
|
513
538
|
def _init_container(self, client: _Client, running_app: RunningApp):
|
|
514
539
|
self._app_id = running_app.app_id
|
|
@@ -516,18 +541,18 @@ class _App:
|
|
|
516
541
|
self._client = client
|
|
517
542
|
|
|
518
543
|
_App._container_app = self
|
|
519
|
-
|
|
544
|
+
local_state = self._local_state
|
|
520
545
|
# Hydrate function objects
|
|
521
546
|
for tag, object_id in running_app.function_ids.items():
|
|
522
|
-
if tag in
|
|
523
|
-
obj =
|
|
547
|
+
if tag in local_state.functions:
|
|
548
|
+
obj = local_state.functions[tag]
|
|
524
549
|
handle_metadata = running_app.object_handle_metadata[object_id]
|
|
525
550
|
obj._hydrate(object_id, client, handle_metadata)
|
|
526
551
|
|
|
527
552
|
# Hydrate class objects
|
|
528
553
|
for tag, object_id in running_app.class_ids.items():
|
|
529
|
-
if tag in
|
|
530
|
-
obj =
|
|
554
|
+
if tag in local_state.classes:
|
|
555
|
+
obj = local_state.classes[tag]
|
|
531
556
|
handle_metadata = running_app.object_handle_metadata[object_id]
|
|
532
557
|
obj._hydrate(object_id, client, handle_metadata)
|
|
533
558
|
|
|
@@ -541,7 +566,7 @@ class _App:
|
|
|
541
566
|
This method is likely to be deprecated in the future in favor of a different
|
|
542
567
|
approach for retrieving the layout of a deployed App.
|
|
543
568
|
"""
|
|
544
|
-
return self.
|
|
569
|
+
return self._local_state.functions
|
|
545
570
|
|
|
546
571
|
@property
|
|
547
572
|
def registered_classes(self) -> dict[str, _Cls]:
|
|
@@ -553,7 +578,7 @@ class _App:
|
|
|
553
578
|
This method is likely to be deprecated in the future in favor of a different
|
|
554
579
|
approach for retrieving the layout of a deployed App.
|
|
555
580
|
"""
|
|
556
|
-
return self.
|
|
581
|
+
return self._local_state.classes
|
|
557
582
|
|
|
558
583
|
@property
|
|
559
584
|
def registered_entrypoints(self) -> dict[str, _LocalEntrypoint]:
|
|
@@ -564,7 +589,7 @@ class _App:
|
|
|
564
589
|
expected to work when a deplyoed App has been retrieved via `modal.App.lookup`.
|
|
565
590
|
This method is likely to be deprecated in the future.
|
|
566
591
|
"""
|
|
567
|
-
return self.
|
|
592
|
+
return self._local_state.local_entrypoints
|
|
568
593
|
|
|
569
594
|
@property
|
|
570
595
|
def registered_web_endpoints(self) -> list[str]:
|
|
@@ -576,7 +601,7 @@ class _App:
|
|
|
576
601
|
This method is likely to be deprecated in the future in favor of a different
|
|
577
602
|
approach for retrieving the layout of a deployed App.
|
|
578
603
|
"""
|
|
579
|
-
return self.
|
|
604
|
+
return self._local_state.web_endpoints
|
|
580
605
|
|
|
581
606
|
def local_entrypoint(
|
|
582
607
|
self, _warn_parentheses_missing: Any = None, *, name: Optional[str] = None
|
|
@@ -637,10 +662,11 @@ class _App:
|
|
|
637
662
|
def wrapped(raw_f: Callable[..., Any]) -> _LocalEntrypoint:
|
|
638
663
|
info = FunctionInfo(raw_f)
|
|
639
664
|
tag = name if name is not None else raw_f.__qualname__
|
|
640
|
-
|
|
665
|
+
local_state = self._local_state
|
|
666
|
+
if tag in local_state.local_entrypoints:
|
|
641
667
|
# TODO: get rid of this limitation.
|
|
642
668
|
raise InvalidError(f"Duplicate local entrypoint name: {tag}. Local entrypoint names must be unique.")
|
|
643
|
-
entrypoint =
|
|
669
|
+
entrypoint = local_state.local_entrypoints[tag] = _LocalEntrypoint(info, self)
|
|
644
670
|
return entrypoint
|
|
645
671
|
|
|
646
672
|
return wrapped
|
|
@@ -732,7 +758,8 @@ class _App:
|
|
|
732
758
|
secrets = secrets or []
|
|
733
759
|
if env:
|
|
734
760
|
secrets = [*secrets, _Secret.from_dict(env)]
|
|
735
|
-
|
|
761
|
+
local_state = self._local_state
|
|
762
|
+
secrets = [*local_state.secrets_default, *secrets]
|
|
736
763
|
|
|
737
764
|
def wrapped(
|
|
738
765
|
f: Union[_PartialFunction, Callable[..., Any], None],
|
|
@@ -840,7 +867,7 @@ class _App:
|
|
|
840
867
|
is_generator=is_generator,
|
|
841
868
|
gpu=gpu,
|
|
842
869
|
network_file_systems=network_file_systems,
|
|
843
|
-
volumes={**
|
|
870
|
+
volumes={**local_state.volumes_default, **volumes},
|
|
844
871
|
cpu=cpu,
|
|
845
872
|
memory=memory,
|
|
846
873
|
ephemeral_disk=ephemeral_disk,
|
|
@@ -866,7 +893,7 @@ class _App:
|
|
|
866
893
|
i6pn_enabled=i6pn_enabled,
|
|
867
894
|
cluster_size=cluster_size, # Experimental: Clustered functions
|
|
868
895
|
rdma=rdma,
|
|
869
|
-
include_source=include_source if include_source is not None else
|
|
896
|
+
include_source=include_source if include_source is not None else local_state.include_source_default,
|
|
870
897
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
871
898
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
872
899
|
restrict_output=_experimental_restrict_output,
|
|
@@ -963,6 +990,7 @@ class _App:
|
|
|
963
990
|
secrets = [*secrets, _Secret.from_dict(env)]
|
|
964
991
|
|
|
965
992
|
def wrapper(wrapped_cls: Union[CLS_T, _PartialFunction]) -> CLS_T:
|
|
993
|
+
local_state = self._local_state
|
|
966
994
|
# Check if the decorated object is a class
|
|
967
995
|
if isinstance(wrapped_cls, _PartialFunction):
|
|
968
996
|
wrapped_cls.registered = True
|
|
@@ -1029,10 +1057,10 @@ class _App:
|
|
|
1029
1057
|
info,
|
|
1030
1058
|
app=self,
|
|
1031
1059
|
image=image or self._get_default_image(),
|
|
1032
|
-
secrets=[*
|
|
1060
|
+
secrets=[*local_state.secrets_default, *secrets],
|
|
1033
1061
|
gpu=gpu,
|
|
1034
1062
|
network_file_systems=network_file_systems,
|
|
1035
|
-
volumes={**
|
|
1063
|
+
volumes={**local_state.volumes_default, **volumes},
|
|
1036
1064
|
cpu=cpu,
|
|
1037
1065
|
memory=memory,
|
|
1038
1066
|
ephemeral_disk=ephemeral_disk,
|
|
@@ -1057,7 +1085,7 @@ class _App:
|
|
|
1057
1085
|
i6pn_enabled=i6pn_enabled,
|
|
1058
1086
|
cluster_size=cluster_size,
|
|
1059
1087
|
rdma=rdma,
|
|
1060
|
-
include_source=include_source if include_source is not None else
|
|
1088
|
+
include_source=include_source if include_source is not None else local_state.include_source_default,
|
|
1061
1089
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
1062
1090
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
1063
1091
|
_experimental_custom_scaling_factor=_experimental_custom_scaling_factor,
|
|
@@ -1067,6 +1095,11 @@ class _App:
|
|
|
1067
1095
|
self._add_function(cls_func, is_web_endpoint=False)
|
|
1068
1096
|
|
|
1069
1097
|
cls: _Cls = _Cls.from_local(user_cls, self, cls_func)
|
|
1098
|
+
for method_name, partial_function in cls._method_partials.items():
|
|
1099
|
+
if partial_function.params.webhook_config is not None:
|
|
1100
|
+
full_name = f"{user_cls.__name__}.{method_name}"
|
|
1101
|
+
local_state.web_endpoints.append(full_name)
|
|
1102
|
+
partial_function.registered = True
|
|
1070
1103
|
|
|
1071
1104
|
tag: str = user_cls.__name__
|
|
1072
1105
|
self._add_class(tag, cls)
|
|
@@ -1102,11 +1135,14 @@ class _App:
|
|
|
1102
1135
|
(with this App's tags taking precedence in the case of conflicts).
|
|
1103
1136
|
|
|
1104
1137
|
"""
|
|
1105
|
-
|
|
1138
|
+
other_app_local_state = other_app._local_state
|
|
1139
|
+
this_local_state = self._local_state
|
|
1140
|
+
|
|
1141
|
+
for tag, function in other_app_local_state.functions.items():
|
|
1106
1142
|
self._add_function(function, False) # TODO(erikbern): webhook config?
|
|
1107
1143
|
|
|
1108
|
-
for tag, cls in
|
|
1109
|
-
existing_cls =
|
|
1144
|
+
for tag, cls in other_app_local_state.classes.items():
|
|
1145
|
+
existing_cls = this_local_state.classes.get(tag)
|
|
1110
1146
|
if existing_cls and existing_cls != cls:
|
|
1111
1147
|
logger.warning(
|
|
1112
1148
|
f"Named app class {tag} with existing value {existing_cls} is being "
|
|
@@ -1116,7 +1152,7 @@ class _App:
|
|
|
1116
1152
|
self._add_class(tag, cls)
|
|
1117
1153
|
|
|
1118
1154
|
if inherit_tags:
|
|
1119
|
-
|
|
1155
|
+
this_local_state.tags = {**other_app_local_state.tags, **this_local_state.tags}
|
|
1120
1156
|
|
|
1121
1157
|
return self
|
|
1122
1158
|
|
|
@@ -1132,7 +1168,7 @@ class _App:
|
|
|
1132
1168
|
|
|
1133
1169
|
"""
|
|
1134
1170
|
# Note that we are requiring the App to be "running" before we set the tags.
|
|
1135
|
-
# Alternatively, we could hold onto the tags (i.e. in `self.
|
|
1171
|
+
# Alternatively, we could hold onto the tags (i.e. in `self._local_state.tags`) and then pass
|
|
1136
1172
|
# then up when AppPublish gets called. I'm not certain we want to support it, though.
|
|
1137
1173
|
# It might not be obvious to users that `.set_tags()` is eager and has immediate effect
|
|
1138
1174
|
# when the App is running, but lazy (and potentially ignored) otherwise. There would be
|
|
@@ -74,6 +74,42 @@ class _FunctionDecoratorType:
|
|
|
74
74
|
self, func: collections.abc.Callable[P, ReturnType]
|
|
75
75
|
) -> modal.functions.Function[P, ReturnType, ReturnType]: ...
|
|
76
76
|
|
|
77
|
+
class _LocalAppState:
|
|
78
|
+
"""All state for apps that's part of the local/definition state"""
|
|
79
|
+
|
|
80
|
+
functions: dict[str, modal._functions._Function]
|
|
81
|
+
classes: dict[str, modal.cls._Cls]
|
|
82
|
+
image_default: typing.Optional[modal.image._Image]
|
|
83
|
+
web_endpoints: list[str]
|
|
84
|
+
local_entrypoints: dict[str, _LocalEntrypoint]
|
|
85
|
+
tags: dict[str, str]
|
|
86
|
+
include_source_default: bool
|
|
87
|
+
secrets_default: collections.abc.Sequence[modal.secret._Secret]
|
|
88
|
+
volumes_default: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
|
|
89
|
+
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
functions: dict[str, modal._functions._Function],
|
|
93
|
+
classes: dict[str, modal.cls._Cls],
|
|
94
|
+
image_default: typing.Optional[modal.image._Image],
|
|
95
|
+
web_endpoints: list[str],
|
|
96
|
+
local_entrypoints: dict[str, _LocalEntrypoint],
|
|
97
|
+
tags: dict[str, str],
|
|
98
|
+
include_source_default: bool,
|
|
99
|
+
secrets_default: collections.abc.Sequence[modal.secret._Secret],
|
|
100
|
+
volumes_default: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume],
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
def __repr__(self):
|
|
106
|
+
"""Return repr(self)."""
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
def __eq__(self, other):
|
|
110
|
+
"""Return self==value."""
|
|
111
|
+
...
|
|
112
|
+
|
|
77
113
|
class _App:
|
|
78
114
|
"""A Modal App is a group of functions and classes that are deployed together.
|
|
79
115
|
|
|
@@ -110,18 +146,15 @@ class _App:
|
|
|
110
146
|
_container_app: typing.ClassVar[typing.Optional[_App]]
|
|
111
147
|
_name: typing.Optional[str]
|
|
112
148
|
_description: typing.Optional[str]
|
|
113
|
-
|
|
114
|
-
_functions: dict[str, modal._functions._Function]
|
|
115
|
-
_classes: dict[str, modal.cls._Cls]
|
|
116
|
-
_image: typing.Optional[modal.image._Image]
|
|
117
|
-
_secrets: collections.abc.Sequence[modal.secret._Secret]
|
|
118
|
-
_volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume]
|
|
119
|
-
_web_endpoints: list[str]
|
|
120
|
-
_local_entrypoints: dict[str, _LocalEntrypoint]
|
|
149
|
+
_local_state_attr: typing.Optional[_LocalAppState]
|
|
121
150
|
_app_id: typing.Optional[str]
|
|
122
151
|
_running_app: typing.Optional[modal.running_app.RunningApp]
|
|
123
152
|
_client: typing.Optional[modal.client._Client]
|
|
124
|
-
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def _local_state(self) -> _LocalAppState:
|
|
156
|
+
"""For internal use only. Do not use this property directly."""
|
|
157
|
+
...
|
|
125
158
|
|
|
126
159
|
def __init__(
|
|
127
160
|
self,
|
|
@@ -630,18 +663,10 @@ class App:
|
|
|
630
663
|
_container_app: typing.ClassVar[typing.Optional[App]]
|
|
631
664
|
_name: typing.Optional[str]
|
|
632
665
|
_description: typing.Optional[str]
|
|
633
|
-
|
|
634
|
-
_functions: dict[str, modal.functions.Function]
|
|
635
|
-
_classes: dict[str, modal.cls.Cls]
|
|
636
|
-
_image: typing.Optional[modal.image.Image]
|
|
637
|
-
_secrets: collections.abc.Sequence[modal.secret.Secret]
|
|
638
|
-
_volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume]
|
|
639
|
-
_web_endpoints: list[str]
|
|
640
|
-
_local_entrypoints: dict[str, LocalEntrypoint]
|
|
666
|
+
_local_state_attr: typing.Optional[_LocalAppState]
|
|
641
667
|
_app_id: typing.Optional[str]
|
|
642
668
|
_running_app: typing.Optional[modal.running_app.RunningApp]
|
|
643
669
|
_client: typing.Optional[modal.client.Client]
|
|
644
|
-
_include_source_default: typing.Optional[bool]
|
|
645
670
|
|
|
646
671
|
def __init__(
|
|
647
672
|
self,
|
|
@@ -664,6 +689,11 @@ class App:
|
|
|
664
689
|
"""
|
|
665
690
|
...
|
|
666
691
|
|
|
692
|
+
@property
|
|
693
|
+
def _local_state(self) -> _LocalAppState:
|
|
694
|
+
"""For internal use only. Do not use this property directly."""
|
|
695
|
+
...
|
|
696
|
+
|
|
667
697
|
@property
|
|
668
698
|
def name(self) -> typing.Optional[str]:
|
|
669
699
|
"""The user-provided name of the App."""
|
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.2.1.
|
|
36
|
+
version: str = "1.2.1.dev9",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.2.1.
|
|
167
|
+
version: str = "1.2.1.dev9",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -577,22 +577,15 @@ More information on class parameterization can be found here: https://modal.com/
|
|
|
577
577
|
# validate signature
|
|
578
578
|
_Cls.validate_construction_mechanism(user_cls)
|
|
579
579
|
|
|
580
|
-
method_partials: dict[str, _PartialFunction] = _find_partial_methods_for_user_cls(
|
|
581
|
-
user_cls, _PartialFunctionFlags.interface_flags()
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
for method_name, partial_function in method_partials.items():
|
|
585
|
-
if partial_function.params.webhook_config is not None:
|
|
586
|
-
full_name = f"{user_cls.__name__}.{method_name}"
|
|
587
|
-
app._web_endpoints.append(full_name)
|
|
588
|
-
partial_function.registered = True
|
|
589
|
-
|
|
590
580
|
# Disable the warning that lifecycle methods are not wrapped
|
|
591
|
-
|
|
581
|
+
lifecycle_method_partials = _find_partial_methods_for_user_cls(
|
|
592
582
|
user_cls, ~_PartialFunctionFlags.interface_flags()
|
|
593
|
-
)
|
|
583
|
+
)
|
|
584
|
+
for partial_function in lifecycle_method_partials.values():
|
|
594
585
|
partial_function.registered = True
|
|
595
586
|
|
|
587
|
+
method_partials = _find_partial_methods_for_user_cls(user_cls, _PartialFunctionFlags.interface_flags())
|
|
588
|
+
|
|
596
589
|
# Get all callables
|
|
597
590
|
callables: dict[str, Callable] = {
|
|
598
591
|
k: pf.raw_f
|