# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
#import six
from six.moves import range, zip, map, filter # NOQA
import fnmatch
import operator
import inspect
import traceback
import time
try:
import numpy as np
except ImportError:
pass
import sys
import six
import shelve
import textwrap
import keyword
import re
import types
import functools
from os.path import splitext, split, basename, dirname
from utool import util_inject
from utool import util_arg
from utool import util_list
from utool import util_print
from utool import util_str
from utool import util_type
from utool._internal import meta_util_six
print, rrr, profile = util_inject.inject2(__name__, '[dbg]')
RAISE_ALL = util_arg.get_argflag('--raise-all', help='Causes ut.printex to always reraise errors')
FORCE_TB = util_arg.get_argflag('--force-tb', help='Causes ut.printex to always print traceback')
# COLORED_EXCEPTIONS = util_arg.get_argflag(('--colorex', '--cex'))
COLORED_EXCEPTIONS = not util_arg.get_argflag(('--no-colorex', '--no-cex'))
[docs]def print_traceback(with_colors=True):
"""
prints current stack
"""
#traceback.print_tb()
import traceback
stack = traceback.extract_stack()
stack_lines = traceback.format_list(stack)
tbtext = ''.join(stack_lines)
if with_colors:
try:
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import TerminalFormatter
lexer = get_lexer_by_name('pytb', stripall=True)
formatter = TerminalFormatter(bg='dark')
formatted_text = highlight(tbtext, lexer, formatter)
print(formatted_text)
except Exception:
print(tbtext)
else:
print(tbtext)
[docs]def ipython_execstr():
return textwrap.dedent(r'''
import sys
embedded = False
if '-w' in sys.argv or '--wait' in sys.argv or '--wshow' in sys.argv:
print('waiting')
in_ = raw_input('press enter')
if '--cmd' in sys.argv or locals().get('in_', '') == 'cmd':
print('[utool.dbg] Requested IPython shell with --cmd argument.')
try:
__IPYTHON__
print('[ipython_execstr] Already in IPython!')
except NameError:
try:
import IPython
print('[utool.dbg] Presenting in new ipython shell.')
embedded = True
IPython.embed()
except Exception as ex:
print('[ipython_execstr]: Error: ' + str(type(ex)) + str(ex))
raise
''')
[docs]def execstr_parent_locals():
parent_locals = get_parent_locals()
return execstr_dict(parent_locals, 'parent_locals')
[docs]def execstr_attr_list(obj_name, attr_list=None):
#if attr_list is None:
#exec(execstr_parent_locals())
#exec('attr_list = dir('+obj_name+')')
execstr_list = [obj_name + '.' + attr for attr in attr_list]
return execstr_list
varname_regex = re.compile('[_A-Za-z][_a-zA-Z0-9]*$')
[docs]def is_valid_varname(varname):
""" Checks syntax and validity of a variable name """
if not isinstance(varname, six.string_types):
return False
match_obj = re.match(varname_regex, varname)
valid_syntax = match_obj is not None
valid_name = not keyword.iskeyword(varname)
isvalid = valid_syntax and valid_name
return isvalid
[docs]def execstr_dict(dict_, local_name=None, exclude_list=None, explicit=False):
"""
returns execable python code that declares variables using keys and values
execstr_dict
Args:
dict_ (dict):
local_name (str): optional: local name of dictionary. Specifying this
is much safer
exclude_list (list):
Returns:
str: execstr --- the executable string that will put keys from dict
into local vars
CommandLine:
python -m utool.util_dbg --test-execstr_dict
Example:
>>> # UNSTABLE_DOCTEST
>>> from utool.util_dbg import * # NOQA
>>> my_dictionary = {'a': True, 'b':False}
>>> execstr = execstr_dict(my_dictionary)
>>> exec(execstr)
>>> assert 'a' in vars() and 'b' in vars(), 'execstr failed'
>>> assert b is False and a is True, 'execstr failed'
>>> result = execstr
>>> print(result)
a = my_dictionary['a']
b = my_dictionary['b']
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_dbg import * # NOQA
>>> import utool as ut
>>> my_dictionary = {'a': True, 'b':False}
>>> execstr = execstr_dict(my_dictionary)
>>> locals_ = locals()
>>> exec(execstr, locals_)
>>> a, b = ut.dict_take(locals_, ['a', 'b'])
>>> assert 'a' in locals_ and 'b' in locals_, 'execstr failed'
>>> assert b is False and a is True, 'execstr failed'
>>> result = execstr
>>> print(result)
a = my_dictionary['a']
b = my_dictionary['b']
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_dbg import * # NOQA
>>> import utool as ut
>>> my_dictionary = {'a': True, 'b':False}
>>> execstr = execstr_dict(my_dictionary, explicit=True)
>>> result = execstr
>>> print(result)
a = True
b = False
"""
import utool as ut
if explicit:
expr_list = []
for (key, val) in sorted(dict_.items()):
assert isinstance(key, six.string_types), 'keys must be strings'
expr_list.append('%s = %s' % (key, ut.repr2(val),))
execstr = '\n'.join(expr_list)
#print(execstr)
return execstr
else:
if local_name is None:
# Magic way of getting the local name of dict_
local_name = get_varname_from_locals(dict_, get_parent_locals())
try:
if exclude_list is None:
exclude_list = []
assert isinstance(exclude_list, list)
exclude_list.append(local_name)
expr_list = []
assert isinstance(dict_, dict), 'incorrect type type(dict_)=%r, dict_=%r' % (type(dict), dict_)
for (key, val) in sorted(dict_.items()):
assert isinstance(key, six.string_types), 'keys must be strings'
if not is_valid_varname(key):
continue
if not any((fnmatch.fnmatch(key, pat) for pat in exclude_list)):
expr = '%s = %s[%s]' % (key, local_name, ut.repr2(key))
expr_list.append(expr)
execstr = '\n'.join(expr_list)
#print(execstr)
return execstr
except Exception as ex:
locals_ = locals()
ut.printex(ex, key_list=['locals_'])
raise
[docs]def execstr_func(func):
print(' ! Getting executable source for: ' + meta_util_six.get_funcname(func))
_src = inspect.getsource(func)
execstr = textwrap.dedent(_src[_src.find(':') + 1:])
# Remove return statments
while True:
stmtx = execstr.find('return') # Find first 'return'
if stmtx == -1:
break # Fail condition
# The characters which might make a return not have its own line
stmt_endx = len(execstr) - 1
for stmt_break in '\n;':
print(execstr)
print('')
print(stmtx)
stmt_endx_new = execstr[stmtx:].find(stmt_break)
if -1 < stmt_endx_new < stmt_endx:
stmt_endx = stmt_endx_new
# now have variables stmt_x, stmt_endx
before = execstr[:stmtx]
after = execstr[stmt_endx:]
execstr = before + after
return execstr
[docs]def save_testdata(*args, **kwargs):
"""
caches testdata
"""
uid = kwargs.get('uid', '')
shelf_fname = 'test_data_%s.shelf' % uid
shelf = shelve.open(shelf_fname)
locals_ = get_parent_locals()
print('save_testdata(%r)' % (args,))
for key in args:
shelf[key] = locals_[key]
shelf.close()
[docs]def load_testdata(*args, **kwargs):
"""
tries to load previously cached testdata
"""
uid = kwargs.get('uid', '')
shelf_fname = 'test_data_%s.shelf' % uid
shelf = shelve.open(shelf_fname)
ret = [shelf[key] for key in args]
shelf.close()
if len(ret) == 1:
ret = ret[0]
print('load_testdata(%r)' % (args,))
return ret
[docs]def import_testdata():
shelf = shelve.open('test_data.shelf')
print('importing\n * ' + '\n * '.join(shelf.keys()))
shelf_exec = execstr_dict(shelf, 'shelf')
exec(shelf_exec)
shelf.close()
return import_testdata.func_code.co_code
[docs]def breakpoint(*tags):
import utool as ut
if ut.get_argflag('--break'):
ut.embed(N=1)
return True
return False
[docs]def fix_embed_globals():
"""
HACK adds current locals() to globals().
Can be dangerous.
"""
import utool as ut
globals_ = ut.get_parent_globals()
locals_ = ut.get_parent_locals()
globals_.update(locals_)
globals_['wasfixed'] = True
[docs]def embed(parent_locals=None, parent_globals=None, exec_lines=None,
remove_pyqt_hook=True, N=0):
"""
Starts interactive session. Similar to keyboard command in matlab.
Wrapper around IPython.embed
Notes:
#https://github.com/ipython/ipython/wiki/Cookbook%3a-Updating-code-for-use-with-IPython-0.11-and-later
import IPython
x = 3
IPython.embed()
c = IPython.Config()
c.InteractiveShellApp.exec_lines = [
'%pylab qt4',
"print 'System Ready!'",
]
def foo():
return x + 3
a = 3
def bar():
return a + 3
bar()
#NameError: global name 'a' is not defined
from IPython.terminal.ipapp import TerminalIPythonApp
x = 3
app = TerminalIPythonApp.instance()
app.initialize(argv=[]) # argv=[] instructs IPython to ignore sys.argv
app.start()
Args:
parent_locals (None):
parent_globals (None):
exec_lines (None):
remove_pyqt_hook (bool):
N (int):
CommandLine:
python -m utool.util_dbg --test-embed
References:
http://stackoverflow.com/questions/27911570/can-you-specify-a-command-to-run-after-you-embed-into-ipython/27914204#27914204
http://stackoverflow.com/questions/15167200/how-do-i-embed-an-ipython-interpreter-into-an-application-running-in-an-ipython
TODO:
try:
get_ipython
except NameError:
banner=exit_msg=''
else:
banner = '*** Nested interpreter ***'
exit_msg = '*** Back in main IPython ***'
# First import the embed function
from IPython.frontend.terminal.embed import InteractiveShellEmbed
# Now create the IPython shell instance. Put ipshell() anywhere in your code
# where you want it to open.
ipshell = InteractiveShellEmbed(banner1=banner, exit_msg=exit_msg)
#Then use ipshell() whenever you want to be dropped into an IPython shell. This
#will allow you to embed (and even nest) IPython interpreters in your code and
#inspect objects or the state of the program.
Example:
>>> # DISABLE_DOCTEST
>>> from utool.util_dbg import * # NOQA
>>> # build test data
>>> parent_locals = None
>>> parent_globals = None
>>> exec_lines = None
>>> remove_pyqt_hook = True
>>> N = 0
>>> # execute function
>>> result = embed(parent_locals, parent_globals, exec_lines, remove_pyqt_hook, N)
>>> # verify results
>>> print(result)
"""
import utool as ut
from functools import partial
import IPython
if parent_globals is None:
parent_globals = get_parent_globals(N=N)
#parent_globals1 = get_parent_globals(N=0)
#exec(execstr_dict(parent_globals1, 'parent_globals1'))
if parent_locals is None:
parent_locals = get_parent_locals(N=N)
stackdepth = N # NOQA
getframe = partial(ut.get_caller_stack_frame, N=N) # NOQA
exec(execstr_dict(parent_globals, 'parent_globals'))
exec(execstr_dict(parent_locals, 'parent_locals'))
print('')
print('================')
print(ut.bubbletext('EMBEDDING'))
print('================')
print('[util] embedding')
try:
if remove_pyqt_hook:
try:
import guitool
guitool.remove_pyqt_input_hook()
except (ImportError, ValueError) as ex:
#print(ex)
printex(ex, iswarning=True)
pass
# make qt not loop forever (I had qflag loop forever with this off)
except ImportError as ex:
print(ex)
NEW_METHOD = False
if NEW_METHOD:
user_ns = globals()
user_ns = globals().copy()
user_ns.update(locals())
if parent_globals is not None:
user_ns.update(parent_globals)
if parent_locals is not None:
user_ns.update(parent_locals)
orig_argv = sys.argv # NOQA
print('About to start_ipython')
config = IPython.Config()
exec_lines_ = [
'%pylab qt4',
'print("Entered IPYTHON via utool")',
'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=11).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=10).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=9).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=8).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=7).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=6).f_code.co_name,))',
#'print("Entry Point: %r" % (ut.get_caller_stack_frame(N=5).f_code.co_name,))',
#execstr_dict(parent_locals)
] + ut.ensure_str_list(exec_lines if exec_lines is not None else [])
config.InteractiveShellApp.exec_lines = exec_lines_
print('Exec Lines: ')
print(ut.indentjoin(exec_lines_, '\n >>> '))
IPython.start_ipython(config=config, argv=[], user_ns=user_ns)
# Exit python immediately if specifed
if user_ns.get('qqq', False) or vars.get('qqq', False) or user_ns.get('EXIT_NOW', False):
print('[utool.embed] EXIT_NOW or qqq specified')
sys.exit(1)
else:
#from IPython.config.loader import Config
# cfg = Config()
#config_dict = {}
#if exec_lines is not None:
# config_dict['exec_lines'] = exec_lines
#IPython.embed(**config_dict)
print('[util] Get stack location with: ')
print('[util] ut.get_caller_stack_frame(N=8).f_code.co_name')
print('[util] set EXIT_NOW or qqq to True(ish) to hard exit on unembed')
#print('set iup to True to draw plottool stuff')
print('[util] call %pylab qt4 to get plottool stuff working')
once = True
# Allow user to set iup and redo the loop
while once or vars().get('iup', False):
if not once:
# SUPER HACKY WAY OF GETTING FIGURES ON THE SCREEN BETWEEN UPDATES
#vars()['iup'] = False
# ALL YOU NEED TO DO IS %pylab qt4
print('re-emebeding')
#import plottool as pt
#pt.update()
#(pt.present())
for _ in range(100):
time.sleep(.01)
once = False
#vars().get('iup', False):
print('[util] calling IPython.embed()')
"""
Notes:
/usr/local/lib/python2.7/dist-packages/IPython/terminal/embed.py
IPython.terminal.embed.InteractiveShellEmbed
# instance comes from IPython.config.configurable.SingletonConfigurable.instance
"""
#c = IPython.Config()
#c.InteractiveShellApp.exec_lines = [
# '%pylab qt4',
# "print 'System Ready!'",
#]
#IPython.embed(config=c)
IPython.embed()
#config = IPython.terminal.ipapp.load_default_config()
#config.InteractiveShellEmbed = config.TerminalInteractiveShell
#module = sys.modules[parent_globals['__name__']]
#config['module'] = module
#config['module'] = module
#embed2(stack_depth=N + 2 + 1)
#IPython.embed(config=config)
#IPython.embed(config=config)
#IPython.embed(module=module)
# Exit python immediately if specifed
if vars().get('EXIT_NOW', False) or vars().get('qqq', False):
print('[utool.embed] EXIT_NOW specified')
sys.exit(1)
[docs]def embed2(**kwargs):
"""
Modified from IPython.terminal.embed.embed so I can mess with stack_depth
"""
config = kwargs.get('config')
header = kwargs.pop('header', u'')
stack_depth = kwargs.pop('stack_depth', 2)
compile_flags = kwargs.pop('compile_flags', None)
import IPython
from IPython.core.interactiveshell import InteractiveShell
from IPython.terminal.embed import InteractiveShellEmbed
if config is None:
config = IPython.terminal.ipapp.load_default_config()
config.InteractiveShellEmbed = config.TerminalInteractiveShell
kwargs['config'] = config
#save ps1/ps2 if defined
ps1 = None
ps2 = None
try:
ps1 = sys.ps1
ps2 = sys.ps2
except AttributeError:
pass
#save previous instance
saved_shell_instance = InteractiveShell._instance
if saved_shell_instance is not None:
cls = type(saved_shell_instance)
cls.clear_instance()
shell = InteractiveShellEmbed.instance(**kwargs)
shell(header=header, stack_depth=stack_depth, compile_flags=compile_flags)
InteractiveShellEmbed.clear_instance()
#restore previous instance
if saved_shell_instance is not None:
cls = type(saved_shell_instance)
cls.clear_instance()
for subclass in cls._walk_mro():
subclass._instance = saved_shell_instance
if ps1 is not None:
sys.ps1 = ps1
sys.ps2 = ps2
[docs]def quitflag(num=None, embed_=False, parent_locals=None, parent_globals=None):
if num is None or util_arg.get_argflag('--quit' + str(num)):
if parent_locals is None:
parent_locals = get_parent_locals()
if parent_globals is None:
parent_globals = get_parent_globals()
exec(execstr_dict(parent_locals, 'parent_locals'))
exec(execstr_dict(parent_globals, 'parent_globals'))
if embed_:
print('Triggered --quit' + str(num))
embed(parent_locals=parent_locals,
parent_globals=parent_globals)
print('Triggered --quit' + str(num))
sys.exit(1)
[docs]def qflag(num=None, embed_=True):
return quitflag(num, embed_=embed_,
parent_locals=get_parent_locals(),
parent_globals=get_parent_globals())
[docs]def quit(num=None, embed_=False):
return quitflag(num, embed_=embed_,
parent_locals=get_parent_locals(),
parent_globals=get_parent_globals())
[docs]def in_jupyter_notebook():
"""
http://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook
"""
try:
cfg = get_ipython().config
#print('cfg = %s' % (ut.dict_str(cfg),))
#x = cfg['IPKernelApp']['parent_appname']
# might not work if using jupyter-console
if cfg['IPKernelApp']['connection_file'].count('jupyter'):
return True
else:
return False
except (AttributeError, NameError):
return False
[docs]def inIPython():
"""
Tests if running in IPython
"""
try:
__IPYTHON__
return True
except NameError:
return False
[docs]def haveIPython():
"""
Tests if IPython is available
"""
try:
import IPython # NOQA
return True
except NameError:
return False
[docs]def print_frame(frame):
frame = frame if 'frame' in vars() else inspect.currentframe()
attr_list = ['f_code.co_name', 'f_code.co_filename', 'f_back', 'f_lineno',
'f_code.co_names']
obj_name = 'frame'
execstr_print_list = ['print("%r=%%r" %% (%s,))' % (_execstr, _execstr)
for _execstr in execstr_attr_list(obj_name, attr_list)]
execstr = '\n'.join(execstr_print_list)
exec(execstr)
local_varnames = util_str.pack_into('; '.join(frame.f_locals.keys()))
print('Local varnames: ' + local_varnames)
print('--- End Frame ---')
[docs]def search_stack_for_localvar(varname):
"""
Finds a local varable somewhere in the stack and returns the value
Args:
varname (str): variable name
Returns:
None if varname is not found else its value
"""
curr_frame = inspect.currentframe()
print(' * Searching parent frames for: ' + str(varname))
frame_no = 0
while curr_frame.f_back is not None:
if varname in curr_frame.f_locals.keys():
print(' * Found in frame: ' + str(frame_no))
return curr_frame.f_locals[varname]
frame_no += 1
curr_frame = curr_frame.f_back
print('... Found nothing in all ' + str(frame_no) + ' frames.')
return None
[docs]def search_stack_for_var(varname, verbose=util_arg.NOT_QUIET):
"""
Finds a varable (local or global) somewhere in the stack and returns the value
Args:
varname (str): variable name
Returns:
None if varname is not found else its value
"""
curr_frame = inspect.currentframe()
if verbose:
print(' * Searching parent frames for: ' + str(varname))
frame_no = 0
while curr_frame.f_back is not None:
if varname in curr_frame.f_locals.keys():
if verbose:
print(' * Found local in frame: ' + str(frame_no))
return curr_frame.f_locals[varname]
if varname in curr_frame.f_globals.keys():
if verbose:
print(' * Found global in frame: ' + str(frame_no))
return curr_frame.f_globals[varname]
frame_no += 1
curr_frame = curr_frame.f_back
if verbose:
print('... Found nothing in all ' + str(frame_no) + ' frames.')
return None
# Alias
get_var_from_stack = search_stack_for_var
get_localvar_from_stack = search_stack_for_localvar
[docs]def get_stack_frame(N=0, strict=True):
frame_level0 = inspect.currentframe()
frame_cur = frame_level0
for _ix in range(N + 1):
frame_next = frame_cur.f_back
if frame_next is None:
if strict:
raise AssertionError('Frame level %r is root' % _ix)
else:
break
frame_cur = frame_next
return frame_cur
[docs]def get_caller_stack_frame(N=0):
return get_stack_frame(N=N + 2)
[docs]def get_parent_frame(N=0):
parent_frame = get_stack_frame(N=N + 2)
return parent_frame
[docs]def get_parent_locals(N=0):
"""
returns the locals of the function that called you
Args:
N (int): (defaults to 0) number of levels up in the stack
Returns:
dict : locals_
"""
parent_frame = get_parent_frame(N=N + 1)
locals_ = parent_frame.f_locals
return locals_
[docs]def get_parent_globals(N=0):
parent_frame = get_parent_frame(N=N + 1)
globals_ = parent_frame.f_globals
return globals_
[docs]def get_caller_locals(N=0):
"""
returns the locals of the function that called you
alias for get_parent_locals
Args:
N (int): (defaults to 0) number of levels up in the stack
Returns:
dict : locals_
"""
locals_ = get_parent_locals(N=N + 1)
return locals_
[docs]def quasiquote(string):
return string.format(**get_caller_locals())
fmtlocals = quasiquote # non-lispy alias for quasiquote
[docs]def get_caller_prefix(N=0, aserror=False):
prefix_fmt = '[!%s]' if aserror else '[%s]'
prefix = prefix_fmt % (get_caller_name(N=N + 1),)
return prefix
[docs]def get_caller_lineno(N=0, strict=True):
parent_frame = get_parent_frame(N=N + 1)
lineno = parent_frame.f_lineno
return lineno
[docs]def get_caller_name(N=0, allow_genexpr=True):
"""
get the name of the function that called you
Args:
N (int): (defaults to 0) number of levels up in the stack
Returns:
str: a function name
"""
if isinstance(N, (list, tuple, range)):
name_list = []
for N_ in N:
try:
name_list.append(get_caller_name(N_))
except AssertionError:
name_list.append('X')
return '[' + ']['.join(name_list) + ']'
parent_frame = get_parent_frame(N=N + 1)
caller_name = parent_frame.f_code.co_name
if not allow_genexpr:
count = 0
while True:
count += 1
if caller_name == '<genexpr>':
parent_frame = get_parent_frame(N=N + count)
caller_name = parent_frame.f_code.co_name
else:
break
#try:
# if 'func' in parent_frame.f_locals:
# caller_name += '(' + meta_util_six.get_funcname(parent_frame.f_locals['func']) + ')'
#except Exception:
# pass
if caller_name == '<module>':
# Make the caller name the filename
co_filename = parent_frame.f_code.co_filename
caller_name = splitext(split(co_filename)[1])[0]
if caller_name == '__init__':
# Make the caller name the filename
caller_name = basename(dirname(co_filename)) + '.' + caller_name
return caller_name
[docs]def get_caller_modname(N=0, allowmain=True):
parent_frame = get_stack_frame(N=N + 2)
assert allowmain is True
caller_modname = parent_frame.f_globals['__name__']
return caller_modname
[docs]def get_current_stack_depth():
import traceback
stack = traceback.extract_stack()
return len(stack)
[docs]def module_functions(module):
module_members = inspect.getmembers(module)
function_list = []
for key, val in module_members:
if inspect.isfunction(val) and inspect.getmodule(val) == module:
function_list.append((key, val))
return function_list
[docs]def public_attributes(input):
public_attr_list = []
all_attr_list = dir(input)
for attr in all_attr_list:
if attr.find('__') == 0:
continue
public_attr_list.append(attr)
return public_attr_list
[docs]def explore_stack():
stack = inspect.stack()
tup = stack[0]
for ix, tup in reversed(list(enumerate(stack))):
frame = tup[0]
print('--- Frame %2d: ---' % (ix))
print_frame(frame)
print('\n')
#next_frame = curr_frame.f_back
[docs]def explore_module(module_, seen=None, maxdepth=2, nonmodules=False):
def __childiter(module):
for aname in iter(dir(module)):
if aname.find('_') == 0:
continue
try:
yield module.__dict__[aname], aname
except KeyError as ex:
print(repr(ex))
pass
def __explore_module(module, indent, seen, depth, maxdepth, nonmodules):
valid_children = []
ret = u''
modname = str(module.__name__)
#modname = repr(module)
for child, aname in __childiter(module):
try:
childtype = type(child)
if not isinstance(childtype, types.ModuleType):
if nonmodules:
#print_(depth)
fullstr = indent + ' ' + str(aname) + ' = ' + repr(child)
truncstr = util_str.truncate_str(fullstr) + '\n'
ret += truncstr
continue
childname = str(child.__name__)
if seen is not None:
if childname in seen:
continue
elif maxdepth is None:
seen.add(childname)
if childname.find('_') == 0:
continue
valid_children.append(child)
except Exception as ex:
print(repr(ex))
pass
# Print
# print_(depth)
ret += indent + modname + '\n'
# Recurse
if maxdepth is not None and depth >= maxdepth:
return ret
ret += ''.join([__explore_module(child,
indent + ' ',
seen, depth + 1,
maxdepth,
nonmodules)
for child in iter(valid_children)])
return ret
#ret +=
#print('#module = ' + str(module_))
ret = __explore_module(module_, ' ', seen, 0, maxdepth, nonmodules)
#print(ret)
sys.stdout.flush()
return ret
[docs]def debug_npstack(stacktup):
print('Debugging numpy [hv]stack:')
print('len(stacktup) = %r' % len(stacktup))
for count, item in enumerate(stacktup):
if isinstance(item, np.ndarray):
print(' * item[%d].shape = %r' % (count, item.shape))
elif isinstance(item, list) or isinstance(item, tuple):
print(' * len(item[%d]) = %d' % (count, len(item)))
print(' * DEBUG LIST')
with util_print.Indenter(' * '):
debug_list(item)
else:
print(' * type(item[%d]) = %r' % (count, type(item)))
[docs]def debug_list(list_):
dbgmessage = []
append = dbgmessage.append
append('debug_list')
dim2 = None
if all([util_type.is_listlike(item) for item in list_]):
append(' * list items are all listlike')
all_lens = [len(item) for item in list_]
if util_list.allsame(all_lens):
dim2 = all_lens[0]
append(' * uniform lens=%d' % dim2)
else:
append(' * nonuniform lens = %r' % np.unique(all_lens).tolist())
else:
all_types = [type(item) for item in list_]
if util_list.allsame(all_types):
append(' * uniform types=%r' % all_types[0])
else:
append(' * nonuniform types: %r' % np.unique(all_types).tolist())
print('\n'.join(dbgmessage))
return dim2
[docs]def debug_hstack(stacktup):
try:
return np.hstack(stacktup)
except ValueError as ex:
print('ValueError in debug_hstack: ' + str(ex))
debug_npstack(stacktup)
raise
[docs]def debug_vstack(stacktup):
try:
return np.vstack(stacktup)
except ValueError as ex:
print('ValueError in debug_vstack: ' + str(ex))
debug_npstack(stacktup)
raise
[docs]def debug_exception(func):
@functools.wraps(func)
def ex_wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as ex:
import utool
msg = ('[tools] ERROR: %s(%r, %r)' % (meta_util_six.get_funcname(func), args, kwargs))
#print(msg)
utool.printex(ex, msg)
#print('[tools] ERROR: %r' % ex)
raise
return ex_wrapper
TB = util_arg.get_flag('--tb')
[docs]def printex(ex, msg='[!?] Caught exception', prefix=None, key_list=[],
locals_=None, iswarning=False, tb=TB, pad_stdout=True, N=0,
use_stdout=False, reraise=False, msg_=None, keys=None, colored=None):
"""
Prints (and/or logs) an exception with relevant info
Args:
ex (Exception): exception to print
msg (str): a message to display to the user
keys (None): a list of strings denoting variables or expressions of interest
iswarning (bool): prints as a warning rather than an error if True (defaults to False)
tb (bool): if True prints the traceback in the error message
pad_stdout (bool): separate the error message from the rest of stdout with newlines
prefix (None):
locals_ (None):
N (int):
use_stdout (bool):
reraise (bool):
msg_ (None):
key_list (list): DEPRICATED use keys
Returns:
None
"""
if isinstance(ex, MemoryError):
import utool as ut
ut.print_resource_usage()
#ut.embed()
if keys is not None:
# shorthand for key_list
key_list = keys
# Get error prefix and local info
if prefix is None:
prefix = get_caller_prefix(aserror=True, N=N)
if locals_ is None:
locals_ = get_caller_locals(N=N)
# build exception message
if msg is True:
key_list = get_caller_locals()
msg = msg_
exstr = formatex(ex, msg, prefix, key_list, locals_, iswarning, tb=tb, colored=colored)
# get requested print function
if use_stdout:
def print_func(*args):
msg = ', '.join(list(map(str, args)))
sys.stdout.write(msg + '\n')
sys.stdout.flush()
else:
import utool as ut
print_func = ut.partial(ut.colorprint, color='yellow' if iswarning else 'red')
# print_func = print
if pad_stdout:
print_func('\n+------\n')
# print the execption
print_func(exstr)
if pad_stdout:
print_func('\nL______\n')
# If you dont know where an error is coming from raise-all
if (reraise and not iswarning) or RAISE_ALL:
sys.stdout.flush()
sys.stderr.flush()
raise ex
[docs]def get_varname_from_stack(var, N=0, **kwargs):
return get_varname_from_locals(var, get_caller_locals(N=N), **kwargs)
[docs]def get_varname_from_locals(val, locals_, default='varname-not-found',
strict=False, cmpfunc_=operator.is_):
""" Finds the string name which has where locals_[name] is val
Check the varname is in the parent namespace
This will only work with objects not primatives
Args:
val (): some value
locals_ (dict): local dictionary to search
default (str):
strict (bool):
Returns:
str: the varname which is Val (if it exists)
"""
if val is None or isinstance(val, (int, float, bool)):
# Cannot work on primative types
return default
try:
for count, val_ in enumerate(six.itervalues(locals_)):
if cmpfunc_(val, val_):
index_ = count
varname = str(list(locals_.keys())[index_])
except NameError:
varname = default
if strict:
raise
return varname
[docs]def get_varval_from_locals(key, locals_, strict=False):
"""
Returns a variable value from locals.
Different from locals()['varname'] because
get_varval_from_locals('varname.attribute', locals())
is allowed
"""
assert isinstance(key, six.string_types), 'must have parsed key into a string already'
if key not in locals_:
dotpos = key.find('.')
if dotpos > -1:
key_ = key[:dotpos]
attrstr_ = key[dotpos:]
try:
baseval = locals_[key_] # NOQA
val = eval('baseval' + attrstr_)
except Exception as ex:
if strict:
raise
val = ex
else:
raise AssertionError('%s = NameError' % (key))
else:
val = locals_[key]
return val
[docs]def get_varstr(val, pad_stdout=True, locals_=None):
# TODO: combine with printex functionality
if locals_ is None:
locals_ = get_parent_locals()
name = get_varname_from_locals(val, locals_)
varstr_list = []
if pad_stdout:
varstr_list.append('\n\n+==========')
varstr_list.append(repr(type(val)) + ' ' + name + ' = ')
varstr_list.append(str(val))
if pad_stdout:
varstr_list.append('L==========')
varstr = '\n'.join(varstr_list)
return varstr
[docs]def super_print(val, locals_=None):
if locals_ is None:
locals_ = get_parent_locals()
print(get_varstr(val, locals_=locals_))
[docs]def print_keys(key_list, locals_=None):
if locals_ is None:
locals_ = get_parent_locals()
strlist_ = parse_locals_keylist(locals_, key_list)
print('\n'.join(strlist_))
[docs]def parse_locals_keylist(locals_, key_list, strlist_=None, prefix=''):
""" For each key in keylist, puts its value in locals into a stringlist
Args:
locals_ (?):
key_list (list):
strlist_ (list): (default = None)
prefix (unicode): (default = u'')
Returns:
list: strlist_
CommandLine:
python -m utool.util_dbg --exec-parse_locals_keylist
Example:
>>> # ENABLE_DOCTEST
>>> from utool.util_dbg import * # NOQA
>>> import utool as ut
>>> locals_ = {'foo': [1,2,3], 'bar': 'spam', 'eggs': 4, 'num': 5}
>>> key_list = [(len, 'foo'), 'bar.lower.__name__', 'eggs', 'num', 'other']
>>> strlist_ = None
>>> prefix = u''
>>> strlist_ = parse_locals_keylist(locals_, key_list, strlist_, prefix)
>>> result = ('strlist_ = %s' % (ut.repr2(strlist_, nl=True),))
>>> print(result)
strlist_ = [
' len(foo) = 3',
" bar.lower.__name__ = 'lower'",
' eggs = 4',
' num = 5',
' other = NameError',
]
"""
from utool import util_str
if strlist_ is None:
strlist_ = []
for key in key_list:
try:
if key is None:
strlist_.append('')
elif isinstance(key, tuple):
# Given a tuple of information
tup = key
func, key_ = tup
val = get_varval_from_locals(key_, locals_)
funcvalstr = str(func(val))
callname = util_str.get_callable_name(func)
strlist_.append('%s %s(%s) = %s' % (prefix, callname, key_, funcvalstr))
elif isinstance(key, six.string_types):
# Try to infer print from variable name
val = get_varval_from_locals(key, locals_)
#valstr = util_str.truncate_str(repr(val), maxlen=200)
valstr = util_str.truncate_str(util_str.repr2(val), maxlen=200)
strlist_.append('%s %s = %s' % (prefix, key, valstr))
else:
# Try to infer print from variable value
val = key
typestr = repr(type(val))
namestr = get_varname_from_locals(val, locals_)
#valstr = util_str.truncate_str(repr(val), maxlen=200)
valstr = util_str.truncate_str(util_str.repr2(val), maxlen=200)
strlist_.append('%s %s %s = %s' % (prefix, typestr, namestr, valstr))
except AssertionError as ex:
strlist_.append(prefix + ' ' + str(ex))
return strlist_
[docs]def get_reprs(*args, **kwargs):
if 'locals_' in kwargs:
locals_ = kwargs['locals_']
else:
locals_ = locals()
locals_.update(get_caller_locals())
msg_list = []
var_list = list(args) + kwargs.get('var_list', [])
for key in var_list:
var = locals_[key]
msg = util_str.horiz_string(str(key) + ' = ', repr(var))
msg_list.append(msg)
reprs = '\n' + util_str.indent('\n##\n'.join(msg_list)) + '\n'
return reprs
[docs]def printvar2(varstr, attr='', typepad=0):
locals_ = get_parent_locals()
printvar(locals_, varstr, attr, typepad=typepad)
[docs]def printvar(locals_, varname, attr='.shape', typepad=0):
#npprintopts = np.get_printoptions()
#np.set_printoptions(threshold=5)
dotpos = varname.find('.')
# Locate var
if dotpos == -1:
var = locals_[varname]
else:
varname_ = varname[:dotpos]
dotname_ = varname[dotpos:]
var_ = locals_[varname_] # NOQA
var = eval('var_' + dotname_)
# Print in format
typestr = str(util_type.get_type(var)).ljust(typepad)
if isinstance(var, np.ndarray):
varstr = eval('str(var' + attr + ')')
print('[var] %s %s = %s' % (typestr, varname + attr, varstr))
elif isinstance(var, list):
if attr == '.shape':
func = 'len'
else:
func = ''
varstr = eval('str(' + func + '(var))')
print('[var] %s len(%s) = %s' % (typestr, varname, varstr))
else:
print('[var] %s %s = %r' % (typestr, varname, var))
#np.set_printoptions(**npprintopts)
#def my_numpy_printops(linewidth=200, threshold=500, precision=8, edgeitems=5):
# np.set_printoptions(linewidth=linewidth,
# precision=precision,
# edgeitems=edgeitems,
# threshold=threshold)
[docs]def dict_dbgstr(dict_name, locals_=None):
if locals_ is None:
locals_ = get_parent_locals()
lenstr = len_dbgstr(dict_name, locals_)
keystr = keys_dbgstr(dict_name, locals_)
return keystr + ' ' + lenstr
#printvar(locals_, dict_name)
[docs]def keys_dbgstr(dict_name, locals_=None):
if locals_ is None:
locals_ = get_parent_locals()
dict_ = locals_[dict_name]
key_str = dict_name + '.keys() = ' + repr(dict_.keys())
return key_str
#dict_ = locals_[dict_name]
[docs]def print_varlen(name_, locals_=None):
if locals_ is None:
locals_ = get_parent_locals()
prefix = get_caller_prefix()
print(prefix + ' ' + len_dbgstr(name_, locals_))
[docs]def len_dbgstr(lenable_name, locals_=None):
try:
if locals_ is None:
locals_ = get_parent_locals()
lenable_ = locals_[lenable_name]
except Exception:
exec(execstr_dict(locals_, 'locals_'))
try:
lenable_ = eval(lenable_name)
except Exception as ex:
print('locals.keys = %r' % (locals_.keys(),))
printex(ex, '[!util_dbg]')
raise Exception('Cannot lendbg: %r' % lenable_name)
len_str = 'len(%s) = %d' % (lenable_name, len(lenable_))
return len_str
[docs]def list_dbgstr(list_name, trunc=2):
locals_ = get_parent_locals()
list_ = locals_[list_name]
if trunc is None:
pos = len(list_)
else:
pos = min(trunc, len(list_) - 1)
list_str = list_name + ' = ' + repr(list_[0:pos],)
return list_str
[docs]def all_rrr():
raise NotImplementedError('!!! STOP !!!')
util_inject.inject_all()
for mod in util_inject.get_injected_modules():
try:
if hasattr(mod, 'rrr'):
mod.rrr()
except Exception as ex:
print(ex)
print('mod = %r ' % mod)
[docs]class EmbedOnException(object):
"""
Context manager which embeds in ipython if an exception is thrown
"""
def __init__(self):
pass
def __enter__(self):
return self
def __call__(self):
return self
def __exit__(self, type_, value, trace):
if trace is not None:
print('!!! EMBED ON EXCEPTION !!!')
print('[util_dbg] %r in context manager!: %s ' % (type_, str(value)))
import utool
import traceback
#traceback.print_stack(type_, value, trace)
traceback.print_exception(type_, value, trace)
#parent_locals = utool.get_parent_locals()
#execstr_parent = utool.execstr_dict(parent_locals, 'parent_locals')
#exec(execstr_parent)
trace_locals = trace.tb_frame.f_locals
execstr_trace = utool.execstr_dict(trace_locals, 'trace_locals')
exec(execstr_trace)
utool.embed()
# maybe this will be easier to type?
embed_on_exception_context = EmbedOnException()
eoxc = embed_on_exception_context
if __name__ == '__main__':
"""
CommandLine:
python -c "import utool, utool.util_dbg; utool.doctest_funcs(utool.util_dbg, allexamples=True)"
python -c "import utool, utool.util_dbg; utool.doctest_funcs(utool.util_dbg)"
python -m utool.util_dbg
python -m utool.util_dbg --allexamples
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()