Skip to content

Clarify namedtuple member rules #1979

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions conformance/results/mypy/namedtuples_define_class.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,19 @@ namedtuples_define_class.py:46: error: Argument 2 to "Point" has incompatible ty
namedtuples_define_class.py:47: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type]
namedtuples_define_class.py:48: error: Too many arguments for "Point" [call-arg]
namedtuples_define_class.py:49: error: Unexpected keyword argument "other" for "Point" [call-arg]
namedtuples_define_class.py:59: error: Non-default NamedTuple fields cannot follow default fields [misc]
namedtuples_define_class.py:98: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
namedtuples_define_class.py:105: error: NamedTuple should be a single base [misc]
namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]
namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg]
namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc]
namedtuples_define_class.py:76: error: NamedTuple field name cannot start with an underscore: _y [misc]
namedtuples_define_class.py:86: error: Non-default NamedTuple fields cannot follow default fields [misc]
namedtuples_define_class.py:125: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
namedtuples_define_class.py:132: error: NamedTuple should be a single base [misc]
"""
conformance_automated = "Fail"
errors_diff = """
Line 79: Expected 1 errors
Line 69: Expected 1 errors
Line 106: Expected 1 errors
Line 59: Unexpected errors ['namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]']
Line 65: Unexpected errors ['namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg]']
Line 67: Unexpected errors ['namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc]']
"""
11 changes: 9 additions & 2 deletions conformance/results/mypy/namedtuples_define_functional.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ namedtuples_define_functional.py:43: error: Argument "x" to "Point6" has incompa
namedtuples_define_functional.py:52: error: "namedtuple()" has duplicate field name "a" [misc]
namedtuples_define_functional.py:53: error: "namedtuple()" field name "def" is a keyword [misc]
namedtuples_define_functional.py:54: error: "namedtuple()" field name "def" is a keyword [misc]
namedtuples_define_functional.py:66: error: Missing positional argument "a" in call to "NT5" [call-arg]
namedtuples_define_functional.py:55: error: "namedtuple()" field name "_d" starts with an underscore [misc]
namedtuples_define_functional.py:66: error: Name "NT5" already defined on line 57 [no-redef]
namedtuples_define_functional.py:67: error: Missing positional argument "_1" in call to "NT5" [call-arg]
namedtuples_define_functional.py:68: error: Too many arguments for "NT5" [call-arg]
namedtuples_define_functional.py:69: error: Missing positional arguments "abc", "_1" in call to "NT5" [call-arg]
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 66: Unexpected errors ['namedtuples_define_functional.py:66: error: Name "NT5" already defined on line 57 [no-redef]']
Line 67: Unexpected errors ['namedtuples_define_functional.py:67: error: Missing positional argument "_1" in call to "NT5" [call-arg]']
Line 68: Unexpected errors ['namedtuples_define_functional.py:68: error: Too many arguments for "NT5" [call-arg]']
"""
2 changes: 1 addition & 1 deletion conformance/results/mypy/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "mypy 1.15.0"
test_duration = 2.1
test_duration = 2.0
14 changes: 9 additions & 5 deletions conformance/results/pyre/namedtuples_define_class.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ namedtuples_define_class.py:46:14 Incompatible parameter type [6]: In call `Poin
namedtuples_define_class.py:47:17 Incompatible parameter type [6]: In call `Point.__init__`, for argument `units`, expected `str` but got `int`.
namedtuples_define_class.py:48:5 Too many arguments [19]: Call `Point.__init__` expects 3 positional arguments, 4 were provided.
namedtuples_define_class.py:49:6 Unexpected keyword [28]: Unexpected keyword argument `other` to call `Point.__init__`.
namedtuples_define_class.py:59:4 Missing named tuple default [74]: Named tuple field without default value may not be preceded by a field with default value.
namedtuples_define_class.py:79:4 Invalid assignment [41]: Cannot reassign final attribute `x`.
namedtuples_define_class.py:98:18 Incompatible parameter type [6]: In call `Property.__init__`, for 2nd positional argument, expected `str` but got `float`.
namedtuples_define_class.py:105:23 Invalid inheritance [39]: If NamedTuple is included as a base class, the class may not extend anything else besides Generic.
namedtuples_define_class.py:67:0 Unable to unpack [23]: Unable to unpack 3 values, 2 were expected.
namedtuples_define_class.py:86:4 Missing named tuple default [74]: Named tuple field without default value may not be preceded by a field with default value.
namedtuples_define_class.py:106:4 Invalid assignment [41]: Cannot reassign final attribute `x`.
namedtuples_define_class.py:125:18 Incompatible parameter type [6]: In call `Property.__init__`, for 2nd positional argument, expected `str` but got `float`.
namedtuples_define_class.py:132:23 Invalid inheritance [39]: If NamedTuple is included as a base class, the class may not extend anything else besides Generic.
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 69: Expected 1 errors
Line 76: Expected 1 errors
Line 67: Unexpected errors ['namedtuples_define_class.py:67:0 Unable to unpack [23]: Unable to unpack 3 values, 2 were expected.']
"""
8 changes: 6 additions & 2 deletions conformance/results/pyre/namedtuples_define_functional.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ namedtuples_define_functional.py:42:17 Incompatible parameter type [6]: In call
namedtuples_define_functional.py:43:14 Incompatible parameter type [6]: In call `Point6.__init__`, for argument `x`, expected `int` but got `float`.
namedtuples_define_functional.py:52:0 Duplicate parameter [65]: Duplicate parameter name `a`.
namedtuples_define_functional.py:52:0 Duplicate parameter [65]: Duplicate parameter name `a`.
namedtuples_define_functional.py:66:0 Missing argument [20]: Call `NT5.__init__` expects argument `a`.
namedtuples_define_functional.py:58:0 Unexpected keyword [28]: Unexpected keyword argument `abc` to call `NT5.__init__`.
namedtuples_define_functional.py:60:0 Unexpected keyword [28]: Unexpected keyword argument `_1` to call `NT6.__init__`.
namedtuples_define_functional.py:69:0 Missing argument [20]: Call `NT5.__init__` expects argument `a`.
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 58: Unexpected errors ['namedtuples_define_functional.py:58:0 Unexpected keyword [28]: Unexpected keyword argument `abc` to call `NT5.__init__`.']
Line 60: Unexpected errors ['namedtuples_define_functional.py:60:0 Unexpected keyword [28]: Unexpected keyword argument `_1` to call `NT6.__init__`.']
"""
2 changes: 1 addition & 1 deletion conformance/results/pyre/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyre 0.9.23"
test_duration = 3.9
test_duration = 7.3
12 changes: 7 additions & 5 deletions conformance/results/pyright/namedtuples_define_class.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ namedtuples_define_class.py:47:24 - error: Argument of type "Literal[3]" cannot
  "Literal[3]" is not assignable to "str" (reportArgumentType)
namedtuples_define_class.py:48:22 - error: Expected 3 positional arguments (reportCallIssue)
namedtuples_define_class.py:49:23 - error: No parameter named "other" (reportCallIssue)
namedtuples_define_class.py:59:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues)
namedtuples_define_class.py:79:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride)
namedtuples_define_class.py:98:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"
namedtuples_define_class.py:69:20 - error: Expected 2 positional arguments (reportCallIssue)
namedtuples_define_class.py:86:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues)
namedtuples_define_class.py:106:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride)
namedtuples_define_class.py:125:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"
  "float" is not assignable to "str" (reportArgumentType)
namedtuples_define_class.py:105:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues)
namedtuples_define_class.py:132:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues)
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 76: Expected 1 errors
"""
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ namedtuples_define_functional.py:43:17 - error: Argument of type "float" cannot
namedtuples_define_functional.py:52:31 - error: Names within a named tuple must be unique (reportGeneralTypeIssues)
namedtuples_define_functional.py:53:33 - error: Field names cannot be a keyword (reportGeneralTypeIssues)
namedtuples_define_functional.py:54:33 - error: Field names cannot be a keyword (reportGeneralTypeIssues)
namedtuples_define_functional.py:66:1 - error: Argument missing for parameter "a" (reportCallIssue)
namedtuples_define_functional.py:60:1 - error: Argument missing for parameter "_d" (reportCallIssue)
namedtuples_define_functional.py:60:13 - error: No parameter named "_1" (reportCallIssue)
namedtuples_define_functional.py:69:1 - error: Argument missing for parameter "a" (reportCallIssue)
"""
conformance_automated = "Pass"
conformance_automated = "Fail"
errors_diff = """
Line 60: Unexpected errors ['namedtuples_define_functional.py:60:1 - error: Argument missing for parameter "_d" (reportCallIssue)', 'namedtuples_define_functional.py:60:13 - error: No parameter named "_1" (reportCallIssue)']
"""
4 changes: 2 additions & 2 deletions conformance/results/pyright/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pyright 1.1.398"
test_duration = 2.3
version = "pyright 1.1.399"
test_duration = 1.5
28 changes: 22 additions & 6 deletions conformance/results/pytype/namedtuples_define_class.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,21 @@ namedtuples_define_class.py:49:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: i
p10 = Point(1, 2, "", other="") # E
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m

namedtuples_define_class.py:95:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Any [assert-type]
namedtuples_define_class.py:69:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Function Point2.__new__ expects 3 arg(s), got 4 [wrong-arg-count]

p12 = Point2(1, 2, "") # E
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m

namedtuples_define_class.py:74:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: collections.namedtuple argument '_y' is not a valid typename or field name. [invalid-namedtuple-arg]

class Point3(NamedTuple):
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
x: int
\u001b[1m\u001b[31m~~~~~~~~~~\u001b[39m\u001b[0m
_y: int # E: illegal field name
\u001b[1m\u001b[31m~~~~~~~~~~~\u001b[39m\u001b[0m

namedtuples_define_class.py:122:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Any [assert-type]

assert_type(pr1[1], float)
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
Expand All @@ -69,13 +83,15 @@ conformance_automated = "Fail"
errors_diff = """
Line 32: Expected 1 errors
Line 33: Expected 1 errors
Line 59: Expected 1 errors
Line 79: Expected 1 errors
Line 98: Expected 1 errors
Line 105: Expected 1 errors
Line 76: Expected 1 errors
Line 86: Expected 1 errors
Line 106: Expected 1 errors
Line 125: Expected 1 errors
Line 132: Expected 1 errors
Line 27: Unexpected errors ['namedtuples_define_class.py:27:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Union[int, str] [assert-type]']
Line 28: Unexpected errors ['namedtuples_define_class.py:28:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Union[int, str] [assert-type]']
Line 29: Unexpected errors ['namedtuples_define_class.py:29:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: tuple[Union[int, str], ...] [assert-type]']
Line 30: Unexpected errors ['namedtuples_define_class.py:30:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: tuple[Union[int, str], ...] [assert-type]']
Line 95: Unexpected errors ['namedtuples_define_class.py:95:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Any [assert-type]']
Line 74: Unexpected errors ["namedtuples_define_class.py:74:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: collections.namedtuple argument '_y' is not a valid typename or field name. [invalid-namedtuple-arg]"]
Line 122: Unexpected errors ['namedtuples_define_class.py:122:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Any [assert-type]']
"""
11 changes: 8 additions & 3 deletions conformance/results/pytype/namedtuples_define_functional.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,19 @@ namedtuples_define_functional.py:54:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[
NT3 = namedtuple("NT3", ["abc", "def"], rename=False) # E?: illegal field name
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m

namedtuples_define_functional.py:63:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Function collections.namedtuple was called with the wrong arguments [wrong-arg-types]
namedtuples_define_functional.py:55:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: collections.namedtuple argument '_d' is not a valid typename or field name. [invalid-namedtuple-arg]

NT4 = namedtuple("NT4", ["abc", "_d"], rename=False) # E?: illegal field name
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m

namedtuples_define_functional.py:66:7: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Function collections.namedtuple was called with the wrong arguments [wrong-arg-types]

NT5 = namedtuple("NT5", "a b c", defaults=(1, 2))
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m

"""
conformance_automated = "Fail"
errors_diff = """
Line 66: Expected 1 errors
Line 63: Unexpected errors ['namedtuples_define_functional.py:63:7: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Function collections.namedtuple was called with the wrong arguments [wrong-arg-types]']
Line 69: Expected 1 errors
Line 66: Unexpected errors ['namedtuples_define_functional.py:66:7: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Function collections.namedtuple was called with the wrong arguments [wrong-arg-types]']
"""
4 changes: 2 additions & 2 deletions conformance/results/pytype/protocols_merging.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ Does not report attempt to instantiate abstract class downgraded from protocol c
output = """
protocols_merging.py:52:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Type annotation for s6 does not match type of assignment [annotation-type-mismatch]

s6: SizedAndClosable1 = SCConcrete2() # E: doesn't implement close
s6: SizedAndClosable1 = SCConcrete2() # E: doesn't implement `__len__`
\u001b[1m\u001b[31m~~\u001b[39m\u001b[0m

protocols_merging.py:53:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Type annotation for s7 does not match type of assignment [annotation-type-mismatch]

s7: SizedAndClosable2 = SCConcrete2() # E: doesn't implement close
s7: SizedAndClosable2 = SCConcrete2() # E: doesn't implement `__len__`
\u001b[1m\u001b[31m~~\u001b[39m\u001b[0m

protocols_merging.py:54:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Type annotation for s8 does not match type of assignment [annotation-type-mismatch]
Expand Down
2 changes: 1 addition & 1 deletion conformance/results/pytype/version.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version = "pytype 2024.10.11"
test_duration = 43.3
test_duration = 36.6
14 changes: 7 additions & 7 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,16 @@ <h3>Python Type System Conformance Test Results</h3>
<div class="table_container"><table><tbody>
<tr><th class="col1">&nbsp;</th>
<th class='tc-header'><div class='tc-name'>mypy 1.15.0</div>
<div class='tc-time'>2.1sec</div>
<div class='tc-time'>2.0sec</div>
</th>
<th class='tc-header'><div class='tc-name'>pyright 1.1.398</div>
<div class='tc-time'>2.3sec</div>
<th class='tc-header'><div class='tc-name'>pyright 1.1.399</div>
<div class='tc-time'>1.5sec</div>
</th>
<th class='tc-header'><div class='tc-name'>pyre 0.9.23</div>
<div class='tc-time'>3.9sec</div>
<div class='tc-time'>7.3sec</div>
</th>
<th class='tc-header'><div class='tc-name'>pytype 2024.10.11</div>
<div class='tc-time'>43.3sec</div>
<div class='tc-time'>36.6sec</div>
</th>
</tr>
<tr><th class="column" colspan="5">
Expand Down Expand Up @@ -445,10 +445,10 @@ <h3>Python Type System Conformance Test Results</h3>
<a class="test_group" href="https://typing.readthedocs.io/en/latest/spec/class-compat.html">Class type compatibility</a>
</th></tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classes_classvar</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Internal error if TypeVarTuple is used in ClassVar.</p><p>Does not reject use of ParamSpec in ClassVar.</p><p>Rejects ClassVar nested in Annotated.</p><p>Does not reject use of ClassVar in TypeAlias definition.</p><p>Does not infer type of ClassVar from assignment if no type is provided.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Internal error if TypeVarTuple is used in ClassVar.</p><p>Does not reject use of ParamSpec in ClassVar.</p><p>Rejects ClassVar nested in Annotated.</p><p>Does not reject use of ClassVar in TypeAlias definition.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject use of TypeVar in ClassVar.</p><p>Does not reject use of ParamSpec in ClassVar.</p><p>Does not reject use of ClassVar as a generic type argument.</p><p>Does not reject use of ClassVar in parameter type annotation.</p><p>Does not reject use of ClassVar in local variable annotation.</p><p>Does not reject use of ClassVar in instance variable annotation.</p><p>Does not reject use of ClassVar in return type annotation.</p><p>Does not reject use of ClassVar in type alias definition.</p><p>Does not infer type from initialization for bare ClassVar.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject use of TypeVar in ClassVar.</p><p>Does not reject use of ParamSpec in ClassVar.</p><p>Does not reject use of ClassVar as a generic type argument.</p><p>Rejects initialization of ClassVar if no type argument is provided.</p><p>Does not reject use of ClassVar in parameter type annotation.</p><p>Does not reject use of ClassVar in local variable annotation.</p><p>Does not reject use of ClassVar in instance variable annotation.</p><p>Does not reject use of ClassVar in return type annotation.</p><p>Does not reject use of ClassVar in type alias definition.</p><p>Does not reject assignment of ClassVar through instance of class.</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject use of TypeVar in ClassVar.</p><p>Does not reject use of ParamSpec in ClassVar.</p><p>Does not reject use of ClassVar as a generic type argument.</p><p>Rejects initialization of ClassVar if no type argument is provided.</p><p>Does not infer ClassVar with no type argument and no assigned value as Any.</p><p>Does not reject use of ClassVar in parameter type annotation.</p><p>Does not reject use of ClassVar in local variable annotation.</p><p>Does not reject use of ClassVar in instance variable annotation.</p><p>Does not reject use of ClassVar in return type annotation.</p><p>Does not reject use of ClassVar in type alias definition.</p><p>Does not reject assignment of ClassVar through instance of class.</p></span></div></th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classes_override</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not handle case where parent class derives from Any.</p></span></div></th>
Expand Down
Loading