Source code for runtimedocs.helpers

import inspect
from collections import OrderedDict

try:
    from collections import ChainMap
    signature_func = inspect.signature
except ImportError:
    from chainmap import ChainMap
    from funcsigs import signature
    signature_func = lambda x: str(signature(x))

# try to import the runtimedocs_types_parsers plugin package to have more parsers for commonly used libraries like:
# numpy, pandas, scipy, etc ...
try:
    from runtimedocs_types_parsers import extra_types_parsers_dict
except ImportError:
    extra_types_parsers_dict = dict()


[docs]def get_type(arg): '''helper function the get the type of an abject as a string.''' return str(type(arg))
[docs]def default_type_parser(arg, max_stringify=1000): ''' default type parser which basically return the repr string of the object. Parameters ---------- arg: object to parse max_stringify: how long at max should be the returned string after doing repr(arg) Returns ------- parsed: OrderedDict('value', ['keys'], ['len']) value: is repr(arg)[:max_stringify] keys: is the the keys in the parsed object and only added to parsed if the object is a dict len: is the the length of the parsed object and only added to parsed if the object is an iterable ''' parsed = OrderedDict(type=get_type(arg)) if hasattr(arg, '__len__'): parsed['len'] = len(arg) if hasattr(arg, 'keys'): parsed['keys'] = str(arg.keys()) parsed['value'] = repr(arg)[:max_stringify] return parsed
[docs]def function_parser(arg): ''' type parser for user defined and builtin functions. Parameters ---------- arg: function to parse Returns ------- parsed: OrderedDict('value', 'signature', 'fullargspec', 'isbuiltin') ''' parsed = OrderedDict(type=get_type(arg)) parsed['name'] = arg.__name__ parsed['signature'] = str(signature_func(arg)) try: parsed['fullargspec'] = str(inspect.getfullargspec(arg)) except Exception as e: parsed['fullargspec'] = str(inspect.getargspec(arg)) parsed['isbuiltin'] = inspect.isbuiltin(arg) #parsed['doc'] = inspect.getdoc(arg) return parsed
[docs]def class_parser(arg): ''' type parser for user defined and builtin classes. Parameters ---------- arg: class to parse Returns ------- parsed: OrderedDict('value', 'signature', 'fullargspec', 'isbuiltin', 'inheritance_tree) ''' parsed = function_parser(arg) parsed['inheritance_tree'] = inspect.getmro(arg) return parsed
[docs]def caller_name(skip=2): """Get a name of a caller in the format module.class.method `skip` specifies how many levels of stack to skip while getting caller name. skip=1 means "who calls me", skip=2 "who calls my caller" etc. An empty string is returned if skipped levels exceed stack height copied from here: https://stackoverflow.com/questions/2654113/python-how-to-get-the-callers-method-name-in-the-called-method """ stack = inspect.stack() start = 0 + skip if len(stack) < start + 1: return '' parentframe = stack[start][0] name = [] module = inspect.getmodule(parentframe) # `modname` can be None when frame is executed directly in console # TODO(techtonik): consider using __main__ if module: name.append(module.__name__) # detect classname if 'self' in parentframe.f_locals: # I don't know any way to detect call from the object method # XXX: there seems to be no way to detect static method call - it will # be just a function call name.append(parentframe.f_locals['self'].__class__.__name__) codename = parentframe.f_code.co_name if codename != '<module>': # top level usually name.append(codename) # function or a method ## Avoid circular refs and frame leaks # https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack del parentframe, stack return ".".join(name)
native_types_parsers_dict = { "<class 'type'>" : class_parser, "<class 'builtin_function_or_method'>": function_parser, "<class 'function'>": function_parser, } common_types_parsers_dict = ChainMap(extra_types_parsers_dict, native_types_parsers_dict)