Skip to content

Commit 33fe15c

Browse files
committed
Improve pyproject.toml validation messages (#3487)
2 parents ef6fd97 + 7119ff1 commit 33fe15c

File tree

3 files changed

+15
-22
lines changed

3 files changed

+15
-22
lines changed

changelog.d/3487.misc.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Modified ``pyproject.toml`` validation exception handling to
2+
make relevant debugging information easier to spot.

setuptools/config/pyprojecttoml.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,14 @@ def validate(config: dict, filepath: _Path) -> bool:
4141
try:
4242
return validator.validate(config)
4343
except validator.ValidationError as ex:
44-
_logger.error(f"configuration error: {ex.summary}") # type: ignore
45-
_logger.debug(ex.details) # type: ignore
46-
error = ValueError(f"invalid pyproject.toml config: {ex.name}") # type: ignore
47-
raise error from None
44+
summary = f"configuration error: {ex.summary}"
45+
if ex.name.strip("`") != "project":
46+
# Probably it is just a field missing/misnamed, not worthy the verbosity...
47+
_logger.debug(summary)
48+
_logger.debug(ex.details)
49+
50+
error = f"invalid pyproject.toml config: {ex.name}."
51+
raise ValueError(f"{error}\n{summary}") from None
4852

4953

5054
def apply_configuration(

setuptools/tests/config/test_pyprojecttoml.py

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import logging
21
import re
32
from configparser import ConfigParser
43
from inspect import cleandoc
@@ -307,7 +306,7 @@ def test_ignore_unrelated_config(tmp_path, example):
307306

308307

309308
@pytest.mark.parametrize(
310-
"example, error_msg, value_shown_in_debug",
309+
"example, error_msg",
311310
[
312311
(
313312
"""
@@ -316,30 +315,18 @@ def test_ignore_unrelated_config(tmp_path, example):
316315
version = "1.2"
317316
requires = ['pywin32; platform_system=="Windows"' ]
318317
""",
319-
"configuration error: `project` must not contain {'requires'} properties",
320-
'"requires": ["pywin32; platform_system==\\"Windows\\""]',
318+
"configuration error: .project. must not contain ..requires.. properties",
321319
),
322320
],
323321
)
324-
def test_invalid_example(tmp_path, caplog, example, error_msg, value_shown_in_debug):
325-
caplog.set_level(logging.DEBUG)
322+
def test_invalid_example(tmp_path, example, error_msg):
326323
pyproject = tmp_path / "pyproject.toml"
327324
pyproject.write_text(cleandoc(example))
328325

329-
caplog.clear()
330-
with pytest.raises(ValueError, match="invalid pyproject.toml"):
326+
pattern = re.compile(f"invalid pyproject.toml.*{error_msg}.*", re.M | re.S)
327+
with pytest.raises(ValueError, match=pattern):
331328
read_configuration(pyproject)
332329

333-
# Make sure the logs give guidance to the user
334-
error_log = caplog.record_tuples[0]
335-
assert error_log[1] == logging.ERROR
336-
assert error_msg in error_log[2]
337-
338-
debug_log = caplog.record_tuples[1]
339-
assert debug_log[1] == logging.DEBUG
340-
debug_msg = "".join(line.strip() for line in debug_log[2].splitlines())
341-
assert value_shown_in_debug in debug_msg
342-
343330

344331
@pytest.mark.parametrize("config", ("", "[tool.something]\nvalue = 42"))
345332
def test_empty(tmp_path, config):

0 commit comments

Comments
 (0)