Skip to content

Commit f903377

Browse files
Clarify namedtuple member rules (#1979)
* add field name restrictions to namedtuple spec * add conformance tests for namedtuple spec changes * regenerate results * mark tests as partial * fix conformance_automated * Regenerate results. --------- Co-authored-by: Rebecca Chen <rechen@fb.com>
1 parent c16b1df commit f903377

12 files changed

+113
-44
lines changed

conformance/results/mypy/namedtuples_define_class.toml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@ namedtuples_define_class.py:46: error: Argument 2 to "Point" has incompatible ty
1111
namedtuples_define_class.py:47: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type]
1212
namedtuples_define_class.py:48: error: Too many arguments for "Point" [call-arg]
1313
namedtuples_define_class.py:49: error: Unexpected keyword argument "other" for "Point" [call-arg]
14-
namedtuples_define_class.py:59: error: Non-default NamedTuple fields cannot follow default fields [misc]
15-
namedtuples_define_class.py:98: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
16-
namedtuples_define_class.py:105: error: NamedTuple should be a single base [misc]
14+
namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]
15+
namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg]
16+
namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc]
17+
namedtuples_define_class.py:76: error: NamedTuple field name cannot start with an underscore: _y [misc]
18+
namedtuples_define_class.py:86: error: Non-default NamedTuple fields cannot follow default fields [misc]
19+
namedtuples_define_class.py:125: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
20+
namedtuples_define_class.py:132: error: NamedTuple should be a single base [misc]
1721
"""
1822
conformance_automated = "Fail"
1923
errors_diff = """
20-
Line 79: Expected 1 errors
24+
Line 69: Expected 1 errors
25+
Line 106: Expected 1 errors
26+
Line 59: Unexpected errors ['namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]']
27+
Line 65: Unexpected errors ['namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg]']
28+
Line 67: Unexpected errors ['namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc]']
2129
"""

conformance/results/mypy/namedtuples_define_functional.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ namedtuples_define_functional.py:43: error: Argument "x" to "Point6" has incompa
1111
namedtuples_define_functional.py:52: error: "namedtuple()" has duplicate field name "a" [misc]
1212
namedtuples_define_functional.py:53: error: "namedtuple()" field name "def" is a keyword [misc]
1313
namedtuples_define_functional.py:54: error: "namedtuple()" field name "def" is a keyword [misc]
14-
namedtuples_define_functional.py:66: error: Missing positional argument "a" in call to "NT5" [call-arg]
14+
namedtuples_define_functional.py:55: error: "namedtuple()" field name "_d" starts with an underscore [misc]
15+
namedtuples_define_functional.py:69: error: Missing positional argument "a" in call to "NT7" [call-arg]
1516
"""
1617
conformance_automated = "Pass"
1718
errors_diff = """
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
conformant = "Pass"
2-
conformance_automated = "Pass"
1+
conformant = "Partial"
2+
notes = """
3+
Doesn't catch illegal field name starting with underscore
4+
"""
5+
conformance_automated = "Fail"
36
errors_diff = """
7+
Line 76: Expected 1 errors
48
"""
59
output = """
610
ERROR namedtuples_define_class.py:32:7-12: Index 3 out of range for tuple with 3 elements [index-error]
@@ -11,8 +15,9 @@ ERROR namedtuples_define_class.py:46:15-17: Argument `Literal['']` is not assign
1115
ERROR namedtuples_define_class.py:47:24-25: Argument `Literal[3]` is not assignable to parameter `units` with type `str` in function `Point.__new__` [bad-argument-type]
1216
ERROR namedtuples_define_class.py:48:22-24: Expected 3 positional arguments, got 4 in function `Point.__new__` [bad-argument-count]
1317
ERROR namedtuples_define_class.py:49:23-28: Unexpected keyword argument `other` in function `Point.__new__` [unexpected-keyword]
14-
ERROR namedtuples_define_class.py:59:5-13: NamedTuple field 'latitude' without a default may not follow NamedTuple field with a default [bad-class-definition]
15-
ERROR namedtuples_define_class.py:79:5-6: Cannot override named tuple element `x` [bad-override]
16-
ERROR namedtuples_define_class.py:98:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type]
17-
ERROR namedtuples_define_class.py:105:7-11: Named tuples do not support multiple inheritance [invalid-inheritance]
18+
ERROR namedtuples_define_class.py:69:20-22: Expected 2 positional arguments, got 3 in function `Point2.__new__` [bad-argument-count]
19+
ERROR namedtuples_define_class.py:86:5-13: NamedTuple field 'latitude' without a default may not follow NamedTuple field with a default [bad-class-definition]
20+
ERROR namedtuples_define_class.py:106:5-6: Cannot override named tuple element `x` [bad-override]
21+
ERROR namedtuples_define_class.py:125:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type]
22+
ERROR namedtuples_define_class.py:132:7-11: Named tuples do not support multiple inheritance [invalid-inheritance]
1823
"""

conformance/results/pyrefly/namedtuples_define_functional.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ ERROR namedtuples_define_functional.py:43:17-20: Argument `float` is not assigna
1616
ERROR namedtuples_define_functional.py:52:31-34: Duplicate field `a` [bad-class-definition]
1717
ERROR namedtuples_define_functional.py:53:33-38: `def` is not a valid identifier [bad-class-definition]
1818
ERROR namedtuples_define_functional.py:54:33-38: `def` is not a valid identifier [bad-class-definition]
19-
ERROR namedtuples_define_functional.py:66:4-6: Missing argument `a` in function `NT5.__new__` [missing-argument]
19+
ERROR namedtuples_define_functional.py:55:33-37: NamedTuple field name may not start with an underscore: `_d` [bad-class-definition]
20+
ERROR namedtuples_define_functional.py:69:4-6: Missing argument `a` in function `NT7.__new__` [missing-argument]
2021
"""

conformance/results/pyright/namedtuples_define_class.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ namedtuples_define_class.py:47:24 - error: Argument of type "Literal[3]" cannot
1010
  "Literal[3]" is not assignable to "str" (reportArgumentType)
1111
namedtuples_define_class.py:48:22 - error: Expected 3 positional arguments (reportCallIssue)
1212
namedtuples_define_class.py:49:23 - error: No parameter named "other" (reportCallIssue)
13-
namedtuples_define_class.py:59:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues)
14-
namedtuples_define_class.py:79:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride)
15-
namedtuples_define_class.py:98:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"
13+
namedtuples_define_class.py:69:20 - error: Expected 2 positional arguments (reportCallIssue)
14+
namedtuples_define_class.py:76:5 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues)
15+
namedtuples_define_class.py:86:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues)
16+
namedtuples_define_class.py:106:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride)
17+
namedtuples_define_class.py:125:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"
1618
  "float" is not assignable to "str" (reportArgumentType)
17-
namedtuples_define_class.py:105:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues)
19+
namedtuples_define_class.py:132:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues)
1820
"""
1921
conformance_automated = "Pass"
2022
errors_diff = """

conformance/results/pyright/namedtuples_define_functional.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
conformant = "Pass"
1+
conformant = "Partial"
22
output = """
33
namedtuples_define_functional.py:16:8 - error: Argument missing for parameter "y" (reportCallIssue)
44
namedtuples_define_functional.py:21:8 - error: Arguments missing for parameters "x", "y" (reportCallIssue)
@@ -15,8 +15,13 @@ namedtuples_define_functional.py:43:17 - error: Argument of type "float" cannot
1515
namedtuples_define_functional.py:52:31 - error: Names within a named tuple must be unique (reportGeneralTypeIssues)
1616
namedtuples_define_functional.py:53:33 - error: Field names cannot be a keyword (reportGeneralTypeIssues)
1717
namedtuples_define_functional.py:54:33 - error: Field names cannot be a keyword (reportGeneralTypeIssues)
18-
namedtuples_define_functional.py:66:1 - error: Argument missing for parameter "a" (reportCallIssue)
18+
namedtuples_define_functional.py:55:33 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues)
19+
namedtuples_define_functional.py:59:33 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues)
20+
namedtuples_define_functional.py:60:13 - error: No parameter named "_1" (reportCallIssue)
21+
namedtuples_define_functional.py:69:1 - error: Argument missing for parameter "a" (reportCallIssue)
1922
"""
20-
conformance_automated = "Pass"
23+
conformance_automated = "Fail"
2124
errors_diff = """
25+
Line 59: Unexpected errors ['namedtuples_define_functional.py:59:33 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues)']
26+
Line 60: Unexpected errors ['namedtuples_define_functional.py:60:13 - error: No parameter named "_1" (reportCallIssue)']
2227
"""

conformance/results/results.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,11 +915,11 @@ <h3>Python Type System Conformance Test Results</h3>
915915
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject override of named tuple attribute in child class.</p></span></div></th>
916916
<th class="column col2 conformant">Pass</th>
917917
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Does not reject override of named tuple attribute in child class.</p></span></div></th>
918-
<th class="column col2 conformant">Pass</th>
918+
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Doesn't catch illegal field name starting with underscore</p></span></div></th>
919919
</tr>
920920
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namedtuples_define_functional</th>
921921
<th class="column col2 conformant">Pass</th>
922-
<th class="column col2 conformant">Pass</th>
922+
<th class="column col2 partially-conformant">Partial</th>
923923
<th class="column col2 conformant">Pass</th>
924924
<th class="column col2 conformant">Pass</th>
925925
</tr>

conformance/results/zuban/namedtuples_define_class.toml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ Does not reject override of named tuple attribute in child class.
44
"""
55
conformance_automated = "Fail"
66
errors_diff = """
7-
Line 79: Expected 1 errors
7+
Line 106: Expected 1 errors
8+
Line 59: Unexpected errors ['namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]']
89
"""
910
output = """
1011
namedtuples_define_class.py:32: error: Tuple index out of range [misc]
@@ -15,7 +16,10 @@ namedtuples_define_class.py:46: error: Argument 2 to "Point" has incompatible ty
1516
namedtuples_define_class.py:47: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type]
1617
namedtuples_define_class.py:48: error: Too many arguments for "Point" [call-arg]
1718
namedtuples_define_class.py:49: error: Unexpected keyword argument "other" for "Point" [call-arg]
18-
namedtuples_define_class.py:59: error: Non-default NamedTuple fields cannot follow default fields [misc]
19-
namedtuples_define_class.py:98: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
20-
namedtuples_define_class.py:105: error: NamedTuple should be a single base [misc]
19+
namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]
20+
namedtuples_define_class.py:69: error: Too many arguments for "Point2" [call-arg]
21+
namedtuples_define_class.py:76: error: NamedTuple field name cannot start with an underscore: _y [misc]
22+
namedtuples_define_class.py:86: error: Non-default NamedTuple fields cannot follow default fields [misc]
23+
namedtuples_define_class.py:125: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type]
24+
namedtuples_define_class.py:132: error: NamedTuple should be a single base [misc]
2125
"""

conformance/results/zuban/namedtuples_define_functional.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ namedtuples_define_functional.py:43: error: Argument "x" to "Point6" has incompa
1313
namedtuples_define_functional.py:52: error: "namedtuple()" has duplicate field name "a" [misc]
1414
namedtuples_define_functional.py:53: error: "namedtuple()" field name "def" is a keyword [misc]
1515
namedtuples_define_functional.py:54: error: "namedtuple()" field name "def" is a keyword [misc]
16-
namedtuples_define_functional.py:66: error: Missing positional argument "a" in call to "NT5" [call-arg]
16+
namedtuples_define_functional.py:55: error: "namedtuple()" field name "_d" starts with an underscore [misc]
17+
namedtuples_define_functional.py:69: error: Missing positional argument "a" in call to "NT7" [call-arg]
1718
"""

conformance/tests/namedtuples_define_class.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,33 @@ class Point(NamedTuple):
4949
p10 = Point(1, 2, "", other="") # E
5050

5151

52+
# > Fields must be annotated attributes - methods and un-annotated attributes are not
53+
# > considered fields.
54+
55+
56+
class Point2(NamedTuple):
57+
x: int
58+
y: int
59+
units = "meters" # Not a field
60+
61+
def is_origin(self) -> int: # Not a field
62+
return self.x == 0 and self.y == 0
63+
64+
65+
p11 = Point2(1, 2)
66+
assert_type(p11, Point2)
67+
x, y = p11
68+
69+
p12 = Point2(1, 2, "") # E
70+
71+
72+
# > Field names may not start with an underscore.
73+
74+
class Point3(NamedTuple):
75+
x: int
76+
_y: int # E: illegal field name
77+
78+
5279
# > The runtime implementation of ``NamedTuple`` enforces that fields with default
5380
# > values must come after fields without default values. Type checkers should
5481
# > likewise enforce this restriction::

0 commit comments

Comments
 (0)