Nicer debug printing of functions.

This commit is contained in:
Florian Bruhin 2014-09-03 08:57:21 +02:00
parent a811f8cb07
commit d836e26107
4 changed files with 110 additions and 11 deletions

View File

@ -27,7 +27,7 @@ import enum
import inspect
import collections
from qutebrowser.utils import usertypes, qtutils, log
from qutebrowser.utils import usertypes, qtutils, log, debug
from qutebrowser.commands import command, cmdexc, argparser
cmd_dict = {}
@ -236,9 +236,10 @@ class register: # pylint: disable=invalid-name
is_flag = typ == bool
args += self._get_argparse_args(param, annotation_info,
is_flag)
log.commands.vdebug('Adding argument {} of type {} -> '
'args {}, kwargs {}'.format(
param.name, typ, args, kwargs))
callsig = debug.format_call(parser.add_argument, args,
kwargs, full=False)
log.commands.vdebug('Adding arg {} of type {} -> {}'.format(
param.name, typ, callsig))
parser.add_argument(*args, **kwargs)
return has_count, desc, parser

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWebKit import QWebSettings
from qutebrowser.commands import cmdexc, argparser
from qutebrowser.utils import log, utils, message
from qutebrowser.utils import log, utils, message, debug
class Command:
@ -138,6 +138,6 @@ class Command:
kwargs = {'count': count}
self._check_prerequisites()
log.commands.debug('posargs: {}'.format(posargs))
log.commands.debug('kwargs: {}'.format(kwargs))
log.commands.debug('Calling {}'.format(
debug.format_call(self.handler, posargs, kwargs)))
self.handler(*posargs, **kwargs)

View File

@ -208,6 +208,18 @@ def signal_name(sig):
return m.group(1)
def _format_args(args=None, kwargs=None):
"""Format a list of arguments/kwargs to a function-call like string."""
if args is not None:
arglist = [utils.compact_text(repr(arg), 50) for arg in args]
else:
arglist = []
if kwargs is not None:
for k, v in kwargs.items():
arglist.append('{}={}'.format(k, utils.compact_text(repr(v), 50)))
return ', '.join(arglist)
def dbg_signal(sig, args):
"""Get a string representation of a signal for debugging.
@ -218,6 +230,26 @@ def dbg_signal(sig, args):
Return:
A human-readable string representation of signal/args.
"""
argstr = ', '.join([utils.elide(str(a).replace('\n', ' '), 20)
for a in args])
return '{}({})'.format(signal_name(sig), argstr)
return '{}({})'.format(signal_name(sig), _format_args(args))
def format_call(func, args=None, kwargs=None, full=True):
"""Get a string representation of a function calls with the given args.
Args:
func: The callable to print.
args: A list of positional arguments.
kwargs: A dict of named arguments.
full: Whether to print the full name
Return:
A string with the function call.
"""
if full:
if func.__module__ is not None:
name = '.'.join([func.__module__, func.__qualname__])
else:
name = func.__qualname__
else:
name = func.__name__
return '{}({})'.format(name, _format_args(args, kwargs))

View File

@ -19,10 +19,14 @@
"""Misc. utility commands exposed to the user."""
from PyQt5.QtCore import pyqtRemoveInputHook, QCoreApplication
from functools import partial
from qutebrowser.utils import usertypes
from qutebrowser.utils import usertypes, log
from qutebrowser.commands import runners, cmdexc, cmdutils
from qutebrowser.config import config, style
_timers = []
@ -57,3 +61,65 @@ def later(ms : int, *command : {'nargs': '+'}):
timer.timeout.connect(partial(_commandrunner.run_safely, cmdline))
timer.timeout.connect(lambda: _timers.remove(timer))
timer.start()
@cmdutils.register(debug=True, name='debug-set-trace')
def set_trace():
"""Break into the debugger in the shell.
//
Based on http://stackoverflow.com/a/1745965/2085149
"""
if sys.stdout is not None:
sys.stdout.flush()
print()
print("When done debugging, remember to execute:")
print(" from PyQt5 import QtCore; QtCore.pyqtRestoreInputHook()")
print("before executing c(ontinue).")
pyqtRemoveInputHook()
pdb.set_trace()
@cmdutils.register(debug=True)
def debug_crash(typ : ('exception', 'segfault') = 'exception'):
"""Crash for debugging purposes.
Args:
typ: either 'exception' or 'segfault'.
Raises:
raises Exception when typ is not segfault.
segfaults when typ is (you don't say...)
"""
if typ == 'segfault':
# From python's Lib/test/crashers/bogus_code_obj.py
co = types.CodeType(0, 0, 0, 0, 0, b'\x04\x71\x00\x00', (), (), (),
'', '', 1, b'')
exec(co) # pylint: disable=exec-used
raise Exception("Segfault failed (wat.)")
else:
raise Exception("Forced crash")
@cmdutils.register(debug=True)
def debug_all_widgets():
"""Print a list of all widgets to debug log."""
s = QCoreApplication.instance().get_all_widgets()
log.misc.debug(s)
@cmdutils.register(debug=True)
def debug_all_objects():
"""Print a list of all objects to the debug log."""
s = QCoreApplication.instance().get_all_objects()
log.misc.debug(s)
@cmdutils.register(debug=True)
def debug_cache_stats():
"""Print LRU cache stats."""
config_info = config.instance().get.cache_info()
style_info = style.get_stylesheet.cache_info()
log.misc.debug('config: {}'.format(config_info))
log.misc.debug('style: {}'.format(style_info))