Skip to content

feat(_ext[sphinx_pytest_fixtures]): Sphinx extension for pytest fixture documentation#656

Merged
tony merged 11 commits intomasterfrom
sphinx-pytest-plugin-fixtures
Apr 3, 2026
Merged

feat(_ext[sphinx_pytest_fixtures]): Sphinx extension for pytest fixture documentation#656
tony merged 11 commits intomasterfrom
sphinx-pytest-plugin-fixtures

Conversation

@tony
Copy link
Copy Markdown
Member

@tony tony commented Apr 3, 2026

Summary

  • New Sphinx extension (docs/_ext/sphinx_pytest_fixtures/) that renders pytest fixtures as first-class API documentation with scope/kind/factory badges, cross-referenced dependencies, and auto-generated usage snippets
  • .. autofixture:: directive — autodoc-style documenter for individual fixtures
  • .. autofixtures:: directive — bulk discovery and rendering from a module
  • .. autofixture-index:: directive — auto-generated summary table with linked return types (via intersphinx) and parsed RST descriptions
  • :fixture: cross-reference role with short-name resolution
  • Scope, kind, and autouse badges with touch-accessible tooltips and WCAG AA contrast compliance (light + dark mode)
  • Responsive layout: mobile metadata stacking, badge font scaling, table scroll wrapper
  • Restructured fixture reference page with Quick Start, decision guide, grouped fixture cards, and configuration reference
  • Badge demo page for visual QA across themes and viewports
  • Fix pytest_plugin.py docstrings: remove duplicate hand-written fields now auto-generated by the extension, update :func::fixture: xrefs

Test plan

  • uv run pytest tests/docs/_ext/test_sphinx_pytest_fixtures.py — 70+ unit tests for detection, metadata, store, badges, validation, index
  • uv run pytest tests/docs/_ext/test_sphinx_pytest_fixtures_integration.py — 39+ integration tests requiring full Sphinx builds
  • uv run ruff check . — no lint violations
  • uv run mypy src tests — type checking passes
  • uv run sphinx-build -b html docs docs/_build/html — docs build without errors
  • Visual inspection of fixture cards, badges, and summary table at /api/testing/pytest-plugin/fixtures/
  • Visual inspection of badge demo at /demo/sphinx-pytest-fixtures-badges/

tony added 9 commits April 3, 2026 06:30
…_pytest_fixtures

why: The new sphinx_pytest_fixtures extension uses docutils node types
that need type stubs for mypy, and its integration tests use a custom
pytest marker.
what:
- Add types-docutils to dev dependencies in pyproject.toml
- Add mypy override to ignore missing imports for sphinx_pytest_fixtures
  and sphinx_pytest_fixtures.* (extension lives under docs/_ext, outside
  the mypy src/tests search path)
- Register "integration" pytest marker for sphinx integration tests
- Update uv.lock with types-docutils resolution
…patibility

why: The new sphinx_pytest_fixtures extension auto-generates "Used by"
and "Returns" fields from introspection, so hand-written duplicates
cause double rendering. Cross-references also need :fixture: role
instead of :func: to resolve against the new py:fixture domain object.
what:
- Change :func:`user_path` to :fixture:`user_path` in home_user_name
  docstring
- Remove manual "Used by: :func:`config_file`, :func:`zshrc`" from
  user_path docstring (now auto-generated)
- Remove redundant Returns section from TestServer docstring (return
  type is inferred from the annotation)
…ixture documentation

why: pytest fixtures lack first-class Sphinx support — they render as
plain functions with full call signatures, hiding scope, dependencies,
and usage patterns. This extension treats fixtures as domain objects
with badge-based metadata, auto-generated usage snippets, and
cross-referenced dependency graphs.
what:
- __init__.py: extension setup, domain registration (py:fixture
  directive + :fixture: xref role), CSS self-registration
- _badges.py: scope/kind/autouse/deprecated badge nodes with
  WCAG AA contrast in light and dark mode
- _constants.py: field labels, config keys, table spec, regex,
  extension version, and store version constants
- _css.py: CSS class name constants for badge/card/index styling
- _detection.py: fixture introspection — marker extraction, scope
  detection, dependency classification, return type annotation,
  factory/async detection, TYPE_CHECKING forward-ref resolution
- _directives.py: PyFixtureDirective (py:fixture), AutofixturesDirective
  (bulk module discovery), AutofixtureIndexDirective (index table)
- _documenter.py: autodoc-style FixtureDocumenter for autofixture::
- _index.py: index table builder with linked return types via
  intersphinx, Flags column with scope/kind/autouse badges
- _metadata.py: FixtureMeta extraction — docstring summary, teardown
  summary from Teardown docstring section, usage snippet generation,
  forward-ref qualification
- _models.py: FixtureMeta and FixtureDep dataclasses, TypedDict for
  store entries, autofixture_index_node placeholder
- _store.py: environment-safe fixture store with merge-info collision
  detection (SPF009), finalization, and builtin URL resolution
- _transforms.py: doctree transforms — badge injection, field list
  augmentation, dependency rendering, callout insertion
- _validation.py: stable warning codes SPF001–SPF006 with configurable
  lint_level (warn or error)
- _static/css/sphinx_pytest_fixtures.css: 387 lines of responsive CSS
  for badge pills, fixture cards, index table, mobile stacking,
  dark-mode tokens, and focus-accessible tooltips
…page

why: The badge demo page needs fixtures that exercise every badge
permutation (scope × kind × state) without depending on libtmux's
real fixtures, which only cover a subset of combinations.
what:
- Add spf_demo_fixtures.py with 9 synthetic @pytest.fixture functions
  covering: plain, session/module/class scope, factory kind,
  override_hook kind, autouse, deprecated, and two combinations
  (session+factory, session+autouse)
…ctree

why: The extension must be listed in conf.py to activate, and the new
demo/ section needs a toctree entry so Sphinx includes it in the build.
what:
- Add "sphinx_pytest_fixtures" to extensions list in docs/conf.py
- Add demo/index to root toctree in docs/index.md
…irectives

why: The previous fixture reference used a single automodule dump that
rendered fixtures as plain functions. The new page uses autofixture
directives to show fixtures grouped by purpose (core, environment,
override hooks, factories) with a decision guide and configuration
reference.
what:
- Rewrite docs/api/testing/pytest-plugin/fixtures.md with Quick Start
  section, "Which Fixture Do I Need?" guide, autofixture-index table,
  grouped autofixture directives with inline examples, and confval
  configuration reference
- Update docs/api/testing/pytest-plugin/usage.md to change {func} xrefs
  to {fixture} xrefs (home_path, user_path, config_file, session,
  server, session_params, TestServer) to match the new domain objects
why: Badge rendering varies across themes, zoom levels, and light/dark
modes. A dedicated demo page provides a visual reference for all badge
permutations to verify rendering correctness during development.
what:
- Add docs/demo/index.md as demo hub with description and toctree
- Add docs/demo/sphinx-pytest-fixtures-badges.md with sections for
  every badge permutation: plain, scope (session/module/class), kind
  (factory/override_hook), state (autouse/deprecated), and
  combinations (session+factory, session+autouse)
…odules

why: Each extension submodule (_detection, _metadata, _store, _badges,
_directives, _validation, _index) has branching logic and edge cases
that must be tested in isolation without requiring full Sphinx builds.
what:
- 1,385 lines of pytest tests covering:
  - _is_pytest_fixture positive/negative detection
  - _get_user_deps filtering of hidden and builtin fixtures
  - _classify_deps partitioning into internal, builtin, external
  - _get_return_annotation with typing generics and forward refs
  - _is_factory heuristic for type[X] and Callable returns
  - _build_usage_snippet for resource, factory, override_hook kinds
  - _build_badge_group_node for scope/kind/autouse/deprecated badges
  - _qualify_forward_ref with TYPE_CHECKING block resolution
  - _extract_summary sentence boundary and EOF handling
  - _extract_teardown_summary from Teardown docstring sections
  - SPF001–SPF009 validation warnings and error-level lint
  - FixtureMeta.param_reprs wiring from :params: directive option
  - Store env_version guard and docname collision detection
  - CSS class contract tests and tabindex accessibility
  - Index table Flags column badge rendering
why: Unit tests verify individual functions but cannot catch issues in
the full Sphinx rendering pipeline — directive registration, doctree
transforms, cross-reference resolution, intersphinx link generation,
and CSS inclusion all require end-to-end Sphinx builds.
what:
- 1,853 lines of pytest integration tests (marked @pytest.mark.integration)
  using Sphinx's make_app test helper, covering:
  - AutofixturesDirective bulk discovery and source-order rendering
  - AutofixtureIndexDirective table structure and linked return types
  - PyFixtureDirective with :scope:, :kind:, :deprecated: options
  - :fixture: cross-reference resolution with short-name fallback
  - Badge rendering for all scope/kind/state permutations
  - Parametrized values as inline and enumerated lists
  - Teardown summary injection into yield-fixture callouts
  - "Used by" cross-document link generation
  - External URL rendering for dependency links
  - :usage: none suppression of auto-generated snippets
  - Excluded fixtures absent from index table
  - Scope/kind pair-index entry structure
  - SPF003 warning for yield fixtures via autodoc
  - Async fixture callout rendering
  - Text builder compatibility (no crash on non-HTML)
@tony tony force-pushed the sphinx-pytest-plugin-fixtures branch from c6d70a8 to cd0fa92 Compare April 3, 2026 13:46
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

❌ Patch coverage is 88.83469% with 206 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.17%. Comparing base (a0c0220) to head (11f5abf).

Files with missing lines Patch % Lines
docs/_ext/sphinx_pytest_fixtures/_transforms.py 64.28% 26 Missing and 19 partials ⚠️
tests/docs/_ext/test_sphinx_pytest_fixtures.py 91.19% 32 Missing and 4 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_documenter.py 72.27% 21 Missing and 7 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_detection.py 78.26% 16 Missing and 4 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_metadata.py 86.29% 9 Missing and 8 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_index.py 84.90% 12 Missing and 4 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_directives.py 92.47% 8 Missing and 6 partials ⚠️
docs/_ext/sphinx_pytest_fixtures/_store.py 85.89% 9 Missing and 2 partials ⚠️
docs/_ext/spf_demo_fixtures.py 71.42% 8 Missing ⚠️
...cs/_ext/test_sphinx_pytest_fixtures_integration.py 98.76% 3 Missing and 2 partials ⚠️
... and 4 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master     #656       +/-   ##
===========================================
+ Coverage   52.06%   67.17%   +15.10%     
===========================================
  Files          25       41       +16     
  Lines        2633     4478     +1845     
  Branches      403      624      +221     
===========================================
+ Hits         1371     3008     +1637     
- Misses       1093     1240      +147     
- Partials      169      230       +61     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tony added 2 commits April 3, 2026 08:51
why: Document the new extension, bug fix, and dev dependency for the
upcoming release notes.
what:
- Add "What's new" entry for sphinx_pytest_fixtures extension listing
  directives, roles, badges, responsive layout, WCAG compliance, and
  test count
- Add "Bug fixes" entry for session_params docstring fix
- Add "Development" entry for types-docutils dev dependency
…ppercase without colon

why: Bold field labels ("Depends on:", "Used by:") competed visually
with fixture names and section headings. The colon is redundant in a
grid layout where spatial alignment already signals key-value pairs.
what:
- Set font-weight: normal on fixture field-list dt elements
- Add text-transform: uppercase with 0.85em font-size and slight
  letter-spacing for a metadata-label treatment
- Hide the Sphinx-injected .colon span via display: none
@tony tony force-pushed the sphinx-pytest-plugin-fixtures branch from cd0fa92 to 4a0dc69 Compare April 3, 2026 13:51
@tony tony marked this pull request as ready for review April 3, 2026 14:28
@tony tony force-pushed the sphinx-pytest-plugin-fixtures branch from 11f5abf to 4a0dc69 Compare April 3, 2026 14:29
@tony tony merged commit 191208d into master Apr 3, 2026
18 checks passed
@tony tony deleted the sphinx-pytest-plugin-fixtures branch April 3, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant