Skip to content

Commit 4115dd3

Browse files
authored
fix(config): report a malformed ini as a handled error instead of a traceback (#4027)
1 parent 0200b89 commit 4115dd3

3 files changed

Lines changed: 20 additions & 1 deletion

File tree

docs/changelog/4027.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Report a malformed ``tox.ini`` or ``setup.cfg`` as a handled error during config discovery instead of raising an
2+
unhandled :class:`configparser.Error` traceback - by :user:`VXNCXNX`

src/tox/config/source/ini.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from collections import defaultdict
66
from configparser import ConfigParser
7+
from configparser import Error as ConfigParserError
78
from itertools import chain
89
from typing import TYPE_CHECKING
910

@@ -34,7 +35,12 @@ def __init__(self, path: Path, content: str | None = None) -> None:
3435
if not path.exists():
3536
raise ValueError
3637
content = path.read_text(encoding="utf-8")
37-
self._parser.read_string(content, str(path))
38+
try:
39+
self._parser.read_string(content, str(path))
40+
except ConfigParserError as exc:
41+
# configparser errors do not derive from ValueError, unlike tomllib ones, so translate them to let
42+
# config discovery report them as a handled error instead of leaking a traceback
43+
raise ValueError(exc) from exc
3844
self._section_mapping: defaultdict[str, list[str]] = defaultdict(list)
3945

4046
def transform_section(self, section: Section) -> Section: # ruff:ignore[no-self-use]

tests/config/source/test_discover.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ def test_malformed_toml_in_dir_reports_error(tox_project: ToxProjectCreator) ->
6767
assert "failed loading" in outcome.out
6868

6969

70+
def test_malformed_ini_in_dir_reports_error(tox_project: ToxProjectCreator) -> None:
71+
"""Config discovery in a directory should report ini parse errors instead of raising a traceback."""
72+
project = tox_project({})
73+
# Write a tox.ini with an unterminated section header
74+
(project.path / "tox.ini").write_text("[tox\nenv_list = a\n", encoding="utf-8")
75+
outcome = project.run("l", "-c", str(project.path))
76+
outcome.assert_failed()
77+
assert "failed loading" in outcome.out
78+
assert "File contains no section headers" in outcome.out
79+
80+
7081
def test_toml_native_preferred_over_legacy_tox_ini(tox_project: ToxProjectCreator) -> None:
7182
"""When pyproject.toml has both legacy_tox_ini and native TOML config, native TOML should win."""
7283
pyproject = """\

0 commit comments

Comments
 (0)