Skip to content

Fix partial state after hookspec validation and historic replay failures(#761) - #783

Open
starx710 wants to merge 10 commits into
pytest-dev:mainfrom
starx710:fix-hookspec-validation-761
Open

starx710 wants to merge 10 commits into
pytest-dev:mainfrom
starx710:fix-hookspec-validation-761

Conversation

@starx710

Copy link
Copy Markdown

Summary

Make failed hookspec validation and historic plugin registration recoverable.

Problem

add_hookspecs() installs specifications before validating existing implementations. A validation error leaves partially installed specifications and prevents a retry, even after the invalid plugin is removed.

When historic replay raises during register(), the plugin and implementations processed earlier remain registered. Replay may also add specifications or register other plugins, so restoring the entire manager would discard valid user changes.

Solution

  • Validate every candidate specification using a temporary HookCaller, then install the prepared specification and historic state. Keep existing caller identities and implementations.
  • On registration failure, remove only the implementation objects added by that registration. Remove its newly created callers only if they remain unused and have no specification.
  • Track active registration ownership so cleanup preserves replacement or nested registrations, including re-registration of the same object without hook implementations.
  • Catch BaseException for cleanup and use a bare raise to preserve the original exception and traceback. Avoid plugin equality during rollback and retain replay side effects.
  • Update the existing 761.bugfix.rst fragment.

Regression Tests

Add 20 test cases (after parametrization) and strengthen the existing late-spec validation test. Coverage includes:

  • Invalid implementations, retry, multi-spec failures, caller/subset identity, duplicate specs and warnings treated as errors.
  • Implementation and result-callback replay failures, including RuntimeError and KeyboardInterrupt, with exception identity and traceback checks.
  • Cleanup of earlier implementations and unused new callers; preservation of existing callers, implementations, specs and history; successful retry.
  • Specs and other plugins added during replay, adopted callers, replacement/re-registered/blocked/removed registrations, and plugin equality that raises.

Validation

Tested on Windows with CPython 3.12.13:

  • uv run pytest -q --tb=short: 239 passed.
  • uv run pre-commit run --all-files: all hooks passed, including Ruff, formatting and mypy.
  • git diff origin/main --check: passed.
  • Running the final regression checks against an isolated, unmodified upstream source snapshot (6995073) produced 19 failures and 2 passing controls. The working checkout was unchanged.
  • Coverage run: _manager.py has no uncovered statements; combined statement/branch coverage is 99%.

Other Python versions and platforms await CI after PR creation.

Related Issue

Fixes #761.

Related: #779 also addresses historic registration rollback.

Prepared with OpenAI Codex; local tests and self-review were performed before submission.

starx710 and others added 10 commits October 13, 2026 23:02
Validate the complete namespace before installation while retaining existing caller identities. Related to pytest-dev#761. AI-assisted with OpenAI Codex.
Cover normal and historic retry, namespace validation, duplicate specifications, and warnings treated as errors. Seven cases fail on the original base; all pass with the fix. AI-assisted with OpenAI Codex.
Remove only implementations and unused callers created by the failed registration. Track active registration ownership to preserve nested replacement registrations, including the same plugin object. Add regression coverage and update the existing issue 761 changelog.
Remove only implementations and unused callers created by the failed registration. Preserve nested registry changes, including re-registration of the same plugin object.
Cover replay and callback failures, original tracebacks, retries, existing state, unused new callers, nested registrations and late-spec validation. Full suite: 239 passed; all pre-commit hooks passed.
Update the existing changelog fragment for hookspec validation and historic registration rollback.
@starx710 starx710 changed the title Fix hookspec validation 761 Fix partial state after hookspec validation and historic replay failures Oct 14, 2026
@starx710 starx710 changed the title Fix partial state after hookspec validation and historic replay failures Fix partial state after hookspec validation and historic replay failures(#761) Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failures during add_hookspecs / historic replay leave partial state

1 participant