@@ -667,6 +667,44 @@ def test_invalid_setattr(self):
667667 msg = "exception context must be None or derive from BaseException"
668668 self .assertRaisesRegex (TE , msg , setattr , exc , '__context__' , 1 )
669669
670+ def test_object_attributes (self ):
671+ # These attributes are implemented as plain object members:
672+ # they accept any object and are reset to None when deleted.
673+ cases = [
674+ (SyntaxError ('msgStr' ), 'msg' ),
675+ (SyntaxError ('msgStr' ), 'filename' ),
676+ (SyntaxError ('msgStr' ), 'lineno' ),
677+ (SyntaxError ('msgStr' ), 'offset' ),
678+ (SyntaxError ('msgStr' ), 'end_lineno' ),
679+ (SyntaxError ('msgStr' ), 'end_offset' ),
680+ (SyntaxError ('msgStr' ), 'text' ),
681+ (SyntaxError ('msgStr' ), 'print_file_and_line' ),
682+ (SyntaxError ('msgStr' ), '_metadata' ),
683+ (ImportError ('msgStr' ), 'msg' ),
684+ (ImportError ('msgStr' ), 'name' ),
685+ (ImportError ('msgStr' ), 'path' ),
686+ (ImportError ('msgStr' ), 'name_from' ),
687+ (SystemExit (1 ), 'code' ),
688+ (StopIteration (), 'value' ),
689+ (NameError ('msgStr' ), 'name' ),
690+ (AttributeError ('msgStr' ), 'name' ),
691+ (AttributeError ('msgStr' ), 'obj' ),
692+ (OSError (2 , 'msgStr' ), 'errno' ),
693+ (OSError (2 , 'msgStr' ), 'strerror' ),
694+ (OSError (2 , 'msgStr' ), 'filename' ),
695+ (OSError (2 , 'msgStr' ), 'filename2' ),
696+ (UnicodeDecodeError ('utf-8' , b'\xff ' , 0 , 1 , 'reasonStr' ), 'reason' ),
697+ ]
698+ if sys .platform == 'win32' :
699+ cases .append ((OSError (2 , 'msgStr' ), 'winerror' ))
700+ for exc , name in cases :
701+ with self .subTest (exc = type (exc ).__name__ , name = name ):
702+ for value in 'strValue' , 42 , [1 , 2 ], None :
703+ setattr (exc , name , value )
704+ self .assertEqual (getattr (exc , name ), value )
705+ delattr (exc , name )
706+ self .assertIsNone (getattr (exc , name ))
707+
670708 def test_invalid_delattr (self ):
671709 TE = TypeError
672710 try :
@@ -724,6 +762,13 @@ def testChainingDescriptors(self):
724762 self .assertTrue (e .__suppress_context__ )
725763 e .__suppress_context__ = False
726764 self .assertFalse (e .__suppress_context__ )
765+ with self .assertRaisesRegex (TypeError ,
766+ 'attribute value type must be bool' ):
767+ e .__suppress_context__ = 1
768+ with self .assertRaisesRegex (TypeError ,
769+ "can't delete numeric/char attribute" ):
770+ del e .__suppress_context__
771+ self .assertFalse (e .__suppress_context__ )
727772
728773 def testKeywordArgs (self ):
729774 # test that builtin exception don't take keyword args,
0 commit comments