bakefile 0.0.10__tar.gz → 0.0.12__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.
- {bakefile-0.0.10 → bakefile-0.0.12}/PKG-INFO +3 -1
- {bakefile-0.0.10 → bakefile-0.0.12}/pyproject.toml +10 -2
- bakefile-0.0.12/src/bake/cli/bake/main.py +116 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bake/reinvocation.py +6 -3
- bakefile-0.0.12/src/bake/cli/bakefile/main.py +77 -0
- bakefile-0.0.12/src/bake/cli/common/app.py +56 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/common/context.py +4 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/common/obj.py +4 -3
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/common/params.py +10 -2
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/lint.py +10 -7
- bakefile-0.0.12/src/bake/ui/console.py +122 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/run/run.py +52 -13
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/run/uv.py +2 -10
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/utils/__init__.py +8 -2
- bakefile-0.0.12/src/bake/utils/settings.py +25 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/__init__.py +2 -0
- bakefile-0.0.12/src/bakelib/refreshable_cache/__init__.py +17 -0
- bakefile-0.0.12/src/bakelib/refreshable_cache/cache.py +250 -0
- bakefile-0.0.12/src/bakelib/refreshable_cache/exceptions.py +2 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/space/base.py +26 -12
- bakefile-0.0.12/src/bakelib/space/lib.py +161 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/space/python.py +12 -0
- bakefile-0.0.12/src/bakelib/space/python_lib.py +77 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/space/utils.py +10 -0
- bakefile-0.0.10/src/bake/cli/bake/main.py +0 -74
- bakefile-0.0.10/src/bake/cli/bakefile/main.py +0 -43
- bakefile-0.0.10/src/bake/cli/common/app.py +0 -54
- bakefile-0.0.10/src/bake/cli/common/callback.py +0 -13
- bakefile-0.0.10/src/bake/ui/console.py +0 -58
- bakefile-0.0.10/src/bake/utils/env.py +0 -10
- {bakefile-0.0.10 → bakefile-0.0.12}/README.md +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/bakebook/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/bakebook/bakebook.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/bakebook/decorator.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/bakebook/get.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bake/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bake/__main__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/__main__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/add_inline.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/export.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/find_python.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/init.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/lint.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/bakefile/uv.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/common/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/common/exception_handler.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/utils/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/cli/utils/version.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/add_inline.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/find_python.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/run_uv.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/manage/write_bakefile.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/py.typed +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/samples/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/samples/simple.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/logger/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/logger/capsys.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/logger/setup.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/logger/utils.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/params.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/run/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/run/script.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/run/splitter.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/ui/style.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/utils/constants.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bake/utils/exceptions.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/environ/__init__.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/environ/bakebook.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/environ/base.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/environ/get_bakebook.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/environ/presets.py +0 -0
- {bakefile-0.0.10 → bakefile-0.0.12}/src/bakelib/space/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: bakefile
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Author: Wisaroot Lertthaweedech
|
|
6
6
|
Author-email: Wisaroot Lertthaweedech <l.wisaroot@gmail.com>
|
|
@@ -18,7 +18,9 @@ Requires-Dist: tomli>=2.0.0 ; python_full_version < '3.11'
|
|
|
18
18
|
Requires-Dist: ty>=0.0.8
|
|
19
19
|
Requires-Dist: typer>=0.21.0
|
|
20
20
|
Requires-Dist: uv>=0.9.20
|
|
21
|
+
Requires-Dist: keyring>=25.7.0 ; extra == 'lib'
|
|
21
22
|
Requires-Dist: pathspec>=1.0.3 ; extra == 'lib'
|
|
23
|
+
Requires-Dist: tenacity>=9.1.2 ; extra == 'lib'
|
|
22
24
|
Requires-Python: >=3.10
|
|
23
25
|
Provides-Extra: lib
|
|
24
26
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "bakefile"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.12" # use git tag
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -26,7 +26,9 @@ dependencies = [
|
|
|
26
26
|
|
|
27
27
|
[project.optional-dependencies]
|
|
28
28
|
lib = [
|
|
29
|
-
"
|
|
29
|
+
"keyring>=25.7.0",
|
|
30
|
+
"pathspec>=1.0.3",
|
|
31
|
+
"tenacity>=9.1.2"
|
|
30
32
|
]
|
|
31
33
|
|
|
32
34
|
[project.scripts]
|
|
@@ -79,5 +81,11 @@ select = [
|
|
|
79
81
|
module-name = ["bake", "bakelib"]
|
|
80
82
|
module-root = "src"
|
|
81
83
|
|
|
84
|
+
[[tool.uv.index]]
|
|
85
|
+
name = "testpypi"
|
|
86
|
+
url = "https://test.pypi.org/simple/"
|
|
87
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
88
|
+
explicit = true
|
|
89
|
+
|
|
82
90
|
[tool.uv.sources]
|
|
83
91
|
python-package = {path = "examples/python-package", editable = true}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from bake.cli.bake.reinvocation import _reinvoke_with_detected_python
|
|
9
|
+
from bake.cli.common.app import (
|
|
10
|
+
add_completion,
|
|
11
|
+
call_app_with_chdir,
|
|
12
|
+
rich_markup_mode,
|
|
13
|
+
show_help_if_no_command,
|
|
14
|
+
)
|
|
15
|
+
from bake.cli.common.context import Context
|
|
16
|
+
from bake.cli.common.obj import BakefileObject, get_bakefile_object, is_bakebook_optional
|
|
17
|
+
from bake.cli.common.params import (
|
|
18
|
+
bakebook_name_option,
|
|
19
|
+
chdir_option,
|
|
20
|
+
dry_run_option,
|
|
21
|
+
file_name_option,
|
|
22
|
+
is_chain_commands_option,
|
|
23
|
+
verbosity_option,
|
|
24
|
+
version_option,
|
|
25
|
+
)
|
|
26
|
+
from bake.ui import console
|
|
27
|
+
from bake.utils.constants import (
|
|
28
|
+
DEFAULT_BAKEBOOK_NAME,
|
|
29
|
+
DEFAULT_CHDIR,
|
|
30
|
+
DEFAULT_FILE_NAME,
|
|
31
|
+
DEFAULT_IS_CHAIN_COMMAND,
|
|
32
|
+
)
|
|
33
|
+
from bake.utils.settings import bake_settings
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def bake_app_callback_with_obj(obj: BakefileObject) -> Callable[..., None]:
|
|
37
|
+
def bake_app_callback(
|
|
38
|
+
ctx: Context,
|
|
39
|
+
_chdir: chdir_option = DEFAULT_CHDIR,
|
|
40
|
+
_file_name: file_name_option = DEFAULT_FILE_NAME,
|
|
41
|
+
_bakebook_name: bakebook_name_option = DEFAULT_BAKEBOOK_NAME,
|
|
42
|
+
_version: version_option = False,
|
|
43
|
+
_is_chain_commands: is_chain_commands_option = DEFAULT_IS_CHAIN_COMMAND,
|
|
44
|
+
_verbosity: verbosity_option = 0,
|
|
45
|
+
_dry_run: dry_run_option = False,
|
|
46
|
+
):
|
|
47
|
+
ctx.obj = obj
|
|
48
|
+
show_help_if_no_command(ctx)
|
|
49
|
+
|
|
50
|
+
return bake_app_callback
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@contextmanager
|
|
54
|
+
def set_argv(argv: list[str]):
|
|
55
|
+
original = sys.argv.copy()
|
|
56
|
+
sys.argv = argv
|
|
57
|
+
try:
|
|
58
|
+
yield
|
|
59
|
+
finally:
|
|
60
|
+
sys.argv = original
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _run_chain_commands(
|
|
64
|
+
remaining_args: list[str], prog_name: str, bake_app: typer.Typer, bakefile_path: Path | None
|
|
65
|
+
) -> int:
|
|
66
|
+
exit_code = 0
|
|
67
|
+
for cmd in remaining_args:
|
|
68
|
+
try:
|
|
69
|
+
with set_argv([prog_name, cmd]):
|
|
70
|
+
console.cmd(" ".join(sys.argv))
|
|
71
|
+
call_app_with_chdir(app=bake_app, bakefile_path=bakefile_path, prog_name=prog_name)
|
|
72
|
+
except SystemExit as e:
|
|
73
|
+
if e.code is not None and e.code != 0:
|
|
74
|
+
exit_code = e.code if isinstance(e.code, int) else 1
|
|
75
|
+
break
|
|
76
|
+
return exit_code
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def main():
|
|
80
|
+
bakefile_obj = get_bakefile_object(rich_markup_mode=rich_markup_mode)
|
|
81
|
+
bakefile_obj.setup_logging()
|
|
82
|
+
bakefile_obj.resolve_bakefile_path()
|
|
83
|
+
|
|
84
|
+
# Check re-invocation with resolved bakefile path
|
|
85
|
+
# If re-invocation happens, process is replaced and we don't return
|
|
86
|
+
_reinvoke_with_detected_python(bakefile_obj.bakefile_path)
|
|
87
|
+
# If returned above, we're in the correct Python
|
|
88
|
+
|
|
89
|
+
bakefile_obj.get_bakebook(
|
|
90
|
+
allow_missing=is_bakebook_optional(remaining_args=bakefile_obj.remaining_args)
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
bakefile_obj.warn_if_no_bakebook(color_echo=bake_settings.should_use_colors())
|
|
94
|
+
|
|
95
|
+
bake_app = typer.Typer(
|
|
96
|
+
add_completion=add_completion,
|
|
97
|
+
rich_markup_mode=rich_markup_mode,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
callback = bake_app_callback_with_obj(obj=bakefile_obj)
|
|
101
|
+
bake_app.callback(invoke_without_command=True)(callback)
|
|
102
|
+
|
|
103
|
+
prog_name = "bake"
|
|
104
|
+
|
|
105
|
+
if bakefile_obj.bakebook is not None:
|
|
106
|
+
bake_app.add_typer(bakefile_obj.bakebook._app)
|
|
107
|
+
|
|
108
|
+
if bakefile_obj.is_chain_commands and bakefile_obj.remaining_args:
|
|
109
|
+
exit_code = _run_chain_commands(
|
|
110
|
+
remaining_args=bakefile_obj.remaining_args,
|
|
111
|
+
prog_name=prog_name,
|
|
112
|
+
bake_app=bake_app,
|
|
113
|
+
bakefile_path=bakefile_obj.bakefile_path,
|
|
114
|
+
)
|
|
115
|
+
raise SystemExit(exit_code)
|
|
116
|
+
call_app_with_chdir(app=bake_app, bakefile_path=bakefile_obj.bakefile_path, prog_name=prog_name)
|
|
@@ -4,7 +4,7 @@ import subprocess
|
|
|
4
4
|
import sys
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
from bake.utils.
|
|
7
|
+
from bake.utils.settings import ENV__BAKE_REINVOKED, bake_settings
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
@@ -21,8 +21,11 @@ def _reinvoke_with_detected_python(bakefile_path: Path | None) -> None:
|
|
|
21
21
|
Returns:
|
|
22
22
|
None. Either calls os.execve() (replaces process) or returns normally.
|
|
23
23
|
"""
|
|
24
|
+
# Access via module path so tests can reassign
|
|
25
|
+
# from bake.utils import settings
|
|
26
|
+
|
|
24
27
|
# 1. Check marker to prevent infinite loops
|
|
25
|
-
if
|
|
28
|
+
if bake_settings.bake_reinvoked:
|
|
26
29
|
logger.debug(
|
|
27
30
|
"Re-invocation marker set, skipping Python check",
|
|
28
31
|
extra={"sys.executable": sys.executable},
|
|
@@ -52,7 +55,7 @@ def _reinvoke_with_detected_python(bakefile_path: Path | None) -> None:
|
|
|
52
55
|
extra={"target_python": str(target_python)},
|
|
53
56
|
)
|
|
54
57
|
env = os.environ.copy()
|
|
55
|
-
env[
|
|
58
|
+
env[ENV__BAKE_REINVOKED] = "1"
|
|
56
59
|
|
|
57
60
|
sys.stdout.flush()
|
|
58
61
|
sys.stderr.flush()
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
|
|
3
|
+
from bake.cli.common.app import (
|
|
4
|
+
BakefileApp,
|
|
5
|
+
add_completion,
|
|
6
|
+
call_app_with_chdir,
|
|
7
|
+
rich_markup_mode,
|
|
8
|
+
show_help_if_no_command,
|
|
9
|
+
)
|
|
10
|
+
from bake.cli.common.context import Context
|
|
11
|
+
from bake.cli.common.obj import BakefileObject, get_bakefile_object
|
|
12
|
+
from bake.cli.common.params import (
|
|
13
|
+
bakebook_name_option,
|
|
14
|
+
chdir_option,
|
|
15
|
+
dry_run_option,
|
|
16
|
+
file_name_option,
|
|
17
|
+
verbosity_option,
|
|
18
|
+
version_option,
|
|
19
|
+
)
|
|
20
|
+
from bake.utils.constants import (
|
|
21
|
+
DEFAULT_BAKEBOOK_NAME,
|
|
22
|
+
DEFAULT_CHDIR,
|
|
23
|
+
DEFAULT_FILE_NAME,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from . import uv
|
|
27
|
+
from .add_inline import add_inline
|
|
28
|
+
from .export import export
|
|
29
|
+
from .find_python import find_python
|
|
30
|
+
from .init import init
|
|
31
|
+
from .lint import lint
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def bakefile_app_callback_with_obj(obj: BakefileObject) -> Callable[..., None]:
|
|
35
|
+
def bakefile_app_callback(
|
|
36
|
+
ctx: Context,
|
|
37
|
+
_chdir: chdir_option = DEFAULT_CHDIR,
|
|
38
|
+
_file_name: file_name_option = DEFAULT_FILE_NAME,
|
|
39
|
+
_bakebook_name: bakebook_name_option = DEFAULT_BAKEBOOK_NAME,
|
|
40
|
+
_version: version_option = False,
|
|
41
|
+
_verbosity: verbosity_option = 0,
|
|
42
|
+
_dry_run: dry_run_option = False,
|
|
43
|
+
):
|
|
44
|
+
ctx.obj = obj
|
|
45
|
+
show_help_if_no_command(ctx)
|
|
46
|
+
|
|
47
|
+
return bakefile_app_callback
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main():
|
|
51
|
+
bakefile_obj = get_bakefile_object(rich_markup_mode=rich_markup_mode)
|
|
52
|
+
bakefile_obj.setup_logging()
|
|
53
|
+
bakefile_obj.resolve_bakefile_path()
|
|
54
|
+
|
|
55
|
+
bakefile_app = BakefileApp(
|
|
56
|
+
add_completion=add_completion,
|
|
57
|
+
rich_markup_mode=rich_markup_mode,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
uv_commands_context_settings = {
|
|
61
|
+
"allow_extra_args": True,
|
|
62
|
+
"ignore_unknown_options": True,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
callback = bakefile_app_callback_with_obj(obj=bakefile_obj)
|
|
66
|
+
bakefile_app.callback(invoke_without_command=True)(callback)
|
|
67
|
+
bakefile_app.command()(init)
|
|
68
|
+
bakefile_app.command()(add_inline)
|
|
69
|
+
bakefile_app.command()(find_python)
|
|
70
|
+
bakefile_app.command()(lint)
|
|
71
|
+
bakefile_app.command()(export)
|
|
72
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.sync)
|
|
73
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.lock)
|
|
74
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.add)
|
|
75
|
+
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.pip)
|
|
76
|
+
bakefile_app.bakefile_object = bakefile_obj
|
|
77
|
+
call_app_with_chdir(app=bakefile_app, bakefile_path=bakefile_obj.bakefile_path)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from collections.abc import Generator
|
|
4
|
+
from contextlib import contextmanager
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from typer.core import MarkupMode
|
|
10
|
+
|
|
11
|
+
from bake.cli.common.context import Context
|
|
12
|
+
from bake.ui import console
|
|
13
|
+
|
|
14
|
+
from .obj import BakefileObject
|
|
15
|
+
|
|
16
|
+
rich_markup_mode: MarkupMode = "rich" if not console.out.no_color else None
|
|
17
|
+
add_completion = True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BakefileApp(typer.Typer):
|
|
21
|
+
bakefile_object: BakefileObject
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if sys.version_info >= (3, 11):
|
|
25
|
+
from contextlib import chdir
|
|
26
|
+
else:
|
|
27
|
+
|
|
28
|
+
@contextmanager
|
|
29
|
+
def chdir(path: Path) -> Generator[None, None, None]:
|
|
30
|
+
"""Change directory context manager for Python < 3.11 compatibility."""
|
|
31
|
+
original = Path.cwd()
|
|
32
|
+
try:
|
|
33
|
+
os.chdir(path)
|
|
34
|
+
yield
|
|
35
|
+
finally:
|
|
36
|
+
os.chdir(original)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def call_app_with_chdir(
|
|
40
|
+
app: typer.Typer,
|
|
41
|
+
bakefile_path: Path | None,
|
|
42
|
+
*args: Any,
|
|
43
|
+
**kwargs: Any,
|
|
44
|
+
) -> None:
|
|
45
|
+
if bakefile_path is not None:
|
|
46
|
+
dir_path = bakefile_path.parent
|
|
47
|
+
with chdir(dir_path):
|
|
48
|
+
app(*args, **kwargs)
|
|
49
|
+
else:
|
|
50
|
+
app(*args, **kwargs)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def show_help_if_no_command(ctx: Context) -> None:
|
|
54
|
+
if ctx.invoked_subcommand is None:
|
|
55
|
+
console.echo(ctx.get_help())
|
|
56
|
+
raise typer.Exit(1)
|
|
@@ -57,6 +57,7 @@ class Context(typer.Context):
|
|
|
57
57
|
stream: bool = True,
|
|
58
58
|
shell: bool | None = None,
|
|
59
59
|
echo: bool = True,
|
|
60
|
+
echo_cmd: str | None = None,
|
|
60
61
|
dry_run: bool | None = None,
|
|
61
62
|
keep_temp_file: bool = False,
|
|
62
63
|
env: dict[str, str] | None = None,
|
|
@@ -74,6 +75,7 @@ class Context(typer.Context):
|
|
|
74
75
|
stream: bool = True,
|
|
75
76
|
shell: bool | None = None,
|
|
76
77
|
echo: bool = True,
|
|
78
|
+
echo_cmd: str | None = None,
|
|
77
79
|
dry_run: bool | None = None,
|
|
78
80
|
keep_temp_file: bool = False,
|
|
79
81
|
env: dict[str, str] | None = None,
|
|
@@ -90,6 +92,7 @@ class Context(typer.Context):
|
|
|
90
92
|
stream: bool = True,
|
|
91
93
|
shell: bool | None = None,
|
|
92
94
|
echo: bool = True,
|
|
95
|
+
echo_cmd: str | None = None,
|
|
93
96
|
dry_run: bool | None = None,
|
|
94
97
|
keep_temp_file: bool = False,
|
|
95
98
|
env: dict[str, str] | None = None,
|
|
@@ -104,6 +107,7 @@ class Context(typer.Context):
|
|
|
104
107
|
stream=stream,
|
|
105
108
|
shell=shell,
|
|
106
109
|
echo=echo,
|
|
110
|
+
echo_cmd=echo_cmd,
|
|
107
111
|
dry_run=self.obj.dry_run if dry_run is None else dry_run,
|
|
108
112
|
keep_temp_file=keep_temp_file,
|
|
109
113
|
env=env,
|
|
@@ -27,7 +27,6 @@ from bake.utils.constants import (
|
|
|
27
27
|
)
|
|
28
28
|
from bake.utils.exceptions import BakebookError, BakefileNotFoundError
|
|
29
29
|
|
|
30
|
-
from .callback import validate_file_name
|
|
31
30
|
from .exception_handler import typer_exception_handler
|
|
32
31
|
from .params import (
|
|
33
32
|
bakebook_name_option,
|
|
@@ -36,6 +35,7 @@ from .params import (
|
|
|
36
35
|
file_name_option,
|
|
37
36
|
is_chain_commands_option,
|
|
38
37
|
remaining_args_argument,
|
|
38
|
+
validate_file_name,
|
|
39
39
|
verbosity_option,
|
|
40
40
|
)
|
|
41
41
|
|
|
@@ -112,8 +112,9 @@ class BakefileObject:
|
|
|
112
112
|
console.echo(f"Searched in: {self.chdir.resolve()}\n")
|
|
113
113
|
|
|
114
114
|
def setup_logging(self):
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
# Verbosity: 0=silent, 1=INFO, 2=DEBUG (CRITICAL+1 silences all logs)
|
|
116
|
+
level_map: dict[int, int] = {0: logging.CRITICAL + 1, 1: logging.INFO, 2: logging.DEBUG}
|
|
117
|
+
log_level = level_map.get(self.verbosity, logging.CRITICAL + 1)
|
|
117
118
|
setup_logging(level_per_module={"": log_level}, is_pretty_log=True)
|
|
118
119
|
|
|
119
120
|
|
|
@@ -3,10 +3,18 @@ from typing import Annotated
|
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
5
|
|
|
6
|
-
from bake.cli.common.callback import validate_file_name_callback
|
|
7
6
|
from bake.cli.utils.version import version_callback
|
|
8
7
|
|
|
9
8
|
|
|
9
|
+
def validate_file_name(value: str) -> str:
|
|
10
|
+
"""Validate file name for --file-name option."""
|
|
11
|
+
if "/" in value or "\\" in value:
|
|
12
|
+
raise typer.BadParameter(f"File name must not contain path separators: {value}")
|
|
13
|
+
if not value.endswith(".py"):
|
|
14
|
+
raise typer.BadParameter(f"File name must end with .py: {value}")
|
|
15
|
+
return value
|
|
16
|
+
|
|
17
|
+
|
|
10
18
|
def verbosity_callback(_ctx: typer.Context, _param: typer.CallbackParam, value: int) -> int:
|
|
11
19
|
"""Validate verbosity level (max 2)."""
|
|
12
20
|
if value > 2:
|
|
@@ -31,7 +39,7 @@ file_name_option = Annotated[
|
|
|
31
39
|
"--file-name",
|
|
32
40
|
"-f",
|
|
33
41
|
help="Path to bakefile.py",
|
|
34
|
-
callback=
|
|
42
|
+
callback=validate_file_name,
|
|
35
43
|
),
|
|
36
44
|
]
|
|
37
45
|
bakebook_name_option = Annotated[
|
|
@@ -5,7 +5,6 @@ from pathlib import Path
|
|
|
5
5
|
from ruff.__main__ import find_ruff_bin
|
|
6
6
|
from ty.__main__ import find_ty_bin
|
|
7
7
|
|
|
8
|
-
from bake.ui import console
|
|
9
8
|
from bake.ui.run import run
|
|
10
9
|
|
|
11
10
|
logger = logging.getLogger(__name__)
|
|
@@ -19,19 +18,19 @@ def run_ruff(
|
|
|
19
18
|
only_bakefile: bool = False,
|
|
20
19
|
check: bool = True,
|
|
21
20
|
dry_run: bool = False,
|
|
21
|
+
echo: bool = True,
|
|
22
22
|
) -> subprocess.CompletedProcess[str]:
|
|
23
23
|
ruff_bin = find_ruff_bin()
|
|
24
24
|
target = bakefile_path.name if only_bakefile else "."
|
|
25
25
|
cmd = [subcommand, *args, target]
|
|
26
|
-
display_cmd = "ruff " + " ".join(cmd)
|
|
27
|
-
console.cmd(display_cmd)
|
|
28
26
|
return run(
|
|
29
27
|
[str(ruff_bin), *cmd],
|
|
30
28
|
cwd=bakefile_path.parent,
|
|
31
29
|
capture_output=True,
|
|
32
30
|
stream=True,
|
|
33
31
|
check=check,
|
|
34
|
-
echo=
|
|
32
|
+
echo=echo,
|
|
33
|
+
echo_cmd="ruff " + " ".join(cmd) if echo else None,
|
|
35
34
|
dry_run=dry_run,
|
|
36
35
|
)
|
|
37
36
|
|
|
@@ -42,6 +41,7 @@ def run_ruff_format(
|
|
|
42
41
|
only_bakefile: bool = False,
|
|
43
42
|
check: bool = True,
|
|
44
43
|
dry_run: bool = False,
|
|
44
|
+
echo: bool = True,
|
|
45
45
|
) -> subprocess.CompletedProcess[str]:
|
|
46
46
|
return run_ruff(
|
|
47
47
|
bakefile_path=bakefile_path,
|
|
@@ -50,6 +50,7 @@ def run_ruff_format(
|
|
|
50
50
|
only_bakefile=only_bakefile,
|
|
51
51
|
check=check,
|
|
52
52
|
dry_run=dry_run,
|
|
53
|
+
echo=echo,
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
|
|
@@ -59,6 +60,7 @@ def run_ruff_check(
|
|
|
59
60
|
only_bakefile: bool = False,
|
|
60
61
|
check: bool = True,
|
|
61
62
|
dry_run: bool = False,
|
|
63
|
+
echo: bool = True,
|
|
62
64
|
) -> subprocess.CompletedProcess[str]:
|
|
63
65
|
return run_ruff(
|
|
64
66
|
bakefile_path=bakefile_path,
|
|
@@ -72,6 +74,7 @@ def run_ruff_check(
|
|
|
72
74
|
only_bakefile=only_bakefile,
|
|
73
75
|
check=check,
|
|
74
76
|
dry_run=dry_run,
|
|
77
|
+
echo=echo,
|
|
75
78
|
)
|
|
76
79
|
|
|
77
80
|
|
|
@@ -82,20 +85,20 @@ def run_ty_check(
|
|
|
82
85
|
only_bakefile: bool = False,
|
|
83
86
|
check: bool = True,
|
|
84
87
|
dry_run: bool = False,
|
|
88
|
+
echo: bool = True,
|
|
85
89
|
) -> subprocess.CompletedProcess[str]:
|
|
86
90
|
ty_bin = find_ty_bin()
|
|
87
91
|
cmd = ["check", "--error-on-warning", "--python", str(python_path)]
|
|
88
92
|
if only_bakefile:
|
|
89
93
|
cmd.append(bakefile_path.name)
|
|
90
94
|
|
|
91
|
-
display_cmd = "ty " + " ".join(cmd)
|
|
92
|
-
console.cmd(display_cmd)
|
|
93
95
|
return run(
|
|
94
96
|
[str(ty_bin), *cmd],
|
|
95
97
|
cwd=bakefile_path.parent,
|
|
96
98
|
capture_output=True,
|
|
97
99
|
stream=True,
|
|
98
100
|
check=check,
|
|
99
|
-
echo=
|
|
101
|
+
echo=echo,
|
|
102
|
+
echo_cmd="ty " + " ".join(cmd) if echo else None,
|
|
100
103
|
dry_run=dry_run,
|
|
101
104
|
)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import textwrap
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from beautysh import BashFormatter
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
from bake.utils.settings import bake_settings
|
|
9
|
+
|
|
10
|
+
out = Console(stderr=False)
|
|
11
|
+
err = Console(stderr=True)
|
|
12
|
+
|
|
13
|
+
BOLD_GREEN = "bold green"
|
|
14
|
+
UNICODE_ENCODINGS = {"utf-8", "utf-16", "utf-32", "utf-16-le", "utf-16-be"}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _supports_unicode() -> bool:
|
|
18
|
+
return sys.stdout.encoding.lower() in UNICODE_ENCODINGS
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _format_prefix(
|
|
22
|
+
console_obj: Console,
|
|
23
|
+
emoji: str | None,
|
|
24
|
+
label: str,
|
|
25
|
+
style: str,
|
|
26
|
+
message: str,
|
|
27
|
+
) -> str:
|
|
28
|
+
formatted_label = f"[{label}]" if console_obj.no_color or out.color_system is None else label
|
|
29
|
+
|
|
30
|
+
# Strip emoji/unicode in non-UTF contexts (e.g., Windows CI) to avoid encoding issues
|
|
31
|
+
emoji_str = ""
|
|
32
|
+
if emoji and _supports_unicode():
|
|
33
|
+
emoji_str = emoji + " "
|
|
34
|
+
|
|
35
|
+
return f"[{style}]{emoji_str}{formatted_label}[/{style}] {message}"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def prefix_out(
|
|
39
|
+
message: str,
|
|
40
|
+
emoji: str | None = None,
|
|
41
|
+
label: str = "INFO",
|
|
42
|
+
style: str = "bold blue",
|
|
43
|
+
**kwargs,
|
|
44
|
+
) -> None:
|
|
45
|
+
out.print(_format_prefix(out, emoji=emoji, label=label, style=style, message=message), **kwargs)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def prefix_err(
|
|
49
|
+
message: str,
|
|
50
|
+
emoji: str | None = None,
|
|
51
|
+
label: str = "INFO",
|
|
52
|
+
style: str = "bold blue",
|
|
53
|
+
**kwargs,
|
|
54
|
+
) -> None:
|
|
55
|
+
err.print(_format_prefix(err, emoji=emoji, label=label, style=style, message=message), **kwargs)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def success(message: str, **kwargs) -> None:
|
|
59
|
+
prefix_out(
|
|
60
|
+
emoji=":white_check_mark:",
|
|
61
|
+
label="SUCCESS",
|
|
62
|
+
style=BOLD_GREEN,
|
|
63
|
+
message=message,
|
|
64
|
+
**kwargs,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def start(message: str, **kwargs) -> None:
|
|
69
|
+
prefix_out(emoji=None, label="START", style="cyan", message=f"{message}...", **kwargs)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def echo(message: Any, **kwargs) -> None:
|
|
73
|
+
out.print(message, **kwargs)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def cmd(cmd_str: str, **kwargs) -> None:
|
|
77
|
+
arrow = "❯" if _supports_unicode() else ">" # noqa: RUF001
|
|
78
|
+
err.print(f"[{BOLD_GREEN}]{arrow}[/{BOLD_GREEN}] [default]{cmd_str}[/default]", **kwargs)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def script_block(title: str, script: str, **kwargs) -> None:
|
|
82
|
+
formatter = BashFormatter()
|
|
83
|
+
formatted, error = formatter.beautify_string(script)
|
|
84
|
+
|
|
85
|
+
if error:
|
|
86
|
+
formatted = textwrap.dedent(script)
|
|
87
|
+
|
|
88
|
+
terminal_width: int = err.size.width
|
|
89
|
+
width = min(70, terminal_width)
|
|
90
|
+
bold_line = "━" * width
|
|
91
|
+
thin_line = "─" * width
|
|
92
|
+
|
|
93
|
+
err.print(bold_line, style=BOLD_GREEN)
|
|
94
|
+
err.print(title, style="bold")
|
|
95
|
+
err.print(thin_line, style=BOLD_GREEN)
|
|
96
|
+
err.print(formatted, highlight=False, **kwargs)
|
|
97
|
+
err.print(bold_line, style=BOLD_GREEN)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def warning(message: str, **kwargs) -> None:
|
|
101
|
+
if bake_settings.github_actions:
|
|
102
|
+
err.print(f"::warning::{message}", **kwargs)
|
|
103
|
+
else:
|
|
104
|
+
prefix_err(
|
|
105
|
+
emoji=":warning-emoji: ",
|
|
106
|
+
label="WARNING",
|
|
107
|
+
style="bold yellow",
|
|
108
|
+
message=message,
|
|
109
|
+
**kwargs,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def error(message: str, **kwargs) -> None:
|
|
114
|
+
if bake_settings.github_actions:
|
|
115
|
+
err.print(f"::error::{message}", **kwargs)
|
|
116
|
+
else:
|
|
117
|
+
prefix_err(emoji=":x:", label="ERROR", style="bold red", message=message, **kwargs)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def github_action_add_mask(value: str, **kwargs) -> None:
|
|
121
|
+
if bake_settings.github_actions:
|
|
122
|
+
out.print(f"::add-mask::{value}", **kwargs)
|