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:
...
@@ -22,15 +22,20 @@ The module defines the following functions:
.. function:: print_tb(traceback, limit=None, file=None)
.. function:: print_tb(traceback, limit=None, file=None)
Print up to *limit* stack trace entries from *traceback*. If *limit* is omitted
Print up to *limit* stack trace entries from *traceback* (starting from
or ``None``, all entries are printed. If *file* is omitted or ``None``, the
the caller's frame) if *limit* is positive. Otherwise, print the last
output goes to ``sys.stderr``; otherwise it should be an open file or file-like
``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries
object to receive the output.
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)
.. 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
*traceback* to *file*. This differs from :func:`print_tb` in the following
ways:
ways:
...
@@ -41,6 +46,7 @@ The module defines the following functions:
...
@@ -41,6 +46,7 @@ The module defines the following functions:
prints the line where the syntax error occurred with a caret indicating the
prints the line where the syntax error occurred with a caret indicating the
approximate position of the error.
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
If *chain* is true (the default), then chained exceptions (the
:attr:`__cause__` or :attr:`__context__` attributes of the exception) will be
:attr:`__cause__` or :attr:`__context__` attributes of the exception) will be
printed as well, like the interpreter itself does when printing an unhandled
printed as well, like the interpreter itself does when printing an unhandled
...
@@ -49,33 +55,41 @@ The module defines the following functions:
...
@@ -49,33 +55,41 @@ The module defines the following functions:
.. function:: print_exc(limit=None, file=None, chain=True)
.. 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)
.. function:: print_last(limit=None, file=None, chain=True)
This is a shorthand for ``print_exception(sys.last_type, sys.last_value,
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
sys.last_traceback, limit, file, chain)``. In general it will work only
an exception has reached an interactive prompt (see :data:`sys.last_type`).
after an exception has reached an interactive prompt (see
:data:`sys.last_type`).
.. function:: print_stack(f=None, limit=None, file=None)
.. function:: print_stack(f=None, limit=None, file=None)
This function prints a stack trace from its invocation point. The optional *f*
Print up to *limit* stack trace entries (starting from the invocation
argument can be used to specify an alternate stack frame to start. The optional
point) if *limit* is positive. Otherwise, print the last ``abs(limit)``
*limit* and *file* arguments have the same meaning as for
entries. If *limit* is omitted or ``None``, all entries are printed.
:func:`print_exception`.
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)
.. function:: extract_tb(traceback, limit=None)
Return a list of up to *limit* "pre-processed" stack trace entries extracted
Return a list of "pre-processed" stack trace entries extracted from the
from the traceback object *traceback*. It is useful for alternate formatting of
traceback object *traceback*. It is useful for alternate formatting of
stack traces. If *limit* is omitted or ``None``, all entries are extracted. A
stack traces. The optional *limit* argument has the same meaning as for
"pre-processed" stack trace entry is a 4-tuple (*filename*, *line number*,
:func:`print_tb`. A "pre-processed" stack trace entry is a 4-tuple
*function name*, *text*) representing the information that is usually printed
(*filename*, *line number*, *function name*, *text*) representing the
for a stack trace. The *text* is a string with leading and trailing whitespace
information that is usually printed for a stack trace. The *text* is a
stripped; if the source is not available it is ``None``.
string with leading and trailing whitespace stripped; if the source is
not available it is ``None``.
.. function:: extract_stack(f=None, limit=None)
.. function:: extract_stack(f=None, limit=None)
...
...
Lib/test/test_traceback.py
View file @
24559e48
...
@@ -6,6 +6,7 @@ import linecache
...
@@ -6,6 +6,7 @@ import linecache
import
sys
import
sys
import
unittest
import
unittest
import
re
import
re
from
test
import
support
from
test.support
import
TESTFN
,
Error
,
captured_output
,
unlink
,
cpython_only
from
test.support
import
TESTFN
,
Error
,
captured_output
,
unlink
,
cpython_only
from
test.script_helper
import
assert_python_ok
from
test.script_helper
import
assert_python_ok
import
textwrap
import
textwrap
...
@@ -453,6 +454,126 @@ class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
...
@@ -453,6 +454,126 @@ class CExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
return
s
.
getvalue
()
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
):
class
MiscTracebackCases
(
unittest
.
TestCase
):
#
#
# Check non-printing functions in traceback module
# Check non-printing functions in traceback module
...
@@ -592,16 +713,14 @@ class TestStack(unittest.TestCase):
...
@@ -592,16 +713,14 @@ class TestStack(unittest.TestCase):
traceback
.
walk_stack
(
None
),
capture_locals
=
True
,
limit
=
1
)
traceback
.
walk_stack
(
None
),
capture_locals
=
True
,
limit
=
1
)
s
=
some_inner
(
3
,
4
)
s
=
some_inner
(
3
,
4
)
self
.
assertEqual
(
self
.
assertEqual
(
[
' File "'
+
__file__
+
'", line 592, '
[
' File "%s", line %d, in some_inner
\
n
'
'in some_inner
\
n
'
' traceback.walk_stack(None), capture_locals=True, limit=1)
\
n
'
' traceback.walk_stack(None), capture_locals=True, limit=1)
\
n
'
' a = 1
\
n
'
' a = 1
\
n
'
' b = 2
\
n
'
' b = 2
\
n
'
' k = 3
\
n
'
' k = 3
\
n
'
' v = 4
\
n
'
' v = 4
\
n
'
%
(
__file__
,
some_inner
.
__code__
.
co_firstlineno
+
4
)
],
s
.
format
())
],
s
.
format
())
class
TestTracebackException
(
unittest
.
TestCase
):
class
TestTracebackException
(
unittest
.
TestCase
):
def
test_smoke
(
self
):
def
test_smoke
(
self
):
...
...
Lib/traceback.py
View file @
24559e48
"""Extract, format and print information about Python stack traces."""
"""Extract, format and print information about Python stack traces."""
import
collections
import
itertools
import
linecache
import
linecache
import
sys
import
sys
import
operator
__all__
=
[
'extract_stack'
,
'extract_tb'
,
'format_exception'
,
__all__
=
[
'extract_stack'
,
'extract_tb'
,
'format_exception'
,
'format_exception_only'
,
'format_list'
,
'format_stack'
,
'format_exception_only'
,
'format_list'
,
'format_stack'
,
...
@@ -315,12 +316,17 @@ class StackSummary(list):
...
@@ -315,12 +316,17 @@ class StackSummary(list):
"""
"""
if
limit
is
None
:
if
limit
is
None
:
limit
=
getattr
(
sys
,
'tracebacklimit'
,
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
()
result
=
klass
()
fnames
=
set
()
fnames
=
set
()
for
pos
,
(
f
,
lineno
)
in
enumerate
(
frame_gen
):
for
f
,
lineno
in
frame_gen
:
if
limit
is
not
None
and
pos
>=
limit
:
break
co
=
f
.
f_code
co
=
f
.
f_code
filename
=
co
.
co_filename
filename
=
co
.
co_filename
name
=
co
.
co_name
name
=
co
.
co_name
...
...
Misc/ACKS
View file @
24559e48
...
@@ -712,6 +712,7 @@ Anton Kasyanov
...
@@ -712,6 +712,7 @@ Anton Kasyanov
Lou Kates
Lou Kates
Makoto Kato
Makoto Kato
Hiroaki Kawai
Hiroaki Kawai
Dmitry Kazakov
Brian Kearns
Brian Kearns
Sebastien Keim
Sebastien Keim
Ryan Kelly
Ryan Kelly
...
...
Misc/NEWS
View file @
24559e48
...
@@ -25,6 +25,9 @@ Core and Builtins
...
@@ -25,6 +25,9 @@ Core and Builtins
Library
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
- Issue #24094: Fix possible crash in json.encode with poorly behaved dict
subclasses.
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