modal 0.73.57__py3-none-any.whl → 0.73.58__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modal/cli/entry_point.py +1 -1
- modal/cli/import_refs.py +31 -18
- modal/cli/launch.py +5 -8
- modal/cli/run.py +36 -13
- modal/client.pyi +2 -2
- modal/serving.py +15 -9
- modal/serving.pyi +14 -6
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/METADATA +1 -1
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/RECORD +14 -14
- modal_version/_version_generated.py +1 -1
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/LICENSE +0 -0
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/WHEEL +0 -0
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/entry_points.txt +0 -0
- {modal-0.73.57.dist-info → modal-0.73.58.dist-info}/top_level.txt +0 -0
modal/cli/entry_point.py
CHANGED
@@ -84,7 +84,7 @@ async def setup(profile: Optional[str] = None):
|
|
84
84
|
|
85
85
|
|
86
86
|
# Commands
|
87
|
-
entrypoint_cli_typer.command("deploy",
|
87
|
+
entrypoint_cli_typer.command("deploy", no_args_is_help=True)(run.deploy)
|
88
88
|
entrypoint_cli_typer.command("serve", no_args_is_help=True)(run.serve)
|
89
89
|
entrypoint_cli_typer.command("shell")(run.shell)
|
90
90
|
entrypoint_cli_typer.add_typer(launch_cli)
|
modal/cli/import_refs.py
CHANGED
@@ -22,6 +22,7 @@ import click
|
|
22
22
|
from rich.console import Console
|
23
23
|
from rich.markdown import Markdown
|
24
24
|
|
25
|
+
from modal._utils.deprecation import deprecation_warning
|
25
26
|
from modal.app import App, LocalEntrypoint
|
26
27
|
from modal.cls import Cls
|
27
28
|
from modal.exception import InvalidError, _CliUserExecutionError
|
@@ -31,16 +32,17 @@ from modal.functions import Function
|
|
31
32
|
@dataclasses.dataclass
|
32
33
|
class ImportRef:
|
33
34
|
file_or_module: str
|
35
|
+
use_module_mode: bool # i.e. using the -m flag
|
34
36
|
|
35
37
|
# object_path is a .-delimited path to the object to execute, or a parent from which to infer the object
|
36
38
|
# e.g.
|
37
39
|
# function or local_entrypoint in module scope
|
38
40
|
# app in module scope [+ method name]
|
39
41
|
# app [+ function/entrypoint on that app]
|
40
|
-
object_path: str
|
42
|
+
object_path: str = dataclasses.field(default="")
|
41
43
|
|
42
44
|
|
43
|
-
def parse_import_ref(object_ref: str) -> ImportRef:
|
45
|
+
def parse_import_ref(object_ref: str, use_module_mode: bool = False) -> ImportRef:
|
44
46
|
if object_ref.find("::") > 1:
|
45
47
|
file_or_module, object_path = object_ref.split("::", 1)
|
46
48
|
elif object_ref.find(":") > 1:
|
@@ -48,23 +50,36 @@ def parse_import_ref(object_ref: str) -> ImportRef:
|
|
48
50
|
else:
|
49
51
|
file_or_module, object_path = object_ref, ""
|
50
52
|
|
51
|
-
return ImportRef(file_or_module, object_path)
|
53
|
+
return ImportRef(file_or_module, use_module_mode, object_path)
|
52
54
|
|
53
55
|
|
54
56
|
DEFAULT_APP_NAME = "app"
|
55
57
|
|
56
58
|
|
57
|
-
def import_file_or_module(
|
59
|
+
def import_file_or_module(import_ref: ImportRef, base_cmd: str = ""):
|
58
60
|
if "" not in sys.path:
|
59
61
|
# When running from a CLI like `modal run`
|
60
62
|
# the current working directory isn't added to sys.path
|
61
63
|
# so we add it in order to make module path specification possible
|
62
64
|
sys.path.insert(0, "") # "" means the current working directory
|
63
65
|
|
64
|
-
if file_or_module.endswith(".py"):
|
66
|
+
if not import_ref.file_or_module.endswith(".py") or import_ref.use_module_mode:
|
67
|
+
if not import_ref.use_module_mode:
|
68
|
+
deprecation_warning(
|
69
|
+
(2025, 2, 6),
|
70
|
+
f"Using Python module paths will require using the -m flag in a future version of Modal.\n"
|
71
|
+
f"Use `{base_cmd} -m {import_ref.file_or_module}` instead.",
|
72
|
+
pending=True,
|
73
|
+
show_source=False,
|
74
|
+
)
|
75
|
+
try:
|
76
|
+
module = importlib.import_module(import_ref.file_or_module)
|
77
|
+
except Exception as exc:
|
78
|
+
raise _CliUserExecutionError(import_ref.file_or_module) from exc
|
79
|
+
else:
|
65
80
|
# when using a script path, that scripts directory should also be on the path as it is
|
66
81
|
# with `python some/script.py`
|
67
|
-
full_path = Path(file_or_module).resolve()
|
82
|
+
full_path = Path(import_ref.file_or_module).resolve()
|
68
83
|
if "." in full_path.name.removesuffix(".py"):
|
69
84
|
raise InvalidError(
|
70
85
|
f"Invalid Modal source filename: {full_path.name!r}."
|
@@ -72,10 +87,10 @@ def import_file_or_module(file_or_module: str):
|
|
72
87
|
)
|
73
88
|
sys.path.insert(0, str(full_path.parent))
|
74
89
|
|
75
|
-
module_name = inspect.getmodulename(file_or_module)
|
90
|
+
module_name = inspect.getmodulename(import_ref.file_or_module)
|
76
91
|
assert module_name is not None
|
77
92
|
# Import the module - see https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
|
78
|
-
spec = importlib.util.spec_from_file_location(module_name, file_or_module)
|
93
|
+
spec = importlib.util.spec_from_file_location(module_name, import_ref.file_or_module)
|
79
94
|
assert spec is not None
|
80
95
|
module = importlib.util.module_from_spec(spec)
|
81
96
|
sys.modules[module_name] = module
|
@@ -84,11 +99,6 @@ def import_file_or_module(file_or_module: str):
|
|
84
99
|
spec.loader.exec_module(module)
|
85
100
|
except Exception as exc:
|
86
101
|
raise _CliUserExecutionError(str(full_path)) from exc
|
87
|
-
else:
|
88
|
-
try:
|
89
|
-
module = importlib.import_module(file_or_module)
|
90
|
-
except Exception as exc:
|
91
|
-
raise _CliUserExecutionError(file_or_module) from exc
|
92
102
|
|
93
103
|
return module
|
94
104
|
|
@@ -227,15 +237,18 @@ def filter_cli_commands(
|
|
227
237
|
return res
|
228
238
|
|
229
239
|
|
230
|
-
def import_app(app_ref: str)
|
231
|
-
|
240
|
+
def import_app(app_ref: str):
|
241
|
+
# TODO: remove when integration tests have been migrated to import_app_from_ref
|
242
|
+
return import_app_from_ref(parse_import_ref(app_ref))
|
243
|
+
|
232
244
|
|
245
|
+
def import_app_from_ref(import_ref: ImportRef, base_cmd: str = "") -> App:
|
233
246
|
# TODO: default could be to just pick up any app regardless if it's called DEFAULT_APP_NAME
|
234
247
|
# as long as there is a single app in the module?
|
235
248
|
import_path = import_ref.file_or_module
|
236
249
|
object_path = import_ref.object_path or DEFAULT_APP_NAME
|
237
250
|
|
238
|
-
module = import_file_or_module(import_ref
|
251
|
+
module = import_file_or_module(import_ref, base_cmd)
|
239
252
|
|
240
253
|
if "." in object_path:
|
241
254
|
raise click.UsageError(f"{object_path} is not a Modal App")
|
@@ -305,7 +318,7 @@ def _get_runnable_app(runnable: Runnable) -> App:
|
|
305
318
|
|
306
319
|
|
307
320
|
def import_and_filter(
|
308
|
-
import_ref: ImportRef, accept_local_entrypoint=True, accept_webhook=False
|
321
|
+
import_ref: ImportRef, *, base_cmd: str, accept_local_entrypoint=True, accept_webhook=False
|
309
322
|
) -> tuple[Optional[Runnable], list[CLICommand]]:
|
310
323
|
"""Takes a function ref string and returns a single determined "runnable" to use, and a list of all available
|
311
324
|
runnables.
|
@@ -321,7 +334,7 @@ def import_and_filter(
|
|
321
334
|
3. if there is a single method (within a class) that one is used
|
322
335
|
"""
|
323
336
|
# all commands:
|
324
|
-
module = import_file_or_module(import_ref
|
337
|
+
module = import_file_or_module(import_ref, base_cmd)
|
325
338
|
cli_commands = list_cli_commands(module)
|
326
339
|
|
327
340
|
# all commands that satisfy local entrypoint/accept webhook limitations AND object path prefix
|
modal/cli/launch.py
CHANGED
@@ -8,11 +8,10 @@ from typing import Any, Optional
|
|
8
8
|
|
9
9
|
from typer import Typer
|
10
10
|
|
11
|
-
from ..app import LocalEntrypoint
|
12
11
|
from ..exception import _CliUserExecutionError
|
13
12
|
from ..output import enable_output
|
14
13
|
from ..runner import run_app
|
15
|
-
from .import_refs import
|
14
|
+
from .import_refs import ImportRef, _get_runnable_app, import_file_or_module
|
16
15
|
|
17
16
|
launch_cli = Typer(
|
18
17
|
name="launch",
|
@@ -29,14 +28,12 @@ def _launch_program(name: str, filename: str, detach: bool, args: dict[str, Any]
|
|
29
28
|
os.environ["MODAL_LAUNCH_ARGS"] = json.dumps(args)
|
30
29
|
|
31
30
|
program_path = str(Path(__file__).parent / "programs" / filename)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
if not isinstance(entrypoint, LocalEntrypoint):
|
36
|
-
raise ValueError(f"{program_path} has no single local_entrypoint")
|
31
|
+
base_cmd = f"modal launch {name}"
|
32
|
+
module = import_file_or_module(ImportRef(program_path, use_module_mode=False), base_cmd=base_cmd)
|
33
|
+
entrypoint = module.main
|
37
34
|
|
38
35
|
app = _get_runnable_app(entrypoint)
|
39
|
-
app.set_description(
|
36
|
+
app.set_description(base_cmd)
|
40
37
|
|
41
38
|
# `launch/` scripts must have a `local_entrypoint()` with no args, for simplicity here.
|
42
39
|
func = entrypoint.info.raw_f
|
modal/cli/run.py
CHANGED
@@ -27,7 +27,14 @@ from ..output import enable_output
|
|
27
27
|
from ..runner import deploy_app, interactive_shell, run_app
|
28
28
|
from ..serving import serve_app
|
29
29
|
from ..volume import Volume
|
30
|
-
from .import_refs import
|
30
|
+
from .import_refs import (
|
31
|
+
CLICommand,
|
32
|
+
MethodReference,
|
33
|
+
_get_runnable_app,
|
34
|
+
import_and_filter,
|
35
|
+
import_app_from_ref,
|
36
|
+
parse_import_ref,
|
37
|
+
)
|
31
38
|
from .utils import ENV_OPTION, ENV_OPTION_HELP, is_tty, stream_app_logs
|
32
39
|
|
33
40
|
|
@@ -324,9 +331,9 @@ class RunGroup(click.Group):
|
|
324
331
|
ctx.ensure_object(dict)
|
325
332
|
ctx.obj["env"] = ensure_env(ctx.params["env"])
|
326
333
|
|
327
|
-
import_ref = parse_import_ref(func_ref)
|
334
|
+
import_ref = parse_import_ref(func_ref, use_module_mode=ctx.params["m"])
|
328
335
|
runnable, all_usable_commands = import_and_filter(
|
329
|
-
import_ref, accept_local_entrypoint=True, accept_webhook=False
|
336
|
+
import_ref, base_cmd="modal run", accept_local_entrypoint=True, accept_webhook=False
|
330
337
|
)
|
331
338
|
if not runnable:
|
332
339
|
help_header = (
|
@@ -368,8 +375,9 @@ class RunGroup(click.Group):
|
|
368
375
|
@click.option("-d", "--detach", is_flag=True, help="Don't stop the app if the local process dies or disconnects.")
|
369
376
|
@click.option("-i", "--interactive", is_flag=True, help="Run the app in interactive mode.")
|
370
377
|
@click.option("-e", "--env", help=ENV_OPTION_HELP, default=None)
|
378
|
+
@click.option("-m", is_flag=True, help="Interpret argument as a Python module path instead of a file/script path")
|
371
379
|
@click.pass_context
|
372
|
-
def run(ctx, write_result, detach, quiet, interactive, env):
|
380
|
+
def run(ctx, write_result, detach, quiet, interactive, env, m):
|
373
381
|
"""Run a Modal function or local entrypoint.
|
374
382
|
|
375
383
|
`FUNC_REF` should be of the format `{file or module}::{function name}`.
|
@@ -385,7 +393,7 @@ def run(ctx, write_result, detach, quiet, interactive, env):
|
|
385
393
|
modal run my_app.py::hello_world
|
386
394
|
```
|
387
395
|
|
388
|
-
If your module only has a single app
|
396
|
+
If your module only has a single app and your app has a
|
389
397
|
single local entrypoint (or single function), you can omit the app and
|
390
398
|
function parts:
|
391
399
|
|
@@ -393,10 +401,12 @@ def run(ctx, write_result, detach, quiet, interactive, env):
|
|
393
401
|
modal run my_app.py
|
394
402
|
```
|
395
403
|
|
396
|
-
Instead of pointing to a file, you can also use the Python module path
|
404
|
+
Instead of pointing to a file, you can also use the Python module path, which
|
405
|
+
by default will ensure that your remote functions will use the same module
|
406
|
+
names as they do locally.
|
397
407
|
|
398
408
|
```
|
399
|
-
modal run my_project.my_app
|
409
|
+
modal run -m my_project.my_app
|
400
410
|
```
|
401
411
|
"""
|
402
412
|
ctx.ensure_object(dict)
|
@@ -407,16 +417,26 @@ def run(ctx, write_result, detach, quiet, interactive, env):
|
|
407
417
|
|
408
418
|
|
409
419
|
def deploy(
|
410
|
-
app_ref: str = typer.Argument(..., help="Path to a Python file with an app
|
420
|
+
app_ref: str = typer.Argument(..., help="Path to a Python file with an app to deploy"),
|
411
421
|
name: str = typer.Option("", help="Name of the deployment."),
|
412
422
|
env: str = ENV_OPTION,
|
413
423
|
stream_logs: bool = typer.Option(False, help="Stream logs from the app upon deployment."),
|
414
424
|
tag: str = typer.Option("", help="Tag the deployment with a version."),
|
425
|
+
use_module_mode: bool = typer.Option(
|
426
|
+
False, "-m", help="Interpret argument as a Python module path instead of a file/script path"
|
427
|
+
),
|
415
428
|
):
|
429
|
+
"""Deploy a Modal application.
|
430
|
+
|
431
|
+
**Usage:**
|
432
|
+
modal deploy my_script.py
|
433
|
+
modal deploy -m my_package.my_mod
|
434
|
+
"""
|
416
435
|
# this ensures that lookups without environment specification use the same env as specified
|
417
436
|
env = ensure_env(env)
|
418
437
|
|
419
|
-
|
438
|
+
import_ref = parse_import_ref(app_ref, use_module_mode=use_module_mode)
|
439
|
+
app = import_app_from_ref(import_ref, base_cmd="modal deploy")
|
420
440
|
|
421
441
|
if name is None:
|
422
442
|
name = app.name
|
@@ -432,6 +452,9 @@ def serve(
|
|
432
452
|
app_ref: str = typer.Argument(..., help="Path to a Python file with an app."),
|
433
453
|
timeout: Optional[float] = None,
|
434
454
|
env: str = ENV_OPTION,
|
455
|
+
use_module_mode: bool = typer.Option(
|
456
|
+
False, "-m", help="Interpret argument as a Python module path instead of a file/script path"
|
457
|
+
),
|
435
458
|
):
|
436
459
|
"""Run a web endpoint(s) associated with a Modal app and hot-reload code.
|
437
460
|
|
@@ -442,13 +465,13 @@ def serve(
|
|
442
465
|
```
|
443
466
|
"""
|
444
467
|
env = ensure_env(env)
|
445
|
-
|
446
|
-
app =
|
468
|
+
import_ref = parse_import_ref(app_ref, use_module_mode=use_module_mode)
|
469
|
+
app = import_app_from_ref(import_ref, base_cmd="modal serve")
|
447
470
|
if app.description is None:
|
448
471
|
app.set_description(_get_clean_app_description(app_ref))
|
449
472
|
|
450
473
|
with enable_output():
|
451
|
-
with serve_app(app,
|
474
|
+
with serve_app(app, import_ref, environment_name=env):
|
452
475
|
if timeout is None:
|
453
476
|
timeout = config["serve_timeout"]
|
454
477
|
if timeout is None:
|
@@ -563,7 +586,7 @@ def shell(
|
|
563
586
|
|
564
587
|
import_ref = parse_import_ref(container_or_function)
|
565
588
|
runnable, all_usable_commands = import_and_filter(
|
566
|
-
import_ref, accept_local_entrypoint=False, accept_webhook=True
|
589
|
+
import_ref, base_cmd="modal shell", accept_local_entrypoint=False, accept_webhook=True
|
567
590
|
)
|
568
591
|
if not runnable:
|
569
592
|
help_header = (
|
modal/client.pyi
CHANGED
@@ -27,7 +27,7 @@ class _Client:
|
|
27
27
|
_snapshotted: bool
|
28
28
|
|
29
29
|
def __init__(
|
30
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.58"
|
31
31
|
): ...
|
32
32
|
def is_closed(self) -> bool: ...
|
33
33
|
@property
|
@@ -85,7 +85,7 @@ class Client:
|
|
85
85
|
_snapshotted: bool
|
86
86
|
|
87
87
|
def __init__(
|
88
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.58"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
modal/serving.py
CHANGED
@@ -14,7 +14,7 @@ from ._utils.async_utils import TaskContext, asyncify, synchronize_api, synchron
|
|
14
14
|
from ._utils.deprecation import deprecation_error
|
15
15
|
from ._utils.logger import logger
|
16
16
|
from ._watcher import watch
|
17
|
-
from .cli.import_refs import
|
17
|
+
from .cli.import_refs import ImportRef, import_app_from_ref
|
18
18
|
from .client import _Client
|
19
19
|
from .config import config
|
20
20
|
from .output import _get_output_manager, enable_output
|
@@ -26,9 +26,11 @@ else:
|
|
26
26
|
_App = TypeVar("_App")
|
27
27
|
|
28
28
|
|
29
|
-
def _run_serve(
|
29
|
+
def _run_serve(
|
30
|
+
import_ref: ImportRef, existing_app_id: str, is_ready: Event, environment_name: str, show_progress: bool
|
31
|
+
):
|
30
32
|
# subprocess entrypoint
|
31
|
-
_app =
|
33
|
+
_app = import_app_from_ref(import_ref, base_cmd="modal serve")
|
32
34
|
blocking_app = synchronizer._translate_out(_app)
|
33
35
|
|
34
36
|
with enable_output(show_progress=show_progress):
|
@@ -36,13 +38,13 @@ def _run_serve(app_ref: str, existing_app_id: str, is_ready: Event, environment_
|
|
36
38
|
|
37
39
|
|
38
40
|
async def _restart_serve(
|
39
|
-
|
41
|
+
import_ref: ImportRef, *, existing_app_id: str, environment_name: str, timeout: float = 5.0
|
40
42
|
) -> SpawnProcess:
|
41
43
|
ctx = multiprocessing.get_context("spawn") # Needed to reload the interpreter
|
42
44
|
is_ready = ctx.Event()
|
43
45
|
output_mgr = OutputManager.get()
|
44
46
|
show_progress = output_mgr is not None
|
45
|
-
p = ctx.Process(target=_run_serve, args=(
|
47
|
+
p = ctx.Process(target=_run_serve, args=(import_ref, existing_app_id, is_ready, environment_name, show_progress))
|
46
48
|
p.start()
|
47
49
|
await asyncify(is_ready.wait)(timeout)
|
48
50
|
# TODO(erikbern): we don't fail if the above times out, but that's somewhat intentional, since
|
@@ -68,7 +70,8 @@ async def _terminate(proc: Optional[SpawnProcess], timeout: float = 5.0):
|
|
68
70
|
|
69
71
|
|
70
72
|
async def _run_watch_loop(
|
71
|
-
|
73
|
+
import_ref: ImportRef,
|
74
|
+
*,
|
72
75
|
app_id: str,
|
73
76
|
watcher: AsyncGenerator[set[str], None],
|
74
77
|
environment_name: str,
|
@@ -88,7 +91,7 @@ async def _run_watch_loop(
|
|
88
91
|
async for trigger_files in watcher:
|
89
92
|
logger.debug(f"The following files triggered an app update: {', '.join(trigger_files)}")
|
90
93
|
await _terminate(curr_proc)
|
91
|
-
curr_proc = await _restart_serve(
|
94
|
+
curr_proc = await _restart_serve(import_ref, existing_app_id=app_id, environment_name=environment_name)
|
92
95
|
finally:
|
93
96
|
await _terminate(curr_proc)
|
94
97
|
|
@@ -96,7 +99,8 @@ async def _run_watch_loop(
|
|
96
99
|
@asynccontextmanager
|
97
100
|
async def _serve_app(
|
98
101
|
app: "_App",
|
99
|
-
|
102
|
+
import_ref: ImportRef,
|
103
|
+
*,
|
100
104
|
_watcher: Optional[AsyncGenerator[set[str], None]] = None, # for testing
|
101
105
|
environment_name: Optional[str] = None,
|
102
106
|
) -> AsyncGenerator["_App", None]:
|
@@ -112,7 +116,9 @@ async def _serve_app(
|
|
112
116
|
mounts_to_watch = app._get_watch_mounts()
|
113
117
|
watcher = watch(mounts_to_watch)
|
114
118
|
async with TaskContext(grace=0.1) as tc:
|
115
|
-
tc.create_task(
|
119
|
+
tc.create_task(
|
120
|
+
_run_watch_loop(import_ref, app_id=app.app_id, watcher=watcher, environment_name=environment_name)
|
121
|
+
)
|
116
122
|
yield app
|
117
123
|
|
118
124
|
|
modal/serving.pyi
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import collections.abc
|
2
|
+
import modal.cli.import_refs
|
2
3
|
import multiprocessing.context
|
3
4
|
import multiprocessing.synchronize
|
4
5
|
import synchronicity.combined_types
|
@@ -8,22 +9,27 @@ import typing_extensions
|
|
8
9
|
_App = typing.TypeVar("_App")
|
9
10
|
|
10
11
|
def _run_serve(
|
11
|
-
|
12
|
+
import_ref: modal.cli.import_refs.ImportRef,
|
12
13
|
existing_app_id: str,
|
13
14
|
is_ready: multiprocessing.synchronize.Event,
|
14
15
|
environment_name: str,
|
15
16
|
show_progress: bool,
|
16
17
|
): ...
|
17
18
|
async def _restart_serve(
|
18
|
-
|
19
|
+
import_ref: modal.cli.import_refs.ImportRef, *, existing_app_id: str, environment_name: str, timeout: float = 5.0
|
19
20
|
) -> multiprocessing.context.SpawnProcess: ...
|
20
21
|
async def _terminate(proc: typing.Optional[multiprocessing.context.SpawnProcess], timeout: float = 5.0): ...
|
21
22
|
async def _run_watch_loop(
|
22
|
-
|
23
|
+
import_ref: modal.cli.import_refs.ImportRef,
|
24
|
+
*,
|
25
|
+
app_id: str,
|
26
|
+
watcher: collections.abc.AsyncGenerator[set[str], None],
|
27
|
+
environment_name: str,
|
23
28
|
): ...
|
24
29
|
def _serve_app(
|
25
30
|
app: _App,
|
26
|
-
|
31
|
+
import_ref: modal.cli.import_refs.ImportRef,
|
32
|
+
*,
|
27
33
|
_watcher: typing.Optional[collections.abc.AsyncGenerator[set[str], None]] = None,
|
28
34
|
environment_name: typing.Optional[str] = None,
|
29
35
|
) -> typing.AsyncContextManager[_App]: ...
|
@@ -33,14 +39,16 @@ class __serve_app_spec(typing_extensions.Protocol):
|
|
33
39
|
def __call__(
|
34
40
|
self,
|
35
41
|
app: _App,
|
36
|
-
|
42
|
+
import_ref: modal.cli.import_refs.ImportRef,
|
43
|
+
*,
|
37
44
|
_watcher: typing.Optional[typing.Generator[set[str], None, None]] = None,
|
38
45
|
environment_name: typing.Optional[str] = None,
|
39
46
|
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[_App]: ...
|
40
47
|
def aio(
|
41
48
|
self,
|
42
49
|
app: _App,
|
43
|
-
|
50
|
+
import_ref: modal.cli.import_refs.ImportRef,
|
51
|
+
*,
|
44
52
|
_watcher: typing.Optional[collections.abc.AsyncGenerator[set[str], None]] = None,
|
45
53
|
environment_name: typing.Optional[str] = None,
|
46
54
|
) -> typing.AsyncContextManager[_App]: ...
|
@@ -22,7 +22,7 @@ modal/app.py,sha256=o5mHoHtn41nkvskX_ekJkyfG6MXwj5rqerRi_nnPd0w,44725
|
|
22
22
|
modal/app.pyi,sha256=0MMCgskIL4r3eq8oBcfm2lLyeao2gXjS3iXaIfmaJ-o,25959
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=4rq2-Bl3Ru8gaL6mi3_XMTXkGvCpo83qwO7mBmg64Oo,7593
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
28
28
|
modal/cls.py,sha256=wztMTYkhJyW9iUVqx4_Gga4bJJpUiPgGsS6iacUqy-A,30001
|
@@ -73,8 +73,8 @@ modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
|
|
73
73
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
74
74
|
modal/secret.py,sha256=U2Jivqdb94eI_BrGCMVbCots8F2gDcbXLMia_gVlej0,10455
|
75
75
|
modal/secret.pyi,sha256=W4g_BOSxafYm-K9PvFc7-li3a-rsCFNkYgHTZXr1AFA,2974
|
76
|
-
modal/serving.py,sha256=
|
77
|
-
modal/serving.pyi,sha256=
|
76
|
+
modal/serving.py,sha256=orZjhyikqk7U77My7GedbVKy65j0_CF7J7mqye86dRw,4650
|
77
|
+
modal/serving.pyi,sha256=KGSaZhg0qwygLmDkhgJedUfWeNSkXsyoOipq10vYffU,1978
|
78
78
|
modal/snapshot.py,sha256=6rQvDP3iX9hdiAudKTy0-m0JESt4kk0q2gusXbaRA-8,1279
|
79
79
|
modal/snapshot.pyi,sha256=Ypd4NKsjOTnnnqXyTGGLKq5lkocRrUURYjY5Pi67_qA,670
|
80
80
|
modal/stream_type.py,sha256=A6320qoAAWhEfwOCZfGtymQTu5AfLfJXXgARqooTPvY,417
|
@@ -121,14 +121,14 @@ modal/cli/app.py,sha256=TmUiFKAE1yc6ll8pfl-wZ2lh9crC31Fu_8_YKCX8NJc,7818
|
|
121
121
|
modal/cli/config.py,sha256=QvFsqO4eUOtI7d_pQAOAyfq_ZitjhPtav3C6GIDQcZM,1680
|
122
122
|
modal/cli/container.py,sha256=FYwEgjf93j4NMorAjGbSV98i1wpebqdAeNU1wfrFp1k,3668
|
123
123
|
modal/cli/dict.py,sha256=8Wq3w-UDaywk8EVNdj-ECCNV9TYHqh4kzhUqhhulatM,4593
|
124
|
-
modal/cli/entry_point.py,sha256=
|
124
|
+
modal/cli/entry_point.py,sha256=dOosuCwhfznwTCB4oMljUFhihq5aLUVoAz7RhcBEDnc,4189
|
125
125
|
modal/cli/environment.py,sha256=Ayddkiq9jdj3XYDJ8ZmUqFpPPH8xajYlbexRkzGtUcg,4334
|
126
|
-
modal/cli/import_refs.py,sha256=
|
127
|
-
modal/cli/launch.py,sha256=
|
126
|
+
modal/cli/import_refs.py,sha256=kbjWZxSyLc6Bp6UxtB7iJ7qp10DG5j7i4bbbA1bSIXQ,13529
|
127
|
+
modal/cli/launch.py,sha256=0_sBu6bv2xJEPWi-rbGS6Ri9ggnkWQvrGlgpYSUBMyY,3097
|
128
128
|
modal/cli/network_file_system.py,sha256=eq3JnwjbfFNsJodIyANHL06ByYc3BSavzdmu8C96cHA,7948
|
129
129
|
modal/cli/profile.py,sha256=rLXfjJObfPNjaZvNfHGIKqs7y9bGYyGe-K7V0w-Ni0M,3110
|
130
130
|
modal/cli/queues.py,sha256=6gTu76dzBtPN5eQVsLrvQpuru5jI9ZCWK5Eh8J8XhaM,4498
|
131
|
-
modal/cli/run.py,sha256=
|
131
|
+
modal/cli/run.py,sha256=rCd-lB6p-l2vd0OrvXcioVN6wn_1EkCiRQLJRC3Z7J4,22764
|
132
132
|
modal/cli/secret.py,sha256=iDsaFUJBq3333ZBVzKPcqyey68w0j82PNddGhRgP2pA,4206
|
133
133
|
modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
|
134
134
|
modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
|
@@ -168,10 +168,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
168
168
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
169
169
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
170
170
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
171
|
-
modal_version/_version_generated.py,sha256=
|
172
|
-
modal-0.73.
|
173
|
-
modal-0.73.
|
174
|
-
modal-0.73.
|
175
|
-
modal-0.73.
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
171
|
+
modal_version/_version_generated.py,sha256=G5__kr5AhSAVmt7cklLxZHp3OMEHBXH7Bvr-Gj7d5rI,149
|
172
|
+
modal-0.73.58.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
173
|
+
modal-0.73.58.dist-info/METADATA,sha256=hYo8IB8JpTwI-uVd-OvMmxAD2Kfig-qLQmsawgeZcaQ,2452
|
174
|
+
modal-0.73.58.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
175
|
+
modal-0.73.58.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
176
|
+
modal-0.73.58.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
177
|
+
modal-0.73.58.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|