Skip to content

Modernize ConftestImportFailure to use the exception chain - #14943

Draft
RonnyPfannschmidt wants to merge 2 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:conftest-import-failure-modernize
Draft

Modernize ConftestImportFailure to use the exception chain#14943
RonnyPfannschmidt wants to merge 2 commits into
pytest-dev:mainfrom
RonnyPfannschmidt:conftest-import-failure-modernize

Conversation

@RonnyPfannschmidt

Copy link
Copy Markdown
Member

Stacked on #14824 — review only the last commit; the first is that PR.

Gives ConftestImportFailure the same shape PluginImportFailure got in #14824: a bare Exception subclass whose argument is the conftest path, with the original error carried by raise ... from on __cause__ instead of a hand-rolled cause attribute duplicating the chain. The custom __init__ and __str__ go away; str(e) is the path, which is exactly what both message consumers want.

Why this is safe:

  • the cause attribute is young — introduced in 8.0 (e1074f9) replacing the old excinfo triplet, without deprecation;
  • the class is private to _pytest.config (not exported as pytest.*), and a GitHub code search finds no external importers, only vendored copies of pytest itself;
  • all five internal consumers (print_conftest_import_error, the --help/--version grace path, Node._repr_failure_py unwrapping, --pdb post-mortem unwrapping, _main) are updated in this PR.

No user-visible output changes.

🤖 Written by Claude Code (Claude Fable 5); reviewed and submitted by @RonnyPfannschmidt.

@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Aug 26, 2026
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the conftest-import-failure-modernize branch 3 times, most recently from efef5df to c5e0b6b Compare August 27, 2026 07:21
RonnyPfannschmidt and others added 2 commits August 27, 2026 21:57
A plugin failing to load during startup escaped `_main` as an unhandled
exception: Python printed a raw traceback and exited 1, which is
indistinguishable from EXIT_TESTSFAILED. Meanwhile a conftest.py failing
to import already returned EXIT_USAGEERROR, which is the inconsistency
pytest-dev#993 was filed about.

Split the failure into the two things it can actually mean:

- the plugin cannot be found at all -- pytest was pointed at something
  which is not there, so this is a usage error (exit 4), matching what
  conftest.py import failures already do.

- the plugin was found but raised while importing -- including a missing
  transitive dependency and a broken pytest11 entry point -- which is a
  defect in the plugin rather than a misuse of pytest, so it is reported
  as an internal error (exit 3).

The plugin traceback is preserved in both the report and the exception
chain (PluginImportFailure is always raised `from` the original error);
losing it was the main objection to the earlier attempt in pytest-dev#7290.

Side effects:

- pytest.main() now returns these exit codes instead of propagating the
  exception to its caller, matching its documented contract.
- a bare `raise ImportError` in a plugin no longer crashes pytest's own
  internals with `IndexError: tuple index out of range` from `e.args[0]`.

conftest.py import failures are deliberately left alone and keep
returning exit 4.

Co-Authored-By: Claude Opus 5 <ai@anthropic.com>
Co-Authored-By: Claude Fable 5 <ai@anthropic.com>
Co-Authored-By: Claude Code <ai@anthropic.com>
Give ConftestImportFailure the same shape PluginImportFailure just got:
a bare Exception subclass whose argument is the conftest path, with the
original error carried by `raise ... from` on __cause__ instead of a
hand-rolled `cause` attribute duplicating it. The custom __init__ and
__str__ go away; str(e) is the path, which is exactly what the two
message consumers want.

The `cause` attribute dates to 8.0 (e1074f9), which replaced the old
excinfo triplet without deprecation; the class is private to
_pytest.config and a code search finds no external consumers, only
vendored copies of pytest itself.

No user-visible output changes.

Co-Authored-By: Claude Fable 5 <ai@anthropic.com>
Co-Authored-By: Claude Code <ai@anthropic.com>
@RonnyPfannschmidt
RonnyPfannschmidt force-pushed the conftest-import-failure-modernize branch from c5e0b6b to 3e02d6b Compare August 27, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant