@@ -7535,6 +7535,83 @@ class GenericNamedTuple(NamedTuple, Generic[T]):
75357535
75367536 self .assertEqual (CallNamedTuple .__orig_bases__ , (NamedTuple ,))
75377537
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+
75387615
75397616class TypedDictTests (BaseTestCase ):
75407617 def test_basics_functional_syntax (self ):
0 commit comments