Source code for foundations.library

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
**library.py**

**Platform:**
	Windows, Linux, Mac Os X.

**Description:**
	This module provides objects for C / C++ libraries binding.

**Others:**

"""

#**********************************************************************************************************************
#***	External imports.
#**********************************************************************************************************************
import ctypes
import os
import platform

#**********************************************************************************************************************
#***	Internal imports.
#**********************************************************************************************************************
import foundations.common
import foundations.dataStructures
import foundations.exceptions
import foundations.verbose

#**********************************************************************************************************************
#***	Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2013 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "thomas.mansencal@gmail.com"
__status__ = "Production"

__all__ = ["LOGGER", "LibraryHook", "Library"]

LOGGER = foundations.verbose.installLogger()

#**********************************************************************************************************************
#***	Module classes and definitions.
#**********************************************************************************************************************
[docs]class LibraryHook(foundations.dataStructures.Structure): """ This class represents a library hook used by the :class:`Library` class to bind target library functions. """ def __init__(self, **kwargs): """ .. Sphinx: Statements updated for auto-documentation purpose. Usage:: LibraryHook(name="FreeImage_GetVersion", argumentsTypes=None, returnValue=ctypes.c_char_p) :param name: Name of the target library function to bind. ( String ) :param argumentsTypes: Required function arguments type (Refer to Python `ctypes - 15.17.1.7 <http://docs.python.org/library/ctypes.html#specifying-the-required-argument-types-function-prototypes>`_ module for more informations). ( List ) :param returnValue: Function return type (Refer to Python `ctypes - 15.17.1.8 <http://docs.python.org/library/ctypes.html#return-types>`_ module for more informations). ( Object ) """ LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__)) foundations.dataStructures.Structure.__init__(self, **kwargs)
[docs]class Library(object): """ | This class provides methods to bind a C / C++ Library. | The class is a singleton and will bind only one time a given library. Each unique library instance is stored in :attr:`Library.instances` attribute and get returned if the library is requested again through a new instantiation. """ __instances = {} """Libraries instances: Each library is instanced once and stored in this attribute. ( Dictionary )""" callback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_int, ctypes.c_char_p) """callback: Defines library callback default function. ( ctypes.CFUNCTYPE )""" #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.LibraryInstantiationError) def __new__(cls, *args, **kwargs): """ This method is the constructor of the class. :param \*args: Arguments. ( \* ) :param \*\*kwargs: Keywords arguments. ( \*\* ) :return: Class instance. ( Library ) """ path = foundations.common.getFirstItem(args) if foundations.common.pathExists(path): if not path in cls._Library__instances: cls._Library__instances[path] = object.__new__(cls) return cls._Library__instances[path] else: raise foundations.exceptions.LibraryInstantiationError( "{0} | '{1}' library path doesn't exists!".format(cls.__class__.__name__, path)) #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.LibraryInitializationError) def __init__(self, path, functions=None, bindLibrary=True): """ .. Sphinx: Statements updated for auto-documentation purpose. Usage:: >>> path = "FreeImage.dll" >>> functions = (LibraryHook(name="FreeImage_GetVersion", argumentsTypes=None, returnValue=ctypes.c_char_p),) >>> library = Library(path, functions) >>> library.FreeImage_GetVersion() 3.13.1 :param path: Library path. ( String ) :param functions: Binding functions list. ( Tuple ) :param bindLibrary: Library will be binded on initialization. ( Boolean ) """ if hasattr(self.instances[path], "_Library__initialized"): return LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__)) # --- Setting class attributes. --- self.__initialized = True self.__path = None self.path = path self.__functions = None self.functions = functions self.__library = None if platform.system() == "Windows" or platform.system() == "Microsoft": loadingFunction = ctypes.windll else: loadingFunction = ctypes.cdll if self.path: self.__library = loadingFunction.LoadLibrary(path) else: raise foundations.exceptions.LibraryInitializationError("{0} | '{1}' library not found!".format( self.__class__.__name__, path)) bindLibrary and self.bindLibrary() #****************************************************************************************************************** #*** Attributes properties. #****************************************************************************************************************** @property def instances(self): """ This method is the property for **self.__instances** attribute. :return: self.__instances. ( WeakValueDictionary ) """ return self.__instances @instances.setter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def instances(self, value): """ This method is the setter method for **self.__instances** attribute. :param value: Attribute value. ( WeakValueDictionary ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "instances")) @instances.deleter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def instances(self): """ This method is the deleter method for **self.__instances** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "instances"))
@property def initialized(self): """ This method is the property for **self.__initialized** attribute. :return: self.__initialized. ( String ) """ return self.__initialized @initialized.setter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def initialized(self, value): """ This method is the setter method for **self.__initialized** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "initialized")) @initialized.deleter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def initialized(self): """ This method is the deleter method for **self.__initialized** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "initialized"))
@property def path(self): """ This method is the property for **self.__path** attribute. :return: self.__path. ( String ) """ return self.__path @path.setter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(AssertionError) def path(self, value): """ This method is the setter method for **self.__path** attribute. :param value: Attribute value. ( String ) """ if value is not None: assert type(value) in (str, unicode), "'{0}' attribute: '{1}' type is not 'str' or 'unicode'!".format( "path", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("path", value) self.__path = value @path.deleter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def path(self): """ This method is the deleter method for **self.__path** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "path"))
@property def functions(self): """ This method is the property for **self.__functions** attribute. :return: self.__functions. ( Tuple ) """ return self.__functions @functions.setter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(AssertionError) def functions(self, value): """ This method is the setter method for **self.__functions** attribute. :param value: Attribute value. ( Tuple ) """ if value is not None: assert type(value) is tuple, "'{0}' attribute: '{1}' type is not 'tuple'!".format("functions", value) for element in value: assert type(element) is LibraryHook, "'{0}' attribute: '{1}' type is not 'LibraryHook'!".format( "functions", element) self.__functions = value @functions.deleter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def functions(self): """ This method is the deleter method for **self.__functions** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "functions"))
@property def library(self): """ This method is the property for **self.__library** attribute. :return: self.__library. ( Object ) """ return self.__library @library.setter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(AssertionError) def library(self, value): """ This method is the setter method for **self.__library** attribute. :param value: Attribute value. ( Object ) """ self.__library = value @library.deleter #*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def library(self): """ This method is the deleter method for **self.__library** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "library")) #****************************************************************************************************************** #*** Class methods. #******************************************************************************************************************
[docs] def bindFunction(self, function): """ This method binds given function to a class object attribute. Usage:: >>> path = "FreeImage.dll" >>> function = LibraryHook(name="FreeImage_GetVersion", argumentsTypes=None, returnValue=ctypes.c_char_p) >>> library = Library(path, bindLibrary=False) >>> library.bindFunction(function) True >>> library.FreeImage_GetVersion() 3.13.1 :param function: Function to bind. ( LibraryHook ) :return: Method success. ( Boolean ) """ LOGGER.debug("> Binding '{0}' library '{1}' function.".format(self.__class__.__name__, function.name)) functionObject = getattr(self.__library, function.name) setattr(self, function.name, functionObject) if function.argumentsTypes: functionObject.argtypes = function.argumentsTypes if function.returnValue: functionObject.restype = function.returnValue return True
[docs] def bindLibrary(self): """ This method binds the Library using functions registered in the **self.__functions** attribute. Usage:: >>> path = "FreeImage.dll" >>> functions = (LibraryHook(name="FreeImage_GetVersion", argumentsTypes=None, returnValue=ctypes.c_char_p),) >>> library = Library(path, functions, bindLibrary=False) >>> library.bindLibrary() True >>> library.FreeImage_GetVersion() 3.13.1 :return: Method success. ( Boolean ) """ if self.__functions: for function in self.__functions: self.bindFunction(function) return True