-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Support recursive NamedTuple #9397
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
Comments
To illustrate the bug with a more "realistic" example, here is the top of an @dataclass
class Order: # the Context
customer: Customer
cart: Sequence[LineItem]
promotion: Optional[Callable[['Order'], float]] = None # the Strategy Mypy 0.910 accepts the code above, but crashes with the code below: class Order(NamedTuple):
customer: Customer
cart: Sequence[LineItem]
promotion: Optional[Callable[['Order'], float]] = None # the Strategy I put The error:
|
I've added the "crash" label in addition to the "bug" label — although the original report is a bug, @ramalho's example is clearly a crash. |
I opened #12629 to discuss the crash. This issue should be focused on the enhancement request (support for recursive namedtuples). Any crashes should get their own issue. |
I believe the source of the problem is in the
Before the final iteration, the reference is considered incomplete. In the final iteration, it is still a placeholder, and reported as an error. Also, the type is deemed to be Any, rather than the type of the class being defined. Why this does not happen with non-NamedTuple classes, I cannot tell. mypy can form a correct TypeInfo for the class and for each of its members.
|
Reworks `mypy.semanal_namedtuple.analyze_namedtuple_classdef` so it can complete recursive type references on a second pass. The accompanying test updates raise some questions: 1. Add odd error cropped up in `check-incremental.test::testIncrementalWithDifferentKindsOfNestedTypesWithinMethod` which made `lookup_fully_qualified` throw an error: E AssertionError: Cannot find component 'NT1@11' for 'b.NT1@11' Somehow this is prevented by a call to `reveal_type` (regardless of value). I cannot determine whether this is caused by this change in itself, or if it stumbled upon a separate issue. 2. In `check-namedtuple.test::testSelfRefNT4`, reveal_type for an item-accessed named tuple value now returns `builtins.object` instead of `Any`. While it is beyond the scope of this PR to fix type-inference for named tuple item access in general, it is unclear whether this an improvement or a slight regression?
Reworks `mypy.semanal_namedtuple.analyze_namedtuple_classdef` so it can complete recursive type references on a second pass. This addresses python#9397. The accompanying test updates raise some questions: 1. Add odd error cropped up in `check-incremental.test::testIncrementalWithDifferentKindsOfNestedTypesWithinMethod` which made `lookup_fully_qualified` throw an error: E AssertionError: Cannot find component 'NT1@11' for 'b.NT1@11' Somehow this is prevented by a call to `reveal_type` (regardless of value). I cannot determine whether this is caused by this change in itself, or if it stumbled upon a separate issue. 2. In `check-namedtuple.test::testSelfRefNT4`, reveal_type for an item-accessed named tuple value now returns `builtins.object` instead of `Any`. While it is beyond the scope of this PR to fix type-inference for named tuple item access in general, it is unclear whether this an improvement or a slight regression?
This is done by letting `mypy.semanal_namedtuple.analyze_namedtuple_classdef` complete recursive type references in a subsequent pass. Fixes python#9397.
This now works on master with |
🐛 Bug Report
NamedTuple's appear to behave in unexpected ways with recursion, especially when compared to frozen dataclasses (which are rather similar, as far as the user is concerned).
To Reproduce
Produces a "mypy-sample1.py:5: error: Cannot resolve name "A" (possible cyclic definition)". However,
Passes MyPy just fine, and as far as a user is concerned, presents a very similar surface for MyPy to type check (i.e. both have a read-only attribute a which is either None or of class A).
Expected Behavior
The expected behaviour would be that both NamedTuple and frozen dataclass behave the same, as NamedTuple and frozen dataclasses present logically similar behaviour with regards to the attribute 'a'.
Actual Behavior
In addition to the odd behaviour with cycle checker triggering on NamedTuple but not on dataclasses, it's possible to fool the cycle checker completely and have MyPy crash by recursing too far (e.g. issue #8695 and although that issue has been reported with a recursive type that could never be instantiated, I've encountered the same behaviour with type definitions that can be instantiated, but not in a minimal example friendly format). I think this specific behaviour is the root cause, as the real problem is that for some reason NamedTuple's are behaving differently to what would be expected.
Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: