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
9ceea101
Commit
9ceea101
authored
Mar 05, 2015
by
Robert Collins
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #22936: Make it possible to show local variables in tracebacks.
parent
66de5374
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
112 additions
and
34 deletions
+112
-34
Doc/library/traceback.rst
Doc/library/traceback.rst
+18
-10
Lib/test/test_traceback.py
Lib/test/test_traceback.py
+60
-8
Lib/traceback.py
Lib/traceback.py
+32
-16
Misc/NEWS
Misc/NEWS
+2
-0
No files found.
Doc/library/traceback.rst
View file @
9ceea101
...
@@ -159,17 +159,21 @@ The module also defines the following classes:
...
@@ -159,17 +159,21 @@ The module also defines the following classes:
:class:`.TracebackException` objects are created from actual exceptions to
:class:`.TracebackException` objects are created from actual exceptions to
capture data for later printing in a lightweight fashion.
capture data for later printing in a lightweight fashion.
.. class:: TracebackException(exc_type, exc_value, exc_traceback,
limit=None, lookup_lines=Tru
e)
.. class:: TracebackException(exc_type, exc_value, exc_traceback,
*, limit=None, lookup_lines=True, capture_locals=Fals
e)
Capture an exception for later rendering. limit, lookup_lines are as for
Capture an exception for later rendering. limit, lookup_lines and
the :class:`.StackSummary` class.
capture_locals=False are as for the :class:`.StackSummary` class.
Note that when locals are captured, they are also shown in the traceback.
.. versionadded:: 3.5
.. versionadded:: 3.5
.. classmethod:: `.from_exception`(exc, limit=None, lookup_lines=True)
.. classmethod:: `.from_exception`(exc, *, limit=None, lookup_lines=True, capture_locals=False)
Capture an exception for later rendering. limit, lookup_lines and
capture_locals=False are as for the :class:`.StackSummary` class.
Capture an exception for later rendering. limit and lookup_lines
Note that when locals are captured, they are also shown in the traceback.
are as for the :class:`.StackSummary` class.
.. versionadded:: 3.5
.. versionadded:: 3.5
...
@@ -190,7 +194,7 @@ capture data for later printing in a lightweight fashion.
...
@@ -190,7 +194,7 @@ capture data for later printing in a lightweight fashion.
error occured.
error occured.
.. attribute:: `.msg` For syntax errors - the compiler error message.
.. attribute:: `.msg` For syntax errors - the compiler error message.
.. method:: TracebackException.format(chain=True)
.. method:: TracebackException.format(
*,
chain=True)
Format the exception.
Format the exception.
...
@@ -227,7 +231,7 @@ capture data for later printing in a lightweight fashion.
...
@@ -227,7 +231,7 @@ capture data for later printing in a lightweight fashion.
:class:`.StackSummary` objects represent a call stack ready for formatting.
:class:`.StackSummary` objects represent a call stack ready for formatting.
.. classmethod:: StackSummary.extract(frame_gen,
limit=None, lookup_lines=Tru
e)
.. classmethod:: StackSummary.extract(frame_gen,
*, limit=None, lookup_lines=True, capture_locals=Fals
e)
Construct a StackSummary object from a frame generator (such as is returned by
Construct a StackSummary object from a frame generator (such as is returned by
`walk_stack` or `walk_tb`.
`walk_stack` or `walk_tb`.
...
@@ -236,6 +240,8 @@ capture data for later printing in a lightweight fashion.
...
@@ -236,6 +240,8 @@ capture data for later printing in a lightweight fashion.
If lookup_lines is False, the returned FrameSummary objects will not have read
If lookup_lines is False, the returned FrameSummary objects will not have read
their lines in yet, making the cost of creating the StackSummary cheaper (which
their lines in yet, making the cost of creating the StackSummary cheaper (which
may be valuable if it may not actually get formatted).
may be valuable if it may not actually get formatted).
If capture_locals is True the local variables in each *FrameSummary* are
captured as object representations.
.. versionadded:: 3.5
.. versionadded:: 3.5
...
@@ -258,8 +264,10 @@ FrameSummary objects represent a single frame in a traceback.
...
@@ -258,8 +264,10 @@ FrameSummary objects represent a single frame in a traceback.
or printed. It may optionally have a stringified version of the frames
or printed. It may optionally have a stringified version of the frames
locals included in it. If *lookup_line* is False, the source code is not
locals included in it. If *lookup_line* is False, the source code is not
looked up until the FrameSummary has the :attr:`line` attribute accessed (which
looked up until the FrameSummary has the :attr:`line` attribute accessed (which
also happens when casting it to a tuple). Line may be directly provided, and
also happens when casting it to a tuple). *line* may be directly provided, and
will prevent line lookups happening at all.
will prevent line lookups happening at all. *locals* is an optional local variable
dictionary, and if supplied the variable representations are stored in the summary
for later display.
.. _traceback-example:
.. _traceback-example:
...
...
Lib/test/test_traceback.py
View file @
9ceea101
...
@@ -15,7 +15,7 @@ import traceback
...
@@ -15,7 +15,7 @@ import traceback
test_code
=
namedtuple
(
'code'
,
[
'co_filename'
,
'co_name'
])
test_code
=
namedtuple
(
'code'
,
[
'co_filename'
,
'co_name'
])
test_frame
=
namedtuple
(
'frame'
,
[
'f_code'
,
'f_globals'
])
test_frame
=
namedtuple
(
'frame'
,
[
'f_code'
,
'f_globals'
,
'f_locals'
])
test_tb
=
namedtuple
(
'tb'
,
[
'tb_frame'
,
'tb_lineno'
,
'tb_next'
])
test_tb
=
namedtuple
(
'tb'
,
[
'tb_frame'
,
'tb_lineno'
,
'tb_next'
])
...
@@ -535,7 +535,7 @@ class TestStack(unittest.TestCase):
...
@@ -535,7 +535,7 @@ class TestStack(unittest.TestCase):
linecache
.
clearcache
()
linecache
.
clearcache
()
linecache
.
updatecache
(
'/foo.py'
,
globals
())
linecache
.
updatecache
(
'/foo.py'
,
globals
())
c
=
test_code
(
'/foo.py'
,
'method'
)
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
None
)
f
=
test_frame
(
c
,
None
,
None
)
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]),
lookup_lines
=
True
)
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]),
lookup_lines
=
True
)
linecache
.
clearcache
()
linecache
.
clearcache
()
self
.
assertEqual
(
s
[
0
].
line
,
"import sys"
)
self
.
assertEqual
(
s
[
0
].
line
,
"import sys"
)
...
@@ -543,14 +543,14 @@ class TestStack(unittest.TestCase):
...
@@ -543,14 +543,14 @@ class TestStack(unittest.TestCase):
def
test_extract_stackup_deferred_lookup_lines
(
self
):
def
test_extract_stackup_deferred_lookup_lines
(
self
):
linecache
.
clearcache
()
linecache
.
clearcache
()
c
=
test_code
(
'/foo.py'
,
'method'
)
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
None
)
f
=
test_frame
(
c
,
None
,
None
)
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]),
lookup_lines
=
False
)
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]),
lookup_lines
=
False
)
self
.
assertEqual
({},
linecache
.
cache
)
self
.
assertEqual
({},
linecache
.
cache
)
linecache
.
updatecache
(
'/foo.py'
,
globals
())
linecache
.
updatecache
(
'/foo.py'
,
globals
())
self
.
assertEqual
(
s
[
0
].
line
,
"import sys"
)
self
.
assertEqual
(
s
[
0
].
line
,
"import sys"
)
def
test_from_list
(
self
):
def
test_from_list
(
self
):
s
=
traceback
.
StackSummary
([(
'foo.py'
,
1
,
'fred'
,
'line'
)])
s
=
traceback
.
StackSummary
.
from_list
([(
'foo.py'
,
1
,
'fred'
,
'line'
)])
self
.
assertEqual
(
self
.
assertEqual
(
[
' File "foo.py", line 1, in fred
\
n
line
\
n
'
],
[
' File "foo.py", line 1, in fred
\
n
line
\
n
'
],
s
.
format
())
s
.
format
())
...
@@ -558,11 +558,42 @@ class TestStack(unittest.TestCase):
...
@@ -558,11 +558,42 @@ class TestStack(unittest.TestCase):
def
test_format_smoke
(
self
):
def
test_format_smoke
(
self
):
# For detailed tests see the format_list tests, which consume the same
# For detailed tests see the format_list tests, which consume the same
# code.
# code.
s
=
traceback
.
StackSummary
([(
'foo.py'
,
1
,
'fred'
,
'line'
)])
s
=
traceback
.
StackSummary
.
from_list
([(
'foo.py'
,
1
,
'fred'
,
'line'
)])
self
.
assertEqual
(
self
.
assertEqual
(
[
' File "foo.py", line 1, in fred
\
n
line
\
n
'
],
[
' File "foo.py", line 1, in fred
\
n
line
\
n
'
],
s
.
format
())
s
.
format
())
def
test_locals
(
self
):
linecache
.
updatecache
(
'/foo.py'
,
globals
())
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
globals
(),
{
'something'
:
1
})
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]),
capture_locals
=
True
)
self
.
assertEqual
(
s
[
0
].
locals
,
{
'something'
:
'1'
})
def
test_no_locals
(
self
):
linecache
.
updatecache
(
'/foo.py'
,
globals
())
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
globals
(),
{
'something'
:
1
})
s
=
traceback
.
StackSummary
.
extract
(
iter
([(
f
,
6
)]))
self
.
assertEqual
(
s
[
0
].
locals
,
None
)
def
test_format_locals
(
self
):
def
some_inner
(
k
,
v
):
a
=
1
b
=
2
return
traceback
.
StackSummary
.
extract
(
traceback
.
walk_stack
(
None
),
capture_locals
=
True
,
limit
=
1
)
s
=
some_inner
(
3
,
4
)
self
.
assertEqual
(
[
' File "'
+
__file__
+
'", line 585, '
'in some_inner
\
n
'
' traceback.walk_stack(None), capture_locals=True, limit=1)
\
n
'
' a = 1
\
n
'
' b = 2
\
n
'
' k = 3
\
n
'
' v = 4
\
n
'
],
s
.
format
())
class
TestTracebackException
(
unittest
.
TestCase
):
class
TestTracebackException
(
unittest
.
TestCase
):
...
@@ -591,9 +622,10 @@ class TestTracebackException(unittest.TestCase):
...
@@ -591,9 +622,10 @@ class TestTracebackException(unittest.TestCase):
except
Exception
as
e
:
except
Exception
as
e
:
exc_info
=
sys
.
exc_info
()
exc_info
=
sys
.
exc_info
()
self
.
expected_stack
=
traceback
.
StackSummary
.
extract
(
self
.
expected_stack
=
traceback
.
StackSummary
.
extract
(
traceback
.
walk_tb
(
exc_info
[
2
]),
limit
=
1
,
lookup_lines
=
False
)
traceback
.
walk_tb
(
exc_info
[
2
]),
limit
=
1
,
lookup_lines
=
False
,
capture_locals
=
True
)
self
.
exc
=
traceback
.
TracebackException
.
from_exception
(
self
.
exc
=
traceback
.
TracebackException
.
from_exception
(
e
,
limit
=
1
,
lookup_lines
=
False
)
e
,
limit
=
1
,
lookup_lines
=
False
,
capture_locals
=
True
)
expected_stack
=
self
.
expected_stack
expected_stack
=
self
.
expected_stack
exc
=
self
.
exc
exc
=
self
.
exc
self
.
assertEqual
(
None
,
exc
.
__cause__
)
self
.
assertEqual
(
None
,
exc
.
__cause__
)
...
@@ -664,13 +696,33 @@ class TestTracebackException(unittest.TestCase):
...
@@ -664,13 +696,33 @@ class TestTracebackException(unittest.TestCase):
linecache
.
clearcache
()
linecache
.
clearcache
()
e
=
Exception
(
"uh oh"
)
e
=
Exception
(
"uh oh"
)
c
=
test_code
(
'/foo.py'
,
'method'
)
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
None
)
f
=
test_frame
(
c
,
None
,
None
)
tb
=
test_tb
(
f
,
6
,
None
)
tb
=
test_tb
(
f
,
6
,
None
)
exc
=
traceback
.
TracebackException
(
Exception
,
e
,
tb
,
lookup_lines
=
False
)
exc
=
traceback
.
TracebackException
(
Exception
,
e
,
tb
,
lookup_lines
=
False
)
self
.
assertEqual
({},
linecache
.
cache
)
self
.
assertEqual
({},
linecache
.
cache
)
linecache
.
updatecache
(
'/foo.py'
,
globals
())
linecache
.
updatecache
(
'/foo.py'
,
globals
())
self
.
assertEqual
(
exc
.
stack
[
0
].
line
,
"import sys"
)
self
.
assertEqual
(
exc
.
stack
[
0
].
line
,
"import sys"
)
def
test_locals
(
self
):
linecache
.
updatecache
(
'/foo.py'
,
globals
())
e
=
Exception
(
"uh oh"
)
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
globals
(),
{
'something'
:
1
,
'other'
:
'string'
})
tb
=
test_tb
(
f
,
6
,
None
)
exc
=
traceback
.
TracebackException
(
Exception
,
e
,
tb
,
capture_locals
=
True
)
self
.
assertEqual
(
exc
.
stack
[
0
].
locals
,
{
'something'
:
'1'
,
'other'
:
"'string'"
})
def
test_no_locals
(
self
):
linecache
.
updatecache
(
'/foo.py'
,
globals
())
e
=
Exception
(
"uh oh"
)
c
=
test_code
(
'/foo.py'
,
'method'
)
f
=
test_frame
(
c
,
globals
(),
{
'something'
:
1
})
tb
=
test_tb
(
f
,
6
,
None
)
exc
=
traceback
.
TracebackException
(
Exception
,
e
,
tb
)
self
.
assertEqual
(
exc
.
stack
[
0
].
locals
,
None
)
def
test_main
():
def
test_main
():
run_unittest
(
__name__
)
run_unittest
(
__name__
)
...
...
Lib/traceback.py
View file @
9ceea101
...
@@ -223,19 +223,19 @@ class FrameSummary:
...
@@ -223,19 +223,19 @@ class FrameSummary:
- :attr:`line` The text from the linecache module for the
- :attr:`line` The text from the linecache module for the
of code that was running when the frame was captured.
of code that was running when the frame was captured.
- :attr:`locals` Either None if locals were not supplied, or a dict
- :attr:`locals` Either None if locals were not supplied, or a dict
mapping the name to the
st
r() of the variable.
mapping the name to the
rep
r() of the variable.
"""
"""
__slots__
=
(
'filename'
,
'lineno'
,
'name'
,
'_line'
,
'locals'
)
__slots__
=
(
'filename'
,
'lineno'
,
'name'
,
'_line'
,
'locals'
)
def
__init__
(
self
,
filename
,
lineno
,
name
,
lookup_line
=
True
,
locals
=
Non
e
,
def
__init__
(
self
,
filename
,
lineno
,
name
,
*
,
lookup_line
=
Tru
e
,
line
=
None
):
l
ocals
=
None
,
l
ine
=
None
):
"""Construct a FrameSummary.
"""Construct a FrameSummary.
:param lookup_line: If True, `linecache` is consulted for the source
:param lookup_line: If True, `linecache` is consulted for the source
code line. Otherwise, the line will be looked up when first needed.
code line. Otherwise, the line will be looked up when first needed.
:param locals: If supplied the frame locals, which will be captured as
:param locals: If supplied the frame locals, which will be captured as
string
s.
object representation
s.
:param line: If provided, use this instead of looking up the line in
:param line: If provided, use this instead of looking up the line in
the linecache.
the linecache.
"""
"""
...
@@ -246,7 +246,7 @@ class FrameSummary:
...
@@ -246,7 +246,7 @@ class FrameSummary:
if
lookup_line
:
if
lookup_line
:
self
.
line
self
.
line
self
.
locals
=
\
self
.
locals
=
\
dict
((
k
,
st
r
(
v
))
for
k
,
v
in
locals
.
items
())
if
locals
else
None
dict
((
k
,
rep
r
(
v
))
for
k
,
v
in
locals
.
items
())
if
locals
else
None
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
return
(
self
.
filename
==
other
.
filename
and
return
(
self
.
filename
==
other
.
filename
and
...
@@ -299,7 +299,8 @@ class StackSummary(list):
...
@@ -299,7 +299,8 @@ class StackSummary(list):
"""A stack of frames."""
"""A stack of frames."""
@
classmethod
@
classmethod
def
extract
(
klass
,
frame_gen
,
limit
=
None
,
lookup_lines
=
True
):
def
extract
(
klass
,
frame_gen
,
*
,
limit
=
None
,
lookup_lines
=
True
,
capture_locals
=
False
):
"""Create a StackSummary from a traceback or stack object.
"""Create a StackSummary from a traceback or stack object.
:param frame_gen: A generator that yields (frame, lineno) tuples to
:param frame_gen: A generator that yields (frame, lineno) tuples to
...
@@ -308,6 +309,8 @@ class StackSummary(list):
...
@@ -308,6 +309,8 @@ class StackSummary(list):
include.
include.
:param lookup_lines: If True, lookup lines for each frame immediately,
:param lookup_lines: If True, lookup lines for each frame immediately,
otherwise lookup is deferred until the frame is rendered.
otherwise lookup is deferred until the frame is rendered.
:param capture_locals: If True, the local variables from each frame will
be captured as object representations into the FrameSummary.
"""
"""
if
limit
is
None
:
if
limit
is
None
:
limit
=
getattr
(
sys
,
'tracebacklimit'
,
None
)
limit
=
getattr
(
sys
,
'tracebacklimit'
,
None
)
...
@@ -324,7 +327,12 @@ class StackSummary(list):
...
@@ -324,7 +327,12 @@ class StackSummary(list):
fnames
.
add
(
filename
)
fnames
.
add
(
filename
)
linecache
.
lazycache
(
filename
,
f
.
f_globals
)
linecache
.
lazycache
(
filename
,
f
.
f_globals
)
# Must defer line lookups until we have called checkcache.
# Must defer line lookups until we have called checkcache.
result
.
append
(
FrameSummary
(
filename
,
lineno
,
name
,
lookup_line
=
False
))
if
capture_locals
:
f_locals
=
f
.
f_locals
else
:
f_locals
=
None
result
.
append
(
FrameSummary
(
filename
,
lineno
,
name
,
lookup_line
=
False
,
locals
=
f_locals
))
for
filename
in
fnames
:
for
filename
in
fnames
:
linecache
.
checkcache
(
filename
)
linecache
.
checkcache
(
filename
)
# If immediate lookup was desired, trigger lookups now.
# If immediate lookup was desired, trigger lookups now.
...
@@ -356,11 +364,16 @@ class StackSummary(list):
...
@@ -356,11 +364,16 @@ class StackSummary(list):
newlines as well, for those items with source text lines.
newlines as well, for those items with source text lines.
"""
"""
result
=
[]
result
=
[]
for
filename
,
lineno
,
name
,
line
in
self
:
for
frame
in
self
:
item
=
' File "{}", line {}, in {}
\
n
'
.
format
(
filename
,
lineno
,
name
)
row
=
[]
if
line
:
row
.
append
(
' File "{}", line {}, in {}
\
n
'
.
format
(
item
=
item
+
' {}
\
n
'
.
format
(
line
.
strip
())
frame
.
filename
,
frame
.
lineno
,
frame
.
name
))
result
.
append
(
item
)
if
frame
.
line
:
row
.
append
(
' {}
\
n
'
.
format
(
frame
.
line
.
strip
()))
if
frame
.
locals
:
for
name
,
value
in
sorted
(
frame
.
locals
.
items
()):
row
.
append
(
' {name} = {value}
\
n
'
.
format
(
name
=
name
,
value
=
value
))
result
.
append
(
''
.
join
(
row
))
return
result
return
result
...
@@ -392,8 +405,8 @@ class TracebackException:
...
@@ -392,8 +405,8 @@ class TracebackException:
- :attr:`msg` For syntax errors - the compiler error message.
- :attr:`msg` For syntax errors - the compiler error message.
"""
"""
def
__init__
(
self
,
exc_type
,
exc_value
,
exc_traceback
,
limit
=
None
,
def
__init__
(
self
,
exc_type
,
exc_value
,
exc_traceback
,
*
,
limit
=
None
,
lookup_lines
=
True
,
_seen
=
None
):
lookup_lines
=
True
,
capture_locals
=
False
,
_seen
=
None
):
# NB: we need to accept exc_traceback, exc_value, exc_traceback to
# NB: we need to accept exc_traceback, exc_value, exc_traceback to
# permit backwards compat with the existing API, otherwise we
# permit backwards compat with the existing API, otherwise we
# need stub thunk objects just to glue it together.
# need stub thunk objects just to glue it together.
...
@@ -411,6 +424,7 @@ class TracebackException:
...
@@ -411,6 +424,7 @@ class TracebackException:
exc_value
.
__cause__
.
__traceback__
,
exc_value
.
__cause__
.
__traceback__
,
limit
=
limit
,
limit
=
limit
,
lookup_lines
=
False
,
lookup_lines
=
False
,
capture_locals
=
capture_locals
,
_seen
=
_seen
)
_seen
=
_seen
)
else
:
else
:
cause
=
None
cause
=
None
...
@@ -422,6 +436,7 @@ class TracebackException:
...
@@ -422,6 +436,7 @@ class TracebackException:
exc_value
.
__context__
.
__traceback__
,
exc_value
.
__context__
.
__traceback__
,
limit
=
limit
,
limit
=
limit
,
lookup_lines
=
False
,
lookup_lines
=
False
,
capture_locals
=
capture_locals
,
_seen
=
_seen
)
_seen
=
_seen
)
else
:
else
:
context
=
None
context
=
None
...
@@ -431,7 +446,8 @@ class TracebackException:
...
@@ -431,7 +446,8 @@ class TracebackException:
exc_value
.
__suppress_context__
if
exc_value
else
False
exc_value
.
__suppress_context__
if
exc_value
else
False
# TODO: locals.
# TODO: locals.
self
.
stack
=
StackSummary
.
extract
(
self
.
stack
=
StackSummary
.
extract
(
walk_tb
(
exc_traceback
),
limit
=
limit
,
lookup_lines
=
lookup_lines
)
walk_tb
(
exc_traceback
),
limit
=
limit
,
lookup_lines
=
lookup_lines
,
capture_locals
=
capture_locals
)
self
.
exc_type
=
exc_type
self
.
exc_type
=
exc_type
# Capture now to permit freeing resources: only complication is in the
# Capture now to permit freeing resources: only complication is in the
# unofficial API _format_final_exc_line
# unofficial API _format_final_exc_line
...
@@ -512,7 +528,7 @@ class TracebackException:
...
@@ -512,7 +528,7 @@ class TracebackException:
msg
=
self
.
msg
or
"<no detail available>"
msg
=
self
.
msg
or
"<no detail available>"
yield
"{}: {}
\
n
"
.
format
(
stype
,
msg
)
yield
"{}: {}
\
n
"
.
format
(
stype
,
msg
)
def
format
(
self
,
chain
=
True
):
def
format
(
self
,
*
,
chain
=
True
):
"""Format the exception.
"""Format the exception.
If chain is not *True*, *__cause__* and *__context__* will not be formatted.
If chain is not *True*, *__cause__* and *__context__* will not be formatted.
...
...
Misc/NEWS
View file @
9ceea101
...
@@ -39,6 +39,8 @@ Library
...
@@ -39,6 +39,8 @@ Library
- Issue #21619: Popen objects no longer leave a zombie after exit in the with
- Issue #21619: Popen objects no longer leave a zombie after exit in the with
statement if the pipe was broken. Patch by Martin Panter.
statement if the pipe was broken. Patch by Martin Panter.
- Issue #22936: Make it possible to show local variables in tracebacks.
- Issue #15955: Add an option to limit the output size in bz2.decompress().
- Issue #15955: Add an option to limit the output size in bz2.decompress().
Patch by Nikolaus Rath.
Patch by Nikolaus Rath.
...
...
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