@@ -682,6 +682,44 @@ def test_invalid_setattr(self):
682682 msg = "exception context must be None or derive from BaseException"
683683 self .assertRaisesRegex (TE , msg , setattr , exc , '__context__' , 1 )
684684
685+ def test_object_attributes (self ):
686+ # These attributes are implemented as plain object members:
687+ # they accept any object and are reset to None when deleted.
688+ cases = [
689+ (SyntaxError ('msgStr' ), 'msg' ),
690+ (SyntaxError ('msgStr' ), 'filename' ),
691+ (SyntaxError ('msgStr' ), 'lineno' ),
692+ (SyntaxError ('msgStr' ), 'offset' ),
693+ (SyntaxError ('msgStr' ), 'end_lineno' ),
694+ (SyntaxError ('msgStr' ), 'end_offset' ),
695+ (SyntaxError ('msgStr' ), 'text' ),
696+ (SyntaxError ('msgStr' ), 'print_file_and_line' ),
697+ (SyntaxError ('msgStr' ), '_metadata' ),
698+ (ImportError ('msgStr' ), 'msg' ),
699+ (ImportError ('msgStr' ), 'name' ),
700+ (ImportError ('msgStr' ), 'path' ),
701+ (ImportError ('msgStr' ), 'name_from' ),
702+ (SystemExit (1 ), 'code' ),
703+ (StopIteration (), 'value' ),
704+ (NameError ('msgStr' ), 'name' ),
705+ (AttributeError ('msgStr' ), 'name' ),
706+ (AttributeError ('msgStr' ), 'obj' ),
707+ (OSError (2 , 'msgStr' ), 'errno' ),
708+ (OSError (2 , 'msgStr' ), 'strerror' ),
709+ (OSError (2 , 'msgStr' ), 'filename' ),
710+ (OSError (2 , 'msgStr' ), 'filename2' ),
711+ (UnicodeDecodeError ('utf-8' , b'\xff ' , 0 , 1 , 'reasonStr' ), 'reason' ),
712+ ]
713+ if sys .platform == 'win32' :
714+ cases .append ((OSError (2 , 'msgStr' ), 'winerror' ))
715+ for exc , name in cases :
716+ with self .subTest (exc = type (exc ).__name__ , name = name ):
717+ for value in 'strValue' , 42 , [1 , 2 ], None :
718+ setattr (exc , name , value )
719+ self .assertEqual (getattr (exc , name ), value )
720+ delattr (exc , name )
721+ self .assertIsNone (getattr (exc , name ))
722+
685723 def test_invalid_delattr (self ):
686724 TE = TypeError
687725 try :
@@ -739,6 +777,13 @@ def testChainingDescriptors(self):
739777 self .assertTrue (e .__suppress_context__ )
740778 e .__suppress_context__ = False
741779 self .assertFalse (e .__suppress_context__ )
780+ with self .assertRaisesRegex (TypeError ,
781+ 'attribute value type must be bool' ):
782+ e .__suppress_context__ = 1
783+ with self .assertRaisesRegex (TypeError ,
784+ "can't delete numeric/char attribute" ):
785+ del e .__suppress_context__
786+ self .assertFalse (e .__suppress_context__ )
742787
743788 def testKeywordArgs (self ):
744789 # test that builtin exception don't take keyword args,
0 commit comments