-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support nested namedtuple classes. #15064
base: master
Are you sure you want to change the base?
Support nested namedtuple classes. #15064
Conversation
This comment has been minimized.
This comment has been minimized.
I'll try to debug more but while it works now for mypy run directly, there's 2 test cases failing I think related to daemon mypy covered here. Any advice for what's needed to support this there would be helpful @ilevkivskyi edit: I have one guess on issue. The current change doesn't look to be defining nested class in right scope. For, class Foo:
class Bar:
...
reveal_type(Foo.Bar()) I see from typing import NamedTuple
class Foo(NamedTuple):
class Bar:
...
x: Bar
reveal_type(Foo.Bar()) I see |
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
@@ -166,6 +166,10 @@ def check_namedtuple_classdef( | |||
# And docstrings. | |||
if isinstance(stmt, ExpressionStmt) and isinstance(stmt.expr, StrExpr): | |||
continue | |||
# Allow nested classes. | |||
if isinstance(stmt, ClassDef): | |||
self.api.analyze_class(stmt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on exploring debugger I feel like this line is wrong. Main issue is for this case,
class A(NamedTuple):
class B:
...
x: B
B must be analyzed before field x's type is examined. If I drop this line then reveal_type(A.B) gives desired result and class gets analyzed I think here, but it introduces an error of Name "Bar" is not defined [name-defined]
from this line. I could maybe add scope here, but sorta feels right path is to analyze nested class defs before processing fields. Seems like I should defer for this and unsure on right way to do it.
edit: The main difference with nested non-namedtuple class is we analyze x's type during analyze_class_body_common after B's class def has been analyzed. For namedtuple case analyze_class_body_common happens but after all attributes have been analyzed first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what's the issue here, but you may need to set up a bunch of state/context in the semantic analyzer to allow nested classes to be processed correctly. For named tuples we probably don't set up all the context right now, since it's not needed to process attributes.
One idea would be to process named tuple class bodies normally (similar to regular classes) in the semantic analyzer even for named tuples, but we'd skip attribute definitions during this pass. The current namedtuple pass would then ignore everything else except attribute definitions. This would be a more complex change, however.
Fixes #5362 including test cases from that report + my own duplicate report. Fairly small change that directly allows class defs and analyzes them so that looking up later finds the needed symbol.
I suspect nested typeddict/enums might have similar issue given semanal_typeddict/enum don't appear to check class defs either.
edit: Was curious, typeddict ones looks to be forbidden in general both in the pep and other type checkers. Nested enum version of this does work with mypy somehow. I'm unsure why though as semanal_enum never examines class defs.