aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py3/IPython/core/debugger.py
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/ipython/py3/IPython/core/debugger.py
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/python/ipython/py3/IPython/core/debugger.py')
-rw-r--r--contrib/python/ipython/py3/IPython/core/debugger.py999
1 files changed, 0 insertions, 999 deletions
diff --git a/contrib/python/ipython/py3/IPython/core/debugger.py b/contrib/python/ipython/py3/IPython/core/debugger.py
deleted file mode 100644
index ba12e3eac3..0000000000
--- a/contrib/python/ipython/py3/IPython/core/debugger.py
+++ /dev/null
@@ -1,999 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Pdb debugger class.
-
-
-This is an extension to PDB which adds a number of new features.
-Note that there is also the `IPython.terminal.debugger` class which provides UI
-improvements.
-
-We also strongly recommend to use this via the `ipdb` package, which provides
-extra configuration options.
-
-Among other things, this subclass of PDB:
- - supports many IPython magics like pdef/psource
- - hide frames in tracebacks based on `__tracebackhide__`
- - allows to skip frames based on `__debuggerskip__`
-
-The skipping and hiding frames are configurable via the `skip_predicates`
-command.
-
-By default, frames from readonly files will be hidden, frames containing
-``__tracebackhide__=True`` will be hidden.
-
-Frames containing ``__debuggerskip__`` will be stepped over, frames who's parent
-frames value of ``__debuggerskip__`` is ``True`` will be skipped.
-
- >>> def helpers_helper():
- ... pass
- ...
- ... def helper_1():
- ... print("don't step in me")
- ... helpers_helpers() # will be stepped over unless breakpoint set.
- ...
- ...
- ... def helper_2():
- ... print("in me neither")
- ...
-
-One can define a decorator that wraps a function between the two helpers:
-
- >>> def pdb_skipped_decorator(function):
- ...
- ...
- ... def wrapped_fn(*args, **kwargs):
- ... __debuggerskip__ = True
- ... helper_1()
- ... __debuggerskip__ = False
- ... result = function(*args, **kwargs)
- ... __debuggerskip__ = True
- ... helper_2()
- ... # setting __debuggerskip__ to False again is not necessary
- ... return result
- ...
- ... return wrapped_fn
-
-When decorating a function, ipdb will directly step into ``bar()`` by
-default:
-
- >>> @foo_decorator
- ... def bar(x, y):
- ... return x * y
-
-
-You can toggle the behavior with
-
- ipdb> skip_predicates debuggerskip false
-
-or configure it in your ``.pdbrc``
-
-
-
-License
--------
-
-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 original 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
-
-
-All the changes since then are under the same license as IPython.
-
-"""
-
-#*****************************************************************************
-#
-# 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 inspect
-import linecache
-import sys
-import warnings
-import re
-import os
-
-from IPython import get_ipython
-from IPython.utils import PyColorize
-from IPython.utils import coloransi, py3compat
-from IPython.core.excolors import exception_colors
-
-# skip module docstests
-__skip_doctest__ = True
-
-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.
-
-DEBUGGERSKIP = "__debuggerskip__"
-
-
-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.
- """
- raise ValueError(
- "`BdbQuit_excepthook` is deprecated since version 5.1",
- )
-
-
-def BdbQuit_IPython_excepthook(self, et, ev, tb, tb_offset=None):
- raise ValueError(
- "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
- DeprecationWarning, stacklevel=2)
-
-
-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()`
-
-
- This debugger can hide and skip frames that are tagged according to some predicates.
- See the `skip_predicates` commands.
-
- """
-
- default_predicates = {
- "tbhide": True,
- "readonly": False,
- "ipython_internal": True,
- "debuggerskip": True,
- }
-
- def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs):
- """Create a new IPython debugger.
-
- Parameters
- ----------
- completekey : default None
- Passed to pdb.Pdb.
- stdin : default None
- Passed to pdb.Pdb.
- stdout : default None
- Passed to pdb.Pdb.
- context : int
- Number of lines of source code context to show when
- displaying stacktrace information.
- **kwargs
- Passed to pdb.Pdb.
-
- Notes
- -----
- 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) as e:
- raise ValueError("Context must be a positive integer") from e
-
- # `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
-
-
- 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
- self.report_skipped = True
-
- # list of predicates we use to skip frames
- self._predicates = self.default_predicates
-
- #
- 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 set_trace(self, frame=None):
- if frame is None:
- frame = sys._getframe().f_back
- self.initial_frame = frame
- return super().set_trace(frame)
-
- def _hidden_predicate(self, frame):
- """
- Given a frame return whether it it should be hidden or not by IPython.
- """
-
- if self._predicates["readonly"]:
- fname = frame.f_code.co_filename
- # we need to check for file existence and interactively define
- # function would otherwise appear as RO.
- if os.path.isfile(fname) and not os.access(fname, os.W_OK):
- return True
-
- if self._predicates["tbhide"]:
- if frame in (self.curframe, getattr(self, "initial_frame", None)):
- return False
- frame_locals = self._get_frame_locals(frame)
- if "__tracebackhide__" not in frame_locals:
- return False
- return frame_locals["__tracebackhide__"]
- return False
-
- def hidden_frames(self, stack):
- """
- Given an index in the stack return whether it should be skipped.
-
- This is used in up/down and where to skip frames.
- """
- # The f_locals dictionary is updated from the actual frame
- # locals whenever the .f_locals accessor is called, so we
- # avoid calling it here to preserve self.curframe_locals.
- # Furthermore, there is no good reason to hide the current frame.
- ip_hide = [self._hidden_predicate(s[0]) for s in stack]
- ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"]
- if ip_start and self._predicates["ipython_internal"]:
- 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 precmd(self, line):
- """Perform useful escapes on the command before it is executed."""
-
- if line.endswith("??"):
- line = "pinfo2 " + line[:-2]
- elif line.endswith("?"):
- line = "pinfo " + line[:-1]
-
- line = super().precmd(line)
-
- return line
-
- 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) as e:
- raise ValueError("Context must be a positive integer") from e
- 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) as e:
- raise ValueError("Context must be a positive integer") from e
- 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 _get_frame_locals(self, frame):
- """ "
- Accessing f_local of current frame reset the namespace, so we want to avoid
- that or the following can happen
-
- ipdb> foo
- "old"
- ipdb> foo = "new"
- ipdb> foo
- "new"
- ipdb> where
- ipdb> foo
- "old"
-
- So if frame is self.current_frame we instead return self.curframe_locals
-
- """
- if frame is self.curframe:
- return self.curframe_locals
- else:
- return frame.f_locals
-
- 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)
-
- import reprlib
-
- ret = []
-
- Colors = self.color_scheme_table.active_colors
- ColorsNormal = Colors.Normal
- tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
- tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
- tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
- tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal)
-
- frame, lineno = frame_lineno
-
- return_value = ''
- loc_frame = self._get_frame_locals(frame)
- if "__return__" in loc_frame:
- rv = loc_frame["__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 loc_frame:
- args = reprlib.repr(loc_frame["__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("%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_predicates(self, args):
- """
- Turn on/off individual predicates as to whether a frame should be hidden/skip.
-
- The global option to skip (or not) hidden frames is set with skip_hidden
-
- To change the value of a predicate
-
- skip_predicates key [true|false]
-
- Call without arguments to see the current values.
-
- To permanently change the value of an option add the corresponding
- command to your ``~/.pdbrc`` file. If you are programmatically using the
- Pdb instance you can also change the ``default_predicates`` class
- attribute.
- """
- if not args.strip():
- print("current predicates:")
- for (p, v) in self._predicates.items():
- print(" ", p, ":", v)
- return
- type_value = args.strip().split(" ")
- if len(type_value) != 2:
- print(
- f"Usage: skip_predicates <type> <value>, with <type> one of {set(self._predicates.keys())}"
- )
- return
-
- type_, value = type_value
- if type_ not in self._predicates:
- print(f"{type_!r} not in {set(self._predicates.keys())}")
- return
- if value.lower() not in ("true", "yes", "1", "no", "false", "0"):
- print(
- f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')"
- )
- return
-
- self._predicates[type_] = value.lower() in ("true", "yes", "1")
- if not any(self._predicates.values()):
- print(
- "Warning, all predicates set to False, skip_hidden may not have any effects."
- )
-
- def do_skip_hidden(self, arg):
- """
- Change whether or not we should skip frames with the
- __tracebackhide__ attribute.
- """
- if not arg.strip():
- print(
- f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change."
- )
- elif arg.strip().lower() in ("true", "yes"):
- self.skip_hidden = True
- elif arg.strip().lower() in ("false", "no"):
- self.skip_hidden = False
- if not any(self._predicates.values()):
- print(
- "Warning, all predicates set to False, skip_hidden may not have any effects."
- )
-
- 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 self._get_frame_locals(obj):
- # 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).
- """
- trace_function = sys.gettrace()
- 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(trace_function)
- 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_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_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_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_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_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_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 break_anywhere(self, frame):
- """
- _stop_in_decorator_internals is overly restrictive, as we may still want
- to trace function calls, so we need to also update break_anywhere so
- that is we don't `stop_here`, because of debugger skip, we may still
- stop at any point inside the function
-
- """
-
- sup = super().break_anywhere(frame)
- if sup:
- return sup
- if self._predicates["debuggerskip"]:
- if DEBUGGERSKIP in frame.f_code.co_varnames:
- return True
- if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
- return True
- return False
-
- def _is_in_decorator_internal_and_should_skip(self, frame):
- """
- Utility to tell us whether we are in a decorator internal and should stop.
-
- """
-
- # if we are disabled don't skip
- if not self._predicates["debuggerskip"]:
- return False
-
- # if frame is tagged, skip by default.
- if DEBUGGERSKIP in frame.f_code.co_varnames:
- return True
-
- # if one of the parent frame value set to True skip as well.
-
- cframe = frame
- while getattr(cframe, "f_back", None):
- cframe = cframe.f_back
- if self._get_frame_locals(cframe).get(DEBUGGERSKIP):
- return True
-
- return False
-
- def stop_here(self, frame):
-
- if self._is_in_decorator_internal_and_should_skip(frame) is True:
- return False
-
- hidden = False
- if self.skip_hidden:
- hidden = self._hidden_predicate(frame)
- if hidden:
- if self.report_skipped:
- 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 __tracebackhide__
- 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:
- counter = 0
- hidden_frames = self.hidden_frames(self.stack)
- for i in range(self.curindex - 1, -1, -1):
- if hidden_frames[i] and self.skip_hidden:
- skipped += 1
- continue
- counter += 1
- if counter >= count:
- break
- else:
- # if no break occurred.
- self.error(
- "all frames above hidden, use `skip_hidden False` to get get into those."
- )
- 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:
- counter = 0
- skipped = 0
- hidden_frames = self.hidden_frames(self.stack)
- for i in range(self.curindex + 1, len(self.stack)):
- if hidden_frames[i] and self.skip_hidden:
- skipped += 1
- continue
- counter += 1
- if counter >= count:
- break
- else:
- self.error(
- "all frames below hidden, use `skip_hidden False` to get get into those."
- )
- 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
-
- def do_context(self, context):
- """context number_of_lines
- Set the number of lines of source code to show when displaying
- stacktrace information.
- """
- try:
- new_context = int(context)
- if new_context <= 0:
- raise ValueError()
- self.context = new_context
- except ValueError:
- self.error("The 'context' command requires a positive integer argument.")
-
-
-class InterruptiblePdb(Pdb):
- """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
-
- def cmdloop(self, intro=None):
- """Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
- try:
- return OldPdb.cmdloop(self, intro=intro)
- 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)