modAL 1.3.2__tar.gz → 1.3.2.dev0__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.3.2 → modal-1.3.2.dev0}/PKG-INFO +1 -1
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_object.py +35 -40
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_output.py +1 -2
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/app.py +0 -34
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/container.py +1 -9
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/entry_point.py +0 -2
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/utils.py +2 -4
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/volume.py +0 -28
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/client.pyi +10 -2
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/functions.pyi +6 -6
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/object.pyi +0 -11
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/runner.py +5 -1
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/token_flow.py +17 -2
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/token_flow.pyi +3 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/SOURCES.txt +0 -2
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api.proto +0 -10
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api_grpc.py +0 -16
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api_pb2.py +67 -87
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api_pb2.pyi +0 -28
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api_pb2_grpc.py +0 -33
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/api_pb2_grpc.pyi +0 -10
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/modal_api_grpc.py +0 -1
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_version/__init__.py +1 -1
- modal-1.3.2/modal/_utils/browser_utils.py +0 -28
- modal-1.3.2/modal/cli/dashboard.py +0 -30
- {modal-1.3.2 → modal-1.3.2.dev0}/LICENSE +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/README.md +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/__main__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_billing.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_clustered_functions.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_clustered_functions.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_container_entrypoint.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_functions.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_grpc_client.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_ipython.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_load_context.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_location.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_partial_function.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_pty.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_resolver.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_resources.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/asgi.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/execution_context.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/telemetry.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_serialization.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_server.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_traceback.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_tunnel.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_tunnel.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_type_manager.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/app_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/async_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/blob_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/deprecation.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/docker_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/function_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/git_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/hash_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/http_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/logger.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/mount_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/name_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/package_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/shell_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_utils/time_utils.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_vendor/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_vendor/tblib.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/_watcher.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/app.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/app.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/billing.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/2023.12.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/2024.04.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/2024.10.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/2025.06.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/README.md +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/builder/base-images.json +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/call_graph.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/_download.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/_traceback.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/cluster.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/config.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/dict.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/environment.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/import_refs.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/launch.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/network_file_system.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/profile.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/programs/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/programs/vscode.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/queues.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/run.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/secret.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/shell.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cli/token.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/client.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cls.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/cls.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/config.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/container_process.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/container_process.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/dict.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/dict.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/environments.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/environments.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/exception.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/experimental/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/experimental/flash.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/experimental/flash.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/experimental/ipython.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/file_io.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/file_io.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/file_pattern_matcher.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/functions.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/gpu.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/image.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/image.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/io_streams.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/io_streams.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/mount.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/mount.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/network_file_system.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/network_file_system.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/object.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/output.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/parallel_map.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/parallel_map.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/partial_function.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/partial_function.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/proxy.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/proxy.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/py.typed +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/queue.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/queue.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/retries.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/runner.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/running_app.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/sandbox.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/sandbox.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/schedule.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/scheduler_placement.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/secret.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/secret.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/server.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/server.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/serving.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/serving.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/snapshot.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/snapshot.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/stream_type.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/volume.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal/volume.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/requires.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal.egg-info/top_level.txt +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/__init__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/py.typed +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router.proto +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/modal_version/__main__.py +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/pyproject.toml +0 -0
- {modal-1.3.2 → modal-1.3.2.dev0}/setup.cfg +0 -0
|
@@ -39,41 +39,6 @@ def _get_environment_name(
|
|
|
39
39
|
return config.get("environment")
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def live_method(method):
|
|
43
|
-
@wraps(method)
|
|
44
|
-
async def wrapped(self, *args, **kwargs):
|
|
45
|
-
await self.hydrate()
|
|
46
|
-
return await method(self, *args, **kwargs)
|
|
47
|
-
|
|
48
|
-
return wrapped
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def live_method_gen(method):
|
|
52
|
-
@wraps(method)
|
|
53
|
-
async def wrapped(self, *args, **kwargs):
|
|
54
|
-
await self.hydrate()
|
|
55
|
-
async with aclosing(method(self, *args, **kwargs)) as stream:
|
|
56
|
-
async for item in stream:
|
|
57
|
-
yield item
|
|
58
|
-
|
|
59
|
-
return wrapped
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def live_method_contextmanager(method):
|
|
63
|
-
# make sure a wrapped function returning an async context manager
|
|
64
|
-
# will not require both an `await func.aio()` and `async with`
|
|
65
|
-
# which would have been the case if it was wrapped in live_method
|
|
66
|
-
|
|
67
|
-
@wraps(method)
|
|
68
|
-
@contextlib.asynccontextmanager
|
|
69
|
-
async def wrapped(self, *args, **kwargs):
|
|
70
|
-
await self.hydrate()
|
|
71
|
-
async with method(self, *args, **kwargs) as ctx:
|
|
72
|
-
yield ctx
|
|
73
|
-
|
|
74
|
-
return wrapped
|
|
75
|
-
|
|
76
|
-
|
|
77
42
|
class _Object:
|
|
78
43
|
_type_prefix: ClassVar[Optional[str]] = None
|
|
79
44
|
_prefix_to_type: ClassVar[dict[str, type]] = {}
|
|
@@ -310,11 +275,6 @@ class _Object:
|
|
|
310
275
|
raise AttributeError(f"Attempting to get object_id of unhydrated {self}")
|
|
311
276
|
return self._object_id
|
|
312
277
|
|
|
313
|
-
@live_method
|
|
314
|
-
async def get_dashboard_url(self) -> str:
|
|
315
|
-
"""mdmd:hidden"""
|
|
316
|
-
return f"https://modal.com/id/{self.object_id}"
|
|
317
|
-
|
|
318
278
|
@property
|
|
319
279
|
def client(self) -> _Client:
|
|
320
280
|
"""mdmd:hidden"""
|
|
@@ -376,3 +336,38 @@ class _Object:
|
|
|
376
336
|
with suppress_tb_frame(): # skip this frame by default
|
|
377
337
|
await resolver.load(self, root_load_context)
|
|
378
338
|
return self
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def live_method(method):
|
|
342
|
+
@wraps(method)
|
|
343
|
+
async def wrapped(self, *args, **kwargs):
|
|
344
|
+
await self.hydrate()
|
|
345
|
+
return await method(self, *args, **kwargs)
|
|
346
|
+
|
|
347
|
+
return wrapped
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def live_method_gen(method):
|
|
351
|
+
@wraps(method)
|
|
352
|
+
async def wrapped(self, *args, **kwargs):
|
|
353
|
+
await self.hydrate()
|
|
354
|
+
async with aclosing(method(self, *args, **kwargs)) as stream:
|
|
355
|
+
async for item in stream:
|
|
356
|
+
yield item
|
|
357
|
+
|
|
358
|
+
return wrapped
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def live_method_contextmanager(method):
|
|
362
|
+
# make sure a wrapped function returning an async context manager
|
|
363
|
+
# will not require both an `await func.aio()` and `async with`
|
|
364
|
+
# which would have been the case if it was wrapped in live_method
|
|
365
|
+
|
|
366
|
+
@wraps(method)
|
|
367
|
+
@contextlib.asynccontextmanager
|
|
368
|
+
async def wrapped(self, *args, **kwargs):
|
|
369
|
+
await self.hydrate()
|
|
370
|
+
async with method(self, *args, **kwargs) as ctx:
|
|
371
|
+
yield ctx
|
|
372
|
+
|
|
373
|
+
return wrapped
|
|
@@ -545,7 +545,7 @@ async def get_app_logs_loop(
|
|
|
545
545
|
output_mgr: OutputManager,
|
|
546
546
|
app_id: str | None = None,
|
|
547
547
|
task_id: str | None = None,
|
|
548
|
-
|
|
548
|
+
app_logs_url: str | None = None,
|
|
549
549
|
):
|
|
550
550
|
last_log_batch_entry_id = ""
|
|
551
551
|
|
|
@@ -600,7 +600,6 @@ async def get_app_logs_loop(
|
|
|
600
600
|
request = api_pb2.AppGetLogsRequest(
|
|
601
601
|
app_id=app_id or "",
|
|
602
602
|
task_id=task_id or "",
|
|
603
|
-
sandbox_id=sandbox_id or "",
|
|
604
603
|
timeout=55,
|
|
605
604
|
last_entry_id=last_log_batch_entry_id,
|
|
606
605
|
)
|
|
@@ -10,9 +10,7 @@ from rich.text import Text
|
|
|
10
10
|
from typer import Argument
|
|
11
11
|
|
|
12
12
|
from modal._object import _get_environment_name
|
|
13
|
-
from modal._output import make_console
|
|
14
13
|
from modal._utils.async_utils import synchronizer
|
|
15
|
-
from modal._utils.browser_utils import open_url_and_display
|
|
16
14
|
from modal.client import _Client
|
|
17
15
|
from modal.environments import ensure_env
|
|
18
16
|
from modal_proto import api_pb2
|
|
@@ -250,35 +248,3 @@ async def history(
|
|
|
250
248
|
|
|
251
249
|
if deployments_with_dirty_commit and not json:
|
|
252
250
|
rich.print("* - repo had uncommitted changes")
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
@app_cli.command("dashboard", no_args_is_help=True)
|
|
256
|
-
@synchronizer.create_blocking
|
|
257
|
-
async def dashboard(
|
|
258
|
-
app_identifier: str = APP_IDENTIFIER,
|
|
259
|
-
*,
|
|
260
|
-
env: Optional[str] = ENV_OPTION,
|
|
261
|
-
):
|
|
262
|
-
"""Open an App's dashboard page in your web browser.
|
|
263
|
-
|
|
264
|
-
**Examples:**
|
|
265
|
-
|
|
266
|
-
Open dashboard for an app by name:
|
|
267
|
-
|
|
268
|
-
```
|
|
269
|
-
modal app dashboard my-app
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Use a specified environment:
|
|
273
|
-
|
|
274
|
-
```
|
|
275
|
-
modal app dashboard my-app --env dev
|
|
276
|
-
```
|
|
277
|
-
"""
|
|
278
|
-
client = await _Client.from_env()
|
|
279
|
-
app_id = await get_app_id.aio(app_identifier, env, client)
|
|
280
|
-
|
|
281
|
-
console = make_console()
|
|
282
|
-
url = f"https://modal.com/id/{app_id}"
|
|
283
|
-
|
|
284
|
-
open_url_and_display(url, "App dashboard", console)
|
|
@@ -13,7 +13,6 @@ from modal.client import _Client
|
|
|
13
13
|
from modal.config import config
|
|
14
14
|
from modal.container_process import _ContainerProcess
|
|
15
15
|
from modal.environments import ensure_env
|
|
16
|
-
from modal.exception import InvalidError
|
|
17
16
|
from modal.stream_type import StreamType
|
|
18
17
|
from modal_proto import api_pb2
|
|
19
18
|
|
|
@@ -53,14 +52,7 @@ def logs(
|
|
|
53
52
|
timestamps: bool = typer.Option(False, "--timestamps", help="Show timestamps for each log line"),
|
|
54
53
|
):
|
|
55
54
|
"""Show logs for a specific container, streaming while active."""
|
|
56
|
-
task_id,
|
|
57
|
-
if container_id.startswith("sb-"):
|
|
58
|
-
sandbox_id = container_id
|
|
59
|
-
elif container_id.startswith("ta-"):
|
|
60
|
-
task_id = container_id
|
|
61
|
-
else:
|
|
62
|
-
raise InvalidError(f"Invalid container ID: {container_id}")
|
|
63
|
-
stream_app_logs(task_id=task_id, sandbox_id=sandbox_id, show_timestamps=timestamps)
|
|
55
|
+
stream_app_logs(task_id=container_id, show_timestamps=timestamps)
|
|
64
56
|
|
|
65
57
|
|
|
66
58
|
@container_cli.command("exec")
|
|
@@ -13,7 +13,6 @@ from .app import app_cli
|
|
|
13
13
|
from .cluster import cluster_cli
|
|
14
14
|
from .config import config_cli
|
|
15
15
|
from .container import container_cli
|
|
16
|
-
from .dashboard import dashboard
|
|
17
16
|
from .dict import dict_cli
|
|
18
17
|
from .environment import environment_cli
|
|
19
18
|
from .launch import launch_cli
|
|
@@ -119,7 +118,6 @@ async def setup(profile: Optional[str] = None):
|
|
|
119
118
|
entrypoint_cli_typer.command("deploy", no_args_is_help=True)(run.deploy)
|
|
120
119
|
entrypoint_cli_typer.command("serve", no_args_is_help=True)(run.serve)
|
|
121
120
|
entrypoint_cli_typer.command("shell")(shell_module.shell)
|
|
122
|
-
entrypoint_cli_typer.command("dashboard")(dashboard)
|
|
123
121
|
entrypoint_cli_typer.add_typer(launch_cli)
|
|
124
122
|
|
|
125
123
|
# Deployments
|
|
@@ -21,16 +21,14 @@ from ..exception import NotFoundError
|
|
|
21
21
|
async def stream_app_logs(
|
|
22
22
|
app_id: Optional[str] = None,
|
|
23
23
|
task_id: Optional[str] = None,
|
|
24
|
-
sandbox_id: Optional[str] = None,
|
|
25
24
|
app_logs_url: Optional[str] = None,
|
|
26
25
|
show_timestamps: bool = False,
|
|
27
26
|
):
|
|
28
27
|
client = await _Client.from_env()
|
|
29
|
-
|
|
30
|
-
output_mgr = OutputManager(status_spinner_text=f"Tailing logs for {display_id}", show_timestamps=show_timestamps)
|
|
28
|
+
output_mgr = OutputManager(status_spinner_text=f"Tailing logs for {app_id}", show_timestamps=show_timestamps)
|
|
31
29
|
try:
|
|
32
30
|
with output_mgr.show_status_spinner():
|
|
33
|
-
await get_app_logs_loop(client, output_mgr, app_id=app_id, task_id=task_id,
|
|
31
|
+
await get_app_logs_loop(client, output_mgr, app_id=app_id, task_id=task_id, app_logs_url=app_logs_url)
|
|
34
32
|
except asyncio.CancelledError:
|
|
35
33
|
pass
|
|
36
34
|
except KeyboardInterrupt:
|
|
@@ -12,7 +12,6 @@ from typer import Argument, Option, Typer
|
|
|
12
12
|
import modal
|
|
13
13
|
from modal._output import OutputManager, ProgressHandler, make_console
|
|
14
14
|
from modal._utils.async_utils import synchronizer
|
|
15
|
-
from modal._utils.browser_utils import open_url_and_display
|
|
16
15
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
17
16
|
from modal.cli._download import _volume_download
|
|
18
17
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
@@ -311,30 +310,3 @@ async def rename(
|
|
|
311
310
|
)
|
|
312
311
|
|
|
313
312
|
await _Volume.rename(old_name, new_name, environment_name=env)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
@volume_cli.command(
|
|
317
|
-
name="dashboard",
|
|
318
|
-
help="Open the Volume's dashboard page in your web browser.",
|
|
319
|
-
rich_help_panel="Management",
|
|
320
|
-
)
|
|
321
|
-
@synchronizer.create_blocking
|
|
322
|
-
async def dashboard(
|
|
323
|
-
volume_name: str = Argument(help="Name of the Volume to view in the dashboard."),
|
|
324
|
-
env: Optional[str] = ENV_OPTION,
|
|
325
|
-
):
|
|
326
|
-
"""Open a Volume's dashboard page in your web browser.
|
|
327
|
-
|
|
328
|
-
**Example:**
|
|
329
|
-
|
|
330
|
-
```
|
|
331
|
-
modal volume dashboard my-volume
|
|
332
|
-
```
|
|
333
|
-
"""
|
|
334
|
-
env = ensure_env(env)
|
|
335
|
-
volume = await _Volume.from_name(volume_name, environment_name=env).hydrate()
|
|
336
|
-
|
|
337
|
-
console = make_console()
|
|
338
|
-
url = f"https://modal.com/id/{volume.object_id}"
|
|
339
|
-
|
|
340
|
-
open_url_and_display(url, "Volume dashboard", console)
|
|
@@ -31,7 +31,11 @@ class _Client:
|
|
|
31
31
|
client_type: int
|
|
32
32
|
|
|
33
33
|
def __init__(
|
|
34
|
-
self,
|
|
34
|
+
self,
|
|
35
|
+
server_url: str,
|
|
36
|
+
client_type: int,
|
|
37
|
+
credentials: typing.Optional[tuple[str, str]],
|
|
38
|
+
version: str = "1.3.2.dev0",
|
|
35
39
|
):
|
|
36
40
|
"""mdmd:hidden
|
|
37
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -163,7 +167,11 @@ class Client:
|
|
|
163
167
|
client_type: int
|
|
164
168
|
|
|
165
169
|
def __init__(
|
|
166
|
-
self,
|
|
170
|
+
self,
|
|
171
|
+
server_url: str,
|
|
172
|
+
client_type: int,
|
|
173
|
+
credentials: typing.Optional[tuple[str, str]],
|
|
174
|
+
version: str = "1.3.2.dev0",
|
|
167
175
|
):
|
|
168
176
|
"""mdmd:hidden
|
|
169
177
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -408,7 +408,7 @@ class Function(
|
|
|
408
408
|
|
|
409
409
|
_call_generator: ___call_generator_spec
|
|
410
410
|
|
|
411
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
411
|
+
class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
412
412
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
413
413
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
414
414
|
...
|
|
@@ -417,7 +417,7 @@ class Function(
|
|
|
417
417
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
418
418
|
...
|
|
419
419
|
|
|
420
|
-
remote: __remote_spec[modal._functions.
|
|
420
|
+
remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
|
|
421
421
|
|
|
422
422
|
class __remote_gen_spec(typing_extensions.Protocol):
|
|
423
423
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -444,7 +444,7 @@ class Function(
|
|
|
444
444
|
"""
|
|
445
445
|
...
|
|
446
446
|
|
|
447
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
447
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
448
448
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
449
449
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
450
450
|
|
|
@@ -467,7 +467,7 @@ class Function(
|
|
|
467
467
|
"""
|
|
468
468
|
...
|
|
469
469
|
|
|
470
|
-
_experimental_spawn: ___experimental_spawn_spec[modal._functions.
|
|
470
|
+
_experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
|
|
471
471
|
|
|
472
472
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
|
|
473
473
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
|
|
@@ -475,7 +475,7 @@ class Function(
|
|
|
475
475
|
|
|
476
476
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
|
|
477
477
|
|
|
478
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
478
|
+
class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
|
|
479
479
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
480
480
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
481
481
|
|
|
@@ -496,7 +496,7 @@ class Function(
|
|
|
496
496
|
"""
|
|
497
497
|
...
|
|
498
498
|
|
|
499
|
-
spawn: __spawn_spec[modal._functions.
|
|
499
|
+
spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
|
|
500
500
|
|
|
501
501
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
502
502
|
"""Return the inner Python object wrapped by this Modal Function."""
|
|
@@ -231,17 +231,6 @@ class Object:
|
|
|
231
231
|
"""mdmd:hidden"""
|
|
232
232
|
...
|
|
233
233
|
|
|
234
|
-
class __get_dashboard_url_spec(typing_extensions.Protocol):
|
|
235
|
-
def __call__(self, /) -> str:
|
|
236
|
-
"""mdmd:hidden"""
|
|
237
|
-
...
|
|
238
|
-
|
|
239
|
-
async def aio(self, /) -> str:
|
|
240
|
-
"""mdmd:hidden"""
|
|
241
|
-
...
|
|
242
|
-
|
|
243
|
-
get_dashboard_url: __get_dashboard_url_spec
|
|
244
|
-
|
|
245
234
|
@property
|
|
246
235
|
def client(self) -> modal.client.Client:
|
|
247
236
|
"""mdmd:hidden"""
|
|
@@ -340,7 +340,11 @@ async def _run_app(
|
|
|
340
340
|
|
|
341
341
|
# Start logs loop
|
|
342
342
|
|
|
343
|
-
logs_loop = tc.create_task(
|
|
343
|
+
logs_loop = tc.create_task(
|
|
344
|
+
get_app_logs_loop(
|
|
345
|
+
load_context.client, output_mgr, app_id=running_app.app_id, app_logs_url=running_app.app_logs_url
|
|
346
|
+
)
|
|
347
|
+
)
|
|
344
348
|
|
|
345
349
|
try:
|
|
346
350
|
# Create all members
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2023
|
|
2
2
|
import itertools
|
|
3
3
|
import os
|
|
4
|
+
import webbrowser
|
|
4
5
|
from collections.abc import AsyncGenerator
|
|
5
6
|
from typing import Optional
|
|
6
7
|
|
|
@@ -11,7 +12,6 @@ from modal_proto import api_pb2
|
|
|
11
12
|
|
|
12
13
|
from ._output import make_console
|
|
13
14
|
from ._utils.async_utils import synchronize_api
|
|
14
|
-
from ._utils.browser_utils import open_url
|
|
15
15
|
from ._utils.http_utils import run_temporary_http_server
|
|
16
16
|
from .client import _Client
|
|
17
17
|
from .config import DEFAULT_SERVER_URL, _lookup_workspace, _store_user_config, config, config_profiles, user_config_path
|
|
@@ -85,7 +85,7 @@ async def _new_token(
|
|
|
85
85
|
async with token_flow.start(source, next_url) as (_, web_url, code):
|
|
86
86
|
with console.status("Waiting for authentication in the web browser", spinner="dots"):
|
|
87
87
|
# Open the web url in the browser
|
|
88
|
-
if
|
|
88
|
+
if _open_url(web_url):
|
|
89
89
|
console.print(
|
|
90
90
|
"The web browser should have opened for you to authenticate and get an API token.\n"
|
|
91
91
|
"If it didn't, please copy this URL into your web browser manually:\n"
|
|
@@ -176,3 +176,18 @@ async def _set_token(
|
|
|
176
176
|
f"Warning: The {env_vars_str} environment variable{s} {verb} set; this will override your new credentials.",
|
|
177
177
|
style="yellow",
|
|
178
178
|
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _open_url(url: str) -> bool:
|
|
182
|
+
"""Opens url in web browser, making sure we use a modern one (not Lynx etc)"""
|
|
183
|
+
if "PYTEST_CURRENT_TEST" in os.environ:
|
|
184
|
+
return False
|
|
185
|
+
try:
|
|
186
|
+
browser = webbrowser.get()
|
|
187
|
+
# zpresto defines `BROWSER=open` by default on macOS, which causes `webbrowser` to return `GenericBrowser`.
|
|
188
|
+
if isinstance(browser, webbrowser.GenericBrowser) and browser.name != "open":
|
|
189
|
+
return False
|
|
190
|
+
else:
|
|
191
|
+
return browser.open_new_tab(url)
|
|
192
|
+
except webbrowser.Error:
|
|
193
|
+
return False
|
|
@@ -111,7 +111,6 @@ modal/_utils/app_utils.py
|
|
|
111
111
|
modal/_utils/async_utils.py
|
|
112
112
|
modal/_utils/auth_token_manager.py
|
|
113
113
|
modal/_utils/blob_utils.py
|
|
114
|
-
modal/_utils/browser_utils.py
|
|
115
114
|
modal/_utils/bytes_io_segment_payload.py
|
|
116
115
|
modal/_utils/deprecation.py
|
|
117
116
|
modal/_utils/docker_utils.py
|
|
@@ -150,7 +149,6 @@ modal/cli/app.py
|
|
|
150
149
|
modal/cli/cluster.py
|
|
151
150
|
modal/cli/config.py
|
|
152
151
|
modal/cli/container.py
|
|
153
|
-
modal/cli/dashboard.py
|
|
154
152
|
modal/cli/dict.py
|
|
155
153
|
modal/cli/entry_point.py
|
|
156
154
|
modal/cli/environment.py
|
|
@@ -3690,15 +3690,6 @@ message WorkspaceBillingReportRequest {
|
|
|
3690
3690
|
repeated string tag_names = 4;
|
|
3691
3691
|
}
|
|
3692
3692
|
|
|
3693
|
-
message WorkspaceDashboardUrlRequest {
|
|
3694
|
-
string environment_name = 1;
|
|
3695
|
-
}
|
|
3696
|
-
|
|
3697
|
-
message WorkspaceDashboardUrlResponse {
|
|
3698
|
-
string url = 1;
|
|
3699
|
-
}
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
3693
|
message WorkspaceNameLookupResponse {
|
|
3703
3694
|
string workspace_name = 1 [deprecated=true];
|
|
3704
3695
|
string username = 2;
|
|
@@ -3933,6 +3924,5 @@ service ModalClient {
|
|
|
3933
3924
|
|
|
3934
3925
|
// Workspaces
|
|
3935
3926
|
rpc WorkspaceBillingReport(WorkspaceBillingReportRequest) returns (stream WorkspaceBillingReportItem);
|
|
3936
|
-
rpc WorkspaceDashboardUrlGet(WorkspaceDashboardUrlRequest) returns (WorkspaceDashboardUrlResponse);
|
|
3937
3927
|
rpc WorkspaceNameLookup(google.protobuf.Empty) returns (WorkspaceNameLookupResponse);
|
|
3938
3928
|
}
|
|
@@ -715,10 +715,6 @@ class ModalClientBase(abc.ABC):
|
|
|
715
715
|
async def WorkspaceBillingReport(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.WorkspaceBillingReportRequest, modal_proto.api_pb2.WorkspaceBillingReportItem]') -> None:
|
|
716
716
|
pass
|
|
717
717
|
|
|
718
|
-
@abc.abstractmethod
|
|
719
|
-
async def WorkspaceDashboardUrlGet(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.WorkspaceDashboardUrlRequest, modal_proto.api_pb2.WorkspaceDashboardUrlResponse]') -> None:
|
|
720
|
-
pass
|
|
721
|
-
|
|
722
718
|
@abc.abstractmethod
|
|
723
719
|
async def WorkspaceNameLookup(self, stream: 'grpclib.server.Stream[google.protobuf.empty_pb2.Empty, modal_proto.api_pb2.WorkspaceNameLookupResponse]') -> None:
|
|
724
720
|
pass
|
|
@@ -1769,12 +1765,6 @@ class ModalClientBase(abc.ABC):
|
|
|
1769
1765
|
modal_proto.api_pb2.WorkspaceBillingReportRequest,
|
|
1770
1766
|
modal_proto.api_pb2.WorkspaceBillingReportItem,
|
|
1771
1767
|
),
|
|
1772
|
-
'/modal.client.ModalClient/WorkspaceDashboardUrlGet': grpclib.const.Handler(
|
|
1773
|
-
self.WorkspaceDashboardUrlGet,
|
|
1774
|
-
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1775
|
-
modal_proto.api_pb2.WorkspaceDashboardUrlRequest,
|
|
1776
|
-
modal_proto.api_pb2.WorkspaceDashboardUrlResponse,
|
|
1777
|
-
),
|
|
1778
1768
|
'/modal.client.ModalClient/WorkspaceNameLookup': grpclib.const.Handler(
|
|
1779
1769
|
self.WorkspaceNameLookup,
|
|
1780
1770
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
@@ -2831,12 +2821,6 @@ class ModalClientStub:
|
|
|
2831
2821
|
modal_proto.api_pb2.WorkspaceBillingReportRequest,
|
|
2832
2822
|
modal_proto.api_pb2.WorkspaceBillingReportItem,
|
|
2833
2823
|
)
|
|
2834
|
-
self.WorkspaceDashboardUrlGet = grpclib.client.UnaryUnaryMethod(
|
|
2835
|
-
channel,
|
|
2836
|
-
'/modal.client.ModalClient/WorkspaceDashboardUrlGet',
|
|
2837
|
-
modal_proto.api_pb2.WorkspaceDashboardUrlRequest,
|
|
2838
|
-
modal_proto.api_pb2.WorkspaceDashboardUrlResponse,
|
|
2839
|
-
)
|
|
2840
2824
|
self.WorkspaceNameLookup = grpclib.client.UnaryUnaryMethod(
|
|
2841
2825
|
channel,
|
|
2842
2826
|
'/modal.client.ModalClient/WorkspaceNameLookup',
|