Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: third_party/logilab/logilab/common/debugger.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/logilab/logilab/common/dbf.py ('k') | third_party/logilab/logilab/common/decorators.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/logilab/logilab/common/debugger.py
diff --git a/third_party/logilab/logilab/common/debugger.py b/third_party/logilab/logilab/common/debugger.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f540a18982d2b1957b39259f3954ac51722bb35
--- /dev/null
+++ b/third_party/logilab/logilab/common/debugger.py
@@ -0,0 +1,214 @@
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of logilab-common.
+#
+# logilab-common is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>.
+"""Customized version of pdb's default debugger.
+
+- sets up a history file
+- uses ipython if available to colorize lines of code
+- overrides list command to search for current block instead
+ of using 5 lines of context
+
+
+
+
+"""
+
+from __future__ import print_function
+
+__docformat__ = "restructuredtext en"
+
+try:
+ import readline
+except ImportError:
+ readline = None
+import os
+import os.path as osp
+import sys
+from pdb import Pdb
+import inspect
+
+from logilab.common.compat import StringIO
+
+try:
+ from IPython import PyColorize
+except ImportError:
+ def colorize(source, *args):
+ """fallback colorize function"""
+ return source
+ def colorize_source(source, *args):
+ return source
+else:
+ def colorize(source, start_lineno, curlineno):
+ """colorize and annotate source with linenos
+ (as in pdb's list command)
+ """
+ parser = PyColorize.Parser()
+ output = StringIO()
+ parser.format(source, output)
+ annotated = []
+ for index, line in enumerate(output.getvalue().splitlines()):
+ lineno = index + start_lineno
+ if lineno == curlineno:
+ annotated.append('%4s\t->\t%s' % (lineno, line))
+ else:
+ annotated.append('%4s\t\t%s' % (lineno, line))
+ return '\n'.join(annotated)
+
+ def colorize_source(source):
+ """colorize given source"""
+ parser = PyColorize.Parser()
+ output = StringIO()
+ parser.format(source, output)
+ return output.getvalue()
+
+
+def getsource(obj):
+ """Return the text of the source code for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a single string. An
+ IOError is raised if the source code cannot be retrieved."""
+ lines, lnum = inspect.getsourcelines(obj)
+ return ''.join(lines), lnum
+
+
+################################################################
+class Debugger(Pdb):
+ """custom debugger
+
+ - sets up a history file
+ - uses ipython if available to colorize lines of code
+ - overrides list command to search for current block instead
+ of using 5 lines of context
+ """
+ def __init__(self, tcbk=None):
+ Pdb.__init__(self)
+ self.reset()
+ if tcbk:
+ while tcbk.tb_next is not None:
+ tcbk = tcbk.tb_next
+ self._tcbk = tcbk
+ self._histfile = os.path.expanduser("~/.pdbhist")
+
+ def setup_history_file(self):
+ """if readline is available, read pdb history file
+ """
+ if readline is not None:
+ try:
+ # XXX try..except shouldn't be necessary
+ # read_history_file() can accept None
+ readline.read_history_file(self._histfile)
+ except IOError:
+ pass
+
+ def start(self):
+ """starts the interactive mode"""
+ self.interaction(self._tcbk.tb_frame, self._tcbk)
+
+ def setup(self, frame, tcbk):
+ """setup hook: set up history file"""
+ self.setup_history_file()
+ Pdb.setup(self, frame, tcbk)
+
+ def set_quit(self):
+ """quit hook: save commands in the history file"""
+ if readline is not None:
+ readline.write_history_file(self._histfile)
+ Pdb.set_quit(self)
+
+ def complete_p(self, text, line, begin_idx, end_idx):
+ """provide variable names completion for the ``p`` command"""
+ namespace = dict(self.curframe.f_globals)
+ namespace.update(self.curframe.f_locals)
+ if '.' in text:
+ return self.attr_matches(text, namespace)
+ return [varname for varname in namespace if varname.startswith(text)]
+
+
+ def attr_matches(self, text, namespace):
+ """implementation coming from rlcompleter.Completer.attr_matches
+ Compute matches when text contains a dot.
+
+ Assuming the text is of the form NAME.NAME....[NAME], and is
+ evaluatable in self.namespace, it will be evaluated and its attributes
+ (as revealed by dir()) are used as possible completions. (For class
+ instances, class members are also considered.)
+
+ WARNING: this can still invoke arbitrary C code, if an object
+ with a __getattr__ hook is evaluated.
+
+ """
+ import re
+ m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+ if not m:
+ return
+ expr, attr = m.group(1, 3)
+ object = eval(expr, namespace)
+ words = dir(object)
+ if hasattr(object, '__class__'):
+ words.append('__class__')
+ words = words + self.get_class_members(object.__class__)
+ matches = []
+ n = len(attr)
+ for word in words:
+ if word[:n] == attr and word != "__builtins__":
+ matches.append("%s.%s" % (expr, word))
+ return matches
+
+ def get_class_members(self, klass):
+ """implementation coming from rlcompleter.get_class_members"""
+ ret = dir(klass)
+ if hasattr(klass, '__bases__'):
+ for base in klass.__bases__:
+ ret = ret + self.get_class_members(base)
+ return ret
+
+ ## specific / overridden commands
+ def do_list(self, arg):
+ """overrides default list command to display the surrounding block
+ instead of 5 lines of context
+ """
+ self.lastcmd = 'list'
+ if not arg:
+ try:
+ source, start_lineno = getsource(self.curframe)
+ print(colorize(''.join(source), start_lineno,
+ self.curframe.f_lineno))
+ except KeyboardInterrupt:
+ pass
+ except IOError:
+ Pdb.do_list(self, arg)
+ else:
+ Pdb.do_list(self, arg)
+ do_l = do_list
+
+ def do_open(self, arg):
+ """opens source file corresponding to the current stack level"""
+ filename = self.curframe.f_code.co_filename
+ lineno = self.curframe.f_lineno
+ cmd = 'emacsclient --no-wait +%s %s' % (lineno, filename)
+ os.system(cmd)
+
+ do_o = do_open
+
+def pm():
+ """use our custom debugger"""
+ dbg = Debugger(sys.last_traceback)
+ dbg.start()
+
+def set_trace():
+ Debugger().set_trace(sys._getframe().f_back)
« no previous file with comments | « third_party/logilab/logilab/common/dbf.py ('k') | third_party/logilab/logilab/common/decorators.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698