bakefile 0.0.3__py3-none-any.whl → 0.0.5__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.
- bake/__init__.py +9 -0
- bake/bakebook/bakebook.py +85 -0
- bake/bakebook/decorator.py +50 -0
- bake/bakebook/get.py +175 -0
- bake/cli/bake/__init__.py +3 -0
- bake/cli/bake/__main__.py +5 -0
- bake/cli/bake/main.py +74 -0
- bake/cli/bake/reinvocation.py +63 -0
- bake/cli/bakefile/__init__.py +3 -0
- bake/cli/bakefile/__main__.py +5 -0
- bake/cli/bakefile/add_inline.py +29 -0
- bake/cli/bakefile/find_python.py +18 -0
- bake/cli/bakefile/init.py +56 -0
- bake/cli/bakefile/lint.py +77 -0
- bake/cli/bakefile/main.py +41 -0
- bake/cli/bakefile/uv.py +146 -0
- bake/cli/common/app.py +54 -0
- bake/cli/common/callback.py +13 -0
- bake/cli/common/context.py +145 -0
- bake/cli/common/exception_handler.py +57 -0
- bake/cli/common/obj.py +214 -0
- bake/cli/common/params.py +72 -0
- bake/cli/utils/__init__.py +0 -0
- bake/cli/utils/version.py +18 -0
- bake/manage/__init__.py +0 -0
- bake/manage/add_inline.py +71 -0
- bake/manage/find_python.py +210 -0
- bake/manage/lint.py +101 -0
- bake/manage/run_uv.py +88 -0
- bake/manage/write_bakefile.py +20 -0
- bake/py.typed +0 -0
- bake/samples/__init__.py +0 -0
- bake/samples/simple.py +9 -0
- bake/ui/__init__.py +10 -0
- bake/ui/console.py +58 -0
- bake/ui/logger/__init__.py +33 -0
- bake/ui/logger/capsys.py +158 -0
- bake/ui/logger/setup.py +53 -0
- bake/ui/logger/utils.py +215 -0
- bake/ui/run/__init__.py +11 -0
- bake/ui/run/run.py +541 -0
- bake/ui/run/script.py +74 -0
- bake/ui/run/splitter.py +237 -0
- bake/ui/run/uv.py +83 -0
- bake/ui/style.py +2 -0
- bake/utils/__init__.py +11 -0
- bake/utils/constants.py +21 -0
- bake/utils/env.py +10 -0
- bake/utils/exceptions.py +17 -0
- {bakefile-0.0.3.dist-info → bakefile-0.0.5.dist-info}/METADATA +14 -2
- bakefile-0.0.5.dist-info/RECORD +61 -0
- {bakefile-0.0.3.dist-info → bakefile-0.0.5.dist-info}/WHEEL +1 -1
- bakefile-0.0.5.dist-info/entry_points.txt +5 -0
- bakelib/__init__.py +4 -0
- bakelib/space/__init__.py +0 -0
- bakelib/space/base.py +73 -0
- bakelib/space/python.py +42 -0
- bakelib/space/utils.py +55 -0
- bakefile/cli/bake/__init__.py +0 -3
- bakefile/cli/bake/main.py +0 -17
- bakefile/cli/bake/resolve_bakebook.py +0 -75
- bakefile/cli/bakefile.py +0 -8
- bakefile-0.0.3.dist-info/RECORD +0 -11
- bakefile-0.0.3.dist-info/entry_points.txt +0 -4
- {bakefile → bake/bakebook}/__init__.py +0 -0
- {bakefile → bake}/cli/__init__.py +0 -0
- /bakefile/py.typed → /bake/cli/common/__init__.py +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from bake.cli.common.app import (
|
|
2
|
+
BakefileApp,
|
|
3
|
+
add_completion,
|
|
4
|
+
bake_app_callback_with_obj,
|
|
5
|
+
rich_markup_mode,
|
|
6
|
+
)
|
|
7
|
+
from bake.cli.common.obj import get_bakefile_object
|
|
8
|
+
|
|
9
|
+
from . import uv
|
|
10
|
+
from .add_inline import add_inline
|
|
11
|
+
from .find_python import find_python
|
|
12
|
+
from .init import init
|
|
13
|
+
from .lint import lint
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
bakefile_obj = get_bakefile_object(rich_markup_mode=rich_markup_mode)
|
|
18
|
+
bakefile_obj.setup_logging()
|
|
19
|
+
bakefile_obj.resolve_bakefile_path()
|
|
20
|
+
|
|
21
|
+
bakefile_app = BakefileApp(
|
|
22
|
+
add_completion=add_completion,
|
|
23
|
+
rich_markup_mode=rich_markup_mode,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
uv_commands_context_settings = {
|
|
27
|
+
"allow_extra_args": True,
|
|
28
|
+
"ignore_unknown_options": True,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
bakefile_app.callback(invoke_without_command=True)(bake_app_callback_with_obj(obj=bakefile_obj))
|
|
32
|
+
bakefile_app.command()(init)
|
|
33
|
+
bakefile_app.command()(add_inline)
|
|
34
|
+
bakefile_app.command()(find_python)
|
|
35
|
+
bakefile_app.command()(lint)
|
|
36
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.sync)
|
|
37
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.lock)
|
|
38
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.add)
|
|
39
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.pip)
|
|
40
|
+
bakefile_app.bakefile_object = bakefile_obj
|
|
41
|
+
bakefile_app()
|
bake/cli/bakefile/uv.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from typing import Annotated, Literal
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from bake.cli.common.context import Context
|
|
6
|
+
from bake.manage.run_uv import run_uv_add, run_uv_lock, run_uv_pip, run_uv_sync
|
|
7
|
+
from bake.ui import console
|
|
8
|
+
from bake.utils.exceptions import BakebookError, PythonNotFoundError
|
|
9
|
+
|
|
10
|
+
PipCommand = Literal[
|
|
11
|
+
"compile",
|
|
12
|
+
"sync",
|
|
13
|
+
"install",
|
|
14
|
+
"uninstall",
|
|
15
|
+
"freeze",
|
|
16
|
+
"list",
|
|
17
|
+
"show",
|
|
18
|
+
"tree",
|
|
19
|
+
"check",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def pip(
|
|
24
|
+
ctx: Context,
|
|
25
|
+
command: Annotated[
|
|
26
|
+
PipCommand,
|
|
27
|
+
typer.Argument(help="UV pip subcommand"),
|
|
28
|
+
],
|
|
29
|
+
) -> None:
|
|
30
|
+
"""
|
|
31
|
+
This runs `[bold cyan]uv pip <command> <args> --python <bakefile-python-path>[/bold cyan]`
|
|
32
|
+
|
|
33
|
+
For complete docs: `[cyan]uv pip --help[/cyan]`
|
|
34
|
+
"""
|
|
35
|
+
bakefile_path = ctx.obj.bakefile_path
|
|
36
|
+
try:
|
|
37
|
+
cmd = [command, *ctx.args]
|
|
38
|
+
result = run_uv_pip(bakefile_path=bakefile_path, cmd=cmd, dry_run=ctx.obj.dry_run)
|
|
39
|
+
raise typer.Exit(result.returncode)
|
|
40
|
+
except (PythonNotFoundError, BakebookError) as e:
|
|
41
|
+
console.error(str(e))
|
|
42
|
+
raise typer.Exit(code=1) from None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def add(ctx: Context) -> None:
|
|
46
|
+
"""
|
|
47
|
+
This runs `[bold cyan]uv add --script bakefile.py <args>[/bold cyan]`
|
|
48
|
+
|
|
49
|
+
Requires PEP 723 inline metadata.
|
|
50
|
+
|
|
51
|
+
To add metadata: `[cyan]bakefile add-inline[/cyan]`
|
|
52
|
+
For project-level deps: `[cyan]uv add[/cyan]`
|
|
53
|
+
For complete docs: `[cyan]uv add --help[/cyan]`
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
bakefile add requests typer
|
|
57
|
+
bakefile add "requests>=2.32.0" --dev
|
|
58
|
+
"""
|
|
59
|
+
bakefile_path = ctx.obj.bakefile_path
|
|
60
|
+
args = ctx.args
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
result = run_uv_add(bakefile_path=bakefile_path, cmd=args, dry_run=ctx.obj.dry_run)
|
|
64
|
+
raise typer.Exit(result.returncode)
|
|
65
|
+
except (PythonNotFoundError, BakebookError) as e:
|
|
66
|
+
console.error(str(e))
|
|
67
|
+
raise typer.Exit(code=1) from None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def lock(
|
|
71
|
+
ctx: Context,
|
|
72
|
+
upgrade: Annotated[
|
|
73
|
+
bool,
|
|
74
|
+
typer.Option("--upgrade", "-U", help="Upgrade package dependencies"),
|
|
75
|
+
] = False,
|
|
76
|
+
) -> None:
|
|
77
|
+
"""
|
|
78
|
+
This runs `[bold cyan]uv lock --script bakefile.py <args>[/bold cyan]`
|
|
79
|
+
|
|
80
|
+
Requires PEP 723 inline metadata.
|
|
81
|
+
|
|
82
|
+
To add metadata: `[cyan]bakefile add-inline[/cyan]`
|
|
83
|
+
For project-level deps: `[cyan]uv lock[/cyan]`
|
|
84
|
+
For complete docs: `[cyan]uv lock --help[/cyan]`
|
|
85
|
+
|
|
86
|
+
Examples:
|
|
87
|
+
bakefile lock
|
|
88
|
+
bakefile lock --upgrade
|
|
89
|
+
bakefile lock --no-build
|
|
90
|
+
"""
|
|
91
|
+
bakefile_path = ctx.obj.bakefile_path
|
|
92
|
+
args = list(ctx.args)
|
|
93
|
+
|
|
94
|
+
if upgrade:
|
|
95
|
+
args.append("--upgrade")
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
result = run_uv_lock(bakefile_path=bakefile_path, cmd=args, dry_run=ctx.obj.dry_run)
|
|
99
|
+
raise typer.Exit(result.returncode)
|
|
100
|
+
except (PythonNotFoundError, BakebookError) as e:
|
|
101
|
+
console.error(str(e))
|
|
102
|
+
raise typer.Exit(code=1) from None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def sync(
|
|
106
|
+
ctx: Context,
|
|
107
|
+
upgrade: Annotated[
|
|
108
|
+
bool,
|
|
109
|
+
typer.Option("--upgrade", "-U", help="Upgrade package dependencies"),
|
|
110
|
+
] = False,
|
|
111
|
+
reinstall: Annotated[
|
|
112
|
+
bool,
|
|
113
|
+
typer.Option("--reinstall", help="Reinstall all packages"),
|
|
114
|
+
] = False,
|
|
115
|
+
) -> None:
|
|
116
|
+
"""
|
|
117
|
+
This runs `[bold cyan]uv sync --script bakefile.py <args>[/bold cyan]`
|
|
118
|
+
|
|
119
|
+
Requires PEP 723 inline metadata.
|
|
120
|
+
|
|
121
|
+
To add metadata: `[cyan]bakefile add-inline[/cyan]`
|
|
122
|
+
For project-level deps: `[cyan]uv sync[/cyan]`
|
|
123
|
+
For complete docs: `[cyan]uv sync --help[/cyan]`
|
|
124
|
+
|
|
125
|
+
Examples:
|
|
126
|
+
bakefile sync
|
|
127
|
+
bakefile sync --upgrade
|
|
128
|
+
bakefile sync --reinstall
|
|
129
|
+
bakefile sync --frozen
|
|
130
|
+
bakefile sync --no-dev
|
|
131
|
+
bakefile sync --no-build
|
|
132
|
+
"""
|
|
133
|
+
bakefile_path = ctx.obj.bakefile_path
|
|
134
|
+
args = list(ctx.args)
|
|
135
|
+
|
|
136
|
+
if upgrade:
|
|
137
|
+
args.append("--upgrade")
|
|
138
|
+
if reinstall:
|
|
139
|
+
args.append("--reinstall")
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
result = run_uv_sync(bakefile_path=bakefile_path, cmd=args, dry_run=ctx.obj.dry_run)
|
|
143
|
+
raise typer.Exit(result.returncode)
|
|
144
|
+
except (PythonNotFoundError, BakebookError) as e:
|
|
145
|
+
console.error(str(e))
|
|
146
|
+
raise typer.Exit(code=1) from None
|
bake/cli/common/app.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from typer.core import MarkupMode
|
|
5
|
+
|
|
6
|
+
from bake.cli.common.context import Context
|
|
7
|
+
from bake.cli.common.params import (
|
|
8
|
+
bakebook_name_option,
|
|
9
|
+
chdir_option,
|
|
10
|
+
dry_run_option,
|
|
11
|
+
file_name_option,
|
|
12
|
+
is_chain_commands_option,
|
|
13
|
+
verbosity_option,
|
|
14
|
+
version_option,
|
|
15
|
+
)
|
|
16
|
+
from bake.ui import console
|
|
17
|
+
from bake.utils.constants import (
|
|
18
|
+
DEFAULT_BAKEBOOK_NAME,
|
|
19
|
+
DEFAULT_CHDIR,
|
|
20
|
+
DEFAULT_FILE_NAME,
|
|
21
|
+
DEFAULT_IS_CHAIN_COMMAND,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from .obj import BakefileObject
|
|
25
|
+
|
|
26
|
+
rich_markup_mode: MarkupMode = "rich" if not console.out.no_color else None
|
|
27
|
+
add_completion = False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BakefileApp(typer.Typer):
|
|
31
|
+
bakefile_object: BakefileObject
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def show_help_if_no_command(ctx: Context) -> None:
|
|
35
|
+
if ctx.invoked_subcommand is None:
|
|
36
|
+
console.echo(ctx.get_help())
|
|
37
|
+
raise typer.Exit(1)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def bake_app_callback_with_obj(obj: BakefileObject) -> Callable:
|
|
41
|
+
def bake_app_callback(
|
|
42
|
+
ctx: Context,
|
|
43
|
+
_chdir: chdir_option = DEFAULT_CHDIR,
|
|
44
|
+
_file_name: file_name_option = DEFAULT_FILE_NAME,
|
|
45
|
+
_bakebook_name: bakebook_name_option = DEFAULT_BAKEBOOK_NAME,
|
|
46
|
+
_version: version_option = False,
|
|
47
|
+
_is_chain_commands: is_chain_commands_option = DEFAULT_IS_CHAIN_COMMAND,
|
|
48
|
+
_verbosity: verbosity_option = 0,
|
|
49
|
+
_dry_run: dry_run_option = False,
|
|
50
|
+
):
|
|
51
|
+
ctx.obj = obj
|
|
52
|
+
show_help_if_no_command(ctx)
|
|
53
|
+
|
|
54
|
+
return bake_app_callback
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def validate_file_name(file_name: str) -> str:
|
|
5
|
+
if "/" in file_name or "\\" in file_name:
|
|
6
|
+
raise typer.BadParameter(f"File name must not contain path separators: {file_name}")
|
|
7
|
+
if not file_name.endswith(".py"):
|
|
8
|
+
raise typer.BadParameter(f"File name must end with .py: {file_name}")
|
|
9
|
+
return file_name
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def validate_file_name_callback(value: str) -> str:
|
|
13
|
+
return validate_file_name(file_name=value)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING, Literal, overload
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
import typer
|
|
7
|
+
from typer.core import TyperCommand
|
|
8
|
+
|
|
9
|
+
from bake.ui.run import run as _run
|
|
10
|
+
from bake.ui.run.script import run_script as _run_script
|
|
11
|
+
|
|
12
|
+
from .obj import BakefileObject
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from bake.bakebook.bakebook import Bakebook
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Context(typer.Context):
|
|
19
|
+
obj: BakefileObject
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def dry_run(self) -> bool:
|
|
23
|
+
return self.obj.dry_run
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def verbosity(self) -> int:
|
|
27
|
+
return self.obj.verbosity
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def bakebook(self) -> "Bakebook | None":
|
|
31
|
+
return self.obj.bakebook
|
|
32
|
+
|
|
33
|
+
@overload
|
|
34
|
+
def run(
|
|
35
|
+
self,
|
|
36
|
+
cmd: str,
|
|
37
|
+
*,
|
|
38
|
+
capture_output: Literal[True] = True,
|
|
39
|
+
check: bool = True,
|
|
40
|
+
cwd: Path | str | None = None,
|
|
41
|
+
stream: bool = True,
|
|
42
|
+
shell: bool | None = None,
|
|
43
|
+
echo: bool = True,
|
|
44
|
+
dry_run: bool | None = None,
|
|
45
|
+
**kwargs,
|
|
46
|
+
) -> subprocess.CompletedProcess[str]: ...
|
|
47
|
+
|
|
48
|
+
@overload
|
|
49
|
+
def run(
|
|
50
|
+
self,
|
|
51
|
+
cmd: str,
|
|
52
|
+
*,
|
|
53
|
+
capture_output: Literal[False],
|
|
54
|
+
check: bool = True,
|
|
55
|
+
cwd: Path | str | None = None,
|
|
56
|
+
stream: bool = True,
|
|
57
|
+
shell: bool | None = None,
|
|
58
|
+
echo: bool = True,
|
|
59
|
+
dry_run: bool | None = None,
|
|
60
|
+
**kwargs,
|
|
61
|
+
) -> subprocess.CompletedProcess[None]: ...
|
|
62
|
+
|
|
63
|
+
@overload
|
|
64
|
+
def run(
|
|
65
|
+
self,
|
|
66
|
+
cmd: list[str] | tuple[str, ...],
|
|
67
|
+
*,
|
|
68
|
+
capture_output: Literal[True] = True,
|
|
69
|
+
check: bool = True,
|
|
70
|
+
cwd: Path | str | None = None,
|
|
71
|
+
stream: bool = True,
|
|
72
|
+
shell: bool | None = None,
|
|
73
|
+
echo: bool = True,
|
|
74
|
+
dry_run: bool | None = None,
|
|
75
|
+
**kwargs,
|
|
76
|
+
) -> subprocess.CompletedProcess[str]: ...
|
|
77
|
+
|
|
78
|
+
@overload
|
|
79
|
+
def run(
|
|
80
|
+
self,
|
|
81
|
+
cmd: list[str] | tuple[str, ...],
|
|
82
|
+
*,
|
|
83
|
+
capture_output: Literal[False],
|
|
84
|
+
check: bool = True,
|
|
85
|
+
cwd: Path | str | None = None,
|
|
86
|
+
stream: bool = True,
|
|
87
|
+
shell: bool | None = None,
|
|
88
|
+
echo: bool = True,
|
|
89
|
+
dry_run: bool | None = None,
|
|
90
|
+
**kwargs,
|
|
91
|
+
) -> subprocess.CompletedProcess[None]: ...
|
|
92
|
+
|
|
93
|
+
def run(
|
|
94
|
+
self,
|
|
95
|
+
cmd: str | list[str] | tuple[str, ...],
|
|
96
|
+
*,
|
|
97
|
+
capture_output: bool = True,
|
|
98
|
+
check: bool = True,
|
|
99
|
+
cwd: Path | str | None = None,
|
|
100
|
+
stream: bool = True,
|
|
101
|
+
shell: bool | None = None,
|
|
102
|
+
echo: bool = True,
|
|
103
|
+
dry_run: bool | None = None,
|
|
104
|
+
**kwargs,
|
|
105
|
+
) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[None]:
|
|
106
|
+
return _run(
|
|
107
|
+
cmd,
|
|
108
|
+
capture_output=capture_output,
|
|
109
|
+
check=check,
|
|
110
|
+
cwd=cwd,
|
|
111
|
+
stream=stream,
|
|
112
|
+
shell=shell,
|
|
113
|
+
echo=echo,
|
|
114
|
+
dry_run=self.obj.dry_run if dry_run is None else dry_run,
|
|
115
|
+
**kwargs,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def run_script(
|
|
119
|
+
self,
|
|
120
|
+
title: str,
|
|
121
|
+
script: str,
|
|
122
|
+
*,
|
|
123
|
+
capture_output: bool = True,
|
|
124
|
+
check: bool = True,
|
|
125
|
+
cwd: Path | str | None = None,
|
|
126
|
+
stream: bool = True,
|
|
127
|
+
echo: bool = True,
|
|
128
|
+
dry_run: bool | None = None,
|
|
129
|
+
**kwargs,
|
|
130
|
+
) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[None]:
|
|
131
|
+
return _run_script(
|
|
132
|
+
title,
|
|
133
|
+
script,
|
|
134
|
+
capture_output=capture_output,
|
|
135
|
+
check=check,
|
|
136
|
+
cwd=cwd,
|
|
137
|
+
stream=stream,
|
|
138
|
+
echo=echo,
|
|
139
|
+
dry_run=self.obj.dry_run if dry_run is None else dry_run,
|
|
140
|
+
**kwargs,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class BakeCommand(TyperCommand):
|
|
145
|
+
context_class: type[click.Context] = Context
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import errno
|
|
2
|
+
import sys
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
from gettext import gettext
|
|
5
|
+
from typing import TextIO, cast
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from typer.core import HAS_RICH, MarkupMode
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@contextmanager
|
|
12
|
+
def typer_exception_handler(
|
|
13
|
+
*,
|
|
14
|
+
standalone_mode: bool,
|
|
15
|
+
rich_markup_mode: MarkupMode,
|
|
16
|
+
):
|
|
17
|
+
# Reference code: https://github.com/fastapi/typer/blob/da9c4c67f3d8e4acd5f76e8909503bb999f1b751/typer/core.py#L186-L248
|
|
18
|
+
try:
|
|
19
|
+
try:
|
|
20
|
+
yield
|
|
21
|
+
except EOFError as e:
|
|
22
|
+
click.echo(file=sys.stderr)
|
|
23
|
+
raise click.Abort() from e
|
|
24
|
+
except KeyboardInterrupt as e:
|
|
25
|
+
raise click.exceptions.Exit(130) from e
|
|
26
|
+
except click.ClickException as e:
|
|
27
|
+
if not standalone_mode:
|
|
28
|
+
raise
|
|
29
|
+
if HAS_RICH and rich_markup_mode is not None:
|
|
30
|
+
from typer import rich_utils
|
|
31
|
+
|
|
32
|
+
rich_utils.rich_format_error(e)
|
|
33
|
+
else:
|
|
34
|
+
e.show()
|
|
35
|
+
sys.exit(e.exit_code)
|
|
36
|
+
except OSError as e:
|
|
37
|
+
if e.errno == errno.EPIPE:
|
|
38
|
+
sys.stdout = cast(TextIO, click.utils.PacifyFlushWrapper(sys.stdout))
|
|
39
|
+
sys.stderr = cast(TextIO, click.utils.PacifyFlushWrapper(sys.stderr))
|
|
40
|
+
sys.exit(1)
|
|
41
|
+
raise
|
|
42
|
+
except click.exceptions.Exit as e:
|
|
43
|
+
if standalone_mode:
|
|
44
|
+
sys.exit(e.exit_code)
|
|
45
|
+
else:
|
|
46
|
+
# return exit code to caller
|
|
47
|
+
raise
|
|
48
|
+
except click.Abort:
|
|
49
|
+
if not standalone_mode:
|
|
50
|
+
raise
|
|
51
|
+
if HAS_RICH and rich_markup_mode is not None:
|
|
52
|
+
from typer import rich_utils
|
|
53
|
+
|
|
54
|
+
rich_utils.rich_abort_error()
|
|
55
|
+
else:
|
|
56
|
+
click.echo(gettext("Aborted!"), file=sys.stderr)
|
|
57
|
+
sys.exit(1)
|
bake/cli/common/obj.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
import typer
|
|
11
|
+
from pydantic import ValidationError
|
|
12
|
+
from rich.traceback import Traceback
|
|
13
|
+
from typer.core import MarkupMode
|
|
14
|
+
from typer.main import get_command_from_info
|
|
15
|
+
|
|
16
|
+
from bake.bakebook.get import (
|
|
17
|
+
get_bakebook_from_target_dir_path,
|
|
18
|
+
resolve_bakefile_path,
|
|
19
|
+
)
|
|
20
|
+
from bake.ui import console, setup_logging
|
|
21
|
+
from bake.utils.constants import (
|
|
22
|
+
DEFAULT_BAKEBOOK_NAME,
|
|
23
|
+
DEFAULT_CHDIR,
|
|
24
|
+
DEFAULT_FILE_NAME,
|
|
25
|
+
DEFAULT_IS_CHAIN_COMMAND,
|
|
26
|
+
GET_BAKEFILE_OBJECT,
|
|
27
|
+
)
|
|
28
|
+
from bake.utils.exceptions import BakebookError, BakefileNotFoundError
|
|
29
|
+
|
|
30
|
+
from .callback import validate_file_name
|
|
31
|
+
from .exception_handler import typer_exception_handler
|
|
32
|
+
from .params import (
|
|
33
|
+
bakebook_name_option,
|
|
34
|
+
chdir_option,
|
|
35
|
+
dry_run_option,
|
|
36
|
+
file_name_option,
|
|
37
|
+
is_chain_commands_option,
|
|
38
|
+
remaining_args_argument,
|
|
39
|
+
verbosity_option,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from bake.bakebook.bakebook import Bakebook
|
|
44
|
+
|
|
45
|
+
logger = logging.Logger(__name__)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class BakefileObject:
|
|
50
|
+
chdir: Path
|
|
51
|
+
file_name: str
|
|
52
|
+
bakebook_name: str
|
|
53
|
+
bakefile_path: Path | None = None
|
|
54
|
+
bakebook: "Bakebook | None" = None
|
|
55
|
+
verbosity: int = 0
|
|
56
|
+
dry_run: bool = False
|
|
57
|
+
remaining_args: list[str] | None = None
|
|
58
|
+
is_chain_commands: bool = False
|
|
59
|
+
|
|
60
|
+
def __post_init__(self):
|
|
61
|
+
validate_file_name(self.file_name)
|
|
62
|
+
|
|
63
|
+
def resolve_bakefile_path(self) -> Path | None:
|
|
64
|
+
if self.bakefile_path is not None:
|
|
65
|
+
return self.bakefile_path
|
|
66
|
+
|
|
67
|
+
with contextlib.suppress(BakefileNotFoundError):
|
|
68
|
+
self.bakefile_path = resolve_bakefile_path(chdir=self.chdir, file_name=self.file_name)
|
|
69
|
+
|
|
70
|
+
return self.bakefile_path
|
|
71
|
+
|
|
72
|
+
def get_bakebook(self, allow_missing: bool):
|
|
73
|
+
if self.bakebook is not None:
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
if self.bakefile_path is None:
|
|
78
|
+
self.bakefile_path = resolve_bakefile_path(
|
|
79
|
+
chdir=self.chdir, file_name=self.file_name
|
|
80
|
+
)
|
|
81
|
+
self.bakebook = get_bakebook_from_target_dir_path(
|
|
82
|
+
target_dir_path=self.bakefile_path, bakebook_name=self.bakebook_name
|
|
83
|
+
)
|
|
84
|
+
except BakefileNotFoundError:
|
|
85
|
+
if allow_missing:
|
|
86
|
+
return
|
|
87
|
+
except BakebookError as e:
|
|
88
|
+
if allow_missing:
|
|
89
|
+
return
|
|
90
|
+
exc_to_show = e.__cause__ if e.__cause__ else e
|
|
91
|
+
|
|
92
|
+
if exc_to_show.__class__ in {ValidationError, BakebookError}:
|
|
93
|
+
console.err.print(
|
|
94
|
+
f"[bold red]{exc_to_show.__class__.__name__}:[/bold red]", end=" "
|
|
95
|
+
)
|
|
96
|
+
console.err.print(exc_to_show)
|
|
97
|
+
console.err.print(f"Searched in: {self.chdir.resolve()}\n")
|
|
98
|
+
else:
|
|
99
|
+
console.err.print(
|
|
100
|
+
Traceback.from_exception(
|
|
101
|
+
type(exc_to_show), exc_to_show, exc_to_show.__traceback__
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
raise SystemExit(1) from e
|
|
105
|
+
|
|
106
|
+
def warn_if_no_bakebook(self, color_echo: bool):
|
|
107
|
+
if self.bakebook is None:
|
|
108
|
+
_ = color_echo # Color handled by console module
|
|
109
|
+
console.warning(f"Bakebook `{self.bakebook_name}` not found in `{self.file_name}`")
|
|
110
|
+
console.echo(f"Searched in: {self.chdir.resolve()}\n")
|
|
111
|
+
|
|
112
|
+
def setup_logging(self):
|
|
113
|
+
level_map = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG}
|
|
114
|
+
log_level = level_map.get(self.verbosity, logging.WARNING)
|
|
115
|
+
setup_logging(level_per_module={"": log_level}, is_pretty_log=True)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
bakefile_obj_app = typer.Typer()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def get_args(args: list[str] | None = None, windows_expand_args: bool = True) -> list[str]:
|
|
122
|
+
if args is None:
|
|
123
|
+
args = sys.argv[1:]
|
|
124
|
+
|
|
125
|
+
# Covered in Click tests
|
|
126
|
+
if os.name == "nt" and windows_expand_args: # pragma: no cover
|
|
127
|
+
args = click.utils._expand_args(args)
|
|
128
|
+
else:
|
|
129
|
+
args = list(args)
|
|
130
|
+
|
|
131
|
+
return args
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def bakefile_obj_app_args(
|
|
135
|
+
args: list[str] | None = None,
|
|
136
|
+
windows_expand_args: bool = True,
|
|
137
|
+
) -> list[str]:
|
|
138
|
+
# source from https://github.com/fastapi/typer/blob/b7f39eaad60141988f5d9a58df72c44d6128cd53/typer/core.py#L175-L185
|
|
139
|
+
|
|
140
|
+
args = get_args(args=args, windows_expand_args=windows_expand_args)
|
|
141
|
+
|
|
142
|
+
prohibited_non_bakefile_obj_app_args: list[str] = ["--help", "--version"]
|
|
143
|
+
|
|
144
|
+
args = [arg for arg in args if arg not in prohibited_non_bakefile_obj_app_args]
|
|
145
|
+
return args
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def is_bakebook_optional(remaining_args: list[str] | None) -> bool:
|
|
149
|
+
args = get_args()
|
|
150
|
+
|
|
151
|
+
some_args: list[str] = ["--help", "--version"]
|
|
152
|
+
is_some_args = len([arg for arg in args if arg in some_args]) > 0
|
|
153
|
+
return is_some_args or remaining_args is None or remaining_args == []
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@bakefile_obj_app.command(
|
|
157
|
+
name=GET_BAKEFILE_OBJECT,
|
|
158
|
+
hidden=True,
|
|
159
|
+
context_settings={
|
|
160
|
+
"allow_extra_args": True,
|
|
161
|
+
"allow_interspersed_args": False,
|
|
162
|
+
"ignore_unknown_options": True,
|
|
163
|
+
},
|
|
164
|
+
)
|
|
165
|
+
def _get_bakefile_object(
|
|
166
|
+
ctx: typer.Context,
|
|
167
|
+
chdir: chdir_option = DEFAULT_CHDIR,
|
|
168
|
+
file_name: file_name_option = DEFAULT_FILE_NAME,
|
|
169
|
+
bakebook_name: bakebook_name_option = DEFAULT_BAKEBOOK_NAME,
|
|
170
|
+
is_chain_commands: is_chain_commands_option = DEFAULT_IS_CHAIN_COMMAND,
|
|
171
|
+
remaining_args: remaining_args_argument = None,
|
|
172
|
+
verbosity: verbosity_option = 0,
|
|
173
|
+
dry_run: dry_run_option = False,
|
|
174
|
+
):
|
|
175
|
+
_ = ctx
|
|
176
|
+
return BakefileObject(
|
|
177
|
+
chdir=chdir,
|
|
178
|
+
file_name=file_name,
|
|
179
|
+
bakebook_name=bakebook_name,
|
|
180
|
+
verbosity=verbosity,
|
|
181
|
+
dry_run=dry_run,
|
|
182
|
+
remaining_args=remaining_args,
|
|
183
|
+
is_chain_commands=is_chain_commands,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def get_bakefile_object(rich_markup_mode: MarkupMode) -> BakefileObject:
|
|
188
|
+
with typer_exception_handler(standalone_mode=True, rich_markup_mode=rich_markup_mode):
|
|
189
|
+
args = bakefile_obj_app_args()
|
|
190
|
+
|
|
191
|
+
for registered_command in bakefile_obj_app.registered_commands:
|
|
192
|
+
if registered_command.name != GET_BAKEFILE_OBJECT:
|
|
193
|
+
continue
|
|
194
|
+
|
|
195
|
+
command = get_command_from_info(
|
|
196
|
+
registered_command,
|
|
197
|
+
pretty_exceptions_short=bakefile_obj_app.pretty_exceptions_short,
|
|
198
|
+
rich_markup_mode=bakefile_obj_app.rich_markup_mode,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
with command.make_context(info_name=GET_BAKEFILE_OBJECT, args=args) as ctx:
|
|
202
|
+
bakefile_obj = command.invoke(ctx)
|
|
203
|
+
if not isinstance(bakefile_obj, BakefileObject):
|
|
204
|
+
msg = (
|
|
205
|
+
f"Expected `bakefile_obj` to be an instance of "
|
|
206
|
+
f"{BakefileObject.__name__}, got {type(bakefile_obj).__name__}"
|
|
207
|
+
)
|
|
208
|
+
raise TypeError(msg)
|
|
209
|
+
return bakefile_obj
|
|
210
|
+
|
|
211
|
+
raise RuntimeError(
|
|
212
|
+
f"Failed to find the `{GET_BAKEFILE_OBJECT}` command in registered commands. "
|
|
213
|
+
f"This should never happen - please report this bug."
|
|
214
|
+
)
|