Add a module for dynamically loading plugins
Change-Id: I662b5989941b467c78a392098db0cd19ff86201c Signed-off-by: Zane Bitter <zbitter@redhat.com>
This commit is contained in:
parent
a0cf5dfa5c
commit
faca9953c0
|
@ -0,0 +1,64 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pkgutil
|
||||
import sys
|
||||
import types
|
||||
|
||||
from heat.openstack.common import log as logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _module_name(*components):
|
||||
return '.'.join(components)
|
||||
|
||||
|
||||
def create_subpackage(path, parent_package_name, subpackage_name="plugins"):
|
||||
package_name = _module_name(parent_package_name, subpackage_name)
|
||||
|
||||
package = types.ModuleType(package_name)
|
||||
package.__path__ = [path] if isinstance(path, basestring) else list(path)
|
||||
sys.modules[package_name] = package
|
||||
|
||||
return package
|
||||
|
||||
|
||||
def _import_module(importer, module_name, package):
|
||||
fullname = _module_name(package.__name__, module_name)
|
||||
if fullname in sys.modules:
|
||||
return sys.modules[fullname]
|
||||
|
||||
loader = importer.find_module(fullname)
|
||||
if loader is None:
|
||||
return None
|
||||
|
||||
module = loader.load_module(fullname)
|
||||
setattr(package, module_name, module)
|
||||
return module
|
||||
|
||||
|
||||
def load_modules(package, ignore_error=False):
|
||||
path = package.__path__
|
||||
for importer, module_name, is_package in pkgutil.walk_packages(path):
|
||||
try:
|
||||
module = _import_module(importer, module_name, package)
|
||||
except ImportError as ex:
|
||||
logger.error(_('Failed to import module %s') % module_name)
|
||||
if not ignore_error:
|
||||
raise
|
||||
else:
|
||||
if module is not None:
|
||||
yield module
|
|
@ -0,0 +1,70 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import nose
|
||||
import pkgutil
|
||||
import sys
|
||||
import unittest
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
import heat.engine
|
||||
from heat.common import plugin_loader
|
||||
|
||||
|
||||
@attr(tag=['unit', 'plugin_loader'])
|
||||
@attr(speed='fast')
|
||||
class PluginLoaderTest(unittest.TestCase):
|
||||
def test_module_name(self):
|
||||
self.assertEqual(plugin_loader._module_name('foo.bar', 'blarg.wibble'),
|
||||
'foo.bar.blarg.wibble')
|
||||
|
||||
def test_create_subpackage_single_path(self):
|
||||
pkg_name = 'heat.engine.test_single_path'
|
||||
self.assertFalse(pkg_name in sys.modules)
|
||||
pkg = plugin_loader.create_subpackage('/tmp',
|
||||
'heat.engine',
|
||||
'test_single_path')
|
||||
self.assertTrue(pkg_name in sys.modules)
|
||||
self.assertEqual(sys.modules[pkg_name], pkg)
|
||||
self.assertEqual(pkg.__path__, ['/tmp'])
|
||||
self.assertEqual(pkg.__name__, pkg_name)
|
||||
|
||||
def test_create_subpackage_path_list(self):
|
||||
path_list = ['/tmp']
|
||||
pkg_name = 'heat.engine.test_path_list'
|
||||
self.assertFalse(pkg_name in sys.modules)
|
||||
pkg = plugin_loader.create_subpackage('/tmp',
|
||||
'heat.engine',
|
||||
'test_path_list')
|
||||
self.assertTrue(pkg_name in sys.modules)
|
||||
self.assertEqual(sys.modules[pkg_name], pkg)
|
||||
self.assertEqual(pkg.__path__, path_list)
|
||||
self.assertFalse(pkg.__path__ is path_list)
|
||||
self.assertEqual(pkg.__name__, pkg_name)
|
||||
|
||||
def test_import_module_existing(self):
|
||||
import heat.engine.service
|
||||
importer = pkgutil.ImpImporter(heat.engine.__path__[0])
|
||||
loaded = plugin_loader._import_module(importer,
|
||||
'service',
|
||||
heat.engine)
|
||||
self.assertTrue(loaded is heat.engine.service)
|
||||
|
||||
def test_import_module_garbage(self):
|
||||
importer = pkgutil.ImpImporter(heat.engine.__path__[0])
|
||||
self.assertEqual(plugin_loader._import_module(importer,
|
||||
'wibble',
|
||||
heat.engine),
|
||||
None)
|
Loading…
Reference in New Issue