[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r9937 - in trunk/gnue-common: src/apps src/base src/datasources s
From: |
reinhard |
Subject: |
[gnue] r9937 - in trunk/gnue-common: src/apps src/base src/datasources src/datasources/drivers/Base src/rpc src/utils utils/helpers |
Date: |
Tue, 6 Oct 2009 08:48:23 -0500 (CDT) |
Author: reinhard
Date: 2009-10-06 08:48:22 -0500 (Tue, 06 Oct 2009)
New Revision: 9937
Added:
trunk/gnue-common/src/base/plugin.py
Removed:
trunk/gnue-common/src/apps/plugin.py
trunk/gnue-common/src/utils/plugin.py
Modified:
trunk/gnue-common/src/datasources/GConnections.py
trunk/gnue-common/src/datasources/drivers/Base/Connection.py
trunk/gnue-common/src/rpc/client.py
trunk/gnue-common/src/rpc/server.py
trunk/gnue-common/utils/helpers/info.py
Log:
Some work on plugin loader library.
Deleted: trunk/gnue-common/src/apps/plugin.py
===================================================================
--- trunk/gnue-common/src/apps/plugin.py 2009-10-06 13:42:11 UTC (rev
9936)
+++ trunk/gnue-common/src/apps/plugin.py 2009-10-06 13:48:22 UTC (rev
9937)
@@ -1,29 +0,0 @@
-# GNU Enterprise Common Library - Plugin support
-#
-# This file is part of GNU Enterprise.
-#
-# GNU Enterprise is free software; you can redistribute it
-# and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
-# version 2, or (at your option) any later version.
-#
-# GNU Enterprise 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. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with program; see the file COPYING. If not,
-# write to the Free Software Foundation, Inc., 59 Temple Place
-# - Suite 330, Boston, MA 02111-1307, USA.
-#
-# Copyright 2001-2009 Free Software Foundation
-#
-# $Id$
-
-"""
-This module is *DEPRECATED*. Please use gnue.common.utils.plugin instead
-"""
-
-from gnue.common.utils.plugin import *
-
Copied: trunk/gnue-common/src/base/plugin.py (from rev 9928,
trunk/gnue-common/src/utils/plugin.py)
===================================================================
--- trunk/gnue-common/src/base/plugin.py (rev 0)
+++ trunk/gnue-common/src/base/plugin.py 2009-10-06 13:48:22 UTC (rev
9937)
@@ -0,0 +1,443 @@
+# GNU Enterprise Common Library - Plugin support
+#
+# Copyright 2001-2009 Free Software Foundation
+#
+# This file is part of GNU Enterprise.
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise 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. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+"""
+Functions to list and load avaliable plugins dynamically.
+
+Plugin handling in GNU Enterprise
+=================================
+
+Plugins are Python modules that implement a defined API and are loaded on
+demand. Usually, there are several plugins of the same type (that means they
+implement the same API) that can be used interchangeable. The user can select
+which plugin he wants to use.
+
+All plugins of a specific type must be Python modules in a defined package.
+For example, all database drivers must be modules in the
+gnue.common.datasources.drivers package.
+
+Any plugin must define a specific symbol (usually a class definition like
+LanguageAdapter, ClientAdapter or Connection) to qualify itself as valid.
+
+Any plugin must immediately check whether it is functional (especially whether
+all dependencies are installed), and import must fail with a meaningful
+exception otherwise. Optionally, a module can also define a function with the
+name __initplugin__ that initializes the module and raises an exception if the
+plugin cannot be initialized.
+
+Plugins can be organized in a tree structure. To load a plugin, any point in
+the tree may be specified. For example, consider there are three plugins named
+base.group.foo, base.group.bar and base.group.baz. "foo" will specify the foo
+plugin, as well as "group.foo". Loading the plugin "group" means to load the
+first available functional plugin in the group.
+
+Modules and packages located within the plugin tree but not being valid plugins
+can define a symbol with the name __noplugin__ to indicate that they are no
+valid plugin. Note that the module defining the __noplugin__ symbol is still
+imported, but no submodules of it. This is useful to exclude, for example,
+abstract base drivers.
+"""
+
+import os
+
+from types import ModuleType
+from gnue.common.base import errors
+
+__all__ = ['LoadError', 'list_plugins', 'find']
+
+# =============================================================================
+# Exceptions
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# Module loading error
+# -----------------------------------------------------------------------------
+
+class LoadError(errors.AdminError):
+ """
+ Indicates a failure to load a given module. Raised by L{find}.
+
+ If e is an Exception of this class, e.exceptions gives a dictionary with
+ the keys being the modules that were trying to be imported and the values
+ being the exception info tuples for the exception that happened trying, and
+ e.detail is a string containing basically the same info.
+ """
+ def __init__(self, name, exceptions):
+
+ self.name = name
+ self.exceptions = exceptions
+
+ if self.exceptions:
+ message = u_("Cannot load plugin '%s'") % self.name
+ detail = u_("The following plugins failed:\n")
+ for (name, exc) in self.exceptions.items():
+ detail += u"* %s: %s" % (name, exc)
+ else:
+ message = u_("Cannot find plugin '%s'") % self.name
+ detail = None
+
+ errors.AdminError.__init__(self, message)
+
+ if detail:
+ self.detail = detail
+
+
+# -----------------------------------------------------------------------------
+# List all available plugins
+# -----------------------------------------------------------------------------
+
+def list_plugins(base, identifier, try_to_init=True):
+ """
+ List all available plugins.
+
+ @param base: Name of the package that contains the plugins.
+ @param identifier: Identifier that a plugin must define to qualify as
+ module.
+ @param try_to_init: If set to False, __initplugin__ is not called.
+ @return: A dictionary with the available plugin module names as keys and
+ either the loaded module or the exception info tuple of the exception
+ raised when trying to import the module as values.
+ """
+ checktype(base, [basestring])
+ checktype(identifier, [basestring])
+
+ # Make sure everything is a string. Non-ASCII characters are not allowed in
+ # Python module names anyway.
+ _base = base.encode()
+ _identifier = identifier.encode()
+
+ # Now recursively list the plugins
+ return __list(_base, _identifier, try_to_init, True)
+
+
+# -----------------------------------------------------------------------------
+# Find a plugin
+# -----------------------------------------------------------------------------
+
+def find(name, base, identifier):
+ """
+ Find a plugin by name. If no plugin is functional, a LoadError is raised.
+
+ @param name: Name of the plugin to find. If the plugin is foo.bar, name
can
+ be bar, or foo.bar, or foo, where the last one returns the first
+ functional plugin in the foo group.
+ @param base: Name of the package that contains the plugins.
+ @param identifier: Identifier that a plugin must define to qualify as
+ module.
+ @return: The loaded module of the plugin.
+ """
+ checktype(name, [basestring])
+ checktype(base, [basestring])
+ checktype(identifier, [basestring])
+
+ # Make sure everything is a string. Non-ASCII characters are not allowed in
+ # Python module names anyway.
+ _name = name.encode()
+ _base = base.encode()
+ _identifier = identifier.encode()
+
+ # First, see if we've already found this module previously
+ try:
+ result = __FIND_CACHE[(_base, _name)]
+ except KeyError:
+ # If not, search for the plugin
+ __FIND_CACHE[(_base, _name)] = __find(_base, _name, _identifier)
+ result = __FIND_CACHE[(_base, _name)]
+
+ if isinstance(result, ModuleType):
+ return result
+ else:
+ raise LoadError, (name, result)
+
+
+# -----------------------------------------------------------------------------
+# A list of all previously failed modules
+# -----------------------------------------------------------------------------
+
+# This dictionary remembers all previous failure of module imports/inits. That
+# is necessary because module initialization code is only run at first import
+# attempt.
+__FAILED_CACHE = {}
+
+
+# -----------------------------------------------------------------------------
+# Mapping of previously found plugins
+# -----------------------------------------------------------------------------
+
+__FIND_CACHE = {}
+
+
+# -----------------------------------------------------------------------------
+# Find all modules and subpackages in a package
+# -----------------------------------------------------------------------------
+
+def __modules(package, want_packages):
+
+ # package.__file__ is a directory if GImportLogger is in use. This makes it
+ # necessary to 'simulate' a package, otherwise stepping down subpackages
+ # won't work.
+ if os.path.isdir(package.__file__):
+ (basedir, basefile) = (package.__file__, '__init__.py')
+ else:
+ (basedir, basefile) = os.path.split(package.__file__)
+
+ basename = os.path.splitext(basefile)[0]
+
+ if basename != '__init__':
+ # This is not a package, so no need to go deeper
+ return []
+
+ # Find all submodules
+ result = {}
+ for subfile in os.listdir(basedir):
+ (subname, subext) = os.path.splitext(subfile)
+ subpath = os.path.join(basedir, subfile)
+ # We are only interested in Python modules or packages
+ if (not want_packages and subext in ['.py', '.pyc', '.pyo'] and \
+ subname != '__init__') or \
+ (os.path.isdir(subpath) and \
+ os.path.isfile(os.path.join(subpath, '__init__.py')) or \
+ os.path.isfile(os.path.join(subpath, '__init__.pyc')) or \
+ os.path.isfile(os.path.join(subpath, '__init__.pyo'))):
+ result[subname] = True
+
+ return result.keys()
+
+
+# -----------------------------------------------------------------------------
+# Recursively list all plugins
+# -----------------------------------------------------------------------------
+
+def __list(base, identifier, try_to_init, top):
+
+ if __FAILED_CACHE.has_key(base):
+ # This has already failed in previous attempt
+ return {base: __FAILED_CACHE[base]}
+
+ try:
+ mod = __import__(base, None, None, '*')
+ except StandardError, e:
+ __FAILED_CACHE[base] = e
+ return {base: __FAILED_CACHE[base]}
+
+ if hasattr(mod, '__noplugin__'):
+ # This is not a plugin, ignore it
+ return {}
+
+ if not top:
+ if hasattr(mod, identifier):
+ # This is already a plugin, no need to go deeper
+ if try_to_init and hasattr(mod, '__initplugin__'):
+ try:
+ mod.__initplugin__()
+ except StandardError, e:
+ __FAILED_CACHE[base] = e
+ return {base: __FAILED_CACHE[base]}
+ return {base: mod}
+
+ # List all submodules
+ result = {}
+ for sub in __modules(mod, False):
+ result.update(__list(base + '.' + sub, identifier, try_to_init, False))
+ return result
+
+
+# -----------------------------------------------------------------------------
+# Recursively find first available plugin and return the module or a dictionary
+# with the exceptions that occured
+# -----------------------------------------------------------------------------
+
+def __first(base, identifier):
+
+ if __FAILED_CACHE.has_key(base):
+ # This has already failed in previous attempt
+ return {base: __FAILED_CACHE[base]}
+
+ try:
+ mod = __import__(base, None, None, '*')
+ except StandardError, e:
+ __FAILED_CACHE[base] = e
+ return {base: __FAILED_CACHE[base]}
+
+ if hasattr(mod, '__noplugin__'):
+ # This is not a plugin, ignore it
+ return {}
+
+ if hasattr(mod, identifier):
+ # This is already a plugin, no need to go deeper
+ if hasattr(mod, '__initplugin__'):
+ try:
+ mod.__initplugin__()
+ except StandardError, e:
+ __FAILED_CACHE[base] = e
+ return {base: __FAILED_CACHE[base]}
+ return mod
+
+ # Search all submodules
+ exceptions = {}
+ for sub in __modules(mod, False):
+ result = __first(base + '.' + sub, identifier)
+ if isinstance(result, ModuleType):
+ return result
+ exceptions.update(result)
+ return exceptions
+
+
+# -----------------------------------------------------------------------------
+# Recursively search for a plugin and return the module or the exceptions that
+# occured
+# -----------------------------------------------------------------------------
+
+def __find(base, name, identifier):
+
+ if __FAILED_CACHE.has_key(base):
+ # This has already failed in previous attempt
+ return {base: __FAILED_CACHE[base]}
+
+ try:
+ mod = __import__(base, None, None, '*')
+ except StandardError, e:
+ __FAILED_CACHE[base] = e
+ return {base: __FAILED_CACHE[base]}
+
+ if hasattr(mod, '__noplugin__'):
+ # This is not a plugin, ignore it
+ return {}
+
+ # Is the searched driver an alias of this module?
+ if hasattr(mod, '__pluginalias__'):
+ if name in mod.__pluginalias__:
+ return __first(base, identifier)
+
+ if __FAILED_CACHE.has_key(base + '.' + name):
+ # This has already failed in previous attempt
+ return {base + '.' + name: __FAILED_CACHE[base + '.' + name]}
+
+ try:
+ mod = __import__(base + '.' + name, None, None, '*')
+ except ImportError:
+ pass
+ except StandardError, e:
+ __FAILED_CACHE[base + '.' + name] = e
+ return {base + '.' + name: __FAILED_CACHE[base + '.' + name]}
+ else:
+ return __first(base + '.' + name, identifier)
+
+ # Search all submodules
+ exceptions = {}
+ for sub in __modules(mod, False):
+ result = __find(base + '.' + sub, name, identifier)
+ if isinstance(result, ModuleType):
+ return result
+ exceptions.update(result)
+
+ return exceptions
+
+
+# =============================================================================
+# Self test code
+# =============================================================================
+
+if __name__ == '__main__':
+
+ # -------------------------------------------------------------------------
+ # list_plugins
+ # -------------------------------------------------------------------------
+
+ def __test_list_plugins():
+
+ base = 'gnue.common.datasources.drivers'
+
+ for (iname, iresult) in (list_plugins(base, 'Connection')).items():
+ print iname[len(base)+1:] + ":",
+ if isinstance(iresult, ModuleType):
+ print "ok"
+ else:
+ print unicode(iresult)
+ print
+
+
+ # -------------------------------------------------------------------------
+ # find
+ # -------------------------------------------------------------------------
+
+ def __test_find():
+
+ base = 'gnue.common.datasources.drivers'
+
+ try:
+ print 'find "postgresql.psycopg2drv":',
+ fmod = find('postgresql.psycopg2drv', base, 'Connection')
+ print fmod.__name__
+ except LoadError, e:
+ print e
+ print "Detail:"
+ print o(e.detail)
+ print
+
+ try:
+ print 'find "pygresql":',
+ fmod = find('pygresql', base, 'Connection')
+ print fmod.__name__
+ except LoadError, e:
+ print e
+ print "Detail:"
+ print o(e.detail)
+ print
+
+ try:
+ print 'find "mysql":',
+ fmod = find('mysql', base, 'Connection')
+ print fmod.__name__
+ except LoadError, e:
+ print e
+ print "Detail:"
+ print o(e.detail)
+ print
+
+ try:
+ print 'find "oracle":',
+ fmod = find('oracle', base, 'Connection')
+ print fmod.__name__
+ except LoadError, e:
+ print e
+ print "Detail:"
+ print o(e.detail)
+ print
+
+ try:
+ print 'find "nonexistent":',
+ fmod = find('nonexistent', base, 'Connection')
+ print fmod.__name__
+ except LoadError, e:
+ print e
+ print "Detail:"
+ print o(e.detail)
+
+
+ # -------------------------------------------------------------------------
+ # Call all tests
+ # -------------------------------------------------------------------------
+
+ __test_list_plugins()
+ __test_find()
Modified: trunk/gnue-common/src/datasources/GConnections.py
===================================================================
--- trunk/gnue-common/src/datasources/GConnections.py 2009-10-06 13:42:11 UTC
(rev 9936)
+++ trunk/gnue-common/src/datasources/GConnections.py 2009-10-06 13:48:22 UTC
(rev 9937)
@@ -29,7 +29,8 @@
import copy, netrc
-from gnue.common.apps import plugin, errors, i18n
+from gnue.common.base import errors, plugin
+from gnue.common.apps import i18n
from gnue.common.utils.FileUtils import openResource, dyn_import
from gnue.common.datasources import Exceptions, GLoginHandler
Modified: trunk/gnue-common/src/datasources/drivers/Base/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/Base/Connection.py
2009-10-06 13:42:11 UTC (rev 9936)
+++ trunk/gnue-common/src/datasources/drivers/Base/Connection.py
2009-10-06 13:48:22 UTC (rev 9937)
@@ -27,8 +27,7 @@
__all__ = ['Connection']
-from gnue.common.base import log
-from gnue.common.apps import GDebug, plugin
+from gnue.common.base import log, plugin
from gnue.common.datasources import GConnections, GSchema
Modified: trunk/gnue-common/src/rpc/client.py
===================================================================
--- trunk/gnue-common/src/rpc/client.py 2009-10-06 13:42:11 UTC (rev 9936)
+++ trunk/gnue-common/src/rpc/client.py 2009-10-06 13:48:22 UTC (rev 9937)
@@ -28,8 +28,7 @@
__all__ = ['attach', 'InvalidAdapter', 'AdapterInitializationError',
'AdapterConfigurationError', 'ProgrammingError',
'AccessDeniedError']
-from gnue.common.apps import plugin
-from gnue.common.base import errors
+from gnue.common.base import errors, plugin
# =============================================================================
# Public functions
Modified: trunk/gnue-common/src/rpc/server.py
===================================================================
--- trunk/gnue-common/src/rpc/server.py 2009-10-06 13:42:11 UTC (rev 9936)
+++ trunk/gnue-common/src/rpc/server.py 2009-10-06 13:48:22 UTC (rev 9937)
@@ -28,7 +28,7 @@
__all__ = ['bind', 'AdapterInitializationError', 'AdapterConfigurationError',
'ProgrammingError', 'InvalidParameter']
-from gnue.common.apps import errors, plugin
+from gnue.common.base import errors, plugin
# =============================================================================
Deleted: trunk/gnue-common/src/utils/plugin.py
===================================================================
--- trunk/gnue-common/src/utils/plugin.py 2009-10-06 13:42:11 UTC (rev
9936)
+++ trunk/gnue-common/src/utils/plugin.py 2009-10-06 13:48:22 UTC (rev
9937)
@@ -1,441 +0,0 @@
-# GNU Enterprise Common Library - Plugin support
-#
-# This file is part of GNU Enterprise.
-#
-# GNU Enterprise is free software; you can redistribute it
-# and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation; either
-# version 2, or (at your option) any later version.
-#
-# GNU Enterprise 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. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public
-# License along with program; see the file COPYING. If not,
-# write to the Free Software Foundation, Inc., 59 Temple Place
-# - Suite 330, Boston, MA 02111-1307, USA.
-#
-# Copyright 2001-2009 Free Software Foundation
-#
-# $Id$
-
-"""
-Functions to list and load avaliable plugins dynamically.
-
-Plugins are Python modules that implement a defined API and are loaded on
-demand. Usually, there are several plugins of the same type (that means they
-implement the same API) that can be used interchangeable. The user can select
-which plugin he wants to use.
-
-All plugins of a specific type must be Python modules in a defined package.
-For example, all database drivers must be modules in the
-gnue.common.datasources.drivers package.
-
-Any plugin must define a specific symbol (usually a class definition like
-LanguageAdapter, ClientAdapter or Connection) to qualify itself as valid.
-
-Any plugin must immediately check whether it is functional (especially whether
-all dependencies are installed), and import must fail with a meaningful
-exception otherwise. Optionally, a module can also define a function with the
-name __initplugin__ that initializes the module and raises an exception if the
-plugin cannot be initialized.
-
-Plugins can be organized in a tree structure. To load a plugin, any point in
-the tree may be specified. For example, consider there are three plugins named
-base.group.foo, base.group.bar and base.group.baz. "foo" will specify the foo
-plugin, as well as "group.foo". Loading the plugin "group" means to load the
-first available functional plugin in the group.
-
-Modules and packages located within the plugin tree but not being valid plugins
-can define a symbol with the name __noplugin__ to indicate that they are no
-valid plugin. Note that the module defining the __noplugin__ symbol is still
-imported, but no submodules of it. This is useful to exclude, for example,
-abstract base drivers.
-"""
-
-import os
-import sys
-
-from types import ModuleType
-from gnue.common.base import errors
-
-__all__ = ['LoadError', 'list_plugins', 'find']
-
-# =============================================================================
-# Exceptions
-# =============================================================================
-
-# -----------------------------------------------------------------------------
-# Module loading error
-# -----------------------------------------------------------------------------
-
-class LoadError(errors.AdminError):
- """
- Indicates a failure to load a given module. Raised by L{find}.
-
- If e is an Exception of this class, e.exceptions gives a dictionary with
- the keys being the modules that were trying to be imported and the values
- being the exception info tuples for the exception that happened trying, and
- e.detail is a string containing basically the same info.
- """
- def __init__(self, name, exceptions):
-
- self.name = name
- self.exceptions = exceptions
-
- if self.exceptions:
- message = u_("Cannot load plugin '%s'") % self.name
- detail = u_("The following plugins failed:\n")
- for (name, exc) in self.exceptions.items():
- detail += u"* %s: %s" % (name, exc)
- else:
- message = u_("Cannot find plugin '%s'") % self.name
- detail = None
-
- errors.AdminError.__init__(self, message)
-
- if detail:
- self.detail = detail
-
-
-# -----------------------------------------------------------------------------
-# List all available plugins
-# -----------------------------------------------------------------------------
-
-def list_plugins(base, identifier, try_to_init=True):
- """
- List all available plugins.
-
- @param base: Name of the package that contains the plugins.
- @param identifier: Identifier that a plugin must define to qualify as
- module.
- @param try_to_init: If set to False, __initplugin__ is not called.
- @return: A dictionary with the available plugin module names as keys and
- either the loaded module or the exception info tuple of the exception
- raised when trying to import the module as values.
- """
- checktype(base, [basestring])
- checktype(identifier, [basestring])
-
- # Make sure everything is a string. Non-ASCII characters are not allowed in
- # Python module names anyway.
- _base = base.encode()
- _identifier = identifier.encode()
-
- # Now recursively list the plugins
- return __list(_base, _identifier, try_to_init, True)
-
-
-# -----------------------------------------------------------------------------
-# Find a plugin
-# -----------------------------------------------------------------------------
-
-def find(name, base, identifier):
- """
- Find a plugin by name. If no plugin is functional, a LoadError is raised.
-
- @param name: Name of the plugin to find. If the plugin is foo.bar, name
can
- be bar, or foo.bar, or foo, where the last one returns the first
- functional plugin in the foo group.
- @param base: Name of the package that contains the plugins.
- @param identifier: Identifier that a plugin must define to qualify as
- module.
- @return: The loaded module of the plugin.
- """
- checktype(name, [basestring])
- checktype(base, [basestring])
- checktype(identifier, [basestring])
-
- # Make sure everything is a string. Non-ASCII characters are not allowed in
- # Python module names anyway.
- _name = name.encode()
- _base = base.encode()
- _identifier = identifier.encode()
-
- # First, see if we've already found this module previously
- global __findCache
- try:
- result = __findCache[(_base, _name)]
- except KeyError:
- # If not, search for the plugin
- result = __findCache[(_base, _name)] = __find(_base, _name,
_identifier)
-
- if isinstance(result, ModuleType):
- return result
- else:
- raise LoadError, (name, result)
-
-
-# -----------------------------------------------------------------------------
-# A list of all previously failed modules
-# -----------------------------------------------------------------------------
-
-# This dictionary remembers all previous failure of module imports/inits. That
-# is necessary because module initialization code is only run at first import
-# attempt.
-__failed = {}
-
-
-# -----------------------------------------------------------------------------
-# Mapping of previously found plugins
-# -----------------------------------------------------------------------------
-
-__findCache = {}
-
-
-# -----------------------------------------------------------------------------
-# Find all modules and subpackages in a package
-# -----------------------------------------------------------------------------
-
-def __modules(package, want_packages):
-
- # package.__file__ is a directory if GImportLogger is in use. This makes it
- # necessary to 'simulate' a package, otherwise stepping down subpackages
- # won't work.
- if os.path.isdir(package.__file__):
- (basedir, basefile) = (package.__file__, '__init__.py')
- else:
- (basedir, basefile) = os.path.split(package.__file__)
-
- (basename, baseext) = os.path.splitext(basefile)
-
- if basename != '__init__':
- # This is not a package, so no need to go deeper
- return []
-
- # Find all submodules
- result = {}
- for subfile in os.listdir(basedir):
- (subname, subext) = os.path.splitext(subfile)
- subpath = os.path.join(basedir, subfile)
- # We are only interested in Python modules or packages
- if (not want_packages and subext in ['.py', '.pyc', '.pyo'] and \
- subname != '__init__') or \
- (os.path.isdir(subpath) and \
- os.path.isfile(os.path.join(subpath, '__init__.py')) or \
- os.path.isfile(os.path.join(subpath, '__init__.pyc')) or \
- os.path.isfile(os.path.join(subpath, '__init__.pyo'))):
- result[subname] = True
-
- return result.keys()
-
-
-# -----------------------------------------------------------------------------
-# Recursively list all plugins
-# -----------------------------------------------------------------------------
-
-def __list(base, identifier, try_to_init, top):
-
- global __failed
-
- if __failed.has_key(base):
- # This has already failed in previous attempt
- return {base: __failed[base]}
-
- try:
- mod = __import__(base, None, None, '*')
- except Exception, e:
- __failed[base] = e
- return {base: __failed[base]}
-
- if hasattr(mod, '__noplugin__'):
- # This is not a plugin, ignore it
- return {}
-
- if not top:
- if hasattr(mod, identifier):
- # This is already a plugin, no need to go deeper
- if try_to_init and hasattr(mod, '__initplugin__'):
- try:
- mod.__initplugin__()
- except Exception, e:
- __failed[base] = e
- return {base: __failed[base]}
- return {base: mod}
-
- # List all submodules
- result = {}
- for sub in __modules(mod, False):
- result.update(__list(base + '.' + sub, identifier, try_to_init, False))
- return result
-
-
-# -----------------------------------------------------------------------------
-# Recursively find first available plugin and return the module or a dictionary
-# with the exceptions that occured
-# -----------------------------------------------------------------------------
-
-def __first(base, identifier):
-
- global __failed
-
- if __failed.has_key(base):
- # This has already failed in previous attempt
- return {base: __failed[base]}
-
- try:
- mod = __import__(base, None, None, '*')
- except Exception, e:
- __failed[base] = e
- return {base: __failed[base]}
-
- if hasattr(mod, '__noplugin__'):
- # This is not a plugin, ignore it
- return {}
-
- if hasattr(mod, identifier):
- # This is already a plugin, no need to go deeper
- if hasattr(mod, '__initplugin__'):
- try:
- mod.__initplugin__()
- except Exception, e:
- __failed[base] = e
- return {base: __failed[base]}
- return mod
-
- # Search all submodules
- exceptions = {}
- for sub in __modules(mod, False):
- result = __first(base + '.' + sub, identifier)
- if isinstance(result, ModuleType):
- return result
- exceptions.update(result)
- return exceptions
-
-
-# -----------------------------------------------------------------------------
-# Recursively search for a plugin and return the module or the exceptions that
-# occured
-# -----------------------------------------------------------------------------
-
-def __find(base, name, identifier):
-
- if __failed.has_key(base):
- # This has already failed in previous attempt
- return {base: __failed[base]}
-
- try:
- mod = __import__(base, None, None, '*')
- except Exception, e:
- __failed[base] = e
- return {base: __failed[base]}
-
- if hasattr(mod, '__noplugin__'):
- # This is not a plugin, ignore it
- return {}
-
- # Is the searched driver an alias of this module?
- if hasattr(mod, '__pluginalias__'):
- if name in mod.__pluginalias__:
- return __first(base, identifier)
-
- if __failed.has_key(base + '.' + name):
- # This has already failed in previous attempt
- return {base + '.' + name: __failed[base + '.' + name]}
-
- try:
- mod = __import__(base + '.' + name, None, None, '*')
- except ImportError:
- pass
- except Exception, e:
- __failed[base + '.' + name] = e
- return {base + '.' + name: __failed[base + '.' + name]}
- else:
- return __first(base + '.' + name, identifier)
-
- # Search all submodules
- exceptions = {}
- for sub in __modules(mod, False):
- result = __find(base + '.' + sub, name, identifier)
- if isinstance(result, ModuleType):
- return result
- exceptions.update(result)
-
- return exceptions
-
-
-# =============================================================================
-# Self test code
-# =============================================================================
-
-if __name__ == '__main__':
-
- basep = 'gnue.common.datasources.drivers'
-
- if len(sys.argv) == 1:
-
- # List all modules
- for (iname, iresult) in(list_plugins(basep, 'Connection')).items():
- print iname[len(basep)+1:] + ":",
- if isinstance(iresult, ModuleType):
- print "ok"
- else:
- print unicode(iresult)
-
- elif sys.argv[1] == 'test':
-
- try:
- print 'find "postgresql.popy":',
- fmod = find('postgresql.popy', basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
-
- print
-
- try:
- print 'find "pygresql":',
- fmod = find('pygresql', basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
-
- print
-
- try:
- print 'find "mysql":',
- fmod = find('mysql', basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
-
- print
-
- try:
- print 'find "oracle":',
- fmod = find('oracle', basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
-
- print
-
- try:
- print 'find "nonexistent":',
- fmod = find('nonexistent', basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
-
- else:
-
- try:
- print 'find %s:' % sys.argv[1],
- fmod = find(sys.argv[1], basep, 'Connection')
- print fmod.__name__
- except LoadError, e:
- print e
- print "Detail:"
- print o(e.detail),
Modified: trunk/gnue-common/utils/helpers/info.py
===================================================================
--- trunk/gnue-common/utils/helpers/info.py 2009-10-06 13:42:11 UTC (rev
9936)
+++ trunk/gnue-common/utils/helpers/info.py 2009-10-06 13:48:22 UTC (rev
9937)
@@ -1,7 +1,7 @@
import sys, os, string, time, gnue
from files import openModuleFile, importModule, SubheadedFile, SVN_BASE
from StringIO import StringIO
-from gnue.common.apps import plugin
+from gnue.common.base import plugin
##
##
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r9937 - in trunk/gnue-common: src/apps src/base src/datasources src/datasources/drivers/Base src/rpc src/utils utils/helpers,
reinhard <=