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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy