[Pytest-commit] commit/py: hpk42: make short-style tracebacks more like native and allow callers
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Sun Jun 29 13:42:47 CEST 2014
1 new commit in py:
https://bitbucket.org/hpk42/py/commits/6698f8b49b78/
Changeset: 6698f8b49b78
User: hpk42
Date: 2014-06-29 13:00:28
Summary: make short-style tracebacks more like native and allow callers
(in particular pytest) to set tb-style on a per-traceback entry basis
Affected #: 5 files
diff -r c769b9203321f3a00aaa37f0d77f98320f92ceea -r 6698f8b49b78c6489c932ce95ebda8dac2a3655d CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,11 @@
methods to allow adding information in the boxed process.
Thanks Marc Schlaich.
+- refactor traceback generation in light of pytest issue 364
+ (shortening tracebacks). you can now set a new traceback style
+ on a per-entry basis such that a caller can force entries to be
+ isplayed as short or long entries.
+
1.4.20
==================================================
diff -r c769b9203321f3a00aaa37f0d77f98320f92ceea -r 6698f8b49b78c6489c932ce95ebda8dac2a3655d py/__init__.py
--- a/py/__init__.py
+++ b/py/__init__.py
@@ -8,7 +8,7 @@
(c) Holger Krekel and others, 2004-2013
"""
-__version__ = '1.4.21.dev1'
+__version__ = '1.4.21.dev2'
from py import _apipkg
diff -r c769b9203321f3a00aaa37f0d77f98320f92ceea -r 6698f8b49b78c6489c932ce95ebda8dac2a3655d py/_code/code.py
--- a/py/_code/code.py
+++ b/py/_code/code.py
@@ -133,12 +133,17 @@
class TracebackEntry(object):
""" a single entry in a traceback """
+ _repr_style = None
exprinfo = None
def __init__(self, rawentry):
self._rawentry = rawentry
self.lineno = rawentry.tb_lineno - 1
+ def set_repr_style(self, mode):
+ assert mode in ("short", "long")
+ self._repr_style = mode
+
@property
def frame(self):
return py.code.Frame(self._rawentry.tb_frame)
@@ -470,17 +475,17 @@
line_index = 0
if line_index < 0:
line_index += len(source)
- for i in range(len(source)):
- if i == line_index:
- prefix = self.flow_marker + " "
- else:
- if short:
- continue
- prefix = " "
- line = prefix + source[i]
- lines.append(line)
+ space_prefix = " "
+ if short:
+ lines.append(space_prefix + source.lines[line_index].strip())
+ else:
+ for line in source.lines[:line_index]:
+ lines.append(space_prefix + line)
+ lines.append(self.flow_marker + " " + source.lines[line_index])
+ for line in source.lines[line_index+1:]:
+ lines.append(space_prefix + line)
if excinfo is not None:
- indent = self._getindent(source)
+ indent = 4 if short else self._getindent(source)
lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
return lines
@@ -520,7 +525,6 @@
return ReprLocals(lines)
def repr_traceback_entry(self, entry, excinfo=None):
- # excinfo is not None if this is the last tb entry
source = self._getentrysource(entry)
if source is None:
source = py.code.Source("???")
@@ -530,11 +534,12 @@
line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
lines = []
- if self.style in ("short", "long"):
- short = self.style == "short"
- reprargs = None
- if not short:
- reprargs = self.repr_args(entry)
+ style = entry._repr_style
+ if style is None:
+ style = self.style
+ if style in ("short", "long"):
+ short = style == "short"
+ reprargs = self.repr_args(entry) if not short else None
s = self.get_source(source, line_index, excinfo, short=short)
lines.extend(s)
if short:
@@ -546,10 +551,10 @@
localsrepr = None
if not short:
localsrepr = self.repr_locals(entry.locals)
- return ReprEntry(lines, reprargs, localsrepr, filelocrepr, short)
+ return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
if excinfo:
lines.extend(self.get_exconly(excinfo, indent=4))
- return ReprEntry(lines, None, None, None, False)
+ return ReprEntry(lines, None, None, None, style)
def _makepath(self, path):
if not self.abspath:
@@ -628,14 +633,18 @@
self.style = style
def toterminal(self, tw):
- sepok = False
- for entry in self.reprentries:
- if self.style == "long":
- if sepok:
+ # the entries might have different styles
+ last_style = None
+ for i, entry in enumerate(self.reprentries):
+ if entry.style == "long":
+ tw.line("")
+ entry.toterminal(tw)
+ if i < len(self.reprentries) - 1:
+ next_entry = self.reprentries[i+1]
+ if entry.style == "long" or \
+ entry.style == "short" and next_entry.style == "long":
tw.sep(self.entrysep)
- tw.line("")
- sepok = True
- entry.toterminal(tw)
+
if self.extraline:
tw.line(self.extraline)
@@ -646,6 +655,8 @@
self.extraline = None
class ReprEntryNative(TerminalRepr):
+ style = "native"
+
def __init__(self, tblines):
self.lines = tblines
@@ -655,15 +666,15 @@
class ReprEntry(TerminalRepr):
localssep = "_ "
- def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, short):
+ def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
self.lines = lines
self.reprfuncargs = reprfuncargs
self.reprlocals = reprlocals
self.reprfileloc = filelocrepr
- self.short = short
+ self.style = style
def toterminal(self, tw):
- if self.short:
+ if self.style == "short":
self.reprfileloc.toterminal(tw)
for line in self.lines:
red = line.startswith("E ")
@@ -680,7 +691,8 @@
tw.line("")
self.reprlocals.toterminal(tw)
if self.reprfileloc:
- tw.line("")
+ if self.lines:
+ tw.line("")
self.reprfileloc.toterminal(tw)
def __str__(self):
diff -r c769b9203321f3a00aaa37f0d77f98320f92ceea -r 6698f8b49b78c6489c932ce95ebda8dac2a3655d setup.py
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
name='py',
description='library with cross-python path, ini-parsing, io, code, log facilities',
long_description = open('README.txt').read(),
- version='1.4.21.dev1',
+ version='1.4.21.dev2',
url='http://pylib.readthedocs.org/',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
diff -r c769b9203321f3a00aaa37f0d77f98320f92ceea -r 6698f8b49b78c6489c932ce95ebda8dac2a3655d testing/code/test_excinfo.py
--- a/testing/code/test_excinfo.py
+++ b/testing/code/test_excinfo.py
@@ -547,7 +547,7 @@
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
lines = reprtb.lines
basename = py.path.local(mod.__file__).basename
- assert lines[0] == '> func1()'
+ assert lines[0] == ' func1()'
assert basename in str(reprtb.reprfileloc.path)
assert reprtb.reprfileloc.lineno == 5
@@ -555,8 +555,8 @@
p = FormattedExcinfo(style="short")
reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
lines = reprtb.lines
- assert lines[0] == '> raise ValueError("hello")'
- assert lines[1] == 'E ValueError: hello'
+ assert lines[0] == ' raise ValueError("hello")'
+ assert lines[1] == 'E ValueError: hello'
assert basename in str(reprtb.reprfileloc.path)
assert reprtb.reprfileloc.lineno == 3
@@ -611,10 +611,10 @@
last_lines = last_reprtb.lines
monkeypatch.undo()
basename = py.path.local(mod.__file__).basename
- assert lines[0] == '> func1()'
+ assert lines[0] == ' func1()'
- assert last_lines[0] == '> raise ValueError("hello")'
- assert last_lines[1] == 'E ValueError: hello'
+ assert last_lines[0] == ' raise ValueError("hello")'
+ assert last_lines[1] == 'E ValueError: hello'
def test_repr_traceback_and_excinfo(self, importasmod):
mod = importasmod("""
@@ -819,3 +819,40 @@
# python 2.4 fails to get the source line for the assert
if py.std.sys.version_info >= (2, 5):
assert s.count('assert 0') == 2
+
+ def test_traceback_repr_style(self, importasmod):
+ mod = importasmod("""
+ def f():
+ g()
+ def g():
+ h()
+ def h():
+ i()
+ def i():
+ raise ValueError()
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ excinfo.traceback = excinfo.traceback.filter()
+ excinfo.traceback[1].set_repr_style("short")
+ excinfo.traceback[2].set_repr_style("short")
+ r = excinfo.getrepr(style="long")
+ tw = TWMock()
+ r.toterminal(tw)
+ for line in tw.lines: print (line)
+ assert tw.lines[0] == ""
+ assert tw.lines[1] == " def f():"
+ assert tw.lines[2] == "> g()"
+ assert tw.lines[3] == ""
+ assert tw.lines[4].endswith("mod.py:3: ")
+ assert tw.lines[5] == ("_ ", None)
+ assert tw.lines[6].endswith("in g")
+ assert tw.lines[7] == " h()"
+ assert tw.lines[8].endswith("in h")
+ assert tw.lines[9] == " i()"
+ assert tw.lines[10] == ("_ ", None)
+ assert tw.lines[11] == ""
+ assert tw.lines[12] == " def i():"
+ assert tw.lines[13] == "> raise ValueError()"
+ assert tw.lines[14] == "E ValueError"
+ assert tw.lines[15] == ""
+ assert tw.lines[16].endswith("mod.py:9: ValueError")
Repository URL: https://bitbucket.org/hpk42/py/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the pytest-commit
mailing list