Repository navigation
fix(corekit): read only a class's own annotations when building an Info constructor (#1692) - #1702
Merged
Merged
Conversation
…fo constructor (#1692) Below Python 3.10 (bpo-43901), cls.__annotations__ of a class declaring none is its nearest base's. info_final therefore built a field-less Info subclass's __init__ from Info's own __finalised__, __additional__ and __excluded__ on 3.6-3.9, and _nested_types resolved an inherited annotation in the subclass's namespace rather than the declaring class's. - infoclass: _own_annotations reads a class's own __dict__ below 3.10 and inspect.get_annotations from 3.10 on, where 3.14's lazy annotations are not in __dict__. info_final and _nested_types both use it. - tests: OwnAnnotationsTests pins the generated signature of a field-less subclass, a subclass of one, a class with fields and a diamond, plus a from_dict rebuild through a field-less subclass; the signature check also runs through the pre-3.10 reader on every version. The issue's three tests and the new ones fail on origin/main under 3.8 and 3.9 and pass here on 3.8, 3.9, 3.10 and 3.14.
Owner
Author
|
Verdict: GOOD TO GO at |
Contributor
|
Coverage: 89.47% (unit tier, Python 3.15,
Per-file detail: the |
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.
Please follow the guide below
You will be asked some questions, please read them carefully and answer honestly
Put an
xinto all the boxes [ ] relevant to your pull request (like that [x])Use Preview tab to see how your pull request will actually look like
Searched for similar pull requests
Followed the coding style (
make pylint,make mypy,make isort)make testpasses, and a test case covers the change (narrow runs only, below)Added a changelog entry under
docs/source/changelog/and regeneratedCHANGELOG.md, if the change is user-visible: N/A — centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657What is the purpose of your pull request?
Tick the commit type your subject line carries.
fix— corrects a defectfeat— adds a featureperf— changes performance, not behaviourrefactor— changes neither behaviour nor performancetest— tests onlydocs— documentation onlyci— workflows or build toolingrelease— bumps the version or rolls up a distributionchore— anything elseDescription of your pull request and other information
Before 3.10 (bpo-43901), a class with no annotations of its own returns its nearest base's from
cls.__annotations__. The new_own_annotationsreads the class's own__dict__below 3.10 and usesinspect.get_annotationsfrom 3.10 on. It cannot use__dict__alone there, because 3.14 keeps lazily evaluated annotations out of__dict__; this is the same split asProtocolBaseinprotocols/protocol.py.info_finaland_nested_typesboth call it now.(self, dict_=None, **kwargs)on every version. A diamond whose middle class is field-less now gets(self, a, c, d); before this fix 3.8 and 3.9 gave(self, c, a, d).from_dictnow rebuilds anInfofield that a field-less subclass inherits. Before, 3.8 and 3.9 resolved that field's annotation in the subclass's namespace and skipped it.Infoclasses, the old and new readers differ only for the four_MultiInfoclasses, and those generate no__init__. So no shipped class changes.cls.__annotations__[...]writes (protocols/data/internet/ipv4.py:74,:150,:345,ipv6.py:76) were measured on 3.8, 3.9, 3.10 and 3.14. Each target class declares its own annotations, and nothing leaked into any base. They are unchanged.Tests: the three tests from the issue and the new
OwnAnnotationsTestsfail onorigin/mainunder 3.8 and 3.9. With this fix they pass on 3.8, 3.9, 3.10 and 3.14, under both pytest and unittest. 15 related modules pass on every version. The one exception istest_final_enforcement.py::VersionPortabilityTestson 3.8, which already fails onmain(ast.unparse).infoclass.pycoverage from this test module goes from 66% to 72% on 3.14.Closes #1692