Skip to content

Commit f2c3b68

Browse files
authored
Revert "bpo-32604: [_xxsubinterpreters] Propagate exceptions. (GH-19768)" (GH-20089)
* Revert "bpo-40613: Remove compiler warning from _xxsubinterpretersmodule (GH-20069)" This reverts commit fa0a66e. * Revert "bpo-32604: [_xxsubinterpreters] Propagate exceptions. (GH-19768)" This reverts commit a1d9e0a.
1 parent 97f33c3 commit f2c3b68

File tree

2 files changed

+123
-1325
lines changed

2 files changed

+123
-1325
lines changed

Lib/test/test__xxsubinterpreters.py

Lines changed: 2 additions & 299 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import builtins
21
from collections import namedtuple
32
import contextlib
43
import itertools
@@ -867,11 +866,10 @@ def assert_run_failed(self, exctype, msg=None):
867866
yield
868867
if msg is None:
869868
self.assertEqual(str(caught.exception).split(':')[0],
870-
exctype.__name__)
869+
str(exctype))
871870
else:
872871
self.assertEqual(str(caught.exception),
873-
"{}: {}".format(exctype.__name__, msg))
874-
self.assertIsInstance(caught.exception.__cause__, exctype)
872+
"{}: {}".format(exctype, msg))
875873

876874
def test_invalid_syntax(self):
877875
with self.assert_run_failed(SyntaxError):
@@ -1062,301 +1060,6 @@ def f():
10621060
self.assertEqual(retcode, 0)
10631061

10641062

1065-
def build_exception(exctype, /, *args, **kwargs):
1066-
# XXX Use __qualname__?
1067-
name = exctype.__name__
1068-
argreprs = [repr(a) for a in args]
1069-
if kwargs:
1070-
kwargreprs = [f'{k}={v!r}' for k, v in kwargs.items()]
1071-
script = f'{name}({", ".join(argreprs)}, {", ".join(kwargreprs)})'
1072-
else:
1073-
script = f'{name}({", ".join(argreprs)})'
1074-
expected = exctype(*args, **kwargs)
1075-
return script, expected
1076-
1077-
1078-
def build_exceptions(self, *exctypes, default=None, custom=None, bases=True):
1079-
if not exctypes:
1080-
raise NotImplementedError
1081-
if not default:
1082-
default = ((), {})
1083-
elif isinstance(default, str):
1084-
default = ((default,), {})
1085-
elif type(default) is not tuple:
1086-
raise NotImplementedError
1087-
elif len(default) != 2:
1088-
default = (default, {})
1089-
elif type(default[0]) is not tuple:
1090-
default = (default, {})
1091-
elif type(default[1]) is not dict:
1092-
default = (default, {})
1093-
# else leave it alone
1094-
1095-
for exctype in exctypes:
1096-
customtype = None
1097-
values = default
1098-
if custom:
1099-
if exctype in custom:
1100-
customtype = exctype
1101-
elif bases:
1102-
for customtype in custom:
1103-
if issubclass(exctype, customtype):
1104-
break
1105-
else:
1106-
customtype = None
1107-
if customtype is not None:
1108-
values = custom[customtype]
1109-
if values is None:
1110-
continue
1111-
args, kwargs = values
1112-
script, expected = build_exception(exctype, *args, **kwargs)
1113-
yield exctype, customtype, script, expected
1114-
1115-
1116-
try:
1117-
raise Exception
1118-
except Exception as exc:
1119-
assert exc.__traceback__ is not None
1120-
Traceback = type(exc.__traceback__)
1121-
1122-
1123-
class RunFailedTests(TestBase):
1124-
1125-
BUILTINS = [v
1126-
for v in vars(builtins).values()
1127-
if (type(v) is type
1128-
and issubclass(v, Exception)
1129-
#and issubclass(v, BaseException)
1130-
)
1131-
]
1132-
BUILTINS_SPECIAL = [
1133-
# These all have extra attributes (i.e. args/kwargs)
1134-
SyntaxError,
1135-
ImportError,
1136-
UnicodeError,
1137-
OSError,
1138-
SystemExit,
1139-
StopIteration,
1140-
]
1141-
1142-
@classmethod
1143-
def build_exceptions(cls, exctypes=None, default=(), custom=None):
1144-
if exctypes is None:
1145-
exctypes = cls.BUILTINS
1146-
if custom is None:
1147-
# Skip the "special" ones.
1148-
custom = {et: None for et in cls.BUILTINS_SPECIAL}
1149-
yield from build_exceptions(*exctypes, default=default, custom=custom)
1150-
1151-
def assertExceptionsEqual(self, exc, expected, *, chained=True):
1152-
if type(expected) is type:
1153-
self.assertIs(type(exc), expected)
1154-
return
1155-
elif not isinstance(exc, Exception):
1156-
self.assertEqual(exc, expected)
1157-
elif not isinstance(expected, Exception):
1158-
self.assertEqual(exc, expected)
1159-
else:
1160-
# Plain equality doesn't work, so we have to compare manually.
1161-
self.assertIs(type(exc), type(expected))
1162-
self.assertEqual(exc.args, expected.args)
1163-
self.assertEqual(exc.__reduce__(), expected.__reduce__())
1164-
if chained:
1165-
self.assertExceptionsEqual(exc.__context__,
1166-
expected.__context__)
1167-
self.assertExceptionsEqual(exc.__cause__,
1168-
expected.__cause__)
1169-
self.assertEqual(exc.__suppress_context__,
1170-
expected.__suppress_context__)
1171-
1172-
def assertTracebacksEqual(self, tb, expected):
1173-
if not isinstance(tb, Traceback):
1174-
self.assertEqual(tb, expected)
1175-
elif not isinstance(expected, Traceback):
1176-
self.assertEqual(tb, expected)
1177-
else:
1178-
self.assertEqual(tb.tb_frame.f_code.co_name,
1179-
expected.tb_frame.f_code.co_name)
1180-
self.assertEqual(tb.tb_frame.f_code.co_filename,
1181-
expected.tb_frame.f_code.co_filename)
1182-
self.assertEqual(tb.tb_lineno, expected.tb_lineno)
1183-
self.assertTracebacksEqual(tb.tb_next, expected.tb_next)
1184-
1185-
# XXX Move this to TestBase?
1186-
@contextlib.contextmanager
1187-
def expected_run_failure(self, expected):
1188-
exctype = expected if type(expected) is type else type(expected)
1189-
1190-
with self.assertRaises(interpreters.RunFailedError) as caught:
1191-
yield caught
1192-
exc = caught.exception
1193-
1194-
modname = exctype.__module__
1195-
if modname == 'builtins' or modname == '__main__':
1196-
exctypename = exctype.__name__
1197-
else:
1198-
exctypename = f'{modname}.{exctype.__name__}'
1199-
if exctype is expected:
1200-
self.assertEqual(str(exc).split(':')[0], exctypename)
1201-
else:
1202-
self.assertEqual(str(exc), f'{exctypename}: {expected}')
1203-
self.assertExceptionsEqual(exc.__cause__, expected)
1204-
if exc.__cause__ is not None:
1205-
self.assertIsNotNone(exc.__cause__.__traceback__)
1206-
1207-
def test_builtin_exceptions(self):
1208-
interpid = interpreters.create()
1209-
msg = '<a message>'
1210-
for i, info in enumerate(self.build_exceptions(
1211-
default=msg,
1212-
custom={
1213-
SyntaxError: ((msg, '<stdin>', 1, 3, 'a +?'), {}),
1214-
ImportError: ((msg,), {'name': 'spam', 'path': '/x/spam.py'}),
1215-
UnicodeError: None,
1216-
#UnicodeError: ((), {}),
1217-
#OSError: ((), {}),
1218-
SystemExit: ((1,), {}),
1219-
StopIteration: (('<a value>',), {}),
1220-
},
1221-
)):
1222-
exctype, _, script, expected = info
1223-
testname = f'{i+1} - {script}'
1224-
script = f'raise {script}'
1225-
1226-
with self.subTest(testname):
1227-
with self.expected_run_failure(expected):
1228-
interpreters.run_string(interpid, script)
1229-
1230-
def test_custom_exception_from___main__(self):
1231-
script = dedent("""
1232-
class SpamError(Exception):
1233-
def __init__(self, q):
1234-
super().__init__(f'got {q}')
1235-
self.q = q
1236-
raise SpamError('eggs')
1237-
""")
1238-
expected = Exception(f'SpamError: got {"eggs"}')
1239-
1240-
interpid = interpreters.create()
1241-
with self.assertRaises(interpreters.RunFailedError) as caught:
1242-
interpreters.run_string(interpid, script)
1243-
cause = caught.exception.__cause__
1244-
1245-
self.assertExceptionsEqual(cause, expected)
1246-
1247-
class SpamError(Exception):
1248-
# The normal Exception.__reduce__() produces a funny result
1249-
# here. So we have to use a custom __new__().
1250-
def __new__(cls, q):
1251-
if type(q) is SpamError:
1252-
return q
1253-
return super().__new__(cls, q)
1254-
def __init__(self, q):
1255-
super().__init__(f'got {q}')
1256-
self.q = q
1257-
1258-
def test_custom_exception(self):
1259-
script = dedent("""
1260-
import test.test__xxsubinterpreters
1261-
SpamError = test.test__xxsubinterpreters.RunFailedTests.SpamError
1262-
raise SpamError('eggs')
1263-
""")
1264-
try:
1265-
ns = {}
1266-
exec(script, ns, ns)
1267-
except Exception as exc:
1268-
expected = exc
1269-
1270-
interpid = interpreters.create()
1271-
with self.expected_run_failure(expected):
1272-
interpreters.run_string(interpid, script)
1273-
1274-
class SpamReducedError(Exception):
1275-
def __init__(self, q):
1276-
super().__init__(f'got {q}')
1277-
self.q = q
1278-
def __reduce__(self):
1279-
return (type(self), (self.q,), {})
1280-
1281-
def test_custom___reduce__(self):
1282-
script = dedent("""
1283-
import test.test__xxsubinterpreters
1284-
SpamError = test.test__xxsubinterpreters.RunFailedTests.SpamReducedError
1285-
raise SpamError('eggs')
1286-
""")
1287-
try:
1288-
exec(script, (ns := {'__name__': '__main__'}), ns)
1289-
except Exception as exc:
1290-
expected = exc
1291-
1292-
interpid = interpreters.create()
1293-
with self.expected_run_failure(expected):
1294-
interpreters.run_string(interpid, script)
1295-
1296-
def test_traceback_propagated(self):
1297-
script = dedent("""
1298-
def do_spam():
1299-
raise Exception('uh-oh')
1300-
def do_eggs():
1301-
return do_spam()
1302-
class Spam:
1303-
def do(self):
1304-
return do_eggs()
1305-
def get_handler():
1306-
def handler():
1307-
return Spam().do()
1308-
return handler
1309-
go = (lambda: get_handler()())
1310-
def iter_all():
1311-
yield from (go() for _ in [True])
1312-
yield None
1313-
def main():
1314-
for v in iter_all():
1315-
pass
1316-
main()
1317-
""")
1318-
try:
1319-
ns = {}
1320-
exec(script, ns, ns)
1321-
except Exception as exc:
1322-
expected = exc
1323-
expectedtb = exc.__traceback__.tb_next
1324-
1325-
interpid = interpreters.create()
1326-
with self.expected_run_failure(expected) as caught:
1327-
interpreters.run_string(interpid, script)
1328-
exc = caught.exception
1329-
1330-
self.assertTracebacksEqual(exc.__cause__.__traceback__,
1331-
expectedtb)
1332-
1333-
def test_chained_exceptions(self):
1334-
script = dedent("""
1335-
try:
1336-
raise ValueError('msg 1')
1337-
except Exception as exc1:
1338-
try:
1339-
raise TypeError('msg 2')
1340-
except Exception as exc2:
1341-
try:
1342-
raise IndexError('msg 3') from exc2
1343-
except Exception:
1344-
raise AttributeError('msg 4')
1345-
""")
1346-
try:
1347-
exec(script, {}, {})
1348-
except Exception as exc:
1349-
expected = exc
1350-
1351-
interpid = interpreters.create()
1352-
with self.expected_run_failure(expected) as caught:
1353-
interpreters.run_string(interpid, script)
1354-
exc = caught.exception
1355-
1356-
# ...just to be sure.
1357-
self.assertIs(type(exc.__cause__), AttributeError)
1358-
1359-
13601063
##################################
13611064
# channel tests
13621065

0 commit comments

Comments
 (0)