-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Support additional args to namedtuple() #5215
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
Conversation
@@ -1,7 +1,7 @@ | |||
[case testNamedTupleUsedAsTuple] | |||
from collections import namedtuple | |||
|
|||
X = namedtuple('X', ['x', 'y']) | |||
X = namedtuple('X', 'x y') |
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.
My change ends up requiring list
to exist in all of these tests. It was easier to just change the namedtuple call than to add [builtins fixtures/list.pyi]
everywhere. I left a few with the list to make sure we test that code path.
test-data/unit/check-namedtuple.test
Outdated
|
||
[builtins fixtures/bool.pyi] | ||
|
||
[case testNamedTupleDefaults-skip] |
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.
will work on enabling this next (#4788)
@@ -13,14 +13,6 @@ s = b'foo' | |||
from typing import TypeVar | |||
T = TypeVar(u'T') | |||
|
|||
[case testNamedTupleUnicode] |
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.
This no longer worked because my stub for namedtuple just has str. Apparently we don't support Text
in the test stubs, so I just moved this test case to the pythoneval tests.
@@ -27,3 +27,4 @@ class int: | |||
class str: pass | |||
class bool: pass | |||
class function: pass | |||
class ellipsis: pass |
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.
This was needed because a few tests that import collections didn't have ...
available in their fixtures, and my stub for namedtuple uses it.
@@ -138,10 +138,6 @@ MypyFile:1( | |||
from collections import namedtuple | |||
N = namedtuple('N') # E: Too few arguments for namedtuple() | |||
|
|||
[case testNamedTupleWithTooManyArguments] |
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.
This test stopped working because this error is now caught during type checking rather than semanal.
mypy/semanal_namedtuple.py
Outdated
return items, types, num_defaults, ok | ||
|
||
def extract_defaults_from_arg(self, call: CallExpr, arg: Expression) -> int: | ||
if not isinstance(arg, (ListExpr, TupleExpr)): |
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.
Technically the defaults argument can be any iterable, but it doesn't seem particularly useful to support that.
Did anyone else review this yet? It seems oddly stalled (I wonder what happened around June 13, a number of PRs saw their last activity around that date). |
No. As far as I can see, it's ready for review. |
I can review it later today. |
Thanks Ivan!
|
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 the fixes! Here are few comments.
mypy/checkexpr.py
Outdated
@@ -200,8 +200,14 @@ def analyze_var_ref(self, var: Var, context: Context) -> Type: | |||
def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: | |||
"""Type check a call expression.""" | |||
if e.analyzed: | |||
if isinstance(e.analyzed, NamedTupleExpr) and not e.analyzed.is_typed: | |||
# Type check the arguments, but ignore the results. |
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.
Could you please add a comment here that generating correct errors in call here depends on the typeshed stub?
mypy/semanal_namedtuple.py
Outdated
info = self.build_namedtuple_typeinfo(name, items, types, {}) | ||
if num_defaults > 0: | ||
default_items = { | ||
arg_name: EllipsisExpr() |
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.
This is a bit hacky so at least deserves a comment why we use EllipsisExpr()
instead of using actual expressions.
If possible, I would just use the actual expressions here.
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 think I can get the actual expressions, but I'm not sure I understand why that would be better. It would make the code more complicated and I don't see much of an advantage.
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.
If this is really complex then it maybe doesn't make sense. In general now that we work on mypyc it is simpler if we keep all real info somewhere in the AST.
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.
Oh yes, this makes sense in the context of mypyc. It isn't too bad actually, I'll just make the change.
mypy/semanal_namedtuple.py
Outdated
if call.arg_kinds != [ARG_POS, ARG_POS]: | ||
# Typed namedtuple doesn't support additional arguments. | ||
if fullname == 'typing.NamedTuple': | ||
return self.fail_namedtuple_arg("Too many arguments for namedtuple()", call) |
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 capitalize namedtuple
-> NamedTuple
due to the proposed change.
test-data/unit/check-namedtuple.test
Outdated
A = namedtuple('A', 'a b') | ||
B = namedtuple('B', 'a b', rename=1) | ||
C = namedtuple('C', 'a b', rename='not a bool') # E: Argument "rename" to "namedtuple" has incompatible type "str"; expected "int" | ||
# This works correctly but also produces "mypy/test-data/unit/lib-stub/collections.pyi:3: note: "namedtuple" defined here" |
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.
You can add an [out]
section at the end that lists all error verbatim instead of using # E:
typename: str, | ||
field_names: Union[str, Iterable[str]], | ||
*, | ||
# really int but many tests don't have bool available |
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 think this should read "really bool".
Thanks for the review! I will push an update soon. |
Will fix the CI failure later today. |
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! One last comment. Could you please also fix the self-check? You can merge it after all tests pass.
mypy/semanal_namedtuple.py
Outdated
if len(defaults) > 0: | ||
default_items = { | ||
# We don't have the actual argument expressions any more, so we | ||
# just use Ellipsis for all defaults. |
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.
This comment is now outdated.
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.
Yes, removed.
Thanks for catching that! I'll close the other ones too. |
By letting typeshed do the work.
Fixes #2124, #2127, #4788.