preconditions()   B
last analyzed

Complexity

Conditions 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 0
loc 31
rs 8.5806
1
2
# :version:      0.1.0
3
# :copyright:    Copyright (C) 2014 Universidad Carlos III de Madrid.
4
#                Todos los derechos reservados.
5
# :license       LASR_UC3M v1.0, ver LICENCIA.txt
6
7
# Este programa es software libre: puede redistribuirlo y/o modificarlo
8
# bajo los terminos de la Licencia Academica Social Robotics Lab - UC3M
9
# publicada por la Universidad Carlos III de Madrid, tanto en su version 1.0
10
# como en una version posterior.
11
12
# Este programa se distribuye con la intencion de que sea util,
13
# pero SIN NINGUNA GARANTIA. Para mas detalles, consulte la
14
# Licencia Academica Social Robotics Lab - UC3M version 1.0 o posterior.
15
16
# Usted ha recibido una copia de la Licencia Academica Social
17
# Robotics Lab - UC3M en el fichero LICENCIA.txt, que tambien se encuentra
18
# disponible en <URL a la LASR_UC3Mv1.0>.
19
20
21
"""
22
Utils to ease the use of functions and methods in Python.
23
24
:author: Victor Gonzalez Pacheco (victor.gonzalez.pacheco at gmail.com)
25
:date: 2014-04
26
"""
27
28
from functools import wraps
29
from contextlib import contextmanager
30
31
32
class PreconditionError(Exception):
33
34
    """
35
    Exception that shuold be raised when the preconditions of a function
36
    are not met
37
    """
38
    pass
39
40
41
@contextmanager
42
def error_handler(logger=None, log_msg='',
43
                  action=None, action_args=None, action_kwargs=None,
44
                  errors=Exception, reraise=False):
45
    """
46
    Context Manager that logs errors and executes an action if error occurs.
47
48
    :param logger: logging function. Default: None
49
    :type logger: callable
50
    :param log_msg: message to add to the logger in case of fail
51
                    (It will be preced to the exception message)
52
    :type log_msg: str
53
    :param action: function to call if an exception occurs. Default: None
54
    :type action: callable
55
    :param action_args: argument list to pass to action. Default:[]
56
    :param action_kwargs: argument keywords to pass to action. Default: {}
57
    :param errors: exceptions to catch. Default: Exception
58
    :type errors: Exception or a list of Exceptions
59
    :param reraise: (default: False) Wether to reraise precondition errors
60
    """
61
    try:
62
        yield
63
    except errors as e:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
64
        exception_msg = ''.join([log_msg, str(e)])
65
        if logger:
66
            logger(str(exception_msg))
67
        if action:
68
            action(*action_args, **action_kwargs)
69
        if reraise:
70
            raise e
71
72
73
def preconditions(precons, logger=None, log_msg='', errors=PreconditionError,
74
                  reraise=True):
75
    """
76
    Decorator that binds precondition checking to a function.
77
78
    :param precons: Preconditions to check
79
                    Must be a function with same attribs as decorated func
80
    :type precons: callable
81
    :param logger: Logger function executed in case of precons fail
82
                   Default: None
83
    :param log_msg: Message to add to the logger in case of fail
84
                    (It will be preced to the exception message)
85
                    Default: ''
86
    :type log_msg: str
87
    :param errors: Exceptions to catch in preconditions.
88
                   Default: L{PreconditionError}
89
    :type errors: Exception or a list of Exceptions
90
    :param reraise: (default: True) Wether to reraise precondition errors
91
92
    :return: None if reraise is false and preconditions do not pass
93
    """
94
    def decor(f):
95
        @wraps(f)
96
        def wrapper(*args, **kwargs):
97
            with error_handler(logger=logger, log_msg=log_msg,
98
                               errors=errors, reraise=reraise):
99
                precons(*args, **kwargs)
100
                return f(*args, **kwargs)
101
            return None  # Arrives here only if reraises=False and precons fail
102
        return wrapper
103
    return decor
104
105
106
def load_class(full_name):
107
    """
108
    Returns an builder of a Python class from its qualified full name.
109
    To build the object of that class, simply call the returned object.
110
111
    Adapted from this SO Answer: http://stackoverflow.com/a/547867/630598
112
113
    :type full_name: string
114
    :param full_name: Class full name: foo.bar.klass
115
    :return: an instance of foo.bar.Klass. It has to be called just
116
117
    Example:
118
119
        >>> # Assume Klass is declared in module foo.bar
120
        >>> class Klass():
121
        >>>    def __init__(self):
122
        >>>         print('klass instantiated')
123
124
        >>> my_class = load_class('foo.bar.Klass')
125
        >>> my_class()
126
        ... 'klass instantiated'
127
    """
128
    module_name, klass_name = full_name.rsplit('.', 1)
129
    mod = __import__(module_name, fromlist=[klass_name])
130
    klass = getattr(mod, klass_name)
131
    return klass
132