Skip to content

Commit 793b42f

Browse files
Fix Windows Python -y init regression
1 parent 2d4f49a commit 793b42f

5 files changed

Lines changed: 108 additions & 20 deletions

File tree

codeflash/cli_cmds/cmd_init.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,22 @@ def init_codeflash(*, skip_confirm: bool = False, skip_api_key: bool = False) ->
7878
did_add_new_key = False if skip_api_key else prompt_api_key()
7979
git_remote = "origin"
8080

81-
if skip_confirm:
82-
from codeflash.setup import detect_project, write_config
83-
84-
detected = detect_project()
85-
configured, message = write_config(detected)
86-
if configured:
87-
click.echo(message)
88-
click.echo()
81+
should_modify, config = should_modify_pyproject_toml(skip_confirm=skip_confirm)
82+
git_remote = config.get("git_remote", "origin") if config else "origin"
83+
84+
if should_modify:
85+
if skip_confirm:
86+
from codeflash.setup import detect_project, write_config
87+
88+
detected = detect_project()
89+
configured, message = write_config(detected)
90+
if configured:
91+
click.echo(message)
92+
click.echo()
93+
else:
94+
click.echo(message)
95+
apologize_and_exit()
8996
else:
90-
click.echo(message)
91-
apologize_and_exit()
92-
else:
93-
should_modify, config = should_modify_pyproject_toml()
94-
95-
git_remote = config.get("git_remote", "origin") if config else "origin"
96-
97-
if should_modify:
9897
setup_info = collect_setup_info()
9998
git_remote = setup_info.git_remote
10099
configured = configure_pyproject_toml(setup_info)

codeflash/cli_cmds/init_config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def is_valid_pyproject_toml(pyproject_toml_path: Union[str, Path]) -> tuple[bool
142142
return True, config, ""
143143

144144

145-
def should_modify_pyproject_toml() -> tuple[bool, dict[str, Any] | None]:
145+
def should_modify_pyproject_toml(*, skip_confirm: bool = False) -> tuple[bool, dict[str, Any] | None]:
146146
"""Check if the current directory contains a valid pyproject.toml file with codeflash config.
147147
148148
If it does, ask the user if they want to re-configure it.
@@ -160,6 +160,9 @@ def should_modify_pyproject_toml() -> tuple[bool, dict[str, Any] | None]:
160160
# needs to be re-configured
161161
return True, None
162162

163+
if skip_confirm:
164+
return False, config
165+
163166
return Confirm.ask(
164167
"✅ A valid Codeflash config already exists in this project. Do you want to re-configure it?",
165168
default=False,

codeflash/setup/config_writer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def _write_pyproject_toml(project_root: Path, config: CodeflashConfig) -> tuple[
8383
doc["tool"]["codeflash"] = codeflash_table
8484

8585
# Write back
86-
with pyproject_path.open("w", encoding="utf8") as f:
86+
with pyproject_path.open("w", encoding="utf8", newline="") as f:
8787
f.write(tomlkit.dumps(doc))
8888

8989
return True, f"Config saved to {pyproject_path}"
@@ -207,7 +207,7 @@ def _remove_from_pyproject(project_root: Path) -> tuple[bool, str]:
207207
if "tool" in doc and "codeflash" in doc["tool"]:
208208
del doc["tool"]["codeflash"]
209209

210-
with pyproject_path.open("w", encoding="utf8") as f:
210+
with pyproject_path.open("w", encoding="utf8", newline="") as f:
211211
f.write(tomlkit.dumps(doc))
212212

213213
return True, "Removed [tool.codeflash] section from pyproject.toml"

tests/test_init_yes.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
from __future__ import annotations
22

33
from argparse import Namespace
4-
from unittest.mock import Mock
4+
from pathlib import Path
5+
from unittest.mock import Mock, patch
56

7+
import pytest
8+
9+
from codeflash.cli_cmds.cmd_init import init_codeflash
10+
from codeflash.cli_cmds.init_config import should_modify_pyproject_toml
11+
from codeflash.cli_cmds.init_javascript import ProjectLanguage
612
from codeflash.main import main
713

814

@@ -39,3 +45,62 @@ def test_main_passes_yes_to_init_actions(monkeypatch) -> None:
3945
main()
4046

4147
install_github_actions.assert_called_once_with(skip_confirm=True)
48+
49+
50+
def test_should_modify_pyproject_toml_skip_confirm_skips_reconfigure_prompt(
51+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
52+
) -> None:
53+
monkeypatch.chdir(tmp_path)
54+
(tmp_path / "src").mkdir()
55+
(tmp_path / "tests").mkdir()
56+
(tmp_path / "pyproject.toml").write_text(
57+
'[tool.codeflash]\nmodule-root = "src"\ntests-root = "tests"\ngit-remote = "upstream"\n',
58+
encoding="utf-8",
59+
)
60+
61+
with patch("rich.prompt.Confirm.ask", side_effect=AssertionError("Confirm.ask should not be called")):
62+
should_modify, config = should_modify_pyproject_toml(skip_confirm=True)
63+
64+
assert should_modify is False
65+
assert config is not None
66+
assert config["git_remote"] == "upstream"
67+
68+
69+
def test_init_codeflash_skip_confirm_reuses_existing_python_config(
70+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
71+
) -> None:
72+
monkeypatch.chdir(tmp_path)
73+
(tmp_path / "src").mkdir()
74+
(tmp_path / "tests").mkdir()
75+
(tmp_path / "pyproject.toml").write_text(
76+
'[tool.codeflash]\nmodule-root = "src"\ntests-root = "tests"\ngit-remote = "upstream"\n',
77+
encoding="utf-8",
78+
)
79+
80+
install_github_app = Mock()
81+
install_github_actions = Mock()
82+
install_vscode_extension = Mock()
83+
detect_project = Mock(side_effect=AssertionError("detect_project should not be called"))
84+
write_config = Mock(side_effect=AssertionError("write_config should not be called"))
85+
exit_mock = Mock(side_effect=SystemExit(0))
86+
87+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.detect_project_language", Mock(return_value=ProjectLanguage.PYTHON))
88+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.install_github_app", install_github_app)
89+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.install_github_actions", install_github_actions)
90+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.install_vscode_extension", install_vscode_extension)
91+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.console.print", Mock())
92+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.ph", Mock())
93+
monkeypatch.setattr("codeflash.cli_cmds.cmd_init.sys.exit", exit_mock)
94+
monkeypatch.setattr("codeflash.setup.detect_project", detect_project)
95+
monkeypatch.setattr("codeflash.setup.write_config", write_config)
96+
97+
with pytest.raises(SystemExit) as exc_info:
98+
init_codeflash(skip_confirm=True, skip_api_key=True)
99+
100+
assert exc_info.value.code == 0
101+
install_github_app.assert_called_once_with("upstream")
102+
install_github_actions.assert_called_once_with(override_formatter_check=True, skip_confirm=True)
103+
install_vscode_extension.assert_called_once()
104+
detect_project.assert_not_called()
105+
write_config.assert_not_called()
106+
exit_mock.assert_called_once_with(0)

tests/test_setup/test_config.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,27 @@ def test_updates_existing_codeflash_section(self, tmp_path):
208208
assert data["tool"]["codeflash"]["module-root"] == "new"
209209
assert data["tool"]["codeflash"]["tests-root"] == "new_tests"
210210

211+
def test_preserves_crlf_newlines_for_existing_pyproject(self, tmp_path):
212+
"""Should not introduce doubled carriage returns when preserving CRLF files."""
213+
pyproject_path = tmp_path / "pyproject.toml"
214+
pyproject_path.write_bytes(b'[project]\r\nname = "myapp"\r\n\r\n[tool.ruff]\r\nline-length = 120\r\n')
215+
216+
config = CodeflashConfig(language="python", module_root="src")
217+
218+
success, message = _write_pyproject_toml(tmp_path, config)
219+
220+
assert success is True
221+
assert message == f"Config saved to {pyproject_path}"
222+
223+
content = pyproject_path.read_bytes()
224+
assert b"\r\r\n" not in content
225+
assert b"\r\n" in content
226+
227+
data = tomlkit.parse(content)
228+
assert data["project"]["name"] == "myapp"
229+
assert data["tool"]["ruff"]["line-length"] == 120
230+
assert data["tool"]["codeflash"]["module-root"] == "src"
231+
211232

212233
class TestWritePackageJson:
213234
"""Tests for writing to package.json."""

0 commit comments

Comments
 (0)