Skip to content

Commit 7ae6414

Browse files
committed
fix(config): include pyproject.toml in multi config file warning
1 parent bd02381 commit 7ae6414

File tree

2 files changed

+51
-47
lines changed

2 files changed

+51
-47
lines changed

commitizen/config/__init__.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .base_config import BaseConfig
1010

1111

12-
def _resolve_config_paths() -> list[Path]:
12+
def _resolve_config_candidates() -> list[BaseConfig]:
1313
git_project_root = git.find_git_project_root()
1414
cfg_search_paths = [Path(".")]
1515

@@ -18,12 +18,18 @@ def _resolve_config_paths() -> list[Path]:
1818

1919
# The following algorithm is ugly, but we need to ensure that the order of the candidates are preserved before v5.
2020
# Also, the number of possible config files is limited, so the complexity is not a problem.
21-
candidates: list[Path] = []
21+
candidates: list[BaseConfig] = []
2222
for dir in cfg_search_paths:
2323
for filename in defaults.CONFIG_FILES:
2424
out_path = dir / Path(filename)
25-
if out_path.exists() and all(not out_path.samefile(p) for p in candidates):
26-
candidates.append(out_path)
25+
if (
26+
out_path.exists()
27+
and not any(
28+
out_path.samefile(candidate.path) for candidate in candidates
29+
)
30+
and not (conf := _create_config_from_path(out_path)).is_empty_config
31+
):
32+
candidates.append(conf)
2733
return candidates
2834

2935

@@ -44,21 +50,11 @@ def read_cfg(filepath: str | None = None) -> BaseConfig:
4450
raise ConfigFileIsEmpty()
4551
return conf
4652

47-
config_candidate_paths = _resolve_config_paths()
48-
49-
# Check for multiple config files and warn the user
50-
config_candidates_exclude_pyproject = [
51-
path for path in config_candidate_paths if path.name != "pyproject.toml"
52-
]
53-
54-
for config_candidate_path in config_candidate_paths:
55-
conf = _create_config_from_path(config_candidate_path)
56-
if not conf.is_empty_config:
57-
if len(config_candidates_exclude_pyproject) > 1:
58-
out.warn(
59-
f"Multiple config files detected: {', '.join(map(str, config_candidates_exclude_pyproject))}. "
60-
f"Using config file: '{config_candidate_path}'."
61-
)
62-
return conf
53+
config_candidates = _resolve_config_candidates()
54+
if len(config_candidates) > 1:
55+
out.warn(
56+
f"Multiple config files detected: {', '.join(str(conf.path) for conf in config_candidates)}. "
57+
f"Using config file: '{config_candidates[0].path}'."
58+
)
6359

64-
return BaseConfig()
60+
return config_candidates[0] if config_candidates else BaseConfig()

tests/test_conf.py

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from commitizen.config.yaml_config import YAMLConfig
1515
from commitizen.exceptions import ConfigFileIsEmpty, InvalidConfigurationError
1616

17-
PYPROJECT = """
17+
TOML_STR = """
1818
[tool.commitizen]
1919
name = "cz_jira"
2020
version = "1.0.0"
@@ -30,12 +30,17 @@
3030
"scripts/generate_documentation.sh"
3131
]
3232
post_bump_hooks = ["scripts/slack_notification.sh"]
33+
"""
34+
35+
PYPROJECT = f"""
36+
{TOML_STR}
3337
3438
[tool.black]
3539
line-length = 88
3640
target-version = ['py36', 'py37', 'py38']
3741
"""
3842

43+
3944
DICT_CONFIG = {
4045
"commitizen": {
4146
"name": "cz_jira",
@@ -198,7 +203,7 @@ def test_load_empty_pyproject_toml_and_cz_toml_with_config(self, tmpdir):
198203
p = tmpdir.join("pyproject.toml")
199204
p.write("")
200205
p = tmpdir.join(".cz.toml")
201-
p.write(PYPROJECT)
206+
p.write(TOML_STR)
202207

203208
cfg = config.read_cfg()
204209
assert cfg.settings == _settings
@@ -240,27 +245,25 @@ def test_load_empty_pyproject_toml_from_config_argument(self, tmpdir):
240245

241246
class TestWarnMultipleConfigFiles:
242247
@pytest.mark.parametrize(
243-
"files,expected_path,should_warn",
248+
"files,expected_path",
244249
[
245250
# Same directory, different file types
246-
([(".cz.toml", PYPROJECT), (".cz.json", JSON_STR)], ".cz.toml", True),
247-
([(".cz.json", JSON_STR), (".cz.yaml", YAML_STR)], ".cz.json", True),
248-
([(".cz.toml", PYPROJECT), (".cz.yaml", YAML_STR)], ".cz.toml", True),
249-
# With pyproject.toml (excluded from warning)
251+
([(".cz.toml", TOML_STR), (".cz.json", JSON_STR)], ".cz.toml"),
252+
([(".cz.json", JSON_STR), (".cz.yaml", YAML_STR)], ".cz.json"),
253+
([(".cz.toml", TOML_STR), (".cz.yaml", YAML_STR)], ".cz.toml"),
254+
# With pyproject.toml
250255
(
251256
[("pyproject.toml", PYPROJECT), (".cz.json", JSON_STR)],
252257
".cz.json",
253-
False,
254258
),
255259
(
256-
[("pyproject.toml", PYPROJECT), (".cz.toml", PYPROJECT)],
260+
[("pyproject.toml", PYPROJECT), (".cz.toml", TOML_STR)],
257261
".cz.toml",
258-
False,
259262
),
260263
],
261264
)
262265
def test_warn_multiple_config_files_same_dir(
263-
self, tmpdir, capsys, files, expected_path, should_warn
266+
self, tmpdir, capsys, files, expected_path
264267
):
265268
"""Test warning when multiple config files exist in same directory."""
266269
with tmpdir.as_cwd():
@@ -270,27 +273,20 @@ def test_warn_multiple_config_files_same_dir(
270273
cfg = config.read_cfg()
271274
captured = capsys.readouterr()
272275

273-
if should_warn:
274-
assert "Multiple config files detected" in captured.err
275-
assert "Using" in captured.err
276-
for filename, _ in files:
277-
if filename != "pyproject.toml":
278-
assert filename in captured.err
279-
else:
280-
assert "Multiple config files detected" not in captured.err
276+
assert "Multiple config files detected" in captured.err
277+
for filename, _ in files:
278+
assert filename in captured.err
279+
assert f"Using config file: '{expected_path}'" in captured.err
281280

282281
assert cfg.path == Path(expected_path)
283-
# Verify config loaded correctly (name and version match expected)
284-
assert cfg.settings["name"] == "cz_jira"
285-
assert cfg.settings["version"] == "1.0.0"
286282

287283
@pytest.mark.parametrize(
288284
"config_file,content",
289285
[
290286
(".cz.json", JSON_STR),
291-
(".cz.toml", PYPROJECT),
287+
(".cz.toml", TOML_STR),
292288
(".cz.yaml", YAML_STR),
293-
("cz.toml", PYPROJECT),
289+
("cz.toml", TOML_STR),
294290
("cz.json", JSON_STR),
295291
("cz.yaml", YAML_STR),
296292
],
@@ -340,11 +336,11 @@ def test_no_warn_with_explicit_config_path(self, tmpdir, capsys):
340336
[
341337
(file, content, with_git)
342338
for file, content in [
343-
(".cz.toml", PYPROJECT),
339+
(".cz.toml", TOML_STR),
344340
(".cz.json", JSON_STR),
345341
(".cz.yaml", YAML_STR),
346342
("pyproject.toml", PYPROJECT),
347-
("cz.toml", PYPROJECT),
343+
("cz.toml", TOML_STR),
348344
("cz.json", JSON_STR),
349345
("cz.yaml", YAML_STR),
350346
]
@@ -368,6 +364,18 @@ def test_no_warn_with_single_config_file(
368364
assert "Multiple config files detected" not in captured.err
369365
assert cfg.path == Path(config_file)
370366

367+
def test_no_warn_with_no_commitizen_section_in_pyproject_toml_and_cz_toml(
368+
self, tmpdir, capsys
369+
):
370+
with tmpdir.as_cwd():
371+
tmpdir.join("pyproject.toml").write("[tool.foo]\nbar = 'baz'")
372+
tmpdir.join(".cz.toml").write(TOML_STR)
373+
374+
cfg = config.read_cfg()
375+
captured = capsys.readouterr()
376+
assert "Multiple config files detected" not in captured.err
377+
assert cfg.path == Path(".cz.toml")
378+
371379

372380
@pytest.mark.parametrize(
373381
"config_file",

0 commit comments

Comments
 (0)