@@ -663,6 +663,43 @@ def test_invalid_setattr(self):
663663 msg = "exception context must be None or derive from BaseException"
664664 self .assertRaisesRegex (TE , msg , setattr , exc , '__context__' , 1 )
665665
666+ def test_object_attributes (self ):
667+ # These attributes are implemented as plain object members:
668+ # they accept any object and are reset to None when deleted.
669+ cases = [
670+ (SyntaxError ('msgStr' ), 'msg' ),
671+ (SyntaxError ('msgStr' ), 'filename' ),
672+ (SyntaxError ('msgStr' ), 'lineno' ),
673+ (SyntaxError ('msgStr' ), 'offset' ),
674+ (SyntaxError ('msgStr' ), 'end_lineno' ),
675+ (SyntaxError ('msgStr' ), 'end_offset' ),
676+ (SyntaxError ('msgStr' ), 'text' ),
677+ (SyntaxError ('msgStr' ), 'print_file_and_line' ),
678+ (ImportError ('msgStr' ), 'msg' ),
679+ (ImportError ('msgStr' ), 'name' ),
680+ (ImportError ('msgStr' ), 'path' ),
681+ (ImportError ('msgStr' ), 'name_from' ),
682+ (SystemExit (1 ), 'code' ),
683+ (StopIteration (), 'value' ),
684+ (NameError ('msgStr' ), 'name' ),
685+ (AttributeError ('msgStr' ), 'name' ),
686+ (AttributeError ('msgStr' ), 'obj' ),
687+ (OSError (2 , 'msgStr' ), 'errno' ),
688+ (OSError (2 , 'msgStr' ), 'strerror' ),
689+ (OSError (2 , 'msgStr' ), 'filename' ),
690+ (OSError (2 , 'msgStr' ), 'filename2' ),
691+ (UnicodeDecodeError ('utf-8' , b'\xff ' , 0 , 1 , 'reasonStr' ), 'reason' ),
692+ ]
693+ if sys .platform == 'win32' :
694+ cases .append ((OSError (2 , 'msgStr' ), 'winerror' ))
695+ for exc , name in cases :
696+ with self .subTest (exc = type (exc ).__name__ , name = name ):
697+ for value in 'strValue' , 42 , [1 , 2 ], None :
698+ setattr (exc , name , value )
699+ self .assertEqual (getattr (exc , name ), value )
700+ delattr (exc , name )
701+ self .assertIsNone (getattr (exc , name ))
702+
666703 def test_invalid_delattr (self ):
667704 TE = TypeError
668705 try :
@@ -720,6 +757,13 @@ def testChainingDescriptors(self):
720757 self .assertTrue (e .__suppress_context__ )
721758 e .__suppress_context__ = False
722759 self .assertFalse (e .__suppress_context__ )
760+ with self .assertRaisesRegex (TypeError ,
761+ 'attribute value type must be bool' ):
762+ e .__suppress_context__ = 1
763+ with self .assertRaisesRegex (TypeError ,
764+ "can't delete numeric/char attribute" ):
765+ del e .__suppress_context__
766+ self .assertFalse (e .__suppress_context__ )
723767
724768 def testKeywordArgs (self ):
725769 # test that builtin exception don't take keyword args,
0 commit comments