Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
3263f687
Commit
3263f687
authored
Feb 28, 2016
by
Martin Panter
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #22836: Keep exception reports sensible despite errors
parent
738f88f6
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
92 additions
and
9 deletions
+92
-9
Doc/c-api/exceptions.rst
Doc/c-api/exceptions.rst
+2
-2
Lib/test/test_exceptions.py
Lib/test/test_exceptions.py
+66
-2
Misc/NEWS
Misc/NEWS
+5
-0
Python/errors.c
Python/errors.c
+12
-4
Python/pythonrun.c
Python/pythonrun.c
+7
-1
No files found.
Doc/c-api/exceptions.rst
View file @
3263f687
...
@@ -74,8 +74,8 @@ Printing and clearing
...
@@ -74,8 +74,8 @@ Printing and clearing
:meth:`__del__` method.
:meth:`__del__` method.
The function is called with a single argument *obj* that identifies the context
The function is called with a single argument *obj* that identifies the context
in which the unraisable exception occurred.
The repr of *obj* will be printed in
in which the unraisable exception occurred.
If possible,
the warning message.
the
repr of *obj* will be printed in the
warning message.
Raising exceptions
Raising exceptions
...
...
Lib/test/test_exceptions.py
View file @
3263f687
...
@@ -7,7 +7,7 @@ import pickle
...
@@ -7,7 +7,7 @@ import pickle
import
weakref
import
weakref
import
errno
import
errno
from
test.support
import
(
TESTFN
,
captured_
output
,
check_impl_detail
,
from
test.support
import
(
TESTFN
,
captured_
stderr
,
check_impl_detail
,
check_warnings
,
cpython_only
,
gc_collect
,
run_unittest
,
check_warnings
,
cpython_only
,
gc_collect
,
run_unittest
,
no_tracing
,
unlink
,
import_module
)
no_tracing
,
unlink
,
import_module
)
...
@@ -20,6 +20,10 @@ class SlottedNaiveException(Exception):
...
@@ -20,6 +20,10 @@ class SlottedNaiveException(Exception):
def
__init__
(
self
,
x
):
def
__init__
(
self
,
x
):
self
.
x
=
x
self
.
x
=
x
class
BrokenStrException
(
Exception
):
def
__str__
(
self
):
raise
Exception
(
"str() is broken"
)
# XXX This is not really enough, each *operation* should be tested!
# XXX This is not really enough, each *operation* should be tested!
class
ExceptionTests
(
unittest
.
TestCase
):
class
ExceptionTests
(
unittest
.
TestCase
):
...
@@ -882,7 +886,7 @@ class ExceptionTests(unittest.TestCase):
...
@@ -882,7 +886,7 @@ class ExceptionTests(unittest.TestCase):
class
MyException
(
Exception
,
metaclass
=
Meta
):
class
MyException
(
Exception
,
metaclass
=
Meta
):
pass
pass
with
captured_
output
(
"stderr"
)
as
stderr
:
with
captured_
stderr
(
)
as
stderr
:
try
:
try
:
raise
KeyError
()
raise
KeyError
()
except
MyException
as
e
:
except
MyException
as
e
:
...
@@ -1011,6 +1015,66 @@ class ExceptionTests(unittest.TestCase):
...
@@ -1011,6 +1015,66 @@ class ExceptionTests(unittest.TestCase):
os
.
listdir
(
__file__
)
os
.
listdir
(
__file__
)
self
.
assertEqual
(
cm
.
exception
.
errno
,
errno
.
ENOTDIR
,
cm
.
exception
)
self
.
assertEqual
(
cm
.
exception
.
errno
,
errno
.
ENOTDIR
,
cm
.
exception
)
def
test_unraisable
(
self
):
# Issue #22836: PyErr_WriteUnraisable() should give sensible reports
class
BrokenDel
:
def
__del__
(
self
):
exc
=
ValueError
(
"del is broken"
)
# The following line is included in the traceback report:
raise
exc
class
BrokenRepr
(
BrokenDel
):
def
__repr__
(
self
):
raise
AttributeError
(
"repr() is broken"
)
class
BrokenExceptionDel
:
def
__del__
(
self
):
exc
=
BrokenStrException
()
# The following line is included in the traceback report:
raise
exc
for
test_class
in
(
BrokenDel
,
BrokenRepr
,
BrokenExceptionDel
):
with
self
.
subTest
(
test_class
):
obj
=
test_class
()
with
captured_stderr
()
as
stderr
:
del
obj
report
=
stderr
.
getvalue
()
self
.
assertIn
(
"Exception ignored"
,
report
)
if
test_class
is
BrokenRepr
:
self
.
assertIn
(
"<object repr() failed>"
,
report
)
else
:
self
.
assertIn
(
test_class
.
__del__
.
__qualname__
,
report
)
self
.
assertIn
(
"test_exceptions.py"
,
report
)
self
.
assertIn
(
"raise exc"
,
report
)
if
test_class
is
BrokenExceptionDel
:
self
.
assertIn
(
"BrokenStrException"
,
report
)
self
.
assertIn
(
"<exception str() failed>"
,
report
)
else
:
self
.
assertIn
(
"ValueError"
,
report
)
self
.
assertIn
(
"del is broken"
,
report
)
self
.
assertTrue
(
report
.
endswith
(
"
\
n
"
))
def
test_unhandled
(
self
):
# Check for sensible reporting of unhandled exceptions
for
exc_type
in
(
ValueError
,
BrokenStrException
):
with
self
.
subTest
(
exc_type
):
try
:
exc
=
exc_type
(
"test message"
)
# The following line is included in the traceback report:
raise
exc
except
exc_type
:
with
captured_stderr
()
as
stderr
:
sys
.
__excepthook__
(
*
sys
.
exc_info
())
report
=
stderr
.
getvalue
()
self
.
assertIn
(
"test_exceptions.py"
,
report
)
self
.
assertIn
(
"raise exc"
,
report
)
self
.
assertIn
(
exc_type
.
__name__
,
report
)
if
exc_type
is
BrokenStrException
:
self
.
assertIn
(
"<exception str() failed>"
,
report
)
else
:
self
.
assertIn
(
"test message"
,
report
)
self
.
assertTrue
(
report
.
endswith
(
"
\
n
"
))
class
ImportErrorTests
(
unittest
.
TestCase
):
class
ImportErrorTests
(
unittest
.
TestCase
):
...
...
Misc/NEWS
View file @
3263f687
...
@@ -10,6 +10,11 @@ Release date: tba
...
@@ -10,6 +10,11 @@ Release date: tba
Core and Builtins
Core and Builtins
-----------------
-----------------
- Issue #22836: Ensure exception reports from PyErr_Display() and
PyErr_WriteUnraisable() are sensible even when formatting them produces
secondary errors. This affects the reports produced by
sys.__excepthook__() and when __del__() raises an exception.
- Issue #26302: Correct behavior to reject comma as a legal character for
- Issue #26302: Correct behavior to reject comma as a legal character for
cookie names.
cookie names.
...
...
Python/errors.c
View file @
3263f687
...
@@ -900,8 +900,12 @@ PyErr_WriteUnraisable(PyObject *obj)
...
@@ -900,8 +900,12 @@ PyErr_WriteUnraisable(PyObject *obj)
if
(
obj
)
{
if
(
obj
)
{
if
(
PyFile_WriteString
(
"Exception ignored in: "
,
f
)
<
0
)
if
(
PyFile_WriteString
(
"Exception ignored in: "
,
f
)
<
0
)
goto
done
;
goto
done
;
if
(
PyFile_WriteObject
(
obj
,
f
,
0
)
<
0
)
if
(
PyFile_WriteObject
(
obj
,
f
,
0
)
<
0
)
{
PyErr_Clear
();
if
(
PyFile_WriteString
(
"<object repr() failed>"
,
f
)
<
0
)
{
goto
done
;
goto
done
;
}
}
if
(
PyFile_WriteString
(
"
\n
"
,
f
)
<
0
)
if
(
PyFile_WriteString
(
"
\n
"
,
f
)
<
0
)
goto
done
;
goto
done
;
}
}
...
@@ -946,9 +950,13 @@ PyErr_WriteUnraisable(PyObject *obj)
...
@@ -946,9 +950,13 @@ PyErr_WriteUnraisable(PyObject *obj)
if
(
v
&&
v
!=
Py_None
)
{
if
(
v
&&
v
!=
Py_None
)
{
if
(
PyFile_WriteString
(
": "
,
f
)
<
0
)
if
(
PyFile_WriteString
(
": "
,
f
)
<
0
)
goto
done
;
goto
done
;
if
(
PyFile_WriteObject
(
v
,
f
,
Py_PRINT_RAW
)
<
0
)
if
(
PyFile_WriteObject
(
v
,
f
,
Py_PRINT_RAW
)
<
0
)
{
PyErr_Clear
();
if
(
PyFile_WriteString
(
"<exception str() failed>"
,
f
)
<
0
)
{
goto
done
;
goto
done
;
}
}
}
}
if
(
PyFile_WriteString
(
"
\n
"
,
f
)
<
0
)
if
(
PyFile_WriteString
(
"
\n
"
,
f
)
<
0
)
goto
done
;
goto
done
;
...
...
Python/pythonrun.c
View file @
3263f687
...
@@ -766,8 +766,11 @@ print_exception(PyObject *f, PyObject *value)
...
@@ -766,8 +766,11 @@ print_exception(PyObject *f, PyObject *value)
/* only print colon if the str() of the
/* only print colon if the str() of the
object is not the empty string
object is not the empty string
*/
*/
if
(
s
==
NULL
)
if
(
s
==
NULL
)
{
PyErr_Clear
();
err
=
-
1
;
err
=
-
1
;
PyFile_WriteString
(
": <exception str() failed>"
,
f
);
}
else
if
(
!
PyUnicode_Check
(
s
)
||
else
if
(
!
PyUnicode_Check
(
s
)
||
PyUnicode_GetLength
(
s
)
!=
0
)
PyUnicode_GetLength
(
s
)
!=
0
)
err
=
PyFile_WriteString
(
": "
,
f
);
err
=
PyFile_WriteString
(
": "
,
f
);
...
@@ -776,6 +779,9 @@ print_exception(PyObject *f, PyObject *value)
...
@@ -776,6 +779,9 @@ print_exception(PyObject *f, PyObject *value)
Py_XDECREF
(
s
);
Py_XDECREF
(
s
);
}
}
/* try to write a newline in any case */
/* try to write a newline in any case */
if
(
err
<
0
)
{
PyErr_Clear
();
}
err
+=
PyFile_WriteString
(
"
\n
"
,
f
);
err
+=
PyFile_WriteString
(
"
\n
"
,
f
);
Py_XDECREF
(
tb
);
Py_XDECREF
(
tb
);
Py_DECREF
(
value
);
Py_DECREF
(
value
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment