pytest_plugin(refactor[types]): Type improvements#521
Merged
Conversation
why: `_ENV` from `_internal/run.py` leaked into public API signatures, causing Sphinx to render its full expanded form (`Mapping[bytes, ...] | Mapping[str, ...]`) in the docs instead of a linkable name. `dict[str, str]` was also used ad-hoc in test annotations without a shared name. what: - Add `Env: t.TypeAlias = _ENV` as public alias for the subprocess env type; replace `env: _ENV | None` in all public signatures - Add `GitCommitEnvVars: t.TypeAlias = dict[str, str]` for the narrower git-commit env type; replace `git_commit_envvars: _ENV` in fixture parameters - Update test TYPE_CHECKING imports to use `GitCommitEnvVars`
…reateRepoFn why: "PytestFixture" is redundant context inside pytest_plugin.py; the shorter name aligns with the existing Fn-suffix convention used by CreateRepoPostInitFn. what: - Rename Protocol class in src/libvcs/pytest_plugin.py - Update all import sites and type annotations across tests and README.md
…nitFn for cross-referencing why: The fixture summary table rendered return types like `CreateRepoFn` as plain text instead of hyperlinks. sphinx_autodoc_pytest_fixtures emits :class:`~libvcs.pytest_plugin.CreateRepoFn` for every fixture returning that type, but Sphinx silently degrades to plain text when the name is absent from the Python domain's object index — which it was, since the Protocol classes had no autoclass directive anywhere. what: - Add a "Types" section to docs/api/pytest-plugin.md with autoclass directives for CreateRepoFn and CreateRepoPostInitFn - Use :special-members: __call__ to expose the callback contract - Use :exclude-members: __init__, _abc_impl, _is_protocol to suppress Protocol internals surfaced by gp-sphinx's global autodoc defaults (private-members: True, autodoc_class_signature: "separated")
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #521 +/- ##
==========================================
- Coverage 57.07% 57.05% -0.03%
==========================================
Files 41 41
Lines 6216 6219 +3
Branches 1074 1074
==========================================
Hits 3548 3548
- Misses 2144 2147 +3
Partials 524 524 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…ars TypeAlias why: sphinx's automodule :members: skips module-level TypeAliases whose value has a __module__ that differs from the documented module (e.g. dict[str, str] has __module__ = 'builtins'). Static source analysis via ModuleAnalyzer.attr_docs only picks up the member when a docstring is present. Without it, GitCommitEnvVars never enters the py:data inventory and cannot be cross-referenced from the fixture summary table. what: - Add one-line docstring to GitCommitEnvVars: TypeAlias so sphinx's static analyser includes it in automodule :members: output, registering it as a py:data entry in the Sphinx inventory
…encing why: The fixture summary table rendered by sphinx-autodoc-pytest-fixtures emits :class: cross-references for every fixture's return type. For GitCommitEnvVars (now a py:data entry after gaining a docstring) to resolve as a clickable link in that table, it must appear in the autodata directive that populates the ## Types section — the same pattern used for CreateRepoFn and CreateRepoPostInitFn. what: - Add .. autodata:: libvcs.pytest_plugin.GitCommitEnvVars at the top of the ## Types block so the type is both documented and reachable as an anchor from the fixture table link
…s: links why: sphinx-autodoc-pytest-fixtures wraps every fixture return-type identifier in a :class: cross-reference so that Sphinx and intersphinx can resolve it. Sphinx 8.x's Python domain only searches py:class and py:exception entries for :class: references; TypeAliases land in the inventory as py:data instead. The result is a broken (unlinked) type name in the fixture summary table for any TypeAlias return type. The same handler was added to unihan-etl's conf.py for the same reason; this brings libvcs in line with that approach. what: - Import typing as t at the top of conf.py - Guard docutils / sphinx type imports under TYPE_CHECKING so mypy gets accurate types without a runtime dependency on types-docutils being present in every environment - Add _on_missing_class_reference(): when a :class: reference cannot be resolved, fall back to searching all Python-domain objects so that py:data entries (TypeAliases) are found and linked - Add setup(app) to wire the handler into Sphinx's missing-reference event
why: env.get_domain() returns Domain, the base class, which does not declare find_obj(). mypy correctly flags this as an attr-defined error because find_obj is defined only on PythonDomain. what: - Import PythonDomain from sphinx.domains.python under TYPE_CHECKING - Annotate py_domain as PythonDomain with a type: ignore[assignment] comment to satisfy mypy while keeping the cast lightweight at runtime
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cleans up the public type surface of
libvcs.pytest_pluginso that downstream projects can import stable, named types and so the Sphinx docs render cross-reference links rather than expanded type strings.Env(public alias for the subprocess env mapping, replacing the private_ENVin allenv:parameters) andGitCommitEnvVars(dict[str, str], the type of thegit_commit_envvarsfixture return value)CreateRepoPytestFixtureFn→CreateRepoFn; the "PytestFixture" infix was redundant insidepytest_plugin.pyand inconsistent with theFn-suffix pattern used byCreateRepoPostInitFnautoclassentries forCreateRepoFnandCreateRepoPostInitFnindocs/api/pytest-plugin.mdsosphinx_autodoc_pytest_fixturesresolves them as hyperlinks in the fixture summary table (previously rendered as plain text because the classes were absent from Sphinx's Python domain index)Breaking change
Replace any
from libvcs.pytest_plugin import CreateRepoPytestFixtureFnwithCreateRepoFn.Test plan
uv run ruff check . --fix --show-fixes; uv run ruff format .; uv run mypy; uv run py.test --reruns 0just build-docs— verifyCreateRepoFnrenders as a hyperlink in the fixture summary table