Commit e753137
authored
Report a bad ini core value as a handled error (#4028)
A bad value in the ini `[tox]` core section exits with a raw traceback,
while the same value in `pyproject.toml` is already reported properly.
```
$ printf '[tox]\nmin_version = notaversion\n' > tox.ini && tox l
File ".../packaging/version.py", line 452, in __init__
raise InvalidVersion(f"Invalid version: {version!r}")
packaging.version.InvalidVersion: Invalid version: 'notaversion'
```
The TOML path, same input, unchanged by this PR:
```
$ printf '[tool.tox]\nmin_version = "notaversion"\n' > pyproject.toml && tox l
ROOT: HandledError| failed to load core.min_version: Invalid version: 'notaversion'
```
After:
```
ROOT: HandledError| failed to load tox.min_version: Invalid version: 'notaversion'
```
`requires = ===bad!!!` and `env_list = {py39,py310` (unbalanced brace)
were tracebacks too, and are now handled the same way.
## The fix
`IniLoader.build` called `self.to(...)` unguarded. `TomlLoader.build`
already wraps the identical call and re-raises as `HandledError`, so
this mirrors it, including letting `HandledError` and `Skip` through
untouched.
## Why the guard is narrow
The wrap only applies to the core section. My first attempt covered
every section and broke 6 existing tests, because two paths deliberately
let raw exceptions through:
- testenv values, where `tox c` renders the exception inline as `#
Exception: ...` (`test_config_bad_dict`, `test_config_bad_bool` and
friends)
- the CLI config file, loaded with `conf is None`
Those are existing behaviour I did not want to change, so the condition
is `conf is None or args.env_name is not None` to bypass. Core values
are the case with no handling at all, because they are loaded before any
guard is in place.
## Verification
`test_ini_core_bad_value_is_handled_error` in
`tests/config/source/test_discover.py`, parametrised over `min_version`,
`requires` and `env_list`. It asserts no unhandled exception leaks, so
it fails on the actual symptom rather than on a message string.
Reverting only the guard condition to always bypass fails it as an
assertion:
```
> assert leaked is None, f"unhandled {type(leaked).__name__}: {leaked}"
E AssertionError: unhandled InvalidVersion: Invalid version: 'notaversion'
E AssertionError: unhandled InvalidRequirement: Expected package name at the start of dependency specifier
E AssertionError: unhandled ValueError: {py39
```
`pytest tests/config/` is 6644 passed, 2 skipped.
`tests/config/cli/test_argcomplete.py` is excluded because `argcomplete`
is not installed here; it fails to collect identically on a clean
checkout.
*Disclosure: written with AI assistance (Claude Code). I reproduced the
traceback and the TOML contrast at the CLI, confirmed the narrow guard
is required by removing it and watching 6 tests break, and ran the
mutation check myself.*
Co-authored-by: VXNCXNX <VXNCXNX@users.noreply.github.com>1 parent 79a45b4 commit e753137
3 files changed
Lines changed: 38 additions & 1 deletion
File tree
- docs/changelog
- src/tox/config/loader/ini
- tests/config/source
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
98 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
99 | 111 | | |
100 | 112 | | |
101 | 113 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
120 | 143 | | |
121 | 144 | | |
122 | 145 | | |
| |||
0 commit comments