loader.py 4.04 KB
Newer Older
André Anjos's avatar
André Anjos committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

###############################################################################
#                                                                             #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/           #
# Contact: beat.support@idiap.ch                                              #
#                                                                             #
# This file is part of the beat.backend.python module of the BEAT platform.   #
#                                                                             #
# Commercial License Usage                                                    #
# Licensees holding valid commercial BEAT licenses may use this file in       #
# accordance with the terms contained in a written agreement between you      #
# and Idiap. For further information contact tto@idiap.ch                     #
#                                                                             #
# Alternatively, this file may be used under the terms of the GNU Affero      #
# Public License version 3 as published by the Free Software and appearing    #
# in the file LICENSE.AGPL included in the packaging of this file.            #
# The BEAT platform is distributed in the hope that it will be useful, but    #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  #
# or FITNESS FOR A PARTICULAR PURPOSE.                                        #
#                                                                             #
# You should have received a copy of the GNU Affero Public License along      #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/.           #
#                                                                             #
###############################################################################


'''Implements a simple loader for Python code'''

import os
import sys
import six
import imp


def load_module(name, path, uses):
Philip ABBET's avatar
Philip ABBET committed
38
    '''Loads the Python file as module, returns  a proper Python module
André Anjos's avatar
André Anjos committed
39 40


Philip ABBET's avatar
Philip ABBET committed
41
    Parameters:
André Anjos's avatar
André Anjos committed
42

Philip ABBET's avatar
Philip ABBET committed
43 44
      name (str): The name of the Python module to create. Must be a valid Python
        symbol name
André Anjos's avatar
André Anjos committed
45

Philip ABBET's avatar
Philip ABBET committed
46 47
      path (str): The full path of the Python file to load the module contents
        from
André Anjos's avatar
André Anjos committed
48

Philip ABBET's avatar
Philip ABBET committed
49 50 51
      uses (dict): A mapping which indicates the name of the library to load (as
        a module for the current library) and the full-path and use mappings of
        such modules.
André Anjos's avatar
André Anjos committed
52 53


Philip ABBET's avatar
Philip ABBET committed
54
    Returns:
André Anjos's avatar
André Anjos committed
55

Philip ABBET's avatar
Philip ABBET committed
56
      module: A valid Python module you can use in an Algorithm or Library.
André Anjos's avatar
André Anjos committed
57

Philip ABBET's avatar
Philip ABBET committed
58
    '''
André Anjos's avatar
André Anjos committed
59

Philip ABBET's avatar
Philip ABBET committed
60
    retval = imp.new_module(name)
André Anjos's avatar
André Anjos committed
61

Philip ABBET's avatar
Philip ABBET committed
62 63 64
    #loads used modules
    for k, v in uses.items():
        retval.__dict__[k] = load_module(k, v['path'], v['uses'])
André Anjos's avatar
André Anjos committed
65

Philip ABBET's avatar
Philip ABBET committed
66 67
    #execute the module code on the context of previously import modules
    exec(compile(open(path, "rb").read(), path, 'exec'), retval.__dict__)
André Anjos's avatar
André Anjos committed
68

Philip ABBET's avatar
Philip ABBET committed
69
    return retval
André Anjos's avatar
André Anjos committed
70 71


72 73 74
#----------------------------------------------------------


André Anjos's avatar
André Anjos committed
75
def run(obj, method, exc=None, *args, **kwargs):
Philip ABBET's avatar
Philip ABBET committed
76
    '''Runs a method on the object and protects its execution
André Anjos's avatar
André Anjos committed
77

Philip ABBET's avatar
Philip ABBET committed
78 79
    In case an exception is raised, it is caught and transformed into the
    exception class the user passed.
André Anjos's avatar
André Anjos committed
80

Philip ABBET's avatar
Philip ABBET committed
81
    Parameters:
André Anjos's avatar
André Anjos committed
82

Philip ABBET's avatar
Philip ABBET committed
83
      obj (object): The python object in which execute the method
André Anjos's avatar
André Anjos committed
84

Philip ABBET's avatar
Philip ABBET committed
85
      method (str): The method name to execute on the object
André Anjos's avatar
André Anjos committed
86

Philip ABBET's avatar
Philip ABBET committed
87 88 89
      exc (class, optional): The class to use as base exception when translating
        the exception from the user code. If you set it to ``None``, then just
        re-throws the user raised exception.
André Anjos's avatar
André Anjos committed
90

Philip ABBET's avatar
Philip ABBET committed
91
      *args: Arguments to the object method, passed unchanged
André Anjos's avatar
André Anjos committed
92

Philip ABBET's avatar
Philip ABBET committed
93
      **kwargs: Arguments to the object method, passed unchanged
André Anjos's avatar
André Anjos committed
94

Philip ABBET's avatar
Philip ABBET committed
95
    Returns:
André Anjos's avatar
André Anjos committed
96

Philip ABBET's avatar
Philip ABBET committed
97
      object: whatever ``obj.method()`` is bound to return.
André Anjos's avatar
André Anjos committed
98

Philip ABBET's avatar
Philip ABBET committed
99
    '''
André Anjos's avatar
André Anjos committed
100

Philip ABBET's avatar
Philip ABBET committed
101
    try:
102 103 104
        if method == '__new__':
            return obj(*args, **kwargs)

Philip ABBET's avatar
Philip ABBET committed
105 106 107 108 109 110 111
        return getattr(obj, method)(*args, **kwargs)
    except Exception as e:
        if exc is not None:
            type, value, traceback = sys.exc_info()
            six.reraise(exc, exc(value), traceback)
        else:
            raise #just re-raise the user exception