Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4071691

Browse files
serhiy-storchakaFullteaR
authored andcommitted
pythongh-108082: C API: Add tests for PyErr_WriteUnraisable() (pythonGH-111455)
Also document the behavior when called with NULL.
1 parentaf4ffa1 commit4071691

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

‎Doc/c-api/exceptions.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,17 @@ Printing and clearing
8888
The function is called with a single argument *obj* that identifies the context
8989
in which the unraisable exception occurred. If possible,
9090
the repr of *obj* will be printed in the warning message.
91+
If *obj* is ``NULL``, only the traceback is printed.
9192
9293
An exception must be set when calling this function.
9394
95+
..versionchanged::3.4
96+
Print a traceback. Print only traceback if *obj* is ``NULL``.
97+
98+
..versionchanged::3.8
99+
Use:func:`sys.unraisablehook`.
100+
101+
94102
..c:function::voidPyErr_DisplayException(PyObject *exc)
95103
96104
Print the standard traceback display of ``exc`` to ``sys.stderr``, including

‎Lib/test/test_capi/test_exceptions.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
NULL=None
1919

20+
classCustomError(Exception):
21+
pass
22+
23+
2024
classTest_Exceptions(unittest.TestCase):
2125

2226
deftest_exception(self):
@@ -270,6 +274,47 @@ def test_setfromerrnowithfilename(self):
270274
(ENOENT,'No such file or directory','file'))
271275
# CRASHES setfromerrnowithfilename(ENOENT, NULL, b'error')
272276

277+
deftest_err_writeunraisable(self):
278+
# Test PyErr_WriteUnraisable()
279+
writeunraisable=_testcapi.err_writeunraisable
280+
firstline=self.test_err_writeunraisable.__code__.co_firstlineno
281+
282+
withsupport.catch_unraisable_exception()ascm:
283+
writeunraisable(CustomError('oops!'),hex)
284+
self.assertEqual(cm.unraisable.exc_type,CustomError)
285+
self.assertEqual(str(cm.unraisable.exc_value),'oops!')
286+
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
287+
firstline+6)
288+
self.assertIsNone(cm.unraisable.err_msg)
289+
self.assertEqual(cm.unraisable.object,hex)
290+
291+
withsupport.catch_unraisable_exception()ascm:
292+
writeunraisable(CustomError('oops!'),NULL)
293+
self.assertEqual(cm.unraisable.exc_type,CustomError)
294+
self.assertEqual(str(cm.unraisable.exc_value),'oops!')
295+
self.assertEqual(cm.unraisable.exc_traceback.tb_lineno,
296+
firstline+15)
297+
self.assertIsNone(cm.unraisable.err_msg)
298+
self.assertIsNone(cm.unraisable.object)
299+
300+
with (support.swap_attr(sys,'unraisablehook',None),
301+
support.captured_stderr()asstderr):
302+
writeunraisable(CustomError('oops!'),hex)
303+
lines=stderr.getvalue().splitlines()
304+
self.assertEqual(lines[0],f'Exception ignored in:{hex!r}')
305+
self.assertEqual(lines[1],'Traceback (most recent call last):')
306+
self.assertEqual(lines[-1],f'{__name__}.CustomError: oops!')
307+
308+
with (support.swap_attr(sys,'unraisablehook',None),
309+
support.captured_stderr()asstderr):
310+
writeunraisable(CustomError('oops!'),NULL)
311+
lines=stderr.getvalue().splitlines()
312+
self.assertEqual(lines[0],'Traceback (most recent call last):')
313+
self.assertEqual(lines[-1],f'{__name__}.CustomError: oops!')
314+
315+
# CRASHES writeunraisable(NULL, hex)
316+
# CRASHES writeunraisable(NULL, NULL)
317+
273318

274319
classTest_PyUnstable_Exc_PrepReraiseStar(ExceptionIsLikeMixin,unittest.TestCase):
275320

‎Modules/_testcapi/exceptions.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,22 @@ _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
303303
Py_RETURN_NONE;
304304
}
305305

306+
staticPyObject*
307+
err_writeunraisable(PyObject*Py_UNUSED(module),PyObject*args)
308+
{
309+
PyObject*exc,*obj;
310+
if (!PyArg_ParseTuple(args,"OO",&exc,&obj)) {
311+
returnNULL;
312+
}
313+
NULLABLE(exc);
314+
NULLABLE(obj);
315+
if (exc) {
316+
PyErr_SetRaisedException(Py_NewRef(exc));
317+
}
318+
PyErr_WriteUnraisable(obj);
319+
Py_RETURN_NONE;
320+
}
321+
306322
/*[clinic input]
307323
_testcapi.unstable_exc_prep_reraise_star
308324
orig: object
@@ -347,6 +363,7 @@ static PyTypeObject PyRecursingInfinitelyError_Type = {
347363

348364
staticPyMethodDeftest_methods[]= {
349365
{"err_restore",err_restore,METH_VARARGS},
366+
{"err_writeunraisable",err_writeunraisable,METH_VARARGS},
350367
_TESTCAPI_ERR_SET_RAISED_METHODDEF
351368
_TESTCAPI_EXCEPTION_PRINT_METHODDEF
352369
_TESTCAPI_FATAL_ERROR_METHODDEF

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp