Source code for bredala.decorations

##########################################################################
# Bredala - Copyright (C) AGrigis, 2015
# Distributed under the terms of the CeCILL-B license, as published by
# the CEA-CNRS-INRIA. Refer to the LICENSE file or to
# http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
# for details.
##########################################################################

"""
Module that sets the package decoration functions dynamically.
"""


# System import
import sys
import inspect
import types

# Bredala import
import bredala


[docs]class Decorations(object): """ A class that decorate a module functions based on the factory, ie. the '_modules' mapping. """
[docs] def hack(self, module, name): """ Method invoked to transform the input module. Parameters ---------- module: object (mandatory) a python module object. name: str (mandatory) the name of the input module. Returns ------- decorated_module: object if a decorator has been registered for this module in the registery return the decorated input python module object, otherwise directly the input python module object. """ # If a decorator is decalred for the module apply it now decorators_struct = bredala._modules.get(name) if decorators_struct is not None: self.decorate(module, name, decorators_struct) return module
[docs] def decorate(self, module, name, decorators_struct): """ Method that decorates the registered function and class methods of a module. Parameters ---------- module: object (mandatory) a python module object. name: str (mandatory) the name of the input module. decorators_struct: dict of dict a dictionary with the functions/methods to be decorated as first keys, the decorator type as second keys and the decorator - decorator parameters as values. """ # Create a class mapping mapping = {} for filter_name in decorators_struct: kname, mname = Decorations.split_class(filter_name) mapping.setdefault(kname, []).append(mname) # Walk on all the module items for module_attr, module_object in module.__dict__.items(): # Function case if isinstance(module_object, types.FunctionType): if "ALL" in decorators_struct: key = "ALL" elif module_object.__name__ in decorators_struct: key = module_object.__name__ else: continue Decorations._decorate(module, module_attr, module_object, decorators_struct[key]) # Class case elif inspect.isclass(module_object): if "ALL" in mapping: allowed_methods = "ALL" elif module_object.__name__ in mapping: allowed_methods = mapping[module_object.__name__] else: continue if sys.version_info[:2] >= (3, 0): methods = inspect.getmembers( module_object, predicate=inspect.isfunction) else: methods = inspect.getmembers( module_object, predicate=inspect.ismethod) for method_name, method in methods: if allowed_methods == "ALL": decorator_struct = decorators_struct["ALL"] elif method_name in allowed_methods: decorator_struct = decorators_struct["{0}.{1}".format( module_object.__name__, method_name)] else: continue Decorations._decorate( module_object, method_name, method, decorator_struct, is_method=True)
@classmethod def _decorate(cls, module, module_attr, module_object, decorator_struct, is_method=False): """ Method that decorates a specific function or class method. Parameters ---------- module: object (mandatory) a python module object. module_attr: str (mandatory) the name of the mofule attribute to be decorated. module_object: object the function/method to be decorated. decorator_struct: dict a dictionary with the decorator types as keys and the decorator - decorator parameters as values. is_method: bool (optional, default False) True if the module object is a method of a class, False otherwise. """ # Get the declared type decorators type_decorators = [] for key in ("inputs", "outputs"): if key not in decorator_struct: continue decorator = decorator_struct[key]["decorator"] registered_types = decorator_struct[key]["types"] type_decorators.append((decorator, registered_types)) # Apply decorators if "signature" in decorator_struct: decorator = decorator_struct["signature"]["decorator"] setattr(module, module_attr, decorator( module_object, use_profiler=bredala.USE_PROFILER, is_method=is_method, type_decorators=type_decorators)) else: for decorator, registered_types in type_decorators: setattr(module, module_attr, decorator(*registered_types)(module_object)) module_object = getattr(module, module_attr) @classmethod
[docs] def split_class(cls, name): """ Split a module name. Parameters ---------- name: str (mandatory) a name describing a class or a class method: <klass> or <klass>.<method>. Returns ------- kname: str the class name. mname: str the associated module name. """ if "." in name: try: kname, mname = name.split(".") except: raise ValueError("'{0}' is not a valid name class or class " "method description.".format(name)) else: kname = name mname = None return kname, mname