diff --git a/codeflash/code_utils/env_utils.py b/codeflash/code_utils/env_utils.py index 08b1fc0da..4200edb7d 100644 --- a/codeflash/code_utils/env_utils.py +++ b/codeflash/code_utils/env_utils.py @@ -2,6 +2,8 @@ import json import os +import shlex +import shutil import tempfile from functools import lru_cache from pathlib import Path @@ -14,21 +16,41 @@ def check_formatter_installed(formatter_cmds: list[str], exit_on_failure: bool = True) -> bool: # noqa - return_code = True - if formatter_cmds[0] == "disabled": - return return_code + if not formatter_cmds or formatter_cmds[0] == "disabled": + return True + + first_cmd = formatter_cmds[0] + cmd_tokens = shlex.split(first_cmd) if isinstance(first_cmd, str) else [first_cmd] + + if not cmd_tokens: + return True + + exe_name = cmd_tokens[0] + command_str = " ".join(formatter_cmds).replace(" $file", "") + + if shutil.which(exe_name) is None: + logger.error( + f"Could not find formatter: {command_str}\n" + f"Please install it or update 'formatter-cmds' in your codeflash configuration" + ) + return False + tmp_code = """print("hello world")""" - with tempfile.TemporaryDirectory() as tmpdir: - tmp_file = Path(tmpdir) / "test_codeflash_formatter.py" - tmp_file.write_text(tmp_code, encoding="utf-8") - try: - format_code(formatter_cmds, tmp_file, print_status=False, exit_on_failure=exit_on_failure) - except Exception: - exit_with_message( - "⚠️ Codeflash requires a code formatter to be installed in your environment, but none was found. Please install a supported formatter, verify the formatter-cmds in your codeflash pyproject.toml config and try again.", - error_on_exit=True, - ) - return return_code + try: + with tempfile.TemporaryDirectory() as tmpdir: + tmp_file = Path(tmpdir) / "test_codeflash_formatter.py" + tmp_file.write_text(tmp_code, encoding="utf-8") + format_code(formatter_cmds, tmp_file, print_status=False, exit_on_failure=False) + return True + except FileNotFoundError: + logger.error( + f"Could not find formatter: {command_str}\n" + f"Please install it or update 'formatter-cmds' in your codeflash configuration" + ) + return False + except Exception as e: + logger.error(f"Formatter failed to run: {command_str}\nError: {e}") + return False @lru_cache(maxsize=1) diff --git a/codeflash/code_utils/formatter.py b/codeflash/code_utils/formatter.py index 67fd45e17..498a8078b 100644 --- a/codeflash/code_utils/formatter.py +++ b/codeflash/code_utils/formatter.py @@ -76,12 +76,9 @@ def apply_formatter_cmds( logger.error(f"Failed to format code with {' '.join(formatter_cmd_list)}") except FileNotFoundError as e: from rich.panel import Panel - from rich.text import Text - panel = Panel( - Text.from_markup(f"⚠️ Formatter command not found: {' '.join(formatter_cmd_list)}", style="bold red"), - expand=False, - ) + command_str = " ".join(str(part) for part in formatter_cmd_list) + panel = Panel(f"⚠️ Formatter command not found: {command_str}", expand=False, border_style="yellow") console.print(panel) if exit_on_failure: raise e from None diff --git a/codeflash/main.py b/codeflash/main.py index 2cb241afd..31afd0305 100644 --- a/codeflash/main.py +++ b/codeflash/main.py @@ -9,6 +9,7 @@ from codeflash.cli_cmds.cli import parse_args, process_pyproject_config from codeflash.cli_cmds.cmd_init import CODEFLASH_LOGO, ask_run_end_to_end_test from codeflash.cli_cmds.console import paneled_text +from codeflash.code_utils import env_utils from codeflash.code_utils.checkpoint import ask_should_use_checkpoint_get_functions from codeflash.code_utils.config_parser import parse_config_file from codeflash.code_utils.version_check import check_for_newer_minor_version @@ -39,6 +40,8 @@ def main() -> None: ask_run_end_to_end_test(args) else: args = process_pyproject_config(args) + if not env_utils.check_formatter_installed(args.formatter_cmds): + return args.previous_checkpoint_functions = ask_should_use_checkpoint_get_functions(args) init_sentry(not args.disable_telemetry, exclude_errors=True) posthog_cf.initialize_posthog(not args.disable_telemetry) diff --git a/codeflash/optimization/optimizer.py b/codeflash/optimization/optimizer.py index c0e0b014b..38b7f0d37 100644 --- a/codeflash/optimization/optimizer.py +++ b/codeflash/optimization/optimizer.py @@ -260,8 +260,6 @@ def run(self) -> None: console.rule() if not env_utils.ensure_codeflash_api_key(): return - if not env_utils.check_formatter_installed(self.args.formatter_cmds): - return if self.args.no_draft and is_pr_draft(): logger.warning("PR is in draft mode, skipping optimization") return