stubgen: don't recurse forever on a class that refers back to itself - #21822
Open
Eljees wants to merge 1 commit into
Open
stubgen: don't recurse forever on a class that refers back to itself#21822Eljees wants to merge 1 commit into
Eljees wants to merge 1 commit into
Conversation
generate_class_stub() recurses into every attribute whose value is a class defined in the same module, so a class that exposes itself (C.C = C), or a pair of classes that expose each other, makes it recurse until Python raises RecursionError. Skip an attribute whose value is the class currently being generated or any class enclosing it: such an attribute is a back reference, not a nested class. Fixes python#11989
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.
Fixes #11989.
InspectionStubGenerator.generate_class_stub()walks the attributes of a class and recurses into every attribute whose value is a class defined in the same module. A class that exposes itself —C.C = C, which is what the issue's_socket.CAPI-style extension types do — therefore makes it recurse into itself until Python raisesRecursionError.The fix skips an attribute whose value is the class currently being generated or any class enclosing it. Such an attribute is a back reference, not a nested class, so nothing that was previously emitted is lost.
Note that comparing names (
attr != class_name), as suggested in the issue, only covers half of the cases: when two classes in the same module expose each other (P.C = C; C.P = P) the names differ and the recursion is unchanged. The identity walk upClassInfo.parenthandles both; the branch already carriedparent_class=class_info, so the chain was available.Tests: two cases in
mypy/test/teststubgen.py— a self-referential class and a mutually referential pair. Both raiseRecursionErroron master and pass with the change; the fullteststubgen.pysuite (367 tests) is green, andself-check,ruffandblackare clean.