@@ -7535,6 +7535,83 @@ class GenericNamedTuple(NamedTuple, Generic[T]):
7535
7535
7536
7536
self .assertEqual (CallNamedTuple .__orig_bases__ , (NamedTuple ,))
7537
7537
7538
+ def test_setname_called_on_values_in_class_dictionary (self ):
7539
+ class Vanilla :
7540
+ def __set_name__ (self , owner , name ):
7541
+ self .name = name
7542
+
7543
+ class Foo (NamedTuple ):
7544
+ attr = Vanilla ()
7545
+
7546
+ foo = Foo ()
7547
+ self .assertEqual (len (foo ), 0 )
7548
+ self .assertNotIn ('attr' , Foo ._fields )
7549
+ self .assertIsInstance (foo .attr , Vanilla )
7550
+ self .assertEqual (foo .attr .name , "attr" )
7551
+
7552
+ class Bar (NamedTuple ):
7553
+ attr : Vanilla = Vanilla ()
7554
+
7555
+ bar = Bar ()
7556
+ self .assertEqual (len (bar ), 1 )
7557
+ self .assertIn ('attr' , Bar ._fields )
7558
+ self .assertIsInstance (bar .attr , Vanilla )
7559
+ self .assertEqual (bar .attr .name , "attr" )
7560
+
7561
+ def test_setname_raises_the_same_as_on_other_classes (self ):
7562
+ class CustomException (BaseException ): pass
7563
+
7564
+ class Annoying :
7565
+ def __set_name__ (self , owner , name ):
7566
+ raise CustomException
7567
+
7568
+ annoying = Annoying ()
7569
+
7570
+ with self .assertRaises (CustomException ) as cm :
7571
+ class NormalClass :
7572
+ attr = annoying
7573
+ normal_exception = cm .exception
7574
+
7575
+ with self .assertRaises (CustomException ) as cm :
7576
+ class NamedTupleClass (NamedTuple ):
7577
+ attr = annoying
7578
+ namedtuple_exception = cm .exception
7579
+
7580
+ self .assertIs (type (namedtuple_exception ), CustomException )
7581
+ self .assertIs (type (namedtuple_exception ), type (normal_exception ))
7582
+
7583
+ self .assertEqual (len (namedtuple_exception .__notes__ ), 1 )
7584
+ self .assertEqual (
7585
+ len (namedtuple_exception .__notes__ ), len (normal_exception .__notes__ )
7586
+ )
7587
+
7588
+ expected_note = (
7589
+ "Error calling __set_name__ on 'Annoying' instance "
7590
+ "'attr' in 'NamedTupleClass'"
7591
+ )
7592
+ self .assertEqual (namedtuple_exception .__notes__ [0 ], expected_note )
7593
+ self .assertEqual (
7594
+ namedtuple_exception .__notes__ [0 ],
7595
+ normal_exception .__notes__ [0 ].replace ("NormalClass" , "NamedTupleClass" )
7596
+ )
7597
+
7598
+ def test_strange_errors_when_accessing_set_name_itself (self ):
7599
+ class CustomException (Exception ): pass
7600
+
7601
+ class Meta (type ):
7602
+ def __getattribute__ (self , attr ):
7603
+ if attr == "__set_name__" :
7604
+ raise CustomException
7605
+ return object .__getattribute__ (self , attr )
7606
+
7607
+ class VeryAnnoying (metaclass = Meta ): pass
7608
+
7609
+ very_annoying = VeryAnnoying ()
7610
+
7611
+ with self .assertRaises (CustomException ):
7612
+ class Foo (NamedTuple ):
7613
+ attr = very_annoying
7614
+
7538
7615
7539
7616
class TypedDictTests (BaseTestCase ):
7540
7617
def test_basics_functional_syntax (self ):
0 commit comments