bakefile 0.0.9__py3-none-any.whl → 0.0.11__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/cli/bake/main.py CHANGED
@@ -1,17 +1,53 @@
1
1
  import sys
2
+ from collections.abc import Callable
2
3
  from contextlib import contextmanager
4
+ from pathlib import Path
3
5
 
4
6
  import typer
5
7
 
6
8
  from bake.cli.bake.reinvocation import _reinvoke_with_detected_python
7
9
  from bake.cli.common.app import (
8
10
  add_completion,
9
- bake_app_callback_with_obj,
11
+ call_app_with_chdir,
10
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,
11
25
  )
12
- from bake.cli.common.obj import get_bakefile_object, is_bakebook_optional
13
26
  from bake.ui import console
14
- from bake.utils import env
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
15
51
 
16
52
 
17
53
  @contextmanager
@@ -24,13 +60,15 @@ def set_argv(argv: list[str]):
24
60
  sys.argv = original
25
61
 
26
62
 
27
- def _run_chain_commands(remaining_args: list[str], prog_name: str, bake_app: typer.Typer) -> int:
63
+ def _run_chain_commands(
64
+ remaining_args: list[str], prog_name: str, bake_app: typer.Typer, bakefile_path: Path | None
65
+ ) -> int:
28
66
  exit_code = 0
29
67
  for cmd in remaining_args:
30
68
  try:
31
69
  with set_argv([prog_name, cmd]):
32
70
  console.cmd(" ".join(sys.argv))
33
- bake_app(prog_name=prog_name)
71
+ call_app_with_chdir(app=bake_app, bakefile_path=bakefile_path, prog_name=prog_name)
34
72
  except SystemExit as e:
35
73
  if e.code is not None and e.code != 0:
36
74
  exit_code = e.code if isinstance(e.code, int) else 1
@@ -52,14 +90,15 @@ def main():
52
90
  allow_missing=is_bakebook_optional(remaining_args=bakefile_obj.remaining_args)
53
91
  )
54
92
 
55
- bakefile_obj.warn_if_no_bakebook(color_echo=env.should_use_colors())
93
+ bakefile_obj.warn_if_no_bakebook(color_echo=bake_settings.should_use_colors())
56
94
 
57
95
  bake_app = typer.Typer(
58
96
  add_completion=add_completion,
59
97
  rich_markup_mode=rich_markup_mode,
60
98
  )
61
99
 
62
- bake_app.callback(invoke_without_command=True)(bake_app_callback_with_obj(obj=bakefile_obj))
100
+ callback = bake_app_callback_with_obj(obj=bakefile_obj)
101
+ bake_app.callback(invoke_without_command=True)(callback)
63
102
 
64
103
  prog_name = "bake"
65
104
 
@@ -68,7 +107,10 @@ def main():
68
107
 
69
108
  if bakefile_obj.is_chain_commands and bakefile_obj.remaining_args:
70
109
  exit_code = _run_chain_commands(
71
- remaining_args=bakefile_obj.remaining_args, prog_name=prog_name, bake_app=bake_app
110
+ remaining_args=bakefile_obj.remaining_args,
111
+ prog_name=prog_name,
112
+ bake_app=bake_app,
113
+ bakefile_path=bakefile_obj.bakefile_path,
72
114
  )
73
115
  raise SystemExit(exit_code)
74
- bake_app(prog_name=prog_name)
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.env import _BAKE_REINVOKED
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 os.environ.get(_BAKE_REINVOKED):
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[_BAKE_REINVOKED] = "1"
58
+ env[ENV__BAKE_REINVOKED] = "1"
56
59
 
57
60
  sys.stdout.flush()
58
61
  sys.stderr.flush()
bake/cli/bakefile/main.py CHANGED
@@ -1,10 +1,27 @@
1
+ from collections.abc import Callable
2
+
1
3
  from bake.cli.common.app import (
2
4
  BakefileApp,
3
5
  add_completion,
4
- bake_app_callback_with_obj,
6
+ call_app_with_chdir,
5
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,
6
24
  )
7
- from bake.cli.common.obj import get_bakefile_object
8
25
 
9
26
  from . import uv
10
27
  from .add_inline import add_inline
@@ -14,6 +31,22 @@ from .init import init
14
31
  from .lint import lint
15
32
 
16
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
+
17
50
  def main():
18
51
  bakefile_obj = get_bakefile_object(rich_markup_mode=rich_markup_mode)
19
52
  bakefile_obj.setup_logging()
@@ -29,7 +62,8 @@ def main():
29
62
  "ignore_unknown_options": True,
30
63
  }
31
64
 
32
- bakefile_app.callback(invoke_without_command=True)(bake_app_callback_with_obj(obj=bakefile_obj))
65
+ callback = bakefile_app_callback_with_obj(obj=bakefile_obj)
66
+ bakefile_app.callback(invoke_without_command=True)(callback)
33
67
  bakefile_app.command()(init)
34
68
  bakefile_app.command()(add_inline)
35
69
  bakefile_app.command()(find_python)
@@ -40,4 +74,4 @@ def main():
40
74
  bakefile_app.command(context_settings=uv_commands_context_settings)(uv.add)
41
75
  bakefile_app.command(context_settings=uv_commands_context_settings)(uv.pip)
42
76
  bakefile_app.bakefile_object = bakefile_obj
43
- bakefile_app()
77
+ call_app_with_chdir(app=bakefile_app, bakefile_path=bakefile_obj.bakefile_path)
bake/cli/common/app.py CHANGED
@@ -1,25 +1,15 @@
1
- from collections.abc import Callable
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
2
7
 
3
8
  import typer
4
9
  from typer.core import MarkupMode
5
10
 
6
11
  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
12
  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
13
 
24
14
  from .obj import BakefileObject
25
15
 
@@ -31,24 +21,36 @@ class BakefileApp(typer.Typer):
31
21
  bakefile_object: BakefileObject
32
22
 
33
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
+
34
53
  def show_help_if_no_command(ctx: Context) -> None:
35
54
  if ctx.invoked_subcommand is None:
36
55
  console.echo(ctx.get_help())
37
56
  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
@@ -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,
bake/cli/common/obj.py CHANGED
@@ -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
- level_map = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG}
116
- log_level = level_map.get(self.verbosity, logging.WARNING)
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
 
bake/cli/common/params.py CHANGED
@@ -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=validate_file_name_callback,
42
+ callback=validate_file_name,
35
43
  ),
36
44
  ]
37
45
  bakebook_name_option = Annotated[
@@ -9,6 +9,8 @@ from bake.utils.exceptions import PythonNotFoundError
9
9
 
10
10
  logger = logging.getLogger(__name__)
11
11
 
12
+ _NO_PROJECT_PYTHON_MSG = "No project Python found"
13
+
12
14
 
13
15
  def is_standalone_bakefile(bakefile_path: Path) -> bool:
14
16
  inline_metadata = read_inline(bakefile_path)
@@ -101,18 +103,33 @@ def _find_project_python(bakefile_path: Path) -> Path | None:
101
103
  # Check if stderr contains "Found `...` at `...` (...)"
102
104
  # where source is "active virtual environment" or "virtual environment"
103
105
  stderr = result.stderr.strip()
104
- pattern = r"Found `[^`]+` at `[^`]+` \(([^)]+)\)"
106
+ pattern = r"Found `[^`]+` at `([^`]+)` \(([^)]+)\)"
105
107
  match = re.search(pattern, stderr)
106
108
 
107
- if result.returncode == 0 and match:
108
- source = match.group(1)
109
- if source in {"active virtual environment", "virtual environment"}:
110
- python_path = Path(result.stdout.strip())
111
- logger.debug(f"Found project Python at {python_path} (source: {source})")
112
- return python_path
109
+ if not (result.returncode == 0 and match):
110
+ logger.debug(_NO_PROJECT_PYTHON_MSG)
111
+ return None
113
112
 
114
- logger.debug("No project Python found")
115
- return None
113
+ source = match.group(2)
114
+ if source not in {"active virtual environment", "virtual environment"}:
115
+ logger.debug(_NO_PROJECT_PYTHON_MSG)
116
+ return None
117
+
118
+ python_path_from_log = Path(match.group(1))
119
+ python_path_from_stdout = Path(result.stdout.strip())
120
+ if python_path_from_log != python_path_from_stdout:
121
+ logger.debug(
122
+ "Python path mismatch between log and stdout",
123
+ extra={
124
+ "python_path_from_log": python_path_from_log,
125
+ "python_path_from_stdout": python_path_from_stdout,
126
+ },
127
+ )
128
+ logger.debug(_NO_PROJECT_PYTHON_MSG)
129
+ return None
130
+
131
+ logger.debug(f"Found project Python at {python_path_from_stdout} (source: {source})")
132
+ return python_path_from_stdout
116
133
 
117
134
 
118
135
  def _create_bakefile_venv(bakefile_path: Path) -> Path | None:
bake/manage/lint.py CHANGED
@@ -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=False,
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=False,
101
+ echo=echo,
102
+ echo_cmd="ty " + " ".join(cmd) if echo else None,
100
103
  dry_run=dry_run,
101
104
  )
bake/ui/console.py CHANGED
@@ -1,26 +1,72 @@
1
+ import sys
1
2
  import textwrap
2
3
  from typing import Any
3
4
 
4
5
  from beautysh import BashFormatter
5
6
  from rich.console import Console
6
7
 
8
+ from bake.utils.settings import bake_settings
9
+
7
10
  out = Console(stderr=False)
8
11
  err = Console(stderr=True)
9
12
 
10
13
  BOLD_GREEN = "bold green"
14
+ UNICODE_ENCODINGS = {"utf-8", "utf-16", "utf-32", "utf-16-le", "utf-16-be"}
11
15
 
12
16
 
13
- def _print(
14
- console_obj: Console, emoji: str | None, label: str, style: str, message: str, **kwargs
15
- ) -> None:
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:
16
28
  formatted_label = f"[{label}]" if console_obj.no_color or out.color_system is None else label
17
29
 
18
- emoji = emoji + " " if emoji else ""
19
- console_obj.print(f"[{style}]{emoji}{formatted_label}[/{style}] {message}", **kwargs)
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)
20
56
 
21
57
 
22
58
  def success(message: str, **kwargs) -> None:
23
- _print(out, ":white_check_mark:", "SUCCESS", BOLD_GREEN, message, **kwargs)
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)
24
70
 
25
71
 
26
72
  def echo(message: Any, **kwargs) -> None:
@@ -28,7 +74,8 @@ def echo(message: Any, **kwargs) -> None:
28
74
 
29
75
 
30
76
  def cmd(cmd_str: str, **kwargs) -> None:
31
- err.print(f"[bold green][/bold green] [default]{cmd_str}[/default]", **kwargs) # noqa: RUF001
77
+ arrow = "❯" if _supports_unicode() else ">" # noqa: RUF001
78
+ err.print(f"[{BOLD_GREEN}]{arrow}[/{BOLD_GREEN}] [default]{cmd_str}[/default]", **kwargs)
32
79
 
33
80
 
34
81
  def script_block(title: str, script: str, **kwargs) -> None:
@@ -51,8 +98,25 @@ def script_block(title: str, script: str, **kwargs) -> None:
51
98
 
52
99
 
53
100
  def warning(message: str, **kwargs) -> None:
54
- _print(err, ":warning-emoji: ", "WARNING", "bold yellow", message, **kwargs)
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
+ )
55
111
 
56
112
 
57
113
  def error(message: str, **kwargs) -> None:
58
- _print(err, ":x:", "ERROR", "bold red", message, **kwargs)
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)