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
##
##
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.