Skip to content

Commit 8a60a13

Browse files
Merge pull request #229 from codeflash-ai/fix-formatter-during-runtime
Exit the cli if user doesn't have the formatter installed while running codeflash (CF-644)
2 parents eae1592 + 4cfaea0 commit 8a60a13

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

codeflash/cli_cmds/cmd_init.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from codeflash.cli_cmds.console import console, logger
2323
from codeflash.code_utils.compat import LF
2424
from codeflash.code_utils.config_parser import parse_config_file
25-
from codeflash.code_utils.env_utils import get_codeflash_api_key
25+
from codeflash.code_utils.env_utils import check_formatter_installed, get_codeflash_api_key
2626
from codeflash.code_utils.git_utils import get_git_remotes, get_repo_owner_and_name
2727
from codeflash.code_utils.github_utils import get_github_secrets_page_url
2828
from codeflash.code_utils.shell_utils import get_shell_rc_path, save_api_key_to_rc
@@ -720,11 +720,7 @@ def configure_pyproject_toml(setup_info: SetupInfo) -> None:
720720
)
721721
elif formatter == "don't use a formatter":
722722
formatter_cmds.append("disabled")
723-
if formatter in ["black", "ruff"]:
724-
try:
725-
subprocess.run([formatter], capture_output=True, check=False)
726-
except (FileNotFoundError, NotADirectoryError):
727-
click.echo(f"⚠️ Formatter not found: {formatter}, please ensure it is installed")
723+
check_formatter_installed(formatter_cmds)
728724
codeflash_section["formatter-cmds"] = formatter_cmds
729725
# Add the 'codeflash' section, ensuring 'tool' section exists
730726
tool_section = pyproject_data.get("tool", tomlkit.table())
@@ -924,6 +920,14 @@ def test_sort():
924920

925921

926922
def run_end_to_end_test(args: Namespace, bubble_sort_path: str, bubble_sort_test_path: str) -> None:
923+
try:
924+
check_formatter_installed(args.formatter_cmds)
925+
except Exception:
926+
logger.error(
927+
"Formatter not found. Review the formatter_cmds in your pyproject.toml file and make sure the formatter is installed."
928+
)
929+
return
930+
927931
command = ["codeflash", "--file", "bubble_sort.py", "--function", "sorter"]
928932
if args.no_pr:
929933
command.append("--no-pr")

codeflash/code_utils/env_utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,52 @@
11
from __future__ import annotations
22

33
import os
4+
import shlex
5+
import subprocess
6+
import tempfile
47
from functools import lru_cache
8+
from pathlib import Path
59
from typing import Optional
610

711
from codeflash.cli_cmds.console import logger
812
from codeflash.code_utils.shell_utils import read_api_key_from_shell_config
913

1014

15+
class FormatterNotFoundError(Exception):
16+
"""Exception raised when a formatter is not found."""
17+
18+
def __init__(self, formatter_cmd: str) -> None:
19+
super().__init__(f"Formatter command not found: {formatter_cmd}")
20+
21+
22+
def check_formatter_installed(formatter_cmds: list[str]) -> bool:
23+
return_code = True
24+
if formatter_cmds[0] == "disabled":
25+
return return_code
26+
tmp_code = """print("hello world")"""
27+
with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", suffix=".py") as f:
28+
f.write(tmp_code)
29+
f.flush()
30+
tmp_file = Path(f.name)
31+
file_token = "$file" # noqa: S105
32+
for command in set(formatter_cmds):
33+
formatter_cmd_list = shlex.split(command, posix=os.name != "nt")
34+
formatter_cmd_list = [tmp_file.as_posix() if chunk == file_token else chunk for chunk in formatter_cmd_list]
35+
try:
36+
result = subprocess.run(formatter_cmd_list, capture_output=True, check=False)
37+
except (FileNotFoundError, NotADirectoryError):
38+
return_code = False
39+
break
40+
if result.returncode:
41+
return_code = False
42+
break
43+
tmp_file.unlink(missing_ok=True)
44+
if not return_code:
45+
msg = f"Error running formatter command: {command}"
46+
raise FormatterNotFoundError(msg)
47+
return return_code
48+
49+
1150
@lru_cache(maxsize=1)
1251
def get_codeflash_api_key() -> str:
1352
api_key = os.environ.get("CODEFLASH_API_KEY") or read_api_key_from_shell_config()

codeflash/optimization/optimizer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def run(self) -> None:
8282
console.rule()
8383
if not env_utils.ensure_codeflash_api_key():
8484
return
85+
if not env_utils.check_formatter_installed(self.args.formatter_cmds):
86+
return
8587
function_optimizer = None
8688
file_to_funcs_to_optimize: dict[Path, list[FunctionToOptimize]]
8789
num_optimizable_functions: int

0 commit comments

Comments
 (0)