pinspect module

This module supplements Python’s introspection capabilities. The class putil.pinspect.Callables “traces” modules and produces a database of callables (functions, classes, methods and class properties) and their attributes (callable type, file name, starting line number). Enclosed functions and classes are supported. For example:

# pinspect_example_1.py
from __future__ import print_function
import math

def my_func(version):
    """ Enclosing function """
    class MyClass(object):
        """ Enclosed class """
        if version == 2:
            import docs.support.python2_module as pm
        else:
            import docs.support.python3_module as pm

        def __init__(self, value):
            self._value = value

        def _get_value(self):
            return self._value

        value = property(_get_value, pm._set_value, None, 'Value property')

def print_name(name):
    print('My name is {0}, and sqrt(2) = {1}'.format(name, math.sqrt(2)))

with

# python2_module.py
def _set_value(self, value):
    self._value = value+2

and

# python3_module.py
def _set_value(self, value):
    self._value = value+3

gives:

>>> from __future__ import print_function
>>> import docs.support.pinspect_example_1, putil.pinspect, sys
>>> cobj = putil.pinspect.Callables(
...     [sys.modules['docs.support.pinspect_example_1'].__file__]
... )
>>> print(cobj)
Modules:
   docs.support.pinspect_example_1
Classes:
   docs.support.pinspect_example_1.my_func.MyClass
docs.support.pinspect_example_1.my_func: func (9-25)
docs.support.pinspect_example_1.my_func.MyClass: class (11-25)
docs.support.pinspect_example_1.my_func.MyClass.__init__: meth (18-20)
docs.support.pinspect_example_1.my_func.MyClass._get_value: meth (21-23)
docs.support.pinspect_example_1.my_func.MyClass.value: prop (24-25)
docs.support.pinspect_example_1.print_name: func (26-27)

The numbers in parenthesis indicate the line number in which the callable starts and ends within the file it is defined in.

Functions

putil.pinspect.get_function_args(func, no_self=False, no_varargs=False)

Returns a tuple of the function argument names in the order they are specified in the function signature

Parameters:
  • func (function object) – Function
  • no_self (boolean) – Flag that indicates whether the function argument self, if present, is included in the output (False) or not (True)
  • no_varargs (boolean) – Flag that indicates whether keyword arguments are included in the output (True) or not (False)
Return type:

tuple

For example:

>>> import putil.pinspect
>>> class MyClass(object):
...     def __init__(self, value, **kwargs):
...         pass
...
>>> putil.pinspect.get_function_args(MyClass.__init__)
('self', 'value', '**kwargs')
>>> putil.pinspect.get_function_args(
...     MyClass.__init__, no_self=True
... )
('value', '**kwargs')
>>> putil.pinspect.get_function_args(
...     MyClass.__init__, no_self=True, no_varargs=True
... )
('value',)
>>> putil.pinspect.get_function_args(
...     MyClass.__init__, no_varargs=True
... )
('self', 'value')
putil.pinspect.get_module_name(module_obj)

Retrieves the module name from a module object

Parameters:

module_obj (object) – Module object

Return type:

string

Raises:
  • RuntimeError (Argument `module_obj` is not valid)
  • RuntimeError (Module object `*[module_name]*` could not be found in loaded modules)

For example:

>>> import putil.pinspect
>>> putil.pinspect.get_module_name(sys.modules['putil.pinspect'])
'putil.pinspect'
putil.pinspect.is_object_module(obj)

Tests if the argument is a module object

Parameters:obj (any) – Object
Return type:boolean
putil.pinspect.is_special_method(name)

Tests if a callable name is a special Python method (has a '__' prefix and suffix)

Parameters:name (string) – Callable name
Return type:boolean
putil.pinspect.private_props(obj)

Yields private properties of an object. A private property is defined as one that has a single underscore (_) before its name

Parameters:obj (object) – Object
Returns:iterator

Classes

class putil.pinspect.Callables(fnames=None)

Bases: object

Generates a list of module callables (functions, classes, methods and class properties) and gets their attributes (callable type, file name, lines span). Information from multiple modules can be stored in the callables database of the object by repeatedly calling putil.pinspect.Callables.trace() with different module file names. A putil.pinspect.Callables object retains knowledge of which modules have been traced so repeated calls to putil.pinspect.Callables.trace() with the same module object will not result in module re-traces (and the consequent performance hit)

Parameters:

fnames (list of strings or None) – File names of the modules to trace. If None no immediate tracing is done

Raises:
  • OSError (File [fname] could not be found)
  • RuntimeError (Argument `fnames` is not valid)
__add__(other)

Merges two objects

Raises:RuntimeError (Conflicting information between objects)

For example:

>>> import putil.eng, putil.exh, putil.pinspect, sys
>>> obj1 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> obj2 = putil.pinspect.Callables(
...     [sys.modules['putil.eng'].__file__]
... )
>>> obj3 = putil.pinspect.Callables([
... sys.modules['putil.exh'].__file__,
... sys.modules['putil.eng'].__file__,
... ])
>>> obj1 == obj3
False
>>> obj1 == obj2
False
>>> obj1+obj2 == obj3
True
__copy__()

Copies object. For example:

>>> import copy, putil.exh, putil.pinspect, sys
>>> obj1 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> obj2 = copy.copy(obj1)
>>> obj1 == obj2
True
__eq__(other)

Tests object equality. For example:

>>> import putil.eng, putil.exh, putil.pinspect, sys
>>> obj1 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> obj2 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> obj3 = putil.pinspect.Callables(
...     [sys.modules['putil.eng'].__file__]
... )
>>> obj1 == obj2
True
>>> obj1 == obj3
False
>>> 5 == obj3
False
__iadd__(other)

Merges an object into an existing object

Raises:RuntimeError (Conflicting information between objects)

For example:

>>> import putil.eng, putil.exh, putil.pinspect, sys
>>> obj1 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> obj2 = putil.pinspect.Callables(
...     [sys.modules['putil.eng'].__file__]
... )
>>> obj3 = putil.pinspect.Callables([
...     sys.modules['putil.exh'].__file__,
...     sys.modules['putil.eng'].__file__,
... ])
>>> obj1 == obj3
False
>>> obj1 == obj2
False
>>> obj1 += obj2
>>> obj1 == obj3
True
__nonzero__()

Returns False if no modules have been traced, True otherwise. For example:

>>> from __future__ import print_function
>>> import putil.eng, putil.pinspect, sys
>>> obj = putil.pinspect.Callables()
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: False
>>> obj.trace([sys.modules['putil.eng'].__file__])
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: True
__repr__()

Returns a string with the expression needed to re-create the object. For example:

>>> import putil.exh, putil.pinspect, sys
>>> obj1 = putil.pinspect.Callables(
...     [sys.modules['putil.exh'].__file__]
... )
>>> repr(obj1)  
"putil.pinspect.Callables(['...exh.py'])"
>>> exec("obj2="+repr(obj1))
>>> obj1 == obj2
True
__str__()

Returns a string with a detailed description of the object’s contents. For example:

>>> from __future__ import print_function
>>> import putil.pinspect, os, sys
>>> import docs.support.pinspect_example_1
>>> cobj = putil.pinspect.Callables([
...     sys.modules['docs.support.pinspect_example_1'].__file__
... ])
>>> print(cobj) 
Modules:
   ...pinspect_example_1
Classes:
   ...pinspect_example_1.my_func.MyClass
...pinspect_example_1.my_func: func (9-25)
...pinspect_example_1.my_func.MyClass: class (11-25)
...pinspect_example_1.my_func.MyClass.__init__: meth (18-20)
...pinspect_example_1.my_func.MyClass._get_value: meth (21-23)
...pinspect_example_1.my_func.MyClass.value: prop (24-25)
...pinspect_example_1.print_name: func (26-27)

The numbers in parenthesis indicate the line number in which the callable starts and ends within the file it is defined in

load(callables_fname)

Loads traced modules information from a JSON file. The loaded module information is merged with any existing module information

Parameters:

callables_fname (FileNameExists) – File name

Raises:
  • OSError (File [fname] could not be found)
  • RuntimeError (Argument `callables_fname` is not valid)
refresh()

Re-traces modules which have been modified since the time they were traced

save(callables_fname)

Saves traced modules information to a JSON file. If the file exists it is overwritten

Parameters:callables_fname (FileName) – File name
Raises:RuntimeError (Argument `fname` is not valid)
trace(fnames)

Generates a list of module callables (functions, classes, methods and class properties) and gets their attributes (callable type, file name, lines span)

Parameters:

fnames (list) – File names of the modules to trace

Raises:
  • OSError (File [fname] could not be found)
  • RuntimeError (Argument `fnames` is not valid)
callables_db

Returns the callables database

Return type:dictionary

The callable database is a dictionary that has the following structure:

  • full callable name (string) – Dictionary key. Elements in the callable path are separated by periods ('.'). For example, method my_method() from class MyClass from module my_module appears as 'my_module.MyClass.my_method'
  • callable properties (dictionary) – Dictionary value. The elements of this dictionary are:
  • type (string)'class' for classes, 'meth' for methods, 'func' for functions or 'prop' for properties or class attributes
  • code_id (tuple or None) – A tuple with the following items:
    • file name (string) – the first item contains the file name where the callable can be found
    • line number (integer) – the second item contains the line number in which the callable code starts (including decorators)
  • last_lineno (integer) – line number in which the callable code ends (including blank lines and comments regardless of their indentation level)
reverse_callables_db

Returns the reverse callables database

Return type:dictionary

The reverse callable database is a dictionary that has the following structure:

  • callable id (tuple) – Dictionary key. Two-element tuple in which the first tuple item is the file name where the callable is defined and the second tuple item is the line number where the callable definition starts
  • full callable name (string) – Dictionary value. Elements in the callable path are separated by periods ('.'). For example, method my_method() from class MyClass from module my_module appears as 'my_module.MyClass.my_method'