[py-svn] r57030 - in py/branch/event/py/code: . testing
hpk at codespeak.net
hpk at codespeak.net
Wed Aug 6 16:54:00 CEST 2008
Author: hpk
Date: Wed Aug 6 16:53:59 2008
New Revision: 57030
Modified:
py/branch/event/py/code/excinfo.py
py/branch/event/py/code/testing/test_excinfo.py
Log:
provide optional nicely formatted info on function args in tracebacks
Modified: py/branch/event/py/code/excinfo.py
==============================================================================
--- py/branch/event/py/code/excinfo.py (original)
+++ py/branch/event/py/code/excinfo.py Wed Aug 6 16:53:59 2008
@@ -47,13 +47,14 @@
""" return True if the exception is an instance of exc """
return isinstance(self.value, exc)
- def getrepr(self, showlocals=False, style="long", tbfilter=True):
+ def getrepr(self, showlocals=False, style="long", tbfilter=True, funcargs=False):
""" return str()able representation of this exception info.
showlocals: show locals per traceback entry
style: long|short|no traceback style
tbfilter: hide entries (where __tracebackhide__ is true)
"""
- fmt = FormattedExcinfo(showlocals=showlocals, style=style, tbfilter=tbfilter)
+ fmt = FormattedExcinfo(showlocals=showlocals, style=style,
+ tbfilter=tbfilter, funcargs=funcargs)
return fmt.repr_excinfo(self)
def __str__(self):
@@ -67,10 +68,11 @@
flow_marker = ">"
fail_marker = "E"
- def __init__(self, showlocals=False, style="long", tbfilter=True):
+ def __init__(self, showlocals=False, style="long", tbfilter=True, funcargs=False):
self.showlocals = showlocals
self.style = style
self.tbfilter = tbfilter
+ self.funcargs = funcargs
def _getindent(self, source):
# figure out indent for given source
@@ -92,6 +94,13 @@
def _saferepr(self, obj):
return safe_repr._repr(obj)
+ def repr_args(self, entry):
+ if self.funcargs:
+ args = []
+ for argname, argvalue in entry.frame.getargs():
+ args.append((argname, self._saferepr(argvalue)))
+ return ReprFuncArgs(args)
+
def get_source(self, source, line_index=-1, excinfo=None):
""" return formatted and marked up source lines. """
lines = []
@@ -148,14 +157,15 @@
source = self._getentrysource(entry)
line_index = entry.lineno - entry.getfirstlinesource()
+ lines = []
if self.style == "long":
- lines = self.get_source(source, line_index, excinfo)
+ reprargs = self.repr_args(entry)
+ lines.extend(self.get_source(source, line_index, excinfo))
message = excinfo and excinfo.exconly() or ""
filelocrepr = ReprFileLocation(entry.path, entry.lineno+1, message)
localsrepr = self.repr_locals(entry.locals)
- return ReprEntry(lines, localsrepr, filelocrepr)
+ return ReprEntry(lines, reprargs, localsrepr, filelocrepr)
else:
- lines = []
if self.style == "short":
line = source[line_index].lstrip()
lines.append(' File "%s", line %d, in %s' % (
@@ -163,7 +173,7 @@
lines.append(" " + line)
if excinfo:
lines.extend(self.get_exconly(excinfo, indent=4))
- return ReprEntry(lines, None, None)
+ return ReprEntry(lines, None, None, None)
def repr_traceback(self, excinfo):
traceback = excinfo.traceback
@@ -233,12 +243,15 @@
class ReprEntry(Repr):
localssep = "_ "
- def __init__(self, lines, reprlocals, filelocrepr):
+ def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr):
self.lines = lines
+ self.reprfuncargs = reprfuncargs
self.reprlocals = reprlocals
self.reprfileloc = filelocrepr
def toterminal(self, tw):
+ if self.reprfuncargs:
+ self.reprfuncargs.toterminal(tw)
for line in self.lines:
tw.line(line)
if self.reprlocals:
@@ -275,3 +288,25 @@
def toterminal(self, tw):
for line in self.lines:
tw.line(line)
+
+class ReprFuncArgs(Repr):
+ def __init__(self, args):
+ self.args = args
+
+ def toterminal(self, tw):
+ if self.args:
+ linesofar = ""
+ for name, value in self.args:
+ ns = "%s = %s" %(name, value)
+ if len(ns) + len(linesofar) + 2 > tw.fullwidth:
+ if linesofar:
+ tw.line(linesofar)
+ linesofar = ns
+ else:
+ if linesofar:
+ linesofar += ", " + ns
+ else:
+ linesofar = ns
+ if linesofar:
+ tw.line(linesofar)
+ tw.line("")
Modified: py/branch/event/py/code/testing/test_excinfo.py
==============================================================================
--- py/branch/event/py/code/testing/test_excinfo.py (original)
+++ py/branch/event/py/code/testing/test_excinfo.py Wed Aug 6 16:53:59 2008
@@ -8,6 +8,7 @@
self.lines.append((sep, line))
def line(self, line):
self.lines.append(line)
+ fullwidth = 80
def test_excinfo_simple():
try:
@@ -303,6 +304,30 @@
assert loc.lineno == 3
#assert loc.message == "ValueError: hello"
+ def test_repr_tracebackentry_lines(self):
+ mod = self.importasmod("""
+ def func1(m, x, y, z):
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = py.test.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120)
+ excinfo.traceback = excinfo.traceback.filter()
+ entry = excinfo.traceback[-1]
+ p = FormattedExcinfo(funcargs=True)
+ reprfuncargs = p.repr_args(entry)
+ assert reprfuncargs.args[0] == ('m', repr("m"*90))
+ assert reprfuncargs.args[1] == ('x', '5')
+ assert reprfuncargs.args[2] == ('y', '13')
+ assert reprfuncargs.args[3] == ('z', repr("z" * 120))
+
+ p = FormattedExcinfo(funcargs=True)
+ repr_entry = p.repr_traceback_entry(entry)
+ assert repr_entry.reprfuncargs.args == reprfuncargs.args
+ tw = TWMock()
+ repr_entry.toterminal(tw)
+ assert tw.lines[0] == "m = " + repr('m' * 90)
+ assert tw.lines[1] == "x = 5, y = 13"
+ assert tw.lines[2] == "z = " + repr('z' * 120)
+
def test_repr_tracebackentry_short(self):
mod = self.importasmod("""
def func1():
@@ -428,7 +453,7 @@
lines = reprentry.lines
assert lines[-1] == "E assert 1 == 2"
- def test_reprexcinfo__formatrepr(self):
+ def test_reprexcinfo_getrepr(self):
mod = self.importasmod("""
def f(x):
raise ValueError(x)
@@ -483,13 +508,19 @@
repr = excinfo.getrepr(**kw)
repr.toterminal(tw)
assert tw.stringio.getvalue()
-
+
+ for combo in self.allcombos():
+ yield format_and_str, combo
+
+ def allcombos(self):
for style in ("long", "short", "no"):
for showlocals in (True, False):
for tbfilter in (True, False):
- kw = {'style': style,
- 'showlocals': showlocals,
- 'tbfilter': tbfilter
- }
- yield format_and_str, kw
+ for funcargs in (True, False):
+ kw = {'style': style,
+ 'showlocals': showlocals,
+ 'funcargs': funcargs,
+ 'tbfilter': tbfilter
+ }
+ yield kw
More information about the pytest-commit
mailing list