exh module

This module can be used to register exceptions and then raise them if a given condition is true. For example:

# exh_example.py
from __future__ import print_function
from putil.exh import addex

def my_func(name):
    """ Sample function """
    # Add exception
    exobj = addex(TypeError, 'Argument `name` is not valid')
    # Conditionally raise exception
    exobj(not isinstance(name, str))
    print('My name is {0}'.format(name))
>>> import docs.support.exh_example
>>> docs.support.exh_example.my_func('Tom')
My name is Tom
>>> docs.support.exh_example.my_func(5) 
Traceback (most recent call last):
    ...
TypeError: Argument `name` is not valid

When my_func() gets called with anything but a string as an argument a TypeError exception is raised with the message 'Argument `name` is not valid'. While adding an exception with putil.exh.addex() and conditionally raising it takes the same number of lines of code as an exception raised inside an if block (or less since the raise condition can be evaluated in the same putil.exh.addex() call) and incurs a slight performance penalty, using the putil.exh module allows for automatic documentation of the exceptions raised by any function, method or class property with the help of the putil.exdoc module.

Functions

putil.exh.addex(extype, exmsg, condition=None, edata=None)

Adds an exception in the global exception handler

Parameters:
  • extype (Exception type object, i.e. RuntimeError, TypeError, etc.) – Exception type; must be derived from the Exception class
  • exmsg (string) – Exception message; it can contain fields to be replaced when the exception is raised via putil.exh.ExHandle.raise_exception_if(). A field starts with the characters '*[' and ends with the characters ']*', the field name follows the same rules as variable names and is between these two sets of characters. For example, '*[fname]*' defines the fname field
  • condition (boolean or None) – Flag that indicates whether the exception is raised (True) or not (False). If None the flag is not used an no exception is raised
  • edata

    Replacement values for fields in the exception message (see putil.exh.ExHandle.add_exception() for how to define fields). Each dictionary entry can only have these two keys:

    • field (string) – Field name
    • value (any) – Field value, to be converted into a string with the format string method

    If None no field replacement is done

Return type:

(if condition is not given or None) function

Raises:
  • RuntimeError (Argument `condition` is not valid)
  • RuntimeError (Argument `edata` is not valid)
  • RuntimeError (Argument `exmsg` is not valid)
  • RuntimeError (Argument `extype` is not valid)
putil.exh.addai(argname, condition=None)

Adds an exception of the type RuntimeError('Argument `*[argname]*` is not valid') in the global exception handler where *[argname]* is the value of the argname argument

Parameters:
  • argname (string) – Argument name
  • condition (boolean or None) – Flag that indicates whether the exception is raised (True) or not (False). If None the flag is not used and no exception is raised
Return type:

(if condition is not given or None) function

Raises:
  • RuntimeError (Argument `argname` is not valid)
  • RuntimeError (Argument `condition` is not valid)
putil.exh.get_exh_obj()

Returns the global exception handler

Return type:putil.exh.ExHandle if global exception handler is set, None otherwise
putil.exh.get_or_create_exh_obj(full_cname=False, exclude=None, callables_fname=None)

Returns the global exception handler if it is set, otherwise creates a new global exception handler and returns it

Parameters:
  • full_cname (boolean) –

    Flag that indicates whether fully qualified function/method/class property names are obtained for functions/methods/class properties that use the exception manager (True) or not (False).

    There is a performance penalty if the flag is True as the call stack needs to be traced. This argument is only relevant if the global exception handler is not set and a new one is created

  • exclude (list of strings or None) – Module exclusion list. A particular callable in an otherwise fully qualified name is omitted if it belongs to a module in this list. If None all callables are included
  • callables_fname (FileNameExists or None) – File name that contains traced modules information. File can be produced by either the putil.pinspect.Callables.save() or putil.exh.ExHandle.save_callables() methods
Return type:

putil.exh.ExHandle

Raises:
  • OSError (File [callables_fname] could not be found
  • RuntimeError (Argument `exclude` is not valid)
  • RuntimeError (Argument `callables_fname` is not valid)
  • RuntimeError (Argument `full_cname` is not valid)
putil.exh.del_exh_obj()

Deletes global exception handler (if set)

putil.exh.set_exh_obj(obj)

Sets the global exception handler

Parameters:obj (putil.exh.ExHandle) – Exception handler
Raises:RuntimeError (Argument `obj` is not valid)

Classes

class putil.exh.ExHandle(full_cname=False, exclude=None, callables_fname=None)

Bases: object

Exception handler

Parameters:
  • full_cname (boolean) –

    Flag that indicates whether fully qualified function/method/class property names are obtained for functions/methods/class properties that use the exception manager (True) or not (False).

    There is a performance penalty if the flag is True as the call stack needs to be traced

  • exclude (list of strings or None) – Module exclusion list. A particular callable in an otherwise fully qualified name is omitted if it belongs to a module in this list. If None all callables are included
  • callables_fname (FileNameExists or None) – File name that contains traced modules information. File can be produced by either the putil.pinspect.Callables.save() or putil.exh.ExHandle.save_callables() methods
Return type:

putil.exh.ExHandle

Raises:
  • OSError (File [callables_fname] could not be found
  • RuntimeError (Argument `exclude` is not valid)
  • RuntimeError (Argument `callables_fname` is not valid)
  • RuntimeError (Argument `full_cname` is not valid)
  • ValueError (Source for module [module_name] could not be found)
__add__(other)

Merges two objects.

Raises:
  • RuntimeError (Incompatible exception handlers)
  • TypeError (Unsupported operand type(s) for +: putil.exh.ExHandle and [other_type])

For example:

>>> import copy, putil.exh, putil.eng, putil.tree
>>> exhobj = putil.exh.set_exh_obj(putil.exh.ExHandle())
>>> putil.eng.peng(100, 3, True)
' 100.000 '
>>> tobj = putil.tree.Tree().add_nodes([{'name':'a', 'data':5}])
>>> obj1 = copy.copy(putil.exh.get_exh_obj())
>>> putil.exh.del_exh_obj()
>>> exhobj = putil.exh.get_or_create_exh_obj()
>>> putil.eng.peng(100, 3, True) # Trace some exceptions
' 100.000 '
>>> obj2 = copy.copy(putil.exh.get_exh_obj())
>>> putil.exh.del_exh_obj()
>>> exhobj = putil.exh.get_or_create_exh_obj()
>>> tobj = putil.tree.Tree().add_nodes([{'name':'a', 'data':5}])
>>> obj3 = copy.copy(putil.exh.get_exh_obj())
>>> obj1 == obj2
False
>>> obj1 == obj3
False
>>> obj1 == obj2+obj3
True
__bool__()

Returns False if exception handler does not have any exception defined, True otherwise.

Note

This method applies to Python 3.x

For example:

>>> from __future__ import print_function
>>> import putil.exh
>>> obj = putil.exh.ExHandle()
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: False
>>> def my_func(exhobj):
...     exhobj.add_exception('test', RuntimeError, 'Message')
>>> my_func(obj)
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: True
__copy__()

Copies object. For example:

>>> import copy, putil.exh, putil.eng
>>> exhobj = putil.exh.set_exh_obj(putil.exh.ExHandle())
>>> putil.eng.peng(100, 3, True)
' 100.000 '
>>> obj1 = putil.exh.get_exh_obj()
>>> obj2 = copy.copy(obj1)
>>> obj1 == obj2
True
__eq__(other)

Tests object equality. For example:

>>> import copy, putil.exh, putil.eng
>>> exhobj = putil.exh.set_exh_obj(putil.exh.ExHandle())
>>> putil.eng.peng(100, 3, True)
' 100.000 '
>>> obj1 = putil.exh.get_exh_obj()
>>> obj2 = copy.copy(obj1)
>>> obj1 == obj2
True
>>> 5 == obj1
False
__iadd__(other)

Merges an object into an existing object.

Raises:
  • RuntimeError (Incompatible exception handlers)
  • TypeError (Unsupported operand type(s) for +: putil.exh.ExHandle and [other_type])

For example:

>>> import copy, putil.exh, putil.eng, putil.tree
>>> exhobj = putil.exh.set_exh_obj(putil.exh.ExHandle())
>>> putil.eng.peng(100, 3, True)
' 100.000 '
>>> tobj = putil.tree.Tree().add_nodes([{'name':'a', 'data':5}])
>>> obj1 = copy.copy(putil.exh.get_exh_obj())
>>> putil.exh.del_exh_obj()
>>> exhobj = putil.exh.get_or_create_exh_obj()
>>> putil.eng.peng(100, 3, True) # Trace some exceptions
' 100.000 '
>>> obj2 = copy.copy(putil.exh.get_exh_obj())
>>> putil.exh.del_exh_obj()
>>> exhobj = putil.exh.get_or_create_exh_obj()
>>> tobj = putil.tree.Tree().add_nodes([{'name':'a', 'data':5}])
>>> obj3 = copy.copy(putil.exh.get_exh_obj())
>>> obj1 == obj2
False
>>> obj1 == obj3
False
>>> obj2 += obj3
>>> obj1 == obj2
True
__nonzero__()

Returns False if exception handler does not have any exception defined, True otherwise.

Note

This method applies to Python 2.7

For example:

>>> from __future__ import print_function
>>> import putil.exh
>>> obj = putil.exh.ExHandle()
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: False
>>> def my_func(exhobj):
...     exhobj.add_exception('test', RuntimeError, 'Message')
>>> my_func(obj)
>>> if obj:
...     print('Boolean test returned: True')
... else:
...     print('Boolean test returned: False')
Boolean test returned: True
__str__()

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

>>> from __future__ import print_function
>>> import docs.support.exh_example
>>> putil.exh.del_exh_obj()
>>> docs.support.exh_example.my_func('Tom')
My name is Tom
>>> print(str(putil.exh.get_exh_obj())) 
Name    : ...
Type    : TypeError
Message : Argument `name` is not valid
Function: None
add_exception(exname, extype, exmsg)

Adds an exception to the handler

Parameters:
  • exname (non-numeric string) – Exception name; has to be unique within the namespace, duplicates are eliminated
  • extype (Exception type object, i.e. RuntimeError, TypeError, etc.) –

    Exception type; must be derived from the Exception class

  • exmsg (string) – Exception message; it can contain fields to be replaced when the exception is raised via putil.exh.ExHandle.raise_exception_if(). A field starts with the characters '*[' and ends with the characters ']*', the field name follows the same rules as variable names and is between these two sets of characters. For example, '*[fname]*' defines the fname field
Return type:

tuple

The returned tuple has the following items:

  • callable id (string) first returned item, identification (as reported by the id built-in function) of the callable where the exception was added
  • exception definition (tuple), second returned item, first item is the exception type and the second item is the exception message
  • callable name (string), third returned item, callable full name (encoded with the ExHandle.encode_call() method
Raises:
  • RuntimeError (Argument `exmsg` is not valid)
  • RuntimeError (Argument `exname` is not valid)
  • RuntimeError (Argument `extype` is not valid)
decode_call(call)

Replaces callable tokens with callable names

Parameters:call (string) – Encoded callable name
Return type:string
encode_call(call)

Replaces callables with tokens to reduce object memory footprint. A callable token is an integer that denotes the order in which the callable was encountered by the encoder, i.e. the first callable encoded is assigned token 0, the second callable encoded is assigned token 1, etc.

Parameters:call (string) – Callable name
Return type:string
raise_exception_if(exname, condition, edata=None)

Raises exception conditionally

Parameters:
  • exname (string) – Exception name
  • condition (boolean) – Flag that indicates whether the exception is raised (True) or not (False)
  • edata (dictionary, iterable of dictionaries or None) –

    Replacement values for fields in the exception message (see putil.exh.ExHandle.add_exception() for how to define fields). Each dictionary entry can only have these two keys:

    • field (string) – Field name
    • value (any) – Field value, to be converted into a string with the format string method

    If None no field replacement is done

Raises:
  • RuntimeError (Argument `condition` is not valid)
  • RuntimeError (Argument `edata` is not valid)
  • RuntimeError (Argument `exname` is not valid)
  • RuntimeError (Field [field_name] not in exception message)
  • ValueError (Exception name [name] not found’)
save_callables(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 `callables_fname` is not valid)
callables_db

Returns the callables database of the modules using the exception handler, as reported by putil.pinspect.Callables.callables_db()

callables_separator

Returns the character ('/') used to separate the sub-parts of fully qualified function names in putil.exh.ExHandle.callables_db() and name key in putil.exh.ExHandle.exceptions_db()

exceptions_db

Returns the exceptions database. This database is a list of dictionaries that contain the following keys:

  • name (string) – Exception name of the form '[callable_identifier]/[exception_name]'. The contents of [callable_identifier] depend on the value of the argument full_cname used to create the exception handler.

    If full_cname is True, [callable_identifier] is the fully qualified callable name as it appears in the callables database (putil.exh.ExHandle.callables_db()).

    If full_cname is False, then [callable_identifier] is a decimal string representation of the callable’s code identifier as reported by the id() function.

    In either case [exception_name] is the name of the exception provided when it was defined in putil.exh.ExHandle.add_exception() (exname argument)

  • data (string) – Text of the form '[exception_type] ([exception_message])[raised]' where [exception_type] and [exception_message] are the exception type and exception message, respectively, given when the exception was defined by putil.exh.ExHandle.add_exception() (extype and exmsg arguments); and raised is an asterisk ('*') when the exception has been raised via putil.exh.ExHandle.raise_exception_if(), the empty string ('') otherwise