Repository navigation
Implement default values on NamedTuple #2719
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
Changes from 1 commit
40c32d3
def572f
8ce550a
6ba17b3
df36213
44f381f
c8715b8
6ad489b
291c059
88b63fb
1fe9792
51c3dc4
91acfc7
3df509a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -294,6 +294,10 @@ class X(NamedTuple): | |
| y: str | ||
|
|
||
| reveal_type(X._fields) # E: Revealed type is 'Tuple[builtins.str, builtins.str]' | ||
| reveal_type(X._field_types) # E: Revealed type is 'builtins.dict[builtins.str, Any]' | ||
| reveal_type(X._field_defaults) # E: Revealed type is 'builtins.dict[builtins.str, Any]' | ||
|
|
||
| [builtins fixtures/dict.pyi] | ||
|
|
||
| [case testNewNamedTupleUnit] | ||
| # flags: --fast-parser --python-version 3.6 | ||
|
|
@@ -349,10 +353,17 @@ import typing | |
|
|
||
| class X(typing.NamedTuple): | ||
| x: int | ||
| y = None # type: int # E: Invalid statement in NamedTuple definition; expected "field_name: field_type" | ||
| x.__init__: int # E: Invalid statement in NamedTuple definition; expected "field_name: field_type" | ||
| y = 1 | ||
| x.x: int | ||
| z: str = 'z' | ||
| aa: int # E: Non-default NamedTuple fields cannot follow default fields | ||
| aa: int | ||
|
|
||
| [out] | ||
| main:6: error: Invalid statement in NamedTuple definition; expected "field_name: field_type" | ||
| main:7: error: Invalid statement in NamedTuple definition; expected "field_name: field_type" | ||
| main:7: error: Type cannot be declared in assignment to non-self attribute | ||
| main:7: error: "int" has no attribute "x" | ||
| main:9: error: Non-default NamedTuple fields cannot follow default fields | ||
|
|
||
| [builtins fixtures/list.pyi] | ||
|
|
||
|
|
@@ -380,7 +391,7 @@ main:8: error: Unsupported type Type["N"] | |
|
|
||
| [case testNewNamedTupleWithDefaults] | ||
| # flags: --fast-parser --python-version 3.6 | ||
| from typing import NamedTuple | ||
| from typing import List, NamedTuple, Optional | ||
|
|
||
| class X(NamedTuple): | ||
| x: int | ||
|
|
@@ -390,6 +401,31 @@ reveal_type(X(1)) # E: Revealed type is 'Tuple[builtins.int, builtins.int, fall | |
| reveal_type(X(1, 2)) # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.X]' | ||
|
|
||
| X(1, 'a') # E: Argument 2 to "X" has incompatible type "str"; expected "int" | ||
| X(1, z=3) # E: Unexpected keyword argument "z" for "X" | ||
|
|
||
| class HasNone(NamedTuple): | ||
| x: int | ||
| y: Optional[int] = None | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for writing more tests. I will be even more happy if you add few more tests for these (also with |
||
|
|
||
| reveal_type(HasNone(1)) # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.HasNone]' | ||
|
|
||
| class Parameterized(NamedTuple): | ||
| x: int | ||
| y: List[int] = [] | ||
|
|
||
| reveal_type(Parameterized(1)) # E: Revealed type is 'Tuple[builtins.int, builtins.list[builtins.int], fallback=__main__.Parameterized]' | ||
| Parameterized(1, ['not an int']) # E: List item 0 has incompatible type "str" | ||
|
|
||
| class Default: | ||
| pass | ||
|
|
||
| class UserDefined(NamedTuple): | ||
| x: Default = Default() | ||
|
|
||
| reveal_type(UserDefined()) # E: Revealed type is 'Tuple[__main__.Default, fallback=__main__.UserDefined]' | ||
| reveal_type(UserDefined(Default())) # E: Revealed type is 'Tuple[__main__.Default, fallback=__main__.UserDefined]' | ||
|
|
||
| [builtins fixtures/list.pyi] | ||
|
|
||
| [case testNewNamedTupleWrongType] | ||
| # flags: --fast-parser --python-version 3.6 | ||
|
|
@@ -401,14 +437,15 @@ class X(NamedTuple): | |
|
|
||
| [case testNewNamedTupleInheritance] | ||
| # flags: --fast-parser --python-version 3.6 | ||
| from typing import NamedTuple | ||
| from typing import cast, NamedTuple | ||
|
|
||
| class X(NamedTuple): | ||
| x: int | ||
| x: str | ||
| y: int = 3 | ||
|
|
||
| class Y(X): | ||
| def method(self) -> int: | ||
| return self.x + self.y | ||
| def method(self) -> str: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test calling base class |
||
| return self.x + cast(str, self.y) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be honest, I don't like casts of unsafe expressions in tests, but formally this test works as it should.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll just change it to access |
||
|
|
||
| reveal_type(Y(1)) # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.Y]' | ||
| reveal_type(Y('a')) # E: Revealed type is 'Tuple[builtins.str, builtins.int, fallback=__main__.Y]' | ||
| Y(y=1, x='1').method() | ||
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 would add few more test cases. For example, the
Nonedefault value mentioned above, user defined classes as field types, wrong types likex: str = 5, etc.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.
Also it makes sense to add tests with classes inheriting form a named tuple with default values.
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.
Thanks for these suggestions! The
x: str = 5case actually wasn't checked, and I had some trouble coming up with a way to make that throw an error, because the body of the NamedTuple is currently almost completely ignored. I managed to fix it by typechecking the body like a normal class. This has the side effect that some errors (stuff likex[0]: int) produce multiple errors on the same line, but that doesn't seem like a big deal.