@@ -4530,9 +4530,16 @@ class Point2D(TypedDict):
4530
4530
x : int
4531
4531
y : int
4532
4532
4533
+ class Point2DGeneric (Generic [T ], TypedDict ):
4534
+ a : T
4535
+ b : T
4536
+
4533
4537
class Bar (_typed_dict_helper .Foo , total = False ):
4534
4538
b : int
4535
4539
4540
+ class BarGeneric (_typed_dict_helper .FooGeneric [T ], total = False ):
4541
+ b : int
4542
+
4536
4543
class LabelPoint2D (Point2D , Label ): ...
4537
4544
4538
4545
class Options (TypedDict , total = False ):
@@ -5890,6 +5897,17 @@ def test_pickle(self):
5890
5897
EmpDnew = pickle .loads (ZZ )
5891
5898
self .assertEqual (EmpDnew ({'name' : 'jane' , 'id' : 37 }), jane )
5892
5899
5900
+ def test_pickle_generic (self ):
5901
+ point = Point2DGeneric (a = 5.0 , b = 3.0 )
5902
+ for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
5903
+ z = pickle .dumps (point , proto )
5904
+ point2 = pickle .loads (z )
5905
+ self .assertEqual (point2 , point )
5906
+ self .assertEqual (point2 , {'a' : 5.0 , 'b' : 3.0 })
5907
+ ZZ = pickle .dumps (Point2DGeneric , proto )
5908
+ Point2DGenericNew = pickle .loads (ZZ )
5909
+ self .assertEqual (Point2DGenericNew ({'a' : 5.0 , 'b' : 3.0 }), point )
5910
+
5893
5911
def test_optional (self ):
5894
5912
EmpD = TypedDict ('EmpD' , {'name' : str , 'id' : int })
5895
5913
@@ -6074,6 +6092,124 @@ def test_get_type_hints(self):
6074
6092
{'a' : typing .Optional [int ], 'b' : int }
6075
6093
)
6076
6094
6095
+ def test_get_type_hints_generic (self ):
6096
+ self .assertEqual (
6097
+ get_type_hints (BarGeneric ),
6098
+ {'a' : typing .Optional [T ], 'b' : int }
6099
+ )
6100
+
6101
+ class FooBarGeneric (BarGeneric [int ]):
6102
+ c : str
6103
+
6104
+ self .assertEqual (
6105
+ get_type_hints (FooBarGeneric ),
6106
+ {'a' : typing .Optional [T ], 'b' : int , 'c' : str }
6107
+ )
6108
+
6109
+ def test_generic_inheritance (self ):
6110
+ class A (TypedDict , Generic [T ]):
6111
+ a : T
6112
+
6113
+ self .assertEqual (A .__bases__ , (Generic , dict ))
6114
+ self .assertEqual (A .__orig_bases__ , (TypedDict , Generic [T ]))
6115
+ self .assertEqual (A .__mro__ , (A , Generic , dict , object ))
6116
+ self .assertEqual (A .__parameters__ , (T ,))
6117
+ self .assertEqual (A [str ].__parameters__ , ())
6118
+ self .assertEqual (A [str ].__args__ , (str ,))
6119
+
6120
+ class A2 (Generic [T ], TypedDict ):
6121
+ a : T
6122
+
6123
+ self .assertEqual (A2 .__bases__ , (Generic , dict ))
6124
+ self .assertEqual (A2 .__orig_bases__ , (Generic [T ], TypedDict ))
6125
+ self .assertEqual (A2 .__mro__ , (A2 , Generic , dict , object ))
6126
+ self .assertEqual (A2 .__parameters__ , (T ,))
6127
+ self .assertEqual (A2 [str ].__parameters__ , ())
6128
+ self .assertEqual (A2 [str ].__args__ , (str ,))
6129
+
6130
+ class B (A [KT ], total = False ):
6131
+ b : KT
6132
+
6133
+ self .assertEqual (B .__bases__ , (Generic , dict ))
6134
+ self .assertEqual (B .__orig_bases__ , (A [KT ],))
6135
+ self .assertEqual (B .__mro__ , (B , Generic , dict , object ))
6136
+ self .assertEqual (B .__parameters__ , (KT ,))
6137
+ self .assertEqual (B .__total__ , False )
6138
+ self .assertEqual (B .__optional_keys__ , frozenset (['b' ]))
6139
+ self .assertEqual (B .__required_keys__ , frozenset (['a' ]))
6140
+
6141
+ self .assertEqual (B [str ].__parameters__ , ())
6142
+ self .assertEqual (B [str ].__args__ , (str ,))
6143
+ self .assertEqual (B [str ].__origin__ , B )
6144
+
6145
+ class C (B [int ]):
6146
+ c : int
6147
+
6148
+ self .assertEqual (C .__bases__ , (Generic , dict ))
6149
+ self .assertEqual (C .__orig_bases__ , (B [int ],))
6150
+ self .assertEqual (C .__mro__ , (C , Generic , dict , object ))
6151
+ self .assertEqual (C .__parameters__ , ())
6152
+ self .assertEqual (C .__total__ , True )
6153
+ self .assertEqual (C .__optional_keys__ , frozenset (['b' ]))
6154
+ self .assertEqual (C .__required_keys__ , frozenset (['a' , 'c' ]))
6155
+ assert C .__annotations__ == {
6156
+ 'a' : T ,
6157
+ 'b' : KT ,
6158
+ 'c' : int ,
6159
+ }
6160
+ with self .assertRaises (TypeError ):
6161
+ C [str ]
6162
+
6163
+
6164
+ class Point3D (Point2DGeneric [T ], Generic [T , KT ]):
6165
+ c : KT
6166
+
6167
+ self .assertEqual (Point3D .__bases__ , (Generic , dict ))
6168
+ self .assertEqual (Point3D .__orig_bases__ , (Point2DGeneric [T ], Generic [T , KT ]))
6169
+ self .assertEqual (Point3D .__mro__ , (Point3D , Generic , dict , object ))
6170
+ self .assertEqual (Point3D .__parameters__ , (T , KT ))
6171
+ self .assertEqual (Point3D .__total__ , True )
6172
+ self .assertEqual (Point3D .__optional_keys__ , frozenset ())
6173
+ self .assertEqual (Point3D .__required_keys__ , frozenset (['a' , 'b' , 'c' ]))
6174
+ assert Point3D .__annotations__ == {
6175
+ 'a' : T ,
6176
+ 'b' : T ,
6177
+ 'c' : KT ,
6178
+ }
6179
+ self .assertEqual (Point3D [int , str ].__origin__ , Point3D )
6180
+
6181
+ with self .assertRaises (TypeError ):
6182
+ Point3D [int ]
6183
+
6184
+ with self .assertRaises (TypeError ):
6185
+ class Point3D (Point2DGeneric [T ], Generic [KT ]):
6186
+ c : KT
6187
+
6188
+ def test_implicit_any_inheritance (self ):
6189
+ class A (TypedDict , Generic [T ]):
6190
+ a : T
6191
+
6192
+ class B (A [KT ], total = False ):
6193
+ b : KT
6194
+
6195
+ class WithImplicitAny (B ):
6196
+ c : int
6197
+
6198
+ self .assertEqual (WithImplicitAny .__bases__ , (Generic , dict ,))
6199
+ self .assertEqual (WithImplicitAny .__mro__ , (WithImplicitAny , Generic , dict , object ))
6200
+ # Consistent with GenericTests.test_implicit_any
6201
+ self .assertEqual (WithImplicitAny .__parameters__ , ())
6202
+ self .assertEqual (WithImplicitAny .__total__ , True )
6203
+ self .assertEqual (WithImplicitAny .__optional_keys__ , frozenset (['b' ]))
6204
+ self .assertEqual (WithImplicitAny .__required_keys__ , frozenset (['a' , 'c' ]))
6205
+ assert WithImplicitAny .__annotations__ == {
6206
+ 'a' : T ,
6207
+ 'b' : KT ,
6208
+ 'c' : int ,
6209
+ }
6210
+ with self .assertRaises (TypeError ):
6211
+ WithImplicitAny [str ]
6212
+
6077
6213
def test_non_generic_subscript (self ):
6078
6214
# For backward compatibility, subscription works
6079
6215
# on arbitrary TypedDict types.
0 commit comments