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
24559e48
Commit
24559e48
authored
May 03, 2015
by
Serhiy Storchaka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #22619: Added negative limit support in the traceback module.
Based on patch by Dmitry Kazakov.
parent
9a578d9e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
170 additions
and
27 deletions
+170
-27
Doc/library/traceback.rst
Doc/library/traceback.rst
+33
-19
Lib/test/test_traceback.py
Lib/test/test_traceback.py
+123
-4
Lib/traceback.py
Lib/traceback.py
+10
-4
Misc/ACKS
Misc/ACKS
+1
-0
Misc/NEWS
Misc/NEWS
+3
-0
No files found.
Doc/library/traceback.rst
View file @
24559e48
...
...
@@ -22,15 +22,20 @@ The module defines the following functions:
.. function:: print_tb(traceback, limit=None, file=None)
Print up to *limit* stack trace entries from *traceback*. If *limit* is omitted
or ``None``, all entries are printed. If *file* is omitted or ``None``, the
output goes to ``sys.stderr``; otherwise it should be an open file or file-like
object to receive the output.
Print up to *limit* stack trace entries from *traceback* (starting from
the caller's frame) if *limit* is positive. Otherwise, print the last
``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries
are printed. If *file* is omitted or ``None``, the output goes to
``sys.stderr``; otherwise it should be an open file or file-like object
to receive the output.
.. versionchanged:: 3.5
Added negative *limit* support.
.. function:: print_exception(type, value, traceback, limit=None, file=None, chain=True)
Print exception information and
up to *limit*
stack trace entries from
Print exception information and stack trace entries from
*traceback* to *file*. This differs from :func:`print_tb` in the following
ways:
...
...
@@ -41,6 +46,7 @@ The module defines the following functions:
prints the line where the syntax error occurred with a caret indicating the
approximate position of the error.
The optional *limit* argument has the same meaning as for :func:`print_tb`.
If *chain* is true (the default), then chained exceptions (the
:attr:`__cause__` or :attr:`__context__` attributes of the exception) will be
printed as well, like the interpreter itself does when printing an unhandled
...
...
@@ -49,33 +55,41 @@ The module defines the following functions:
.. function:: print_exc(limit=None, file=None, chain=True)
This is a shorthand for ``print_exception(*sys.exc_info())``.
This is a shorthand for ``print_exception(*sys.exc_info(), limit, file,
chain)``.
.. function:: print_last(limit=None, file=None, chain=True)
This is a shorthand for ``print_exception(sys.last_type, sys.last_value,
sys.last_traceback, limit, file)``. In general it will work only after
an exception has reached an interactive prompt (see :data:`sys.last_type`).
sys.last_traceback, limit, file, chain)``. In general it will work only
after an exception has reached an interactive prompt (see
:data:`sys.last_type`).
.. function:: print_stack(f=None, limit=None, file=None)
This function prints a stack trace from its invocation point. The optional *f*
argument can be used to specify an alternate stack frame to start. The optional
*limit* and *file* arguments have the same meaning as for
:func:`print_exception`.
Print up to *limit* stack trace entries (starting from the invocation
point) if *limit* is positive. Otherwise, print the last ``abs(limit)``
entries. If *limit* is omitted or ``None``, all entries are printed.
The optional *f* argument can be used to specify an alternate stack frame
to start. The optional *file* argument has the same meaning as for
:func:`print_tb`.
.. versionchanged:: 3.5
Added negative *limit* support.
.. function:: extract_tb(traceback, limit=None)
Return a list of up to *limit* "pre-processed" stack trace entries extracted
from the traceback object *traceback*. It is useful for alternate formatting of
stack traces. If *limit* is omitted or ``None``, all entries are extracted. A
"pre-processed" stack trace entry is a 4-tuple (*filename*, *line number*,
*function name*, *text*) representing the information that is usually printed
for a stack trace. The *text* is a string with leading and trailing whitespace
stripped; if the source is not available it is ``None``.
Return a list of "pre-processed" stack trace entries extracted from the
traceback object *traceback*. It is useful for alternate formatting of
stack traces. The optional *limit* argument has the same meaning as for
:func:`print_tb`. A "pre-processed" stack trace entry is a 4-tuple
(*filename*, *line number*, *function name*, *text*) representing the
information that is usually printed for a stack trace. The *text* is a
string with leading and trailing whitespace stripped; if the source is
not available it is ``None``.
.. function:: extract_stack(f=None, limit=None)
...
...
Lib/test/test_traceback.py
View file @
24559e48
...
...
@@ -6,6 +6,7 @@ import linecache
import
sys
import
unittest
import
re
from
test
import
support
from
test.support
import
TESTFN
,
Error
,
captured_output
,
unlink
,
cpython_only
from
test.script_helper
import
assert_python_ok
import
textwrap
...
...
@@ -453,6 +454,126 @@ class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
return
s
.
getvalue
()
class
LimitTests
(
unittest
.
TestCase
):
''' Tests for limit argument.
It's enough to test extact_tb, extract_stack and format_exception '''
def
last_raises1
(
self
):
raise
Exception
(
'Last raised'
)
def
last_raises2
(
self
):
self
.
last_raises1
()
def
last_raises3
(
self
):
self
.
last_raises2
()
def
last_raises4
(
self
):
self
.
last_raises3
()
def
last_raises5
(
self
):
self
.
last_raises4
()
def
last_returns_frame1
(
self
):
return
sys
.
_getframe
()
def
last_returns_frame2
(
self
):
return
self
.
last_returns_frame1
()
def
last_returns_frame3
(
self
):
return
self
.
last_returns_frame2
()
def
last_returns_frame4
(
self
):
return
self
.
last_returns_frame3
()
def
last_returns_frame5
(
self
):
return
self
.
last_returns_frame4
()
def
test_extract_stack
(
self
):
frame
=
self
.
last_returns_frame5
()
def
extract
(
**
kwargs
):
return
traceback
.
extract_stack
(
frame
,
**
kwargs
)
def
assertEqualExcept
(
actual
,
expected
,
ignore
):
self
.
assertEqual
(
actual
[:
ignore
],
expected
[:
ignore
])
self
.
assertEqual
(
actual
[
ignore
+
1
:],
expected
[
ignore
+
1
:])
self
.
assertEqual
(
len
(
actual
),
len
(
expected
))
with
support
.
swap_attr
(
sys
,
'tracebacklimit'
,
1000
):
nolim
=
extract
()
self
.
assertGreater
(
len
(
nolim
),
5
)
self
.
assertEqual
(
extract
(
limit
=
2
),
nolim
[
-
2
:])
assertEqualExcept
(
extract
(
limit
=
100
),
nolim
[
-
100
:],
-
5
-
1
)
self
.
assertEqual
(
extract
(
limit
=-
2
),
nolim
[:
2
])
assertEqualExcept
(
extract
(
limit
=-
100
),
nolim
[:
100
],
len
(
nolim
)
-
5
-
1
)
self
.
assertEqual
(
extract
(
limit
=
0
),
[])
del
sys
.
tracebacklimit
assertEqualExcept
(
extract
(),
nolim
,
-
5
-
1
)
sys
.
tracebacklimit
=
2
self
.
assertEqual
(
extract
(),
nolim
[
-
2
:])
self
.
assertEqual
(
extract
(
limit
=
3
),
nolim
[
-
3
:])
self
.
assertEqual
(
extract
(
limit
=-
3
),
nolim
[:
3
])
sys
.
tracebacklimit
=
0
self
.
assertEqual
(
extract
(),
[])
sys
.
tracebacklimit
=
-
1
self
.
assertEqual
(
extract
(),
[])
def
test_extract_tb
(
self
):
try
:
self
.
last_raises5
()
except
Exception
:
exc_type
,
exc_value
,
tb
=
sys
.
exc_info
()
def
extract
(
**
kwargs
):
return
traceback
.
extract_tb
(
tb
,
**
kwargs
)
with
support
.
swap_attr
(
sys
,
'tracebacklimit'
,
1000
):
nolim
=
extract
()
self
.
assertEqual
(
len
(
nolim
),
5
+
1
)
self
.
assertEqual
(
extract
(
limit
=
2
),
nolim
[:
2
])
self
.
assertEqual
(
extract
(
limit
=
10
),
nolim
)
self
.
assertEqual
(
extract
(
limit
=-
2
),
nolim
[
-
2
:])
self
.
assertEqual
(
extract
(
limit
=-
10
),
nolim
)
self
.
assertEqual
(
extract
(
limit
=
0
),
[])
del
sys
.
tracebacklimit
self
.
assertEqual
(
extract
(),
nolim
)
sys
.
tracebacklimit
=
2
self
.
assertEqual
(
extract
(),
nolim
[:
2
])
self
.
assertEqual
(
extract
(
limit
=
3
),
nolim
[:
3
])
self
.
assertEqual
(
extract
(
limit
=-
3
),
nolim
[
-
3
:])
sys
.
tracebacklimit
=
0
self
.
assertEqual
(
extract
(),
[])
sys
.
tracebacklimit
=
-
1
self
.
assertEqual
(
extract
(),
[])
def
test_format_exception
(
self
):
try
:
self
.
last_raises5
()
except
Exception
:
exc_type
,
exc_value
,
tb
=
sys
.
exc_info
()
# [1:-1] to exclude "Traceback (...)" header and
# exception type and value
def
extract
(
**
kwargs
):
return
traceback
.
format_exception
(
exc_type
,
exc_value
,
tb
,
**
kwargs
)[
1
:
-
1
]
with
support
.
swap_attr
(
sys
,
'tracebacklimit'
,
1000
):
nolim
=
extract
()
self
.
assertEqual
(
len
(
nolim
),
5
+
1
)
self
.
assertEqual
(
extract
(
limit
=
2
),
nolim
[:
2
])
self
.
assertEqual
(
extract
(
limit
=
10
),
nolim
)
self
.
assertEqual
(
extract
(
limit
=-
2
),
nolim
[
-
2
:])
self
.
assertEqual
(
extract
(
limit
=-
10
),
nolim
)
self
.
assertEqual
(
extract
(
limit
=
0
),
[])
del
sys
.
tracebacklimit
self
.
assertEqual
(
extract
(),
nolim
)
sys
.
tracebacklimit
=
2
self
.
assertEqual
(
extract
(),
nolim
[:
2
])
self
.
assertEqual
(
extract
(
limit
=
3
),
nolim
[:
3
])
self
.
assertEqual
(
extract
(
limit
=-
3
),
nolim
[
-
3
:])
sys
.
tracebacklimit
=
0
self
.
assertEqual
(
extract
(),
[])
sys
.
tracebacklimit
=
-
1
self
.
assertEqual
(
extract
(),
[])
class
MiscTracebackCases
(
unittest
.
TestCase
):
#
# Check non-printing functions in traceback module
...
...
@@ -592,16 +713,14 @@ class TestStack(unittest.TestCase):
traceback
.
walk_stack
(
None
),
capture_locals
=
True
,
limit
=
1
)
s
=
some_inner
(
3
,
4
)
self
.
assertEqual
(
[
' File "'
+
__file__
+
'", line 592, '
'in some_inner
\
n
'
[
' File "%s", line %d, 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
'
' v = 4
\
n
'
%
(
__file__
,
some_inner
.
__code__
.
co_firstlineno
+
4
)
],
s
.
format
())
class
TestTracebackException
(
unittest
.
TestCase
):
def
test_smoke
(
self
):
...
...
Lib/traceback.py
View file @
24559e48
"""Extract, format and print information about Python stack traces."""
import
collections
import
itertools
import
linecache
import
sys
import
operator
__all__
=
[
'extract_stack'
,
'extract_tb'
,
'format_exception'
,
'format_exception_only'
,
'format_list'
,
'format_stack'
,
...
...
@@ -315,12 +316,17 @@ class StackSummary(list):
"""
if
limit
is
None
:
limit
=
getattr
(
sys
,
'tracebacklimit'
,
None
)
if
limit
is
not
None
and
limit
<
0
:
limit
=
0
if
limit
is
not
None
:
if
limit
>=
0
:
frame_gen
=
itertools
.
islice
(
frame_gen
,
limit
)
else
:
frame_gen
=
collections
.
deque
(
frame_gen
,
maxlen
=-
limit
)
result
=
klass
()
fnames
=
set
()
for
pos
,
(
f
,
lineno
)
in
enumerate
(
frame_gen
):
if
limit
is
not
None
and
pos
>=
limit
:
break
for
f
,
lineno
in
frame_gen
:
co
=
f
.
f_code
filename
=
co
.
co_filename
name
=
co
.
co_name
...
...
Misc/ACKS
View file @
24559e48
...
...
@@ -712,6 +712,7 @@ Anton Kasyanov
Lou Kates
Makoto Kato
Hiroaki Kawai
Dmitry Kazakov
Brian Kearns
Sebastien Keim
Ryan Kelly
...
...
Misc/NEWS
View file @
24559e48
...
...
@@ -25,6 +25,9 @@ Core and Builtins
Library
-------
- Issue #22619: Added negative limit support in the traceback module.
Based on patch by Dmitry Kazakov.
- Issue #24094: Fix possible crash in json.encode with poorly behaved dict
subclasses.
...
...
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