bakefile 0.0.4__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
- {bakefile → bake/utils}/env.py +3 -1
- bake/utils/exceptions.py +17 -0
- {bakefile-0.0.4.dist-info → bakefile-0.0.5.dist-info}/METADATA +14 -2
- bakefile-0.0.5.dist-info/RECORD +61 -0
- {bakefile-0.0.4.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/__init__.py +0 -13
- bakefile/cli/bake/__init__.py +0 -3
- bakefile/cli/bake/main.py +0 -127
- bakefile/cli/bake/resolve_bakebook.py +0 -103
- bakefile/cli/bake/utils.py +0 -25
- bakefile/cli/bakefile.py +0 -19
- bakefile/cli/utils/version.py +0 -9
- bakefile/exceptions.py +0 -9
- bakefile-0.0.4.dist-info/RECORD +0 -16
- bakefile-0.0.4.dist-info/entry_points.txt +0 -4
- {bakefile/cli/utils → bake/bakebook}/__init__.py +0 -0
- {bakefile → bake}/cli/__init__.py +0 -0
- /bakefile/py.typed → /bake/cli/common/__init__.py +0 -0
bake/ui/run/splitter.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import select
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import threading
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
# No PTY locks needed - each thread reads from its own PTY fd independently
|
|
9
|
+
# Locks were causing race conditions where threads waited while their process exited
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class OutputSplitter:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
stream: bool = True,
|
|
16
|
+
capture: bool = True,
|
|
17
|
+
pty_fd: int | None = None,
|
|
18
|
+
encoding: str | None = None,
|
|
19
|
+
):
|
|
20
|
+
self._stream = stream
|
|
21
|
+
self._capture = capture
|
|
22
|
+
self._pty_fd = pty_fd
|
|
23
|
+
self._encoding = encoding
|
|
24
|
+
self._stdout_data = b""
|
|
25
|
+
self._stderr_data = b""
|
|
26
|
+
|
|
27
|
+
def _read_stream(self, stream, target, output_list):
|
|
28
|
+
for line in iter(stream.readline, b""):
|
|
29
|
+
if self._stream:
|
|
30
|
+
target.buffer.write(line)
|
|
31
|
+
target.buffer.flush()
|
|
32
|
+
if self._capture:
|
|
33
|
+
output_list.append(line)
|
|
34
|
+
stream.close()
|
|
35
|
+
|
|
36
|
+
def _handle_data(self, data: bytes, target, output_list) -> bool:
|
|
37
|
+
"""Handle data chunk: return False if data is empty (EOF)."""
|
|
38
|
+
if not data:
|
|
39
|
+
return False
|
|
40
|
+
if self._stream:
|
|
41
|
+
target.buffer.write(data)
|
|
42
|
+
target.buffer.flush()
|
|
43
|
+
if self._capture:
|
|
44
|
+
output_list.append(data)
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
def _read_pty(self, pty_fd: int, target, output_list, proc: subprocess.Popen):
|
|
48
|
+
"""Read from PTY file descriptor in chunks and stream to output."""
|
|
49
|
+
import fcntl
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
while True:
|
|
53
|
+
# Try immediate non-blocking read first (catches fast-exiting processes)
|
|
54
|
+
try:
|
|
55
|
+
# Set non-blocking mode
|
|
56
|
+
flags = fcntl.fcntl(pty_fd, fcntl.F_GETFL)
|
|
57
|
+
fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
58
|
+
|
|
59
|
+
data = os.read(pty_fd, 4096)
|
|
60
|
+
if not self._handle_data(data, target, output_list):
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
# Restore blocking mode
|
|
64
|
+
fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags)
|
|
65
|
+
except BlockingIOError:
|
|
66
|
+
# No data available yet, restore blocking mode and wait with select
|
|
67
|
+
fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags)
|
|
68
|
+
|
|
69
|
+
# Wait for data to be available
|
|
70
|
+
ready, _, _ = select.select([pty_fd], [], [], 0.1)
|
|
71
|
+
|
|
72
|
+
if ready:
|
|
73
|
+
data = os.read(pty_fd, 4096)
|
|
74
|
+
if not self._handle_data(data, target, output_list):
|
|
75
|
+
break
|
|
76
|
+
|
|
77
|
+
# Check if process exited after reading data
|
|
78
|
+
if proc.poll() is not None:
|
|
79
|
+
self._drain_pty(pty_fd, target, output_list)
|
|
80
|
+
break
|
|
81
|
+
finally:
|
|
82
|
+
os.close(pty_fd)
|
|
83
|
+
|
|
84
|
+
def _read_pty_data(self, pty_fd: int, target, output_list) -> bool:
|
|
85
|
+
"""Read and handle available PTY data. Returns False on EOF/error."""
|
|
86
|
+
try:
|
|
87
|
+
data = os.read(pty_fd, 4096)
|
|
88
|
+
return self._handle_data(data, target, output_list)
|
|
89
|
+
except OSError:
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
def _try_select_read(self, pty_fd: int, timeout: float) -> tuple[bool, bool]:
|
|
93
|
+
"""Try to read using select.select().
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
(success, has_data): success if select worked, has_data if ready
|
|
97
|
+
"""
|
|
98
|
+
try:
|
|
99
|
+
ready, _, _ = select.select([pty_fd], [], [], timeout)
|
|
100
|
+
return True, bool(ready)
|
|
101
|
+
except OSError:
|
|
102
|
+
# On Windows, select.select() raises OSError for non-socket file descriptors
|
|
103
|
+
return False, False
|
|
104
|
+
|
|
105
|
+
def _read_and_handle(self, pty_fd: int, target, output_list) -> bool:
|
|
106
|
+
"""Read from PTY and handle data.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
True if data was handled, False if EOF/error
|
|
110
|
+
"""
|
|
111
|
+
try:
|
|
112
|
+
data = os.read(pty_fd, 4096)
|
|
113
|
+
return self._handle_data(data, target, output_list)
|
|
114
|
+
except OSError:
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
def _handle_data_ready(self, pty_fd: int, target, output_list) -> bool:
|
|
118
|
+
"""Handle data ready from select.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
True if should continue draining, False if done
|
|
122
|
+
"""
|
|
123
|
+
return self._read_and_handle(pty_fd, target, output_list)
|
|
124
|
+
|
|
125
|
+
def _handle_timeout(
|
|
126
|
+
self,
|
|
127
|
+
pty_fd: int,
|
|
128
|
+
target,
|
|
129
|
+
output_list,
|
|
130
|
+
select_works: bool,
|
|
131
|
+
consecutive_timeouts: int,
|
|
132
|
+
) -> tuple[bool, int]:
|
|
133
|
+
"""Handle timeout when no data ready.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
(should_continue, new_timeout_count)
|
|
137
|
+
"""
|
|
138
|
+
# Try direct read after 2 consecutive timeouts or if select doesn't work
|
|
139
|
+
if not select_works or consecutive_timeouts >= 2:
|
|
140
|
+
if not self._read_and_handle(pty_fd, target, output_list):
|
|
141
|
+
return False, 0
|
|
142
|
+
return True, 0 # Got data, reset timeout counter
|
|
143
|
+
return True, consecutive_timeouts + 1
|
|
144
|
+
|
|
145
|
+
def _drain_pty(self, pty_fd: int, target, output_list):
|
|
146
|
+
"""Drain remaining data from PTY after process exits.
|
|
147
|
+
|
|
148
|
+
We need to handle OS timing: proc.poll() may return exit code before the
|
|
149
|
+
PTY buffer is fully flushed. We use select to wait for data with increasing
|
|
150
|
+
timeouts, and also try direct reads as a fallback in case select doesn't
|
|
151
|
+
detect readiness (e.g., in tests with mocked os.read or on Windows with
|
|
152
|
+
non-socket file descriptors).
|
|
153
|
+
"""
|
|
154
|
+
time.sleep(0.005)
|
|
155
|
+
|
|
156
|
+
timeout = 0.05
|
|
157
|
+
consecutive_timeouts = 0
|
|
158
|
+
max_timeouts = 4
|
|
159
|
+
select_works = True
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
while consecutive_timeouts < max_timeouts:
|
|
163
|
+
# Check if data is ready via select
|
|
164
|
+
if select_works:
|
|
165
|
+
select_works, ready = self._try_select_read(pty_fd, timeout)
|
|
166
|
+
else:
|
|
167
|
+
ready = False
|
|
168
|
+
|
|
169
|
+
if ready:
|
|
170
|
+
# Data ready - read and handle
|
|
171
|
+
if not self._handle_data_ready(pty_fd, target, output_list):
|
|
172
|
+
return
|
|
173
|
+
consecutive_timeouts = 0
|
|
174
|
+
timeout = 0.02
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
# No data ready - increment timeout and try direct read
|
|
178
|
+
timeout = min(timeout * 1.5, 0.2)
|
|
179
|
+
|
|
180
|
+
should_continue, consecutive_timeouts = self._handle_timeout(
|
|
181
|
+
pty_fd, target, output_list, select_works, consecutive_timeouts
|
|
182
|
+
)
|
|
183
|
+
if not should_continue:
|
|
184
|
+
return
|
|
185
|
+
except OSError:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
def attach(self, proc: subprocess.Popen):
|
|
189
|
+
threads = []
|
|
190
|
+
|
|
191
|
+
# Handle PTY stdout (for color-preserving output on Unix)
|
|
192
|
+
if self._pty_fd is not None:
|
|
193
|
+
stdout_list = []
|
|
194
|
+
t = threading.Thread(
|
|
195
|
+
target=self._read_pty, args=(self._pty_fd, sys.stdout, stdout_list, proc)
|
|
196
|
+
)
|
|
197
|
+
t.daemon = True
|
|
198
|
+
t.start()
|
|
199
|
+
threads.append((t, stdout_list, "stdout"))
|
|
200
|
+
|
|
201
|
+
# Handle regular stdout
|
|
202
|
+
elif proc.stdout:
|
|
203
|
+
stdout_list = []
|
|
204
|
+
t = threading.Thread(
|
|
205
|
+
target=self._read_stream, args=(proc.stdout, sys.stdout, stdout_list)
|
|
206
|
+
)
|
|
207
|
+
t.daemon = True
|
|
208
|
+
t.start()
|
|
209
|
+
threads.append((t, stdout_list, "stdout"))
|
|
210
|
+
|
|
211
|
+
# Handle stderr (regular pipe)
|
|
212
|
+
if proc.stderr:
|
|
213
|
+
stderr_list = []
|
|
214
|
+
t = threading.Thread(
|
|
215
|
+
target=self._read_stream, args=(proc.stderr, sys.stderr, stderr_list)
|
|
216
|
+
)
|
|
217
|
+
t.daemon = True
|
|
218
|
+
t.start()
|
|
219
|
+
threads.append((t, stderr_list, "stderr"))
|
|
220
|
+
|
|
221
|
+
return threads
|
|
222
|
+
|
|
223
|
+
def finalize(self, threads):
|
|
224
|
+
for t, data_list, name in threads:
|
|
225
|
+
t.join()
|
|
226
|
+
if name == "stdout":
|
|
227
|
+
self._stdout_data = b"".join(data_list)
|
|
228
|
+
else:
|
|
229
|
+
self._stderr_data = b"".join(data_list)
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def stdout(self) -> bytes:
|
|
233
|
+
return self._stdout_data
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def stderr(self) -> bytes:
|
|
237
|
+
return self._stderr_data
|
bake/ui/run/uv.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Literal, overload
|
|
4
|
+
|
|
5
|
+
from uv import find_uv_bin
|
|
6
|
+
|
|
7
|
+
from bake.ui import console
|
|
8
|
+
from bake.ui.run.run import run
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@overload
|
|
12
|
+
def run_uv(
|
|
13
|
+
cmd: list[str] | tuple[str, ...],
|
|
14
|
+
*,
|
|
15
|
+
capture_output: Literal[True] = True,
|
|
16
|
+
check: bool = True,
|
|
17
|
+
cwd: Path | str | None = None,
|
|
18
|
+
stream: bool = False,
|
|
19
|
+
shell: bool | None = None,
|
|
20
|
+
echo: bool = True,
|
|
21
|
+
dry_run: bool = False,
|
|
22
|
+
keep_temp_file: bool = False,
|
|
23
|
+
env: dict[str, str] | None = None,
|
|
24
|
+
_encoding: str | None = None,
|
|
25
|
+
**kwargs,
|
|
26
|
+
) -> subprocess.CompletedProcess[str]: ...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@overload
|
|
30
|
+
def run_uv(
|
|
31
|
+
cmd: list[str] | tuple[str, ...],
|
|
32
|
+
*,
|
|
33
|
+
capture_output: Literal[False],
|
|
34
|
+
check: bool = True,
|
|
35
|
+
cwd: Path | str | None = None,
|
|
36
|
+
stream: bool = False,
|
|
37
|
+
echo: bool = True,
|
|
38
|
+
dry_run: bool = False,
|
|
39
|
+
keep_temp_file: bool = False,
|
|
40
|
+
env: dict[str, str] | None = None,
|
|
41
|
+
_encoding: str | None = None,
|
|
42
|
+
**kwargs,
|
|
43
|
+
) -> subprocess.CompletedProcess[None]: ...
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def run_uv(
|
|
47
|
+
cmd: list[str] | tuple[str, ...],
|
|
48
|
+
*,
|
|
49
|
+
capture_output: bool = True,
|
|
50
|
+
check: bool = True,
|
|
51
|
+
cwd: Path | str | None = None,
|
|
52
|
+
stream: bool = False,
|
|
53
|
+
echo: bool = True,
|
|
54
|
+
dry_run: bool = False,
|
|
55
|
+
keep_temp_file: bool = False,
|
|
56
|
+
env: dict[str, str] | None = None,
|
|
57
|
+
_encoding: str | None = None,
|
|
58
|
+
**kwargs,
|
|
59
|
+
) -> subprocess.CompletedProcess[str] | subprocess.CompletedProcess[None]:
|
|
60
|
+
uv_bin = find_uv_bin()
|
|
61
|
+
|
|
62
|
+
# Build display string: "uv" + command parts (no full binary path)
|
|
63
|
+
display_cmd = "uv " + " ".join(cmd)
|
|
64
|
+
|
|
65
|
+
# Echo command to console if requested
|
|
66
|
+
if echo:
|
|
67
|
+
console.cmd(display_cmd)
|
|
68
|
+
|
|
69
|
+
# Call run with full uv binary path, echo=False (already displayed), pass through options
|
|
70
|
+
return run(
|
|
71
|
+
[uv_bin, *cmd],
|
|
72
|
+
capture_output=capture_output,
|
|
73
|
+
check=check,
|
|
74
|
+
cwd=cwd,
|
|
75
|
+
stream=stream,
|
|
76
|
+
shell=False,
|
|
77
|
+
echo=False,
|
|
78
|
+
dry_run=dry_run,
|
|
79
|
+
keep_temp_file=keep_temp_file,
|
|
80
|
+
env=env,
|
|
81
|
+
_encoding=_encoding,
|
|
82
|
+
**kwargs,
|
|
83
|
+
)
|
bake/ui/style.py
ADDED
bake/utils/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from bake.utils.constants import DEFAULT_BAKEBOOK_NAME, DEFAULT_FILE_NAME
|
|
2
|
+
from bake.utils.env import should_use_colors
|
|
3
|
+
from bake.utils.exceptions import BakebookError, BaseBakefileError
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"DEFAULT_BAKEBOOK_NAME",
|
|
7
|
+
"DEFAULT_FILE_NAME",
|
|
8
|
+
"BakebookError",
|
|
9
|
+
"BaseBakefileError",
|
|
10
|
+
"should_use_colors",
|
|
11
|
+
]
|
bake/utils/constants.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
# Default value
|
|
4
|
+
DEFAULT_CHDIR = Path(".")
|
|
5
|
+
DEFAULT_FILE_NAME = "bakefile.py"
|
|
6
|
+
DEFAULT_BAKEBOOK_NAME = "bakebook"
|
|
7
|
+
DEFAULT_IS_CHAIN_COMMAND = False
|
|
8
|
+
|
|
9
|
+
# CLI command names
|
|
10
|
+
CMD_BAKE = "bake"
|
|
11
|
+
CMD_BAKEFILE = "bakefile"
|
|
12
|
+
CMD_INIT = "init"
|
|
13
|
+
CMD_ADD_INLINE = "add-inline"
|
|
14
|
+
CMD_LINT = "lint"
|
|
15
|
+
|
|
16
|
+
# Bakefile app command name
|
|
17
|
+
GET_BAKEFILE_OBJECT = "get_bakefile_object"
|
|
18
|
+
|
|
19
|
+
# Others
|
|
20
|
+
BAKEBOOK_NAME_IN_SAMPLES = "__bakebook__"
|
|
21
|
+
BAKE_COMMAND_KWARGS = "_bake_command_kwargs"
|
{bakefile → bake/utils}/env.py
RENAMED
bake/utils/exceptions.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Custom exceptions for bakefile."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BaseBakefileError(Exception):
|
|
5
|
+
"""Base exception for all bakefile errors."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BakebookError(BaseBakefileError):
|
|
9
|
+
"""Exception raised when bakebook cannot be loaded or validated (unexpected error)."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BakefileNotFoundError(BakebookError):
|
|
13
|
+
"""Exception raised when bakefile.py is not found (expected/suppressable error)."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PythonNotFoundError(BaseBakefileError):
|
|
17
|
+
"""Exception raised when Python executable cannot be found or created."""
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: bakefile
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Author: Wisaroot Lertthaweedech
|
|
6
6
|
Author-email: Wisaroot Lertthaweedech <l.wisaroot@gmail.com>
|
|
7
|
+
Requires-Dist: beautysh>=6.4.2
|
|
8
|
+
Requires-Dist: click>=8.3.1
|
|
9
|
+
Requires-Dist: loguru>=0.7.3
|
|
10
|
+
Requires-Dist: orjson>=3.11.5
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
7
12
|
Requires-Dist: pydantic>=2.12.5
|
|
8
|
-
Requires-Dist:
|
|
13
|
+
Requires-Dist: rich>=14.2.0
|
|
14
|
+
Requires-Dist: ruff>=0.14.10
|
|
15
|
+
Requires-Dist: tomli>=2.0.0 ; python_full_version < '3.11'
|
|
16
|
+
Requires-Dist: ty>=0.0.8
|
|
17
|
+
Requires-Dist: typer>=0.21.0
|
|
18
|
+
Requires-Dist: uv>=0.9.20
|
|
19
|
+
Requires-Dist: pathspec>=1.0.3 ; extra == 'lib'
|
|
9
20
|
Requires-Python: >=3.10
|
|
21
|
+
Provides-Extra: lib
|
|
10
22
|
Description-Content-Type: text/markdown
|
|
11
23
|
|
|
12
24
|
[](https://github.com/wislertt/bakefile/actions/workflows/cd.yml)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
bake/__init__.py,sha256=SG-g8MVoBbXURlAP-OhtjMUMnRPTfi9lQ9WQD0EX7IE,338
|
|
2
|
+
bake/bakebook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
bake/bakebook/bakebook.py,sha256=o1sp8Wewxdqr7k12qT-Q4ZrKQ7c7jDliiNCYrVG93NA,2939
|
|
4
|
+
bake/bakebook/decorator.py,sha256=t2I6Pf1vdTk7k8lTzZCqq71-hzcXFvFYbuFV_Wvg45Q,1545
|
|
5
|
+
bake/bakebook/get.py,sha256=fx5WV66OIBrywPN0thePXAJk2gt7wvTVAxYQqZ_PMao,5807
|
|
6
|
+
bake/cli/__init__.py,sha256=da1PTClDMl-IBkrSvq6JC1lnS-K_BASzCvxVhNxN5Ls,13
|
|
7
|
+
bake/cli/bake/__init__.py,sha256=CJokSP1t1KXaIqjkjFQ8_gbaSZ9RRB4YdemIoSTqRcI,56
|
|
8
|
+
bake/cli/bake/__main__.py,sha256=5Ui5_OD1-oG1ou6boak63EPQDmRsW9sGOVVDgXJaNec,133
|
|
9
|
+
bake/cli/bake/main.py,sha256=Lr6eyfaf4-zDRrF0GK9bjjFWop66ydewV5tNUluDd9M,2262
|
|
10
|
+
bake/cli/bake/reinvocation.py,sha256=Ifqc8ZAM7NMyrKU2jkmw1agCEI-Sx7yvLLBiFRi23_0,1985
|
|
11
|
+
bake/cli/bakefile/__init__.py,sha256=_zD3rXQHLr6EWHADdPLAmnc2A5C3dhmBuvP5uJ-_A58,60
|
|
12
|
+
bake/cli/bakefile/__main__.py,sha256=FVntzkZdzdygSWjMzyneXCXsM-MDTPmC3GUk4JZiYFU,137
|
|
13
|
+
bake/cli/bakefile/add_inline.py,sha256=V98T50SLMPqnWVtyEO_6hL17r4n3ZtkSC8NSEqdyHzc,919
|
|
14
|
+
bake/cli/bakefile/find_python.py,sha256=J2HDs_nfNODqCHBZCNM64ESB4kVZK-C04i-KNmVUoSs,539
|
|
15
|
+
bake/cli/bakefile/init.py,sha256=0QuvADFOZZUBN2BUJfK90aEY1oUzoSNVRiljlUSjLu0,1825
|
|
16
|
+
bake/cli/bakefile/lint.py,sha256=DJkIJNBOef6JvgwQ3iL9jTrLqgUyn66Mhv6cuAgqXk0,2509
|
|
17
|
+
bake/cli/bakefile/main.py,sha256=5O08RTx8tKHTMio8-RdEsLC6bUD7AKQ6rPNLBZqQiJ0,1352
|
|
18
|
+
bake/cli/bakefile/uv.py,sha256=PMFG3BdofzGWkor4fMEi3GE4G7hGtclCgPm2xlaPDso,4013
|
|
19
|
+
bake/cli/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
bake/cli/common/app.py,sha256=ViRqRX2DsLoKAunGKd6vOiwk4Xqmug1Gkux4_1RZX_U,1444
|
|
21
|
+
bake/cli/common/callback.py,sha256=NmrZUl5eRr95nluomTwcKjTU7dSKjWcQVli5VEdZk-4,439
|
|
22
|
+
bake/cli/common/context.py,sha256=p3_YCExH4NIIgB4ZTax2fYFOjI__Ig4FffbqegtPE8Q,3699
|
|
23
|
+
bake/cli/common/exception_handler.py,sha256=2vLbqMeZlLxKqNWUkTs3cA-8l6IjK0dU3SyZlRb96YI,1759
|
|
24
|
+
bake/cli/common/obj.py,sha256=O23DCxdoAV7Pujxk_ylrSKHL-7DSS1-7BZuxpa0Hv5M,7016
|
|
25
|
+
bake/cli/common/params.py,sha256=rhLa34SY92nXfUaKo0SQMKK__xRnrmHejHa25tRyKdg,2002
|
|
26
|
+
bake/cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
bake/cli/utils/version.py,sha256=aiweLD0vDezBlJAcCC99oMms71WGD9CWSJuZ4i3VLHA,390
|
|
28
|
+
bake/manage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
+
bake/manage/add_inline.py,sha256=yefHmF33ghCB8NZ-v61ybeVsaeE8iDFvfRGeTAKg4I8,2245
|
|
30
|
+
bake/manage/find_python.py,sha256=oVmd8KaSsgDQWHuGZpYiQx-DHn50P9EkRi6-YIad99E,7165
|
|
31
|
+
bake/manage/lint.py,sha256=OqwYFF8GGvzHGVPuJcWMRAv5esXEIX4nQXdGcChnkqA,2394
|
|
32
|
+
bake/manage/run_uv.py,sha256=QzlKeVpr20dXNDcwUgyJqnXT4MofRqK-6XkWpzBbUhE,3234
|
|
33
|
+
bake/manage/write_bakefile.py,sha256=efGViLk7sh-QX9Mox7yQw_A1Tp7EOuc_vmSTbFmXUm0,736
|
|
34
|
+
bake/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
bake/samples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
+
bake/samples/simple.py,sha256=tTL2OVqQXMYwIlgd1K5gtUKDzxx2CDEb24JLzXkadYg,192
|
|
37
|
+
bake/ui/__init__.py,sha256=DeuVKFwrmhEcwcZnstItPecnvYugpLcPM_a7YEhnqD8,187
|
|
38
|
+
bake/ui/console.py,sha256=C5wrbsOc-wwcx0hGmCozHvGCNTWgGhsh-5vxl880xS4,1689
|
|
39
|
+
bake/ui/logger/__init__.py,sha256=bup2cssTHhergh47s6uYbGtY2dJNxlKKH6otBc4ECFM,728
|
|
40
|
+
bake/ui/logger/capsys.py,sha256=KZL6k7Werp_8styfJKfIvQyv0-gJq54vY3hSJFIacEM,5267
|
|
41
|
+
bake/ui/logger/setup.py,sha256=OrX9UiY0iBGfWWfhMJCdfqCRJsL5yC3rIdIEOn7rveo,1377
|
|
42
|
+
bake/ui/logger/utils.py,sha256=dcppxoS_pX92AFcHIerJGI2_JBHBNghRQmQqlZmmj2Q,7218
|
|
43
|
+
bake/ui/run/__init__.py,sha256=RLQN4f6mY2wyWtqe2e9B1jKwR5P9IyBcZGLdOwj91Ds,336
|
|
44
|
+
bake/ui/run/run.py,sha256=5ve7qbl37hRTpbLFf-wDtmG3RuVKYPlSUOsRlSZ9nUU,17390
|
|
45
|
+
bake/ui/run/script.py,sha256=fk7KiDklYDYpFGkH3wu-hZGI4OnvgcB8z5jtNt41Hg0,2263
|
|
46
|
+
bake/ui/run/splitter.py,sha256=92h4KaomqoYsxi9xZoLoSvk-7JdBF0YL-QNPpVaXqEA,8139
|
|
47
|
+
bake/ui/run/uv.py,sha256=3NpnjgAwQNijJiUT_H6U-3mTHQgBZPlJbNWEeYCZY1g,2077
|
|
48
|
+
bake/ui/style.py,sha256=v9dferzV317Acb0GHpVK_niCj_s2HtL-yiToBZtXky4,70
|
|
49
|
+
bake/utils/__init__.py,sha256=GUu_xlJy3RAHo6UcZXu2x4khxGqLHMA9Zos4hDiQIY8,326
|
|
50
|
+
bake/utils/constants.py,sha256=mRq5IpgOTdlHOTWPq5dx0A-LwhiFkWgYHfr8cLWG7rY,471
|
|
51
|
+
bake/utils/env.py,sha256=bzNdH_2bTJebQaw7D0uVJv-vzZ-uYl0pCAS8oQONVsA,190
|
|
52
|
+
bake/utils/exceptions.py,sha256=pwsQnKH5ljMNxmqEREutXa7TohiBHATHg_D5kQUPT30,519
|
|
53
|
+
bakelib/__init__.py,sha256=sZeRiNINWL8xI3b1MxkGyF3f2lKMjyhjKt7qyCCAufs,126
|
|
54
|
+
bakelib/space/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
+
bakelib/space/base.py,sha256=HzJYzwbeX5YN6Esmxt4fSDRGJNUk4OfZ3Zf9m0bNsX4,2103
|
|
56
|
+
bakelib/space/python.py,sha256=rlEJW5y1q00lGMHwYXicwTt1a4NUXfSei-T_pg88oMA,1223
|
|
57
|
+
bakelib/space/utils.py,sha256=SfNRFeAm35zfF01-fdxKXTlw2uL6DyU0TJXDFkUG7Zk,1471
|
|
58
|
+
bakefile-0.0.5.dist-info/WHEEL,sha256=XjEbIc5-wIORjWaafhI6vBtlxDBp7S9KiujWF1EM7Ak,79
|
|
59
|
+
bakefile-0.0.5.dist-info/entry_points.txt,sha256=Ecvvh7BYHCPJ0UdntrDc3Od6AZdRPXN5Z7o_7ok_0Qw,107
|
|
60
|
+
bakefile-0.0.5.dist-info/METADATA,sha256=vBmhYvnlTTuO2x4IpgNudcEBITAy23VZGvmYahT99kY,2302
|
|
61
|
+
bakefile-0.0.5.dist-info/RECORD,,
|
bakelib/__init__.py
ADDED
|
File without changes
|
bakelib/space/base.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from bake import Bakebook, Context, command
|
|
6
|
+
from bake.ui import console
|
|
7
|
+
|
|
8
|
+
from .utils import remove_git_clean_candidates
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BaseSpace(Bakebook):
|
|
12
|
+
@command(help="Run linters and formatters")
|
|
13
|
+
def lint(self, ctx: Context) -> None:
|
|
14
|
+
ctx.run(
|
|
15
|
+
[
|
|
16
|
+
"bunx",
|
|
17
|
+
"prettier@latest",
|
|
18
|
+
"--write",
|
|
19
|
+
"**/*.{js,jsx,ts,tsx,css,json,json5,yaml,yml,md}",
|
|
20
|
+
]
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
@command(help="Run unit tests")
|
|
24
|
+
def test(self, ctx: Context) -> None:
|
|
25
|
+
_ = ctx
|
|
26
|
+
console.error("No implementation")
|
|
27
|
+
raise typer.Exit(1)
|
|
28
|
+
|
|
29
|
+
@command(help="Clean gitignored files with optional exclusions")
|
|
30
|
+
def clean(
|
|
31
|
+
self,
|
|
32
|
+
ctx: Context,
|
|
33
|
+
exclude_patterns: Annotated[
|
|
34
|
+
list[str] | None,
|
|
35
|
+
typer.Option(
|
|
36
|
+
"--exclude-patterns",
|
|
37
|
+
"-e",
|
|
38
|
+
help="Patterns to exclude",
|
|
39
|
+
),
|
|
40
|
+
] = None,
|
|
41
|
+
use_default_excludes: Annotated[
|
|
42
|
+
bool,
|
|
43
|
+
typer.Option(
|
|
44
|
+
"--no-default-excludes",
|
|
45
|
+
help="Do not apply default exclude patterns",
|
|
46
|
+
is_flag=True,
|
|
47
|
+
),
|
|
48
|
+
] = False,
|
|
49
|
+
) -> None:
|
|
50
|
+
results = ctx.run("git clean -fdX -n", stream=False, dry_run=False, echo=True)
|
|
51
|
+
|
|
52
|
+
exclude_patterns: set[str] = set(exclude_patterns if exclude_patterns else [])
|
|
53
|
+
|
|
54
|
+
if not use_default_excludes:
|
|
55
|
+
exclude_patterns |= {".env", ".cache"}
|
|
56
|
+
|
|
57
|
+
console.err.print(f"Exclude pattens: {exclude_patterns}")
|
|
58
|
+
|
|
59
|
+
remove_git_clean_candidates(
|
|
60
|
+
git_clean_dry_run_output=results.stdout,
|
|
61
|
+
exclude_patterns=exclude_patterns,
|
|
62
|
+
dry_run=ctx.dry_run,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@command(help="Clean all gitignored files")
|
|
66
|
+
def clean_all(self, ctx: Context) -> None:
|
|
67
|
+
ctx.run("git clean -fdX")
|
|
68
|
+
|
|
69
|
+
@command(help="Setup development environment")
|
|
70
|
+
def setup_dev(self, ctx: Context) -> None:
|
|
71
|
+
_ = ctx
|
|
72
|
+
console.error("No implementation")
|
|
73
|
+
raise typer.Exit(1)
|
bakelib/space/python.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from bake import Context
|
|
2
|
+
|
|
3
|
+
from .base import BaseSpace
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PythonSpace(BaseSpace):
|
|
7
|
+
def lint(self, ctx: Context) -> None:
|
|
8
|
+
super().lint(ctx=ctx)
|
|
9
|
+
|
|
10
|
+
ctx.run(
|
|
11
|
+
[
|
|
12
|
+
"uv",
|
|
13
|
+
"run",
|
|
14
|
+
"toml-sort",
|
|
15
|
+
"--sort-inline-arrays",
|
|
16
|
+
"--in-place",
|
|
17
|
+
"--sort-first=project,dependency-groups",
|
|
18
|
+
"pyproject.toml",
|
|
19
|
+
]
|
|
20
|
+
)
|
|
21
|
+
ctx.run(["uv", "run", "ruff", "format", "--exit-non-zero-on-format", "."])
|
|
22
|
+
ctx.run(["uv", "run", "ruff", "check", "--fix", "--exit-non-zero-on-fix", "."])
|
|
23
|
+
ctx.run(["uv", "run", "ty", "check", "--error-on-warning", "."])
|
|
24
|
+
ctx.run(["uv", "run", "deptry", "."])
|
|
25
|
+
|
|
26
|
+
def test(self, ctx: Context) -> None:
|
|
27
|
+
ctx.run(
|
|
28
|
+
[
|
|
29
|
+
"uv",
|
|
30
|
+
"run",
|
|
31
|
+
"pytest",
|
|
32
|
+
"tests/",
|
|
33
|
+
"--cov=src",
|
|
34
|
+
"--cov-report=html",
|
|
35
|
+
"--cov-report=term-missing",
|
|
36
|
+
"--cov-report=xml",
|
|
37
|
+
]
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def setup_dev(self, ctx: Context) -> None:
|
|
41
|
+
super().clean(ctx=ctx)
|
|
42
|
+
ctx.run("uv sync --all-extras --all-groups --frozen")
|
bakelib/space/utils.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pathspec
|
|
5
|
+
from pathspec.patterns.gitignore.basic import GitIgnoreBasicPattern
|
|
6
|
+
|
|
7
|
+
from bake.ui import console
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _skip_msg(path: Path, suffix: str, dry_run: bool) -> None:
|
|
11
|
+
verb = "Would skip" if dry_run else "Skipping"
|
|
12
|
+
console.echo(f"[yellow]~[/yellow] {verb} {suffix}{path}")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _remove_msg(path: Path, dry_run: bool) -> None:
|
|
16
|
+
verb = "Would remove" if dry_run else "Removing"
|
|
17
|
+
console.echo(f"[red]-[/red] [dim]{verb}[/dim] {path}")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _should_remove_path(path: Path, dry_run: bool) -> None:
|
|
21
|
+
_remove_msg(path, dry_run)
|
|
22
|
+
if dry_run:
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
if path.is_dir():
|
|
26
|
+
shutil.rmtree(path)
|
|
27
|
+
else:
|
|
28
|
+
path.unlink(missing_ok=True)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def remove_git_clean_candidates(
|
|
32
|
+
git_clean_dry_run_output: str, exclude_patterns: set[str], dry_run: bool
|
|
33
|
+
) -> None:
|
|
34
|
+
spec = pathspec.PathSpec.from_lines(
|
|
35
|
+
GitIgnoreBasicPattern,
|
|
36
|
+
exclude_patterns,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
for line in git_clean_dry_run_output.splitlines():
|
|
40
|
+
line = line.strip()
|
|
41
|
+
if not line.startswith("Would remove "):
|
|
42
|
+
continue
|
|
43
|
+
|
|
44
|
+
rel_path = line.removeprefix("Would remove ").strip()
|
|
45
|
+
path = Path(rel_path)
|
|
46
|
+
|
|
47
|
+
if spec.match_file(rel_path):
|
|
48
|
+
_skip_msg(path, "", dry_run)
|
|
49
|
+
continue
|
|
50
|
+
|
|
51
|
+
if path.is_dir() and (path / ".git").exists():
|
|
52
|
+
_skip_msg(path, "git repository ", dry_run)
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
_should_remove_path(path, dry_run)
|