← Back to index

namedtuples_define_class.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 13
FP: 0
FN: 1
Optional: 0 / 0
1"""
2Tests NamedTuple definitions using the class syntax.
3"""
4
5# Specification: https://typing.readthedocs.io/en/latest/spec/namedtuples.html#defining-named-tuples
6
7# > Type checkers should support the class syntax
8
9from typing import Generic, NamedTuple, TypeVar, assert_type
12class Point(NamedTuple):
13 x: int
14 y: int
15 units: str = "meters"
18# > Type checkers should synthesize a ``__new__`` method based on
19# > the named tuple fields.
21p1 = Point(1, 2)
22assert_type(p1, Point)
23assert_type(p1[0], int)
24assert_type(p1[1], int)
25assert_type(p1[2], str)
26assert_type(p1[-1], str)
27assert_type(p1[-2], int)
28assert_type(p1[-3], int)
29assert_type(p1[0:2], tuple[int, int])
30assert_type(p1[0:], tuple[int, int, str])
32print(p1[3]) # E
[index-out-of-bounds] Index 3 is out of bounds for tuple `Point` with length 3
33print(p1[-4]) # E
[index-out-of-bounds] Index -4 is out of bounds for tuple `Point` with length 3
35p2 = Point(1, 2, "")
36assert_type(p2, Point)
38p3 = Point(x=1, y=2)
39assert_type(p3, Point)
41p4 = Point(x=1, y=2, units="")
42assert_type(p4, Point)
44p5 = Point(1) # E
[missing-argument] No argument provided for required parameter `y`
45p6 = Point(x=1) # E
[missing-argument] No argument provided for required parameter `y`
46p7 = Point(1, "") # E
[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]`
47p8 = Point(1, 2, units=3) # E
[invalid-argument-type] Argument is incorrect: Expected `str`, found `Literal[3]`
48p9 = Point(1, 2, "", "") # E
[too-many-positional-arguments] Too many positional arguments: expected 4, got 5
49p10 = Point(1, 2, "", other="") # E
[unknown-argument] Argument `other` does not match any known parameter
52# > Fields must be annotated attributes - methods and un-annotated attributes are not
53# > considered fields.
56class Point2(NamedTuple):
57 x: int
58 y: int
59 units = "meters" # Not a field
61 def is_origin(self) -> int: # Not a field
62 return self.x == 0 and self.y == 0
65p11 = Point2(1, 2)
66assert_type(p11, Point2)
67x, y = p11
69p12 = Point2(1, 2, "") # E
[too-many-positional-arguments] Too many positional arguments: expected 3, got 4
72# > Field names may not start with an underscore.
74class Point3(NamedTuple):
75 x: int
76 _y: int # E: illegal field name
[invalid-named-tuple] NamedTuple field `_y` cannot start with an underscore
79# > The runtime implementation of ``NamedTuple`` enforces that fields with default
80# > values must come after fields without default values. Type checkers should
81# > likewise enforce this restriction::
84class Location(NamedTuple):
85 altitude: float = 0.0
86 latitude: float # E: previous field has a default value
[invalid-named-tuple] NamedTuple field without default value cannot follow field(s) with default value(s): Field `latitude` defined here without a default value
89# > A named tuple class can be subclassed, but any fields added by the subclass
90# > are not considered part of the named tuple type. Type checkers should enforce
91# > that these newly-added fields do not conflict with the named tuple fields
92# > in the base class.
95class PointWithName(Point):
96 name: str = "" # OK
99pn1 = PointWithName(1, 2, "")
100pnt1: tuple[int, int, str] = pn1
101assert_type(pn1.name, str)
104class BadPointWithName(Point):
105 name: str = "" # OK
106 x: int = 0 # E
Expected a ty diagnostic for this line
109# > In Python 3.11 and newer, the class syntax supports generic named tuple classes.
110# > Type checkers should support this.
112T = TypeVar("T")
115class Property(NamedTuple, Generic[T]):
116 name: str
117 value: T
120pr1 = Property("", 3.4)
121assert_type(pr1, Property[float])
122assert_type(pr1[1], float)
123assert_type(pr1.value, float)
125Property[str]("", 3.1) # E
[invalid-argument-type] Argument is incorrect: Expected `str`, found `float`
128# > ``NamedTuple`` does not support multiple inheritance. Type checkers should
129# > enforce this limitation.
132class Unit(NamedTuple, object): # E
[invalid-named-tuple] NamedTuple class `Unit` cannot use multiple inheritance except with `Generic[]`
133 name: str