Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
804
venv/Lib/site-packages/IPython/core/debugger.py
Normal file
804
venv/Lib/site-packages/IPython/core/debugger.py
Normal file
|
@ -0,0 +1,804 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Pdb debugger class.
|
||||
|
||||
Modified from the standard pdb.Pdb class to avoid including readline, so that
|
||||
the command line completion of other programs which include this isn't
|
||||
damaged.
|
||||
|
||||
In the future, this class will be expanded with improvements over the standard
|
||||
pdb.
|
||||
|
||||
The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
|
||||
changes. Licensing should therefore be under the standard Python terms. For
|
||||
details on the PSF (Python Software Foundation) standard license, see:
|
||||
|
||||
https://docs.python.org/2/license.html
|
||||
"""
|
||||
|
||||
#*****************************************************************************
|
||||
#
|
||||
# This file is licensed under the PSF license.
|
||||
#
|
||||
# Copyright (C) 2001 Python Software Foundation, www.python.org
|
||||
# Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
|
||||
#
|
||||
#
|
||||
#*****************************************************************************
|
||||
|
||||
import bdb
|
||||
import functools
|
||||
import inspect
|
||||
import linecache
|
||||
import sys
|
||||
import warnings
|
||||
import re
|
||||
|
||||
from IPython import get_ipython
|
||||
from IPython.utils import PyColorize
|
||||
from IPython.utils import coloransi, py3compat
|
||||
from IPython.core.excolors import exception_colors
|
||||
from IPython.testing.skipdoctest import skip_doctest
|
||||
|
||||
|
||||
prompt = 'ipdb> '
|
||||
|
||||
#We have to check this directly from sys.argv, config struct not yet available
|
||||
from pdb import Pdb as OldPdb
|
||||
|
||||
# Allow the set_trace code to operate outside of an ipython instance, even if
|
||||
# it does so with some limitations. The rest of this support is implemented in
|
||||
# the Tracer constructor.
|
||||
|
||||
def make_arrow(pad):
|
||||
"""generate the leading arrow in front of traceback or debugger"""
|
||||
if pad >= 2:
|
||||
return '-'*(pad-2) + '> '
|
||||
elif pad == 1:
|
||||
return '>'
|
||||
return ''
|
||||
|
||||
|
||||
def BdbQuit_excepthook(et, ev, tb, excepthook=None):
|
||||
"""Exception hook which handles `BdbQuit` exceptions.
|
||||
|
||||
All other exceptions are processed using the `excepthook`
|
||||
parameter.
|
||||
"""
|
||||
warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if et==bdb.BdbQuit:
|
||||
print('Exiting Debugger.')
|
||||
elif excepthook is not None:
|
||||
excepthook(et, ev, tb)
|
||||
else:
|
||||
# Backwards compatibility. Raise deprecation warning?
|
||||
BdbQuit_excepthook.excepthook_ori(et,ev,tb)
|
||||
|
||||
|
||||
def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
|
||||
warnings.warn(
|
||||
"`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
print('Exiting Debugger.')
|
||||
|
||||
|
||||
class Tracer(object):
|
||||
"""
|
||||
DEPRECATED
|
||||
|
||||
Class for local debugging, similar to pdb.set_trace.
|
||||
|
||||
Instances of this class, when called, behave like pdb.set_trace, but
|
||||
providing IPython's enhanced capabilities.
|
||||
|
||||
This is implemented as a class which must be initialized in your own code
|
||||
and not as a standalone function because we need to detect at runtime
|
||||
whether IPython is already active or not. That detection is done in the
|
||||
constructor, ensuring that this code plays nicely with a running IPython,
|
||||
while functioning acceptably (though with limitations) if outside of it.
|
||||
"""
|
||||
|
||||
@skip_doctest
|
||||
def __init__(self, colors=None):
|
||||
"""
|
||||
DEPRECATED
|
||||
|
||||
Create a local debugger instance.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
colors : str, optional
|
||||
The name of the color scheme to use, it must be one of IPython's
|
||||
valid color schemes. If not given, the function will default to
|
||||
the current IPython scheme when running inside IPython, and to
|
||||
'NoColor' otherwise.
|
||||
|
||||
Examples
|
||||
--------
|
||||
::
|
||||
|
||||
from IPython.core.debugger import Tracer; debug_here = Tracer()
|
||||
|
||||
Later in your code::
|
||||
|
||||
debug_here() # -> will open up the debugger at that point.
|
||||
|
||||
Once the debugger activates, you can use all of its regular commands to
|
||||
step through code, set breakpoints, etc. See the pdb documentation
|
||||
from the Python standard library for usage details.
|
||||
"""
|
||||
warnings.warn("`Tracer` is deprecated since version 5.1, directly use "
|
||||
"`IPython.core.debugger.Pdb.set_trace()`",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
ip = get_ipython()
|
||||
if ip is None:
|
||||
# Outside of ipython, we set our own exception hook manually
|
||||
sys.excepthook = functools.partial(BdbQuit_excepthook,
|
||||
excepthook=sys.excepthook)
|
||||
def_colors = 'NoColor'
|
||||
else:
|
||||
# In ipython, we use its custom exception handler mechanism
|
||||
def_colors = ip.colors
|
||||
ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
|
||||
|
||||
if colors is None:
|
||||
colors = def_colors
|
||||
|
||||
# The stdlib debugger internally uses a modified repr from the `repr`
|
||||
# module, that limits the length of printed strings to a hardcoded
|
||||
# limit of 30 characters. That much trimming is too aggressive, let's
|
||||
# at least raise that limit to 80 chars, which should be enough for
|
||||
# most interactive uses.
|
||||
try:
|
||||
from reprlib import aRepr
|
||||
aRepr.maxstring = 80
|
||||
except:
|
||||
# This is only a user-facing convenience, so any error we encounter
|
||||
# here can be warned about but can be otherwise ignored. These
|
||||
# printouts will tell us about problems if this API changes
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
self.debugger = Pdb(colors)
|
||||
|
||||
def __call__(self):
|
||||
"""Starts an interactive debugger at the point where called.
|
||||
|
||||
This is similar to the pdb.set_trace() function from the std lib, but
|
||||
using IPython's enhanced debugger."""
|
||||
|
||||
self.debugger.set_trace(sys._getframe().f_back)
|
||||
|
||||
|
||||
RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
|
||||
|
||||
|
||||
def strip_indentation(multiline_string):
|
||||
return RGX_EXTRA_INDENT.sub('', multiline_string)
|
||||
|
||||
|
||||
def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
|
||||
"""Make new_fn have old_fn's doc string. This is particularly useful
|
||||
for the ``do_...`` commands that hook into the help system.
|
||||
Adapted from from a comp.lang.python posting
|
||||
by Duncan Booth."""
|
||||
def wrapper(*args, **kw):
|
||||
return new_fn(*args, **kw)
|
||||
if old_fn.__doc__:
|
||||
wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
|
||||
return wrapper
|
||||
|
||||
|
||||
class Pdb(OldPdb):
|
||||
"""Modified Pdb class, does not load readline.
|
||||
|
||||
for a standalone version that uses prompt_toolkit, see
|
||||
`IPython.terminal.debugger.TerminalPdb` and
|
||||
`IPython.terminal.debugger.set_trace()`
|
||||
"""
|
||||
|
||||
def __init__(self, color_scheme=None, completekey=None,
|
||||
stdin=None, stdout=None, context=5, **kwargs):
|
||||
"""Create a new IPython debugger.
|
||||
|
||||
:param color_scheme: Deprecated, do not use.
|
||||
:param completekey: Passed to pdb.Pdb.
|
||||
:param stdin: Passed to pdb.Pdb.
|
||||
:param stdout: Passed to pdb.Pdb.
|
||||
:param context: Number of lines of source code context to show when
|
||||
displaying stacktrace information.
|
||||
:param kwargs: Passed to pdb.Pdb.
|
||||
The possibilities are python version dependent, see the python
|
||||
docs for more info.
|
||||
"""
|
||||
|
||||
# Parent constructor:
|
||||
try:
|
||||
self.context = int(context)
|
||||
if self.context <= 0:
|
||||
raise ValueError("Context must be a positive integer")
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError("Context must be a positive integer")
|
||||
|
||||
# `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
|
||||
OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
|
||||
|
||||
# IPython changes...
|
||||
self.shell = get_ipython()
|
||||
|
||||
if self.shell is None:
|
||||
save_main = sys.modules['__main__']
|
||||
# No IPython instance running, we must create one
|
||||
from IPython.terminal.interactiveshell import \
|
||||
TerminalInteractiveShell
|
||||
self.shell = TerminalInteractiveShell.instance()
|
||||
# needed by any code which calls __import__("__main__") after
|
||||
# the debugger was entered. See also #9941.
|
||||
sys.modules['__main__'] = save_main
|
||||
|
||||
if color_scheme is not None:
|
||||
warnings.warn(
|
||||
"The `color_scheme` argument is deprecated since version 5.1",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
else:
|
||||
color_scheme = self.shell.colors
|
||||
|
||||
self.aliases = {}
|
||||
|
||||
# Create color table: we copy the default one from the traceback
|
||||
# module and add a few attributes needed for debugging
|
||||
self.color_scheme_table = exception_colors()
|
||||
|
||||
# shorthands
|
||||
C = coloransi.TermColors
|
||||
cst = self.color_scheme_table
|
||||
|
||||
cst['NoColor'].colors.prompt = C.NoColor
|
||||
cst['NoColor'].colors.breakpoint_enabled = C.NoColor
|
||||
cst['NoColor'].colors.breakpoint_disabled = C.NoColor
|
||||
|
||||
cst['Linux'].colors.prompt = C.Green
|
||||
cst['Linux'].colors.breakpoint_enabled = C.LightRed
|
||||
cst['Linux'].colors.breakpoint_disabled = C.Red
|
||||
|
||||
cst['LightBG'].colors.prompt = C.Blue
|
||||
cst['LightBG'].colors.breakpoint_enabled = C.LightRed
|
||||
cst['LightBG'].colors.breakpoint_disabled = C.Red
|
||||
|
||||
cst['Neutral'].colors.prompt = C.Blue
|
||||
cst['Neutral'].colors.breakpoint_enabled = C.LightRed
|
||||
cst['Neutral'].colors.breakpoint_disabled = C.Red
|
||||
|
||||
|
||||
# Add a python parser so we can syntax highlight source while
|
||||
# debugging.
|
||||
self.parser = PyColorize.Parser(style=color_scheme)
|
||||
self.set_colors(color_scheme)
|
||||
|
||||
# Set the prompt - the default prompt is '(Pdb)'
|
||||
self.prompt = prompt
|
||||
self.skip_hidden = True
|
||||
|
||||
def set_colors(self, scheme):
|
||||
"""Shorthand access to the color table scheme selector method."""
|
||||
self.color_scheme_table.set_active_scheme(scheme)
|
||||
self.parser.style = scheme
|
||||
|
||||
|
||||
def hidden_frames(self, stack):
|
||||
"""
|
||||
Given an index in the stack return wether it should be skipped.
|
||||
|
||||
This is used in up/down and where to skip frames.
|
||||
"""
|
||||
ip_hide = [s[0].f_locals.get("__tracebackhide__", False) for s in stack]
|
||||
ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"]
|
||||
if ip_start:
|
||||
ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)]
|
||||
return ip_hide
|
||||
|
||||
def interaction(self, frame, traceback):
|
||||
try:
|
||||
OldPdb.interaction(self, frame, traceback)
|
||||
except KeyboardInterrupt:
|
||||
self.stdout.write("\n" + self.shell.get_exception_only())
|
||||
|
||||
def new_do_frame(self, arg):
|
||||
OldPdb.do_frame(self, arg)
|
||||
|
||||
def new_do_quit(self, arg):
|
||||
|
||||
if hasattr(self, 'old_all_completions'):
|
||||
self.shell.Completer.all_completions=self.old_all_completions
|
||||
|
||||
return OldPdb.do_quit(self, arg)
|
||||
|
||||
do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
|
||||
|
||||
def new_do_restart(self, arg):
|
||||
"""Restart command. In the context of ipython this is exactly the same
|
||||
thing as 'quit'."""
|
||||
self.msg("Restart doesn't make sense here. Using 'quit' instead.")
|
||||
return self.do_quit(arg)
|
||||
|
||||
def print_stack_trace(self, context=None):
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
if context is None:
|
||||
context = self.context
|
||||
try:
|
||||
context=int(context)
|
||||
if context <= 0:
|
||||
raise ValueError("Context must be a positive integer")
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError("Context must be a positive integer")
|
||||
try:
|
||||
skipped = 0
|
||||
for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack):
|
||||
if hidden and self.skip_hidden:
|
||||
skipped += 1
|
||||
continue
|
||||
if skipped:
|
||||
print(
|
||||
f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
|
||||
)
|
||||
skipped = 0
|
||||
self.print_stack_entry(frame_lineno, context=context)
|
||||
if skipped:
|
||||
print(
|
||||
f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
|
||||
context=None):
|
||||
if context is None:
|
||||
context = self.context
|
||||
try:
|
||||
context=int(context)
|
||||
if context <= 0:
|
||||
raise ValueError("Context must be a positive integer")
|
||||
except (TypeError, ValueError):
|
||||
raise ValueError("Context must be a positive integer")
|
||||
print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
|
||||
|
||||
# vds: >>
|
||||
frame, lineno = frame_lineno
|
||||
filename = frame.f_code.co_filename
|
||||
self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
|
||||
# vds: <<
|
||||
|
||||
def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
|
||||
if context is None:
|
||||
context = self.context
|
||||
try:
|
||||
context=int(context)
|
||||
if context <= 0:
|
||||
print("Context must be a positive integer", file=self.stdout)
|
||||
except (TypeError, ValueError):
|
||||
print("Context must be a positive integer", file=self.stdout)
|
||||
try:
|
||||
import reprlib # Py 3
|
||||
except ImportError:
|
||||
import repr as reprlib # Py 2
|
||||
|
||||
ret = []
|
||||
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
|
||||
tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
|
||||
tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
|
||||
tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
|
||||
ColorsNormal)
|
||||
|
||||
frame, lineno = frame_lineno
|
||||
|
||||
return_value = ''
|
||||
if '__return__' in frame.f_locals:
|
||||
rv = frame.f_locals['__return__']
|
||||
#return_value += '->'
|
||||
return_value += reprlib.repr(rv) + '\n'
|
||||
ret.append(return_value)
|
||||
|
||||
#s = filename + '(' + `lineno` + ')'
|
||||
filename = self.canonic(frame.f_code.co_filename)
|
||||
link = tpl_link % py3compat.cast_unicode(filename)
|
||||
|
||||
if frame.f_code.co_name:
|
||||
func = frame.f_code.co_name
|
||||
else:
|
||||
func = "<lambda>"
|
||||
|
||||
call = ''
|
||||
if func != '?':
|
||||
if '__args__' in frame.f_locals:
|
||||
args = reprlib.repr(frame.f_locals['__args__'])
|
||||
else:
|
||||
args = '()'
|
||||
call = tpl_call % (func, args)
|
||||
|
||||
# The level info should be generated in the same format pdb uses, to
|
||||
# avoid breaking the pdbtrack functionality of python-mode in *emacs.
|
||||
if frame is self.curframe:
|
||||
ret.append('> ')
|
||||
else:
|
||||
ret.append(' ')
|
||||
ret.append(u'%s(%s)%s\n' % (link,lineno,call))
|
||||
|
||||
start = lineno - 1 - context//2
|
||||
lines = linecache.getlines(filename)
|
||||
start = min(start, len(lines) - context)
|
||||
start = max(start, 0)
|
||||
lines = lines[start : start + context]
|
||||
|
||||
for i,line in enumerate(lines):
|
||||
show_arrow = (start + 1 + i == lineno)
|
||||
linetpl = (frame is self.curframe or show_arrow) \
|
||||
and tpl_line_em \
|
||||
or tpl_line
|
||||
ret.append(self.__format_line(linetpl, filename,
|
||||
start + 1 + i, line,
|
||||
arrow = show_arrow) )
|
||||
return ''.join(ret)
|
||||
|
||||
def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
|
||||
bp_mark = ""
|
||||
bp_mark_color = ""
|
||||
|
||||
new_line, err = self.parser.format2(line, 'str')
|
||||
if not err:
|
||||
line = new_line
|
||||
|
||||
bp = None
|
||||
if lineno in self.get_file_breaks(filename):
|
||||
bps = self.get_breaks(filename, lineno)
|
||||
bp = bps[-1]
|
||||
|
||||
if bp:
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
bp_mark = str(bp.number)
|
||||
bp_mark_color = Colors.breakpoint_enabled
|
||||
if not bp.enabled:
|
||||
bp_mark_color = Colors.breakpoint_disabled
|
||||
|
||||
numbers_width = 7
|
||||
if arrow:
|
||||
# This is the line with the error
|
||||
pad = numbers_width - len(str(lineno)) - len(bp_mark)
|
||||
num = '%s%s' % (make_arrow(pad), str(lineno))
|
||||
else:
|
||||
num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
|
||||
|
||||
return tpl_line % (bp_mark_color + bp_mark, num, line)
|
||||
|
||||
|
||||
def print_list_lines(self, filename, first, last):
|
||||
"""The printing (as opposed to the parsing part of a 'list'
|
||||
command."""
|
||||
try:
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
|
||||
tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
|
||||
src = []
|
||||
if filename == "<string>" and hasattr(self, "_exec_filename"):
|
||||
filename = self._exec_filename
|
||||
|
||||
for lineno in range(first, last+1):
|
||||
line = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
break
|
||||
|
||||
if lineno == self.curframe.f_lineno:
|
||||
line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
|
||||
else:
|
||||
line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
|
||||
|
||||
src.append(line)
|
||||
self.lineno = lineno
|
||||
|
||||
print(''.join(src), file=self.stdout)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
def do_skip_hidden(self, arg):
|
||||
"""
|
||||
Change whether or not we should skip frames with the
|
||||
__tracebackhide__ attribute.
|
||||
"""
|
||||
if arg.strip().lower() in ("true", "yes"):
|
||||
self.skip_hidden = True
|
||||
elif arg.strip().lower() in ("false", "no"):
|
||||
self.skip_hidden = False
|
||||
|
||||
def do_list(self, arg):
|
||||
"""Print lines of code from the current stack frame
|
||||
"""
|
||||
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), file=self.stdout)
|
||||
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
|
||||
self.print_list_lines(self.curframe.f_code.co_filename, first, last)
|
||||
|
||||
# vds: >>
|
||||
lineno = first
|
||||
filename = self.curframe.f_code.co_filename
|
||||
self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
|
||||
# vds: <<
|
||||
|
||||
do_l = do_list
|
||||
|
||||
def getsourcelines(self, obj):
|
||||
lines, lineno = inspect.findsource(obj)
|
||||
if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
|
||||
# must be a module frame: do not try to cut a block out of it
|
||||
return lines, 1
|
||||
elif inspect.ismodule(obj):
|
||||
return lines, 1
|
||||
return inspect.getblock(lines[lineno:]), lineno+1
|
||||
|
||||
def do_longlist(self, arg):
|
||||
"""Print lines of code from the current stack frame.
|
||||
|
||||
Shows more lines than 'list' does.
|
||||
"""
|
||||
self.lastcmd = 'longlist'
|
||||
try:
|
||||
lines, lineno = self.getsourcelines(self.curframe)
|
||||
except OSError as err:
|
||||
self.error(err)
|
||||
return
|
||||
last = lineno + len(lines)
|
||||
self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
|
||||
do_ll = do_longlist
|
||||
|
||||
def do_debug(self, arg):
|
||||
"""debug code
|
||||
Enter a recursive debugger that steps through the code
|
||||
argument (which is an arbitrary expression or statement to be
|
||||
executed in the current environment).
|
||||
"""
|
||||
sys.settrace(None)
|
||||
globals = self.curframe.f_globals
|
||||
locals = self.curframe_locals
|
||||
p = self.__class__(completekey=self.completekey,
|
||||
stdin=self.stdin, stdout=self.stdout)
|
||||
p.use_rawinput = self.use_rawinput
|
||||
p.prompt = "(%s) " % self.prompt.strip()
|
||||
self.message("ENTERING RECURSIVE DEBUGGER")
|
||||
sys.call_tracing(p.run, (arg, globals, locals))
|
||||
self.message("LEAVING RECURSIVE DEBUGGER")
|
||||
sys.settrace(self.trace_dispatch)
|
||||
self.lastcmd = p.lastcmd
|
||||
|
||||
def do_pdef(self, arg):
|
||||
"""Print the call signature for any callable object.
|
||||
|
||||
The debugger interface to %pdef"""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
|
||||
|
||||
def do_pdoc(self, arg):
|
||||
"""Print the docstring for an object.
|
||||
|
||||
The debugger interface to %pdoc."""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
|
||||
|
||||
def do_pfile(self, arg):
|
||||
"""Print (or run through pager) the file where an object is defined.
|
||||
|
||||
The debugger interface to %pfile.
|
||||
"""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
|
||||
|
||||
def do_pinfo(self, arg):
|
||||
"""Provide detailed information about an object.
|
||||
|
||||
The debugger interface to %pinfo, i.e., obj?."""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
|
||||
|
||||
def do_pinfo2(self, arg):
|
||||
"""Provide extra detailed information about an object.
|
||||
|
||||
The debugger interface to %pinfo2, i.e., obj??."""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
|
||||
|
||||
def do_psource(self, arg):
|
||||
"""Print (or run through pager) the source code for an object."""
|
||||
namespaces = [('Locals', self.curframe.f_locals),
|
||||
('Globals', self.curframe.f_globals)]
|
||||
self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
|
||||
|
||||
def do_where(self, arg):
|
||||
"""w(here)
|
||||
Print a stack trace, with the most recent frame at the bottom.
|
||||
An arrow indicates the "current frame", which determines the
|
||||
context of most commands. 'bt' is an alias for this command.
|
||||
|
||||
Take a number as argument as an (optional) number of context line to
|
||||
print"""
|
||||
if arg:
|
||||
try:
|
||||
context = int(arg)
|
||||
except ValueError as err:
|
||||
self.error(err)
|
||||
return
|
||||
self.print_stack_trace(context)
|
||||
else:
|
||||
self.print_stack_trace()
|
||||
|
||||
do_w = do_where
|
||||
|
||||
def stop_here(self, frame):
|
||||
hidden = False
|
||||
if self.skip_hidden:
|
||||
hidden = frame.f_locals.get("__tracebackhide__", False)
|
||||
if hidden:
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
print(f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n")
|
||||
|
||||
return super().stop_here(frame)
|
||||
|
||||
def do_up(self, arg):
|
||||
"""u(p) [count]
|
||||
Move the current frame count (default one) levels up in the
|
||||
stack trace (to an older frame).
|
||||
|
||||
Will skip hidden frames.
|
||||
"""
|
||||
## modified version of upstream that skips
|
||||
# frames with __tracebackide__
|
||||
if self.curindex == 0:
|
||||
self.error("Oldest frame")
|
||||
return
|
||||
try:
|
||||
count = int(arg or 1)
|
||||
except ValueError:
|
||||
self.error("Invalid frame count (%s)" % arg)
|
||||
return
|
||||
skipped = 0
|
||||
if count < 0:
|
||||
_newframe = 0
|
||||
else:
|
||||
_newindex = self.curindex
|
||||
counter = 0
|
||||
hidden_frames = self.hidden_frames(self.stack)
|
||||
for i in range(self.curindex - 1, -1, -1):
|
||||
frame = self.stack[i][0]
|
||||
if hidden_frames[i] and self.skip_hidden:
|
||||
skipped += 1
|
||||
continue
|
||||
counter += 1
|
||||
if counter >= count:
|
||||
break
|
||||
else:
|
||||
# if no break occured.
|
||||
self.error("all frames above hidden")
|
||||
return
|
||||
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
_newframe = i
|
||||
self._select_frame(_newframe)
|
||||
if skipped:
|
||||
print(
|
||||
f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
|
||||
)
|
||||
|
||||
def do_down(self, arg):
|
||||
"""d(own) [count]
|
||||
Move the current frame count (default one) levels down in the
|
||||
stack trace (to a newer frame).
|
||||
|
||||
Will skip hidden frames.
|
||||
"""
|
||||
if self.curindex + 1 == len(self.stack):
|
||||
self.error("Newest frame")
|
||||
return
|
||||
try:
|
||||
count = int(arg or 1)
|
||||
except ValueError:
|
||||
self.error("Invalid frame count (%s)" % arg)
|
||||
return
|
||||
if count < 0:
|
||||
_newframe = len(self.stack) - 1
|
||||
else:
|
||||
_newindex = self.curindex
|
||||
counter = 0
|
||||
skipped = 0
|
||||
hidden_frames = self.hidden_frames(self.stack)
|
||||
for i in range(self.curindex + 1, len(self.stack)):
|
||||
frame = self.stack[i][0]
|
||||
if hidden_frames[i] and self.skip_hidden:
|
||||
skipped += 1
|
||||
continue
|
||||
counter += 1
|
||||
if counter >= count:
|
||||
break
|
||||
else:
|
||||
self.error("all frames bellow hidden")
|
||||
return
|
||||
|
||||
Colors = self.color_scheme_table.active_colors
|
||||
ColorsNormal = Colors.Normal
|
||||
if skipped:
|
||||
print(
|
||||
f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
|
||||
)
|
||||
_newframe = i
|
||||
|
||||
self._select_frame(_newframe)
|
||||
|
||||
do_d = do_down
|
||||
do_u = do_up
|
||||
|
||||
class InterruptiblePdb(Pdb):
|
||||
"""Version of debugger where KeyboardInterrupt exits the debugger altogether."""
|
||||
|
||||
def cmdloop(self):
|
||||
"""Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
|
||||
try:
|
||||
return OldPdb.cmdloop(self)
|
||||
except KeyboardInterrupt:
|
||||
self.stop_here = lambda frame: False
|
||||
self.do_quit("")
|
||||
sys.settrace(None)
|
||||
self.quitting = False
|
||||
raise
|
||||
|
||||
def _cmdloop(self):
|
||||
while True:
|
||||
try:
|
||||
# keyboard interrupts allow for an easy way to cancel
|
||||
# the current command, so allow them during interactive input
|
||||
self.allow_kbdint = True
|
||||
self.cmdloop()
|
||||
self.allow_kbdint = False
|
||||
break
|
||||
except KeyboardInterrupt:
|
||||
self.message('--KeyboardInterrupt--')
|
||||
raise
|
||||
|
||||
|
||||
def set_trace(frame=None):
|
||||
"""
|
||||
Start debugging from `frame`.
|
||||
|
||||
If frame is not specified, debugging starts from caller's frame.
|
||||
"""
|
||||
Pdb().set_trace(frame or sys._getframe().f_back)
|
Loading…
Add table
Add a link
Reference in a new issue