bakefile 0.0.5__tar.gz → 0.0.7__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.5 → bakefile-0.0.7}/PKG-INFO +2 -1
- {bakefile-0.0.5 → bakefile-0.0.7}/pyproject.toml +9 -8
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/__init__.py +2 -2
- bakefile-0.0.7/src/bake/cli/bakefile/export.py +212 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/main.py +2 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/app.py +1 -1
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/context.py +33 -33
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/obj.py +3 -1
- bakefile-0.0.7/src/bake/manage/write_bakefile.py +39 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/samples/simple.py +1 -2
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/__init__.py +2 -1
- bakefile-0.0.7/src/bake/ui/params.py +5 -0
- bakefile-0.0.7/src/bake/ui/run/__init__.py +5 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/run/run.py +60 -55
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/run/splitter.py +13 -1
- bakefile-0.0.7/src/bakelib/space/base.py +193 -0
- bakefile-0.0.7/src/bakelib/space/python.py +80 -0
- bakefile-0.0.7/src/bakelib/space/utils.py +118 -0
- bakefile-0.0.5/src/bake/manage/write_bakefile.py +0 -20
- bakefile-0.0.5/src/bake/ui/run/__init__.py +0 -11
- bakefile-0.0.5/src/bakelib/space/base.py +0 -73
- bakefile-0.0.5/src/bakelib/space/python.py +0 -42
- bakefile-0.0.5/src/bakelib/space/utils.py +0 -55
- {bakefile-0.0.5 → bakefile-0.0.7}/README.md +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/bakebook/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/bakebook/bakebook.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/bakebook/decorator.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/bakebook/get.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bake/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bake/__main__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bake/main.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bake/reinvocation.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/__main__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/add_inline.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/find_python.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/init.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/lint.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/bakefile/uv.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/callback.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/exception_handler.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/common/params.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/utils/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/cli/utils/version.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/manage/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/manage/add_inline.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/manage/find_python.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/manage/lint.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/manage/run_uv.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/py.typed +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/samples/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/console.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/logger/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/logger/capsys.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/logger/setup.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/logger/utils.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/run/script.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/run/uv.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/ui/style.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/utils/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/utils/constants.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/utils/env.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bake/utils/exceptions.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/src/bakelib/__init__.py +0 -0
- {bakefile-0.0.5 → bakefile-0.0.7}/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.7
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Author: Wisaroot Lertthaweedech
|
|
6
6
|
Author-email: Wisaroot Lertthaweedech <l.wisaroot@gmail.com>
|
|
@@ -10,6 +10,7 @@ Requires-Dist: loguru>=0.7.3
|
|
|
10
10
|
Requires-Dist: orjson>=3.11.5
|
|
11
11
|
Requires-Dist: pydantic-settings>=2.0.0
|
|
12
12
|
Requires-Dist: pydantic>=2.12.5
|
|
13
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
13
14
|
Requires-Dist: rich>=14.2.0
|
|
14
15
|
Requires-Dist: ruff>=0.14.10
|
|
15
16
|
Requires-Dist: tomli>=2.0.0 ; python_full_version < '3.11'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "bakefile"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.7" # use git tag
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -12,9 +12,9 @@ dependencies = [
|
|
|
12
12
|
"click>=8.3.1",
|
|
13
13
|
"loguru>=0.7.3",
|
|
14
14
|
"orjson>=3.11.5",
|
|
15
|
-
# "pathspec>=1.0.3",
|
|
16
15
|
"pydantic-settings>=2.0.0",
|
|
17
16
|
"pydantic>=2.12.5",
|
|
17
|
+
"pyyaml>=6.0.3",
|
|
18
18
|
"rich>=14.2.0",
|
|
19
19
|
"ruff>=0.14.10",
|
|
20
20
|
"tomli>=2.0.0; python_version < '3.11'",
|
|
@@ -36,9 +36,12 @@ bf = "bake.cli.bakefile:main"
|
|
|
36
36
|
[dependency-groups]
|
|
37
37
|
dev = [
|
|
38
38
|
"deptry>=0.24.0",
|
|
39
|
+
"pandas>=2.3.3",
|
|
39
40
|
"pre-commit>=4.5.1",
|
|
40
41
|
"pytest-cov>=7.0.0",
|
|
41
42
|
"pytest>=9.0.2",
|
|
43
|
+
"python-dotenv>=1.2.1",
|
|
44
|
+
"python_package",
|
|
42
45
|
"toml-sort>=0.24.3"
|
|
43
46
|
]
|
|
44
47
|
|
|
@@ -47,12 +50,7 @@ requires = ["uv_build>=0.9.18,<0.10.0"]
|
|
|
47
50
|
build-backend = "uv_build"
|
|
48
51
|
|
|
49
52
|
[tool.deptry]
|
|
50
|
-
known_first_party = ["bake", "bakelib"]
|
|
51
|
-
|
|
52
|
-
[tool.pytest.ini_options]
|
|
53
|
-
markers = [
|
|
54
|
-
"integration: marks tests as integration tests (slower, full flow tests)"
|
|
55
|
-
]
|
|
53
|
+
known_first_party = ["bake", "bakelib", "python_package"]
|
|
56
54
|
|
|
57
55
|
[tool.ruff]
|
|
58
56
|
line-length = 100
|
|
@@ -77,3 +75,6 @@ select = [
|
|
|
77
75
|
[tool.uv.build-backend]
|
|
78
76
|
module-name = ["bake", "bakelib"]
|
|
79
77
|
module-root = "src"
|
|
78
|
+
|
|
79
|
+
[tool.uv.sources]
|
|
80
|
+
python-package = {path = "examples/python-package", editable = true}
|
|
@@ -2,8 +2,8 @@ from bake.bakebook.bakebook import Bakebook
|
|
|
2
2
|
from bake.bakebook.decorator import command
|
|
3
3
|
from bake.cli.common.context import BakeCommand, Context
|
|
4
4
|
from bake.cli.utils.version import _get_version
|
|
5
|
-
from bake.ui import console
|
|
5
|
+
from bake.ui import console, params
|
|
6
6
|
|
|
7
7
|
__version__ = _get_version()
|
|
8
8
|
|
|
9
|
-
__all__ = ["BakeCommand", "Bakebook", "Context", "__version__", "command", "console"]
|
|
9
|
+
__all__ = ["BakeCommand", "Bakebook", "Context", "__version__", "command", "console", "params"]
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import shlex
|
|
2
|
+
from collections.abc import Callable, Hashable
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated, Any, Literal
|
|
5
|
+
|
|
6
|
+
import orjson
|
|
7
|
+
import typer
|
|
8
|
+
import yaml
|
|
9
|
+
from pydantic_settings import BaseSettings
|
|
10
|
+
|
|
11
|
+
from bake.cli.common.context import Context
|
|
12
|
+
from bake.ui import console
|
|
13
|
+
|
|
14
|
+
ExportFormat = Literal["sh", "dotenv", "json", "yaml"]
|
|
15
|
+
JsonValue = str | float | bool | None | list[Any] | dict[Hashable, Any]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _format_shell_value(value: JsonValue) -> str:
|
|
19
|
+
"""Format a value for shell export.
|
|
20
|
+
|
|
21
|
+
Expects JSON-serializable types (str, int, float, bool, None, list, dict).
|
|
22
|
+
Raises TypeError for unexpected types.
|
|
23
|
+
|
|
24
|
+
SecretStr values are masked for security.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
value : Any
|
|
29
|
+
The value to format for shell export
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
str
|
|
34
|
+
Shell-formatted string ready for export
|
|
35
|
+
|
|
36
|
+
Raises
|
|
37
|
+
------
|
|
38
|
+
TypeError
|
|
39
|
+
If value is not one of the expected types
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
if isinstance(value, (list, dict)):
|
|
43
|
+
# Complex types: JSON string, then shell-quote it
|
|
44
|
+
return shlex.quote(orjson.dumps(value).decode())
|
|
45
|
+
elif isinstance(value, str):
|
|
46
|
+
# Strings: shell-quote directly
|
|
47
|
+
return shlex.quote(value)
|
|
48
|
+
elif value is None:
|
|
49
|
+
# None becomes empty string
|
|
50
|
+
return ""
|
|
51
|
+
elif isinstance(value, bool):
|
|
52
|
+
# Booleans: lowercase true/false for shell compatibility
|
|
53
|
+
return str(value).lower()
|
|
54
|
+
elif isinstance(value, (int, float)):
|
|
55
|
+
# Numbers: convert to string, no quoting needed
|
|
56
|
+
return str(value)
|
|
57
|
+
raise TypeError(
|
|
58
|
+
f"Unexpected type for shell export: {type(value).__name__}. "
|
|
59
|
+
f"Expected one of: str, int, float, bool, None, list, dict"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _format_dotenv_value(value: JsonValue) -> str:
|
|
64
|
+
"""Format a value for dotenv export.
|
|
65
|
+
|
|
66
|
+
Uses smart quote selection to produce valid dotenv format that
|
|
67
|
+
python-dotenv's parser can handle.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
value : JsonValue
|
|
72
|
+
The value to format for dotenv export
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
str
|
|
77
|
+
Dotenv-formatted string ready for export
|
|
78
|
+
|
|
79
|
+
Raises
|
|
80
|
+
------
|
|
81
|
+
TypeError
|
|
82
|
+
If value is not one of the expected types
|
|
83
|
+
"""
|
|
84
|
+
if isinstance(value, (list, dict)):
|
|
85
|
+
# Complex types: JSON string, then wrap in double quotes
|
|
86
|
+
json_str = orjson.dumps(value).decode()
|
|
87
|
+
return '"' + json_str.replace("\\", "\\\\").replace('"', '\\"') + '"'
|
|
88
|
+
elif isinstance(value, str):
|
|
89
|
+
# Strings: use smart quote selection
|
|
90
|
+
if value.isalnum():
|
|
91
|
+
return value
|
|
92
|
+
if "'" in value and '"' not in value:
|
|
93
|
+
# Has single quotes only: use double quotes
|
|
94
|
+
return f'"{value}"'
|
|
95
|
+
if '"' in value and "'" not in value:
|
|
96
|
+
# Has double quotes only: use single quotes
|
|
97
|
+
return f"'{value}'"
|
|
98
|
+
# Has both or special chars: use double quotes with escaping
|
|
99
|
+
return '"' + value.replace("\\", "\\\\").replace('"', '\\"') + '"'
|
|
100
|
+
elif value is None:
|
|
101
|
+
return ""
|
|
102
|
+
elif isinstance(value, bool):
|
|
103
|
+
return str(value).lower()
|
|
104
|
+
elif isinstance(value, (int, float)):
|
|
105
|
+
return str(value)
|
|
106
|
+
raise TypeError(
|
|
107
|
+
f"Unexpected type for dotenv export: {type(value).__name__}. "
|
|
108
|
+
f"Expected one of: str, int, float, bool, None, list, dict"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _format_vars(data: dict, value_formatter: Callable[[JsonValue], str], prefix: str = "") -> str:
|
|
113
|
+
lines: list[str] = []
|
|
114
|
+
for field_name, value in data.items():
|
|
115
|
+
formatted_val = value_formatter(value)
|
|
116
|
+
lines.append(f"{prefix}{field_name.upper()}={formatted_val}")
|
|
117
|
+
return "\n".join(lines)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class ExportFormatter:
|
|
121
|
+
def __call__(self, data: dict[str, Any]) -> str:
|
|
122
|
+
raise NotImplementedError("....")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ShExportFormatter(ExportFormatter):
|
|
126
|
+
def __call__(self, data: dict[str, Any]) -> str:
|
|
127
|
+
return _format_vars(data, value_formatter=_format_shell_value, prefix="export ")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class DotEnvExportFormatter(ExportFormatter):
|
|
131
|
+
def __call__(self, data: dict[str, Any]) -> str:
|
|
132
|
+
return _format_vars(data, value_formatter=_format_dotenv_value, prefix="")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class JsonExportFormatter(ExportFormatter):
|
|
136
|
+
def __call__(self, data: dict[str, Any]) -> str:
|
|
137
|
+
return orjson.dumps(data, option=orjson.OPT_INDENT_2).decode()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class YamlExportFormatter(ExportFormatter):
|
|
141
|
+
def __call__(self, data: dict[str, Any]) -> str:
|
|
142
|
+
return yaml.dump(data, default_flow_style=False, sort_keys=False)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _export(
|
|
146
|
+
bakebook: BaseSettings,
|
|
147
|
+
format: ExportFormat = "sh",
|
|
148
|
+
output: Path | None = None,
|
|
149
|
+
) -> None:
|
|
150
|
+
formatters: dict[str, ExportFormatter] = {
|
|
151
|
+
"sh": ShExportFormatter(),
|
|
152
|
+
"dotenv": DotEnvExportFormatter(),
|
|
153
|
+
"json": JsonExportFormatter(),
|
|
154
|
+
"yaml": YamlExportFormatter(),
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
formatter = formatters.get(format)
|
|
158
|
+
if formatter is None:
|
|
159
|
+
raise ValueError(f"Unknown format: {format}")
|
|
160
|
+
|
|
161
|
+
data: dict[str, Any] = bakebook.model_dump(mode="json")
|
|
162
|
+
content = formatter(data)
|
|
163
|
+
|
|
164
|
+
if output:
|
|
165
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
166
|
+
output.write_text(content, encoding="utf-8")
|
|
167
|
+
elif content != "":
|
|
168
|
+
console.echo(content, overflow="ignore", crop=False)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def export(
|
|
172
|
+
ctx: Context,
|
|
173
|
+
format: Annotated[
|
|
174
|
+
ExportFormat,
|
|
175
|
+
typer.Option(
|
|
176
|
+
"--format",
|
|
177
|
+
"-f",
|
|
178
|
+
help="Output format",
|
|
179
|
+
),
|
|
180
|
+
] = "sh",
|
|
181
|
+
output: Annotated[
|
|
182
|
+
Path | None,
|
|
183
|
+
typer.Option(
|
|
184
|
+
"--output",
|
|
185
|
+
"-o",
|
|
186
|
+
help="Output file path (default: stdout)",
|
|
187
|
+
exists=False,
|
|
188
|
+
),
|
|
189
|
+
] = None,
|
|
190
|
+
) -> None:
|
|
191
|
+
"""Export bakebook args to external formats.
|
|
192
|
+
|
|
193
|
+
Export Pydantic-validated bakebook args to various formats for use
|
|
194
|
+
outside Python runtime (shell scripts, GitHub Actions, .env files, etc.).
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
197
|
+
# Export to shell for eval
|
|
198
|
+
bakefile export --format sh
|
|
199
|
+
|
|
200
|
+
# Export to dotenv file
|
|
201
|
+
bakefile export --format dotenv --output .env
|
|
202
|
+
|
|
203
|
+
# Export to JSON
|
|
204
|
+
bakefile export --format json --output config.json
|
|
205
|
+
"""
|
|
206
|
+
if ctx.obj.bakebook is None:
|
|
207
|
+
ctx.obj.get_bakebook(allow_missing=False)
|
|
208
|
+
|
|
209
|
+
if ctx.obj.bakebook is None:
|
|
210
|
+
raise RuntimeError("Bakebook not found.")
|
|
211
|
+
|
|
212
|
+
_export(bakebook=ctx.obj.bakebook, format=format, output=output)
|
|
@@ -8,6 +8,7 @@ from bake.cli.common.obj import get_bakefile_object
|
|
|
8
8
|
|
|
9
9
|
from . import uv
|
|
10
10
|
from .add_inline import add_inline
|
|
11
|
+
from .export import export
|
|
11
12
|
from .find_python import find_python
|
|
12
13
|
from .init import init
|
|
13
14
|
from .lint import lint
|
|
@@ -33,6 +34,7 @@ def main():
|
|
|
33
34
|
bakefile_app.command()(add_inline)
|
|
34
35
|
bakefile_app.command()(find_python)
|
|
35
36
|
bakefile_app.command()(lint)
|
|
37
|
+
bakefile_app.command()(export)
|
|
36
38
|
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.sync)
|
|
37
39
|
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.lock)
|
|
38
40
|
bakefile_app.command(context_settings=uv_commands_context_settings)(uv.add)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import subprocess
|
|
2
|
+
from collections.abc import Generator
|
|
3
|
+
from contextlib import contextmanager
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
from typing import TYPE_CHECKING, Literal, overload
|
|
4
6
|
|
|
@@ -6,6 +8,7 @@ import click
|
|
|
6
8
|
import typer
|
|
7
9
|
from typer.core import TyperCommand
|
|
8
10
|
|
|
11
|
+
from bake.ui.run import CmdType
|
|
9
12
|
from bake.ui.run import run as _run
|
|
10
13
|
from bake.ui.run.script import run_script as _run_script
|
|
11
14
|
|
|
@@ -22,6 +25,19 @@ class Context(typer.Context):
|
|
|
22
25
|
def dry_run(self) -> bool:
|
|
23
26
|
return self.obj.dry_run
|
|
24
27
|
|
|
28
|
+
@dry_run.setter
|
|
29
|
+
def dry_run(self, value: bool) -> None:
|
|
30
|
+
self.obj.dry_run = value
|
|
31
|
+
|
|
32
|
+
@contextmanager
|
|
33
|
+
def override_dry_run(self, dry_run: bool) -> Generator[None, None, None]:
|
|
34
|
+
original = self.obj.dry_run
|
|
35
|
+
self.obj.dry_run = dry_run
|
|
36
|
+
try:
|
|
37
|
+
yield
|
|
38
|
+
finally:
|
|
39
|
+
self.obj.dry_run = original
|
|
40
|
+
|
|
25
41
|
@property
|
|
26
42
|
def verbosity(self) -> int:
|
|
27
43
|
return self.obj.verbosity
|
|
@@ -33,37 +49,7 @@ class Context(typer.Context):
|
|
|
33
49
|
@overload
|
|
34
50
|
def run(
|
|
35
51
|
self,
|
|
36
|
-
cmd:
|
|
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, ...],
|
|
52
|
+
cmd: CmdType,
|
|
67
53
|
*,
|
|
68
54
|
capture_output: Literal[True] = True,
|
|
69
55
|
check: bool = True,
|
|
@@ -72,13 +58,15 @@ class Context(typer.Context):
|
|
|
72
58
|
shell: bool | None = None,
|
|
73
59
|
echo: bool = True,
|
|
74
60
|
dry_run: bool | None = None,
|
|
61
|
+
keep_temp_file: bool = False,
|
|
62
|
+
env: dict[str, str] | None = None,
|
|
75
63
|
**kwargs,
|
|
76
64
|
) -> subprocess.CompletedProcess[str]: ...
|
|
77
65
|
|
|
78
66
|
@overload
|
|
79
67
|
def run(
|
|
80
68
|
self,
|
|
81
|
-
cmd:
|
|
69
|
+
cmd: CmdType,
|
|
82
70
|
*,
|
|
83
71
|
capture_output: Literal[False],
|
|
84
72
|
check: bool = True,
|
|
@@ -87,12 +75,14 @@ class Context(typer.Context):
|
|
|
87
75
|
shell: bool | None = None,
|
|
88
76
|
echo: bool = True,
|
|
89
77
|
dry_run: bool | None = None,
|
|
78
|
+
keep_temp_file: bool = False,
|
|
79
|
+
env: dict[str, str] | None = None,
|
|
90
80
|
**kwargs,
|
|
91
81
|
) -> subprocess.CompletedProcess[None]: ...
|
|
92
82
|
|
|
93
83
|
def run(
|
|
94
84
|
self,
|
|
95
|
-
cmd:
|
|
85
|
+
cmd: CmdType,
|
|
96
86
|
*,
|
|
97
87
|
capture_output: bool = True,
|
|
98
88
|
check: bool = True,
|
|
@@ -101,6 +91,9 @@ class Context(typer.Context):
|
|
|
101
91
|
shell: bool | None = None,
|
|
102
92
|
echo: bool = True,
|
|
103
93
|
dry_run: bool | None = None,
|
|
94
|
+
keep_temp_file: bool = False,
|
|
95
|
+
env: dict[str, str] | None = None,
|
|
96
|
+
_encoding: str | None = None,
|
|
104
97
|
**kwargs,
|
|
105
98
|
) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[None]:
|
|
106
99
|
return _run(
|
|
@@ -112,6 +105,9 @@ class Context(typer.Context):
|
|
|
112
105
|
shell=shell,
|
|
113
106
|
echo=echo,
|
|
114
107
|
dry_run=self.obj.dry_run if dry_run is None else dry_run,
|
|
108
|
+
keep_temp_file=keep_temp_file,
|
|
109
|
+
env=env,
|
|
110
|
+
_encoding=_encoding,
|
|
115
111
|
**kwargs,
|
|
116
112
|
)
|
|
117
113
|
|
|
@@ -126,6 +122,8 @@ class Context(typer.Context):
|
|
|
126
122
|
stream: bool = True,
|
|
127
123
|
echo: bool = True,
|
|
128
124
|
dry_run: bool | None = None,
|
|
125
|
+
keep_temp_file: bool = False,
|
|
126
|
+
env: dict[str, str] | None = None,
|
|
129
127
|
**kwargs,
|
|
130
128
|
) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[None]:
|
|
131
129
|
return _run_script(
|
|
@@ -137,6 +135,8 @@ class Context(typer.Context):
|
|
|
137
135
|
stream=stream,
|
|
138
136
|
echo=echo,
|
|
139
137
|
dry_run=self.obj.dry_run if dry_run is None else dry_run,
|
|
138
|
+
keep_temp_file=keep_temp_file,
|
|
139
|
+
env=env,
|
|
140
140
|
**kwargs,
|
|
141
141
|
)
|
|
142
142
|
|
|
@@ -81,9 +81,11 @@ class BakefileObject:
|
|
|
81
81
|
self.bakebook = get_bakebook_from_target_dir_path(
|
|
82
82
|
target_dir_path=self.bakefile_path, bakebook_name=self.bakebook_name
|
|
83
83
|
)
|
|
84
|
-
except BakefileNotFoundError:
|
|
84
|
+
except BakefileNotFoundError as e:
|
|
85
85
|
if allow_missing:
|
|
86
86
|
return
|
|
87
|
+
console.error(str(e))
|
|
88
|
+
raise SystemExit(1) from e
|
|
87
89
|
except BakebookError as e:
|
|
88
90
|
if allow_missing:
|
|
89
91
|
return
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import types
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from bake.samples import simple
|
|
5
|
+
from bake.utils.constants import BAKEBOOK_NAME_IN_SAMPLES
|
|
6
|
+
|
|
7
|
+
# Allowed sample modules
|
|
8
|
+
# This dictionary acts as a whitelist for security - only these modules can be used
|
|
9
|
+
ALLOWED_SAMPLE_MODULES: dict[str, types.ModuleType] = {
|
|
10
|
+
simple.__name__: simple,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def write_bakefile(
|
|
15
|
+
bakefile_path: Path, bakebook_name: str, sample_module: types.ModuleType
|
|
16
|
+
) -> None:
|
|
17
|
+
if not hasattr(sample_module, BAKEBOOK_NAME_IN_SAMPLES):
|
|
18
|
+
raise ValueError(
|
|
19
|
+
f"Module `{sample_module.__name__}` must have `{BAKEBOOK_NAME_IN_SAMPLES}` attribute"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
module_name = sample_module.__name__
|
|
23
|
+
if module_name not in ALLOWED_SAMPLE_MODULES:
|
|
24
|
+
raise ValueError(
|
|
25
|
+
f"Module `{module_name}` is not in the allowed sample modules list. "
|
|
26
|
+
f"Allowed modules: {list(ALLOWED_SAMPLE_MODULES.keys())}"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
allowed_module = ALLOWED_SAMPLE_MODULES[module_name]
|
|
30
|
+
if sample_module is not allowed_module:
|
|
31
|
+
raise ValueError(f"Module `{module_name}` does not match the allowed module object")
|
|
32
|
+
|
|
33
|
+
if allowed_module.__file__ is None:
|
|
34
|
+
raise ValueError(f"Could not find file for module `{module_name}`")
|
|
35
|
+
|
|
36
|
+
source_file_path = Path(allowed_module.__file__)
|
|
37
|
+
original_bakefile_content = source_file_path.read_text()
|
|
38
|
+
customized_content = original_bakefile_content.replace(BAKEBOOK_NAME_IN_SAMPLES, bakebook_name)
|
|
39
|
+
bakefile_path.write_text(customized_content)
|