From d61ed8c0147bc5ab9d11a342a8767957b680ab6e Mon Sep 17 00:00:00 2001 From: cfbolz Date: Thu, 20 Sep 2007 17:26:09 +0200 Subject: [PATCH] [svn r46772] add a custom pdb.Pdb subclass that has the ability to properly list the lines generated by py.code.Source. Very useful in PyPy debugging. --HG-- branch : trunk --- py/test/custompdb.py | 72 +++++++++++++++++++++++ py/test/rsession/executor.py | 4 +- py/test/rsession/testing/test_lsession.py | 8 +-- py/test/terminal/terminal.py | 4 +- 4 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 py/test/custompdb.py diff --git a/py/test/custompdb.py b/py/test/custompdb.py new file mode 100644 index 000000000..f449e471b --- /dev/null +++ b/py/test/custompdb.py @@ -0,0 +1,72 @@ +import pdb, sys, linecache + +class Pdb(pdb.Pdb): + def do_list(self, arg): + self.lastcmd = 'list' + last = None + if arg: + try: + x = eval(arg, {}, {}) + if type(x) == type(()): + first, last = x + first = int(first) + last = int(last) + if last < first: + # Assume it's a count + last = first + last + else: + first = max(1, int(x) - 5) + except: + print '*** Error in argument:', repr(arg) + return + elif self.lineno is None: + first = max(1, self.curframe.f_lineno - 5) + else: + first = self.lineno + 1 + if last is None: + last = first + 10 + filename = self.curframe.f_code.co_filename + breaklist = self.get_file_breaks(filename) + try: + for lineno in range(first, last+1): + # start difference from normal do_line + line = self._getline(filename, lineno) + # end difference from normal do_line + if not line: + print '[EOF]' + break + else: + s = repr(lineno).rjust(3) + if len(s) < 4: s = s + ' ' + if lineno in breaklist: s = s + 'B' + else: s = s + ' ' + if lineno == self.curframe.f_lineno: + s = s + '->' + print s + '\t' + line, + self.lineno = lineno + except KeyboardInterrupt: + pass + do_l = do_list + + def _getline(self, filename, lineno): + if hasattr(filename, "__source__"): + try: + return filename.__source__.lines[lineno - 1] + "\n" + except IndexError: + return None + return linecache.getline(filename, lineno) + +def post_mortem(t): + # again, a copy of the version in pdb.py + t = outcome.excinfo._excinfo[2] + p = Pdb() + p.reset() + while t.tb_next is not None: + t = t.tb_next + p.interaction(t.tb_frame, t) + +def set_trace(): + # again, a copy of the version in pdb.py + Pdb().set_trace(sys._getframe().f_back) + + diff --git a/py/test/rsession/executor.py b/py/test/rsession/executor.py index d0d826c95..7b035e0e6 100644 --- a/py/test/rsession/executor.py +++ b/py/test/rsession/executor.py @@ -7,6 +7,7 @@ from py.__.test.outcome import SerializableOutcome, ReprOutcome from py.__.test.rsession.box import Box from py.__.test import repevent from py.__.test.outcome import Skipped, Failed +import py.__.test.custompdb class RunExecutor(object): """ Same as in executor, but just running run @@ -55,8 +56,7 @@ class RunExecutor(object): self.reporter(repevent.ImmediateFailure(self.item, ReprOutcome(outcome.make_repr (self.config.option.tbstyle)))) - import pdb - pdb.post_mortem(excinfo._excinfo[2]) + py.__.test.custompdb.post_mortem(excinfo._excinfo[2]) # XXX hmm, we probably will not like to continue from that # point raise SystemExit() diff --git a/py/test/rsession/testing/test_lsession.py b/py/test/rsession/testing/test_lsession.py index c0dadb0fd..2231af740 100644 --- a/py/test/rsession/testing/test_lsession.py +++ b/py/test/rsession/testing/test_lsession.py @@ -6,6 +6,7 @@ import py from py.__.test.rsession.rsession import LSession from py.__.test import repevent from py.__.test.rsession.local import box_runner, plain_runner, apigen_runner +import py.__.test.custompdb def setup_module(mod): mod.tmp = py.test.ensuretemp("lsession_module") @@ -78,14 +79,13 @@ class TestLSession(object): def test_1(): assert 0 """)) - import pdb l = [] def some_fun(*args): l.append(args) try: - post_mortem = pdb.post_mortem - pdb.post_mortem = some_fun + post_mortem = py.__.test.custompdb.post_mortem + py.__.test.custompdb.post_mortem = some_fun args = [str(tmpdir.join(subdir)), '--pdb'] config = py.test.config._reparse(args) lsession = LSession(config) @@ -101,7 +101,7 @@ class TestLSession(object): assert len(failure_events) == 1 assert len(l) == 1 finally: - pdb.post_mortem = post_mortem + py.__.test.custompdb.post_mortem = post_mortem def test_minus_x(self): if not hasattr(py.std.os, 'fork'): diff --git a/py/test/terminal/terminal.py b/py/test/terminal/terminal.py index ffa0c17d4..6edb19c94 100644 --- a/py/test/terminal/terminal.py +++ b/py/test/terminal/terminal.py @@ -4,6 +4,7 @@ from time import time as now from py.__.test.terminal.out import getout from py.__.test.representation import Presenter from py.__.test.outcome import Skipped, Passed, Failed +import py.__.test.custompdb def getrelpath(source, dest): base = source.common(dest) @@ -97,9 +98,8 @@ class TerminalSession(Session): if isinstance(outcome, Failed): print "dispatching to ppdb", colitem self.repr_failure(colitem, outcome) - import pdb self.out.write('\n%s\n' % (outcome.excinfo.exconly(),)) - pdb.post_mortem(outcome.excinfo._excinfo[2]) + py.__.test.custompdb.post_mortem(excinfo._excinfo[2]) if isinstance(colitem, py.test.collect.Module): resultstring = self.repr_progress_module_result(colitem, outcome) if resultstring: