|
25 | 25 | from urllib.error import URLError |
26 | 26 | import urllib.request |
27 | 27 | from test.support import os_helper |
| 28 | +from test import support |
28 | 29 | from test.support import findfile, check__all__ |
29 | 30 | from test.support.os_helper import FakePath, TESTFN |
30 | 31 |
|
@@ -1055,64 +1056,32 @@ def test_expat_entityresolver_default(self): |
1055 | 1056 | self.assertEqual(result.getvalue(), start + |
1056 | 1057 | b"<doc></doc>") |
1057 | 1058 |
|
1058 | | - def test_external_entity_ref_keyboard_interrupt(self): |
1059 | | - # gh-148427: KeyboardInterrupt must propagate, not be swallowed |
| 1059 | + @support.subTests("exc_type", [KeyboardInterrupt, SystemExit, ValueError]) |
| 1060 | + def test_external_entity_parser_with_exceptions(self, exc_type): |
| 1061 | + # gh-148427: BaseException subclasses must propagate, not be swallowed |
1060 | 1062 | def raise_on_entity(name, attrs): |
1061 | 1063 | if name == 'entity': |
1062 | | - raise KeyboardInterrupt('test') |
1063 | | - eh = mock.Mock() |
1064 | | - eh.startElement.side_effect = raise_on_entity |
| 1064 | + raise exc_type("test") |
1065 | 1065 |
|
1066 | | - parser = create_parser() |
1067 | | - parser.setFeature(feature_external_ges, True) |
1068 | | - parser.setEntityResolver(self.TestEntityResolver()) |
1069 | | - parser.setContentHandler(eh) |
1070 | | - |
1071 | | - parser.feed('<!DOCTYPE doc [\n') |
1072 | | - parser.feed(' <!ENTITY test SYSTEM "whatever">\n') |
1073 | | - parser.feed(']>\n') |
1074 | | - with self.assertRaises(KeyboardInterrupt): |
1075 | | - parser.feed('<doc>&test;</doc>') |
1076 | | - |
1077 | | - def test_external_entity_ref_system_exit(self): |
1078 | | - # gh-148427: SystemExit must propagate, not be swallowed |
1079 | | - def raise_on_entity(name, attrs): |
1080 | | - if name == 'entity': |
1081 | | - raise SystemExit(42) |
1082 | | - eh = mock.Mock() |
1083 | | - eh.startElement.side_effect = raise_on_entity |
1084 | | - |
1085 | | - parser = create_parser() |
1086 | | - parser.setFeature(feature_external_ges, True) |
1087 | | - parser.setEntityResolver(self.TestEntityResolver()) |
1088 | | - parser.setContentHandler(eh) |
1089 | | - |
1090 | | - parser.feed('<!DOCTYPE doc [\n') |
1091 | | - parser.feed(' <!ENTITY test SYSTEM "whatever">\n') |
1092 | | - parser.feed(']>\n') |
1093 | | - with self.assertRaises(SystemExit): |
1094 | | - parser.feed('<doc>&test;</doc>') |
1095 | | - |
1096 | | - def test_external_entity_ref_stack_cleanup(self): |
1097 | | - # gh-148427: _entity_stack must be cleaned up after errors |
1098 | | - def raise_on_entity(name, attrs): |
1099 | | - if name == 'entity': |
1100 | | - raise ValueError('test error') |
1101 | | - eh = mock.Mock() |
1102 | | - eh.startElement.side_effect = raise_on_entity |
| 1066 | + handler = mock.Mock() |
| 1067 | + handler.startElement = raise_on_entity |
1103 | 1068 |
|
1104 | 1069 | parser = create_parser() |
1105 | 1070 | parser.setFeature(feature_external_ges, True) |
1106 | 1071 | parser.setEntityResolver(self.TestEntityResolver()) |
1107 | | - parser.setContentHandler(eh) |
| 1072 | + parser.setContentHandler(handler) |
1108 | 1073 |
|
1109 | 1074 | parser.feed('<!DOCTYPE doc [\n') |
1110 | 1075 | parser.feed(' <!ENTITY test SYSTEM "whatever">\n') |
1111 | 1076 | parser.feed(']>\n') |
1112 | | - with self.assertRaises(SAXParseException): |
1113 | | - parser.feed('<doc>&test;</doc>') |
1114 | | - |
1115 | | - self.assertEqual(len(parser._entity_stack), 0) |
| 1077 | + trigger = '<doc>&test;</doc>' |
| 1078 | + |
| 1079 | + if issubclass(exc_type, Exception): |
| 1080 | + self.assertRaises(SAXParseException, parser.feed, trigger) |
| 1081 | + self.assertEqual(len(parser._entity_stack), 0) |
| 1082 | + else: |
| 1083 | + with self.assertRaisesRegex(exc_type, "test"): |
| 1084 | + parser.feed(trigger) |
1116 | 1085 |
|
1117 | 1086 | # ===== Attributes support |
1118 | 1087 |
|
|
0 commit comments