source: TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/utils/factory.py @ 6570

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/utils/factory.py@6570
Revision 6570, 4.8 KB checked in by pjkersha, 11 years ago (diff)
  • Refactored classfactory module as a more generic factory for importing any module object
  • Started unit tests with refactored SAML SOAP bindings.
Line 
1"""
2Class Factory
3
4NERC DataGrid project
5"""
6__author__ = "C Byrom - Tessella"
7__date__ = "28/08/08"
8__copyright__ = "(C) 2009 Science and Technology Facilities Council"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = '$Id: $'
12import traceback
13import logging, os, sys
14log = logging.getLogger(__name__)
15
16
17def importModuleObject(moduleName, objectName=None, objectType=None):
18    '''Import from a string module name and object name.  Object can be
19    any entity contained in a module
20   
21    @param moduleName: Name of module containing the class
22    @type moduleName: str
23    @param className: Name of the class to import.  If none is given, the
24    class name will be assumed to be the last component of modulePath
25    @type className: str
26    @rtype: class object
27    @return: imported class'''
28   
29    if className is None:
30        _moduleName, className = moduleName.rsplit('.', 1)
31    else:
32        _moduleName = moduleName
33   
34    log.debug("Importing %r ..." % className) 
35     
36    module = __import__(_moduleName, globals(), locals(), [])
37    components = _moduleName.split('.')
38    try:
39        for component in components[1:]:
40            module = getattr(module, component)
41    except AttributeError, e:
42        raise AttributeError("Error importing %r: %s" %
43                             (className, traceback.format_exc()))
44
45    importedObject = getattr(module, className)
46
47    # Check class inherits from a base class
48    if objectType and not issubclass(importedObject, objectType):
49        raise TypeError("Specified class %r must be derived from %r; got %r" %
50                        (className, objectType, importedObject))
51   
52    log.info('Imported %r from module, %r', className, _moduleName)
53    return importedObject
54
55
56def callModuleObject(moduleName, className=None, moduleFilePath=None, 
57                     objectType=None, objectArgs=(), objectProperties={}):
58    '''
59    Create and return an instance of the specified class or invoke callable
60    @param moduleName: Name of module containing the class
61    @type moduleName: str
62    @param className: Name of the class to instantiate.  May be None in
63    which case, the class name is parsed from the moduleName last element
64    @type className: str
65    @param moduleFilePath: Path to the module - if unset, assume module on
66    system path already
67    @type moduleFilePath: str
68    @param objectProperties: dict of properties to use when instantiating the
69    class
70    @type objectProperties: dict
71    @param objectType: expected type for the object to instantiate - to
72    enforce use of specific interfaces
73    @type objectType: object
74    @return: object - instance of the class specified
75    '''
76
77   
78    # ensure that properties is a dict - NB, it may be passed in as a null
79    # value which can override the default val
80    if not objectProperties:
81        objectProperties = {}
82
83    # variable to store original state of the system path
84    sysPathBak = None
85    try:
86        try:
87            # Module file path may be None if the new module to be loaded
88            # can be found in the existing system path           
89            if moduleFilePath:
90                if not os.path.exists(moduleFilePath):
91                    raise IOError("Module file path '%s' doesn't exist" % 
92                                  moduleFilePath)
93                         
94                # Temporarily extend system path ready for import
95                sysPathBak = sys.path
96                         
97                sys.path.append(moduleFilePath)
98
99           
100            # Import module name specified in properties file
101            importedObject = importModuleObject(moduleName, 
102                                                objectName=objectName,
103                                                objectType=objectType)
104        finally:
105            # revert back to original sys path, if necessary
106            # NB, python requires the use of a try/finally OR a try/except
107            # block - not both combined
108            if sysPathBak:
109                sys.path = sysPathBak
110                           
111    except Exception, e:
112        log.error('%r module import raised %r type exception: %r' % 
113                  (moduleName, e.__class__, traceback.format_exc()))
114        raise 
115
116    # Instantiate class
117    log.debug('Instantiating object "%s"' % importedObject.__name__)
118    try:
119        if objectArgs:
120            object = importedObject(*objectArgs, **objectProperties)
121        else:
122            object = importedObject(**objectProperties)
123           
124        return object
125
126    except Exception, e:
127        log.error("Instantiating module object, %r: %r" % 
128                                                    (importedObject.__name__, 
129                                                     traceback.format_exc()))
130        raise
Note: See TracBrowser for help on using the repository browser.