Repository navigation
DM-56680: Degrade autotypes enum-member references when a build reuses pickled doctrees - #555
Merged
Merged
Conversation
A model that inherits a field whose Annotated metadata names enum members renders that annotation from its source text, because autodoc's attribute documenter copies each base class's source annotations onto the class it documents. The xrefs sub-extension recognized the resulting ExecutionPhase.PENDING references only by reading that copy back out of the class's __annotations__. A build that reuses pickled doctrees never runs autodoc, so the copy was missing and the references warned under nitpicky mode. Read the source annotations of every class in the MRO from Sphinx's ModuleAnalyzer instead, which is where autodoc gets them and which depends on nothing the read phase did. The sys.modules scans behind the typing registry and the MRO root namespace had the same kind of dependency: they saw only what autodoc had imported. Import the documented modules, known from the pickled build environment, before scanning. Also keep each cached class alive in the fragment cache, so the id() an entry is filed under cannot be reused by another class.
Documentation preview
Build |
4 tasks
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.
Summary
Fixes #554. With Sphinx 9, a nitpicky build that reuses pickled doctrees (for example
docs-linkcheckafterdocsover one doctree directory) warnedpy:class reference target not found: ExecutionPhase.PENDINGfor a model that inherits a field whoseAnnotatedmetadata names enum members.Cause. The issue's working assumption is right, and is now checked against Sphinx's source: autodoc's attribute documenter (
AttributeDocumenter.update_annotations) copies the source text of each MRO class's annotations onto the class it documents, for attributes that class doesn't annotate itself.documenteer.ext.autotypes.xrefsrecognized the resulting references only by reading that copy back from the class's__annotations__. A doctree-reusing build never runs autodoc, so the copy isn't there.Fix.
_class_annotation_valuesnow also reads each MRO class's source annotations from Sphinx'sModuleAnalyzer, the same place autodoc gets them. This depends on nothing the read phase did._project_typing_registryand_mro_root_namespace(the third to-do in the issue) had the same kind of dependency: they scansys.modules, which holds only what has been imported so far, and cache the result. Both now import the documented modules first, using the names stored in the pickled build environment. None of the existing test roots showed a failure from this in a two-pass build, because earlier rungs usually import the package anyway, so this part is a precaution covered by unit tests rather than a fix for an observed failure.id(cls)alone, so a garbage-collected class's entry could be served to a new class at the same address. The new tests exposed this as an order-dependent test failure.Behavior change to be aware of. The fragment set for a class now always includes the names in the metadata positions of its MRO's source annotations, not only when autodoc happened to copy them. So
ExecutionPhase.PENDINGalso degrades if it is referenced in the context of the base class that writes it. Names that no annotation of the class's MRO writes still warn.Validation steps
nox -s "test-3.13(sphinx='8')" "test-3.13(sphinx='9')": 1180 passed on Sphinx 9, Sphinx 8 session also green.tests/ext/autotypes_test.pyon Python 3.14 with Sphinx 9: 50 passed.nox -s lintandnox -s "typing-3.13(sphinx='8')" "typing-3.13(sphinx='9')": clean.xrefs.pychange.sphinx-build -nprocesses over thetest-autotypes-annotatedroot sharing a doctree directory (-b dummy, then-b html): threeExecutionPhase.*warnings before the fix, none after.Not done: I did not run Safir's
nox -s docs docs-linkcheckagainst this branch. The test root models the Safir shape (uws.JobinheritingSerializedJob.phase), but confirming on Safir itself is still open.References
nitpick_ignoreworkaround to remove after a release with this fix)