@@ -682,6 +682,44 @@ def test_invalid_setattr(self):
682682msg="exception context must be None or derive from BaseException"
683683self.assertRaisesRegex(TE, msg, setattr, exc, '__context__', 1)
684684685+deftest_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+ifsys.platform=='win32':
714+cases.append((OSError(2, 'msgStr'), 'winerror'))
715+forexc, nameincases:
716+withself.subTest(exc=type(exc).__name__, name=name):
717+forvaluein'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+685723deftest_invalid_delattr(self):
686724TE=TypeError
687725try:
@@ -739,6 +777,13 @@ def testChainingDescriptors(self):
739777self.assertTrue(e.__suppress_context__)
740778e.__suppress_context__=False
741779self.assertFalse(e.__suppress_context__)
780+withself.assertRaisesRegex(TypeError,
781+'attribute value type must be bool'):
782+e.__suppress_context__=1
783+withself.assertRaisesRegex(TypeError,
784+"can't delete numeric/char attribute"):
785+dele.__suppress_context__
786+self.assertFalse(e.__suppress_context__)
742787743788deftestKeywordArgs(self):
744789# test that builtin exception don't take keyword args,