Source code for minkit

########################################
# MIT License
#
# Copyright (c) 2020 Miguel Ramos Pernas
########################################
from .base.core import get_exposed_package_objects
from .backends import core as backends_core
from .backends import aop

import inspect
import os

PACKAGE_PATH = os.path.dirname(os.path.abspath(__file__))

__all__ = ['Backend']

minkit_api = get_exposed_package_objects(PACKAGE_PATH)

globals().update(minkit_api)

__all__ += list(minkit_api.keys())

__all__.sort()


[docs]class Backend(object): _exposed_objects = tuple(n for n, c in minkit_api.items( ) if inspect.isclass(c)) # loading all the classes def __init__(self, btype=backends_core.CPU, **kwargs): ''' Object used in order to do operations with objects of the :mod:`minkit` module. Any object depending on a backend can be directly built using this class, which will forward itself during its construction. :param btype: backend type ('cpu', 'cuda', 'opencl'). :type btype: str :param kwargs: arguments forwarded to the backend constructor \ (cuda and opencl backends only). See below for more details. :type kwargs: dict The keyword arguments can contain any of the following: * device * interactive These arguments are only available in *cuda* and *opencl* backends only. ''' super(Backend, self).__init__() self.__btype = btype.lower() self.__aop = aop.ArrayOperations(self, **kwargs) for n in Backend._exposed_objects: setattr(self, n, object_wrapper(minkit_api[n], self)) @property def aop(self): ''' Object to do operations on arrays. :type: ArrayOperations ''' return self.__aop @property def btype(self): ''' Backend type. :type: str ''' return self.__btype
class object_wrapper(object): def __init__(self, cls, backend): ''' Object to wrap the members of other objects so the backend is always set to that provided to this class. :param cls: class to wrap. :type cls: class :param backend: backend to use when calling the members. :type backend: Backend ''' super(object_wrapper, self).__init__() self._cls = cls self._backend = backend def __call_wrapper(self, func): ''' ''' if 'backend' in inspect.getfullargspec(func).args: def wrapper(*args, **kwargs): return func(*args, backend=self._backend, **kwargs) else: def wrapper(*args, **kwargs): return func(*args, **kwargs) wrapper.__name__ = func.__name__ wrapper.__doc__ = f''' Wrapper around the "{func.__name__}" function, which automatically sets the backend. ''' return wrapper def __call__(self, *args, **kwargs): ''' Initialize the wrapped class. :param args: arguments forwarded to the __init__ function. :type args: tuple :param kwargs: arguments forwarded to the __init__ function. :type kwargs: dict :returns: Wrapped object. ''' return self.__call_wrapper(self._cls)(*args, **kwargs) def __getattr__(self, name): ''' Get the given member of the object. :param name: name of the member. :type name: str :returns: Wrapped function. :rtype: function ''' return self.__call_wrapper(getattr(self._cls, name)) def __repr__(self): ''' Represent this class as a string. :returns: This class as a string. :rtype: str ''' return f'object_wrapper({self._cls.__name__})' # Determine the default backend DEFAULT_BACKEND_TYPE = os.environ.get( 'MINKIT_BACKEND', backends_core.CPU).lower() if DEFAULT_BACKEND_TYPE == backends_core.CPU: DEFAULT_BACKEND = Backend(DEFAULT_BACKEND_TYPE) else: dev = os.environ.get('MINKIT_DEVICE', 0) itv = os.environ.get('MINKIT_INTERACTIVE', True) DEFAULT_BACKEND = Backend(DEFAULT_BACKEND_TYPE, device=dev, interactive=itv) backends_core.set_default_aop(DEFAULT_BACKEND.aop)