discover extensions via entry points
Currently, nova client can only discover extensions in two ways: 1. Installing the extension in the novaclient/v1_1/contrib/ directory. 2. Installing the extension in the top-level python path or modifying the path to be picked up by pkgutils.iter_modules() This patch allows a third, more flexible option of discovering extensions via entry points. This means the extension can be installed anywhere and entry points can be registered with python to be picked up by pkg_resources.iter_entry_points(). To register an entry point, simply add the extension module to the setup() call in setup.py like this: setuptools.setup( name='mydistribution', packages=setuptools.find_packages(), entry_points={ 'novaclient.extension' : [ 'foo = mydistribution.mynovaclientexts.foo' ] }, ) Change-Id: Ic1e223a9173546131e742506897f585f4ac65767
This commit is contained in:
parent
4ad512b50e
commit
aa5622147f
@ -24,6 +24,7 @@ import httplib2
|
||||
import imp
|
||||
import itertools
|
||||
import os
|
||||
import pkg_resources
|
||||
import pkgutil
|
||||
import sys
|
||||
import logging
|
||||
@ -257,7 +258,8 @@ class OpenStackComputeShell(object):
|
||||
extensions = []
|
||||
for name, module in itertools.chain(
|
||||
self._discover_via_python_path(),
|
||||
self._discover_via_contrib_path(version)):
|
||||
self._discover_via_contrib_path(version),
|
||||
self._discover_via_entry_points()):
|
||||
|
||||
extension = novaclient.extension.Extension(name, module)
|
||||
extensions.append(extension)
|
||||
@ -289,6 +291,13 @@ class OpenStackComputeShell(object):
|
||||
module = imp.load_source(name, ext_path)
|
||||
yield name, module
|
||||
|
||||
def _discover_via_entry_points(self):
|
||||
for ep in pkg_resources.iter_entry_points('novaclient.extension'):
|
||||
name = ep.name
|
||||
module = ep.load()
|
||||
|
||||
yield name, module
|
||||
|
||||
def _add_bash_completion_subparser(self, subparsers):
|
||||
subparser = subparsers.add_parser('bash_completion',
|
||||
add_help=False,
|
||||
|
79
tests/test_discover.py
Normal file
79
tests/test_discover.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 mock
|
||||
import imp
|
||||
import inspect
|
||||
import pkg_resources
|
||||
|
||||
import novaclient.shell
|
||||
from tests import utils
|
||||
|
||||
|
||||
class DiscoverTest(utils.TestCase):
|
||||
|
||||
def test_discover_via_entry_points(self):
|
||||
|
||||
def mock_iter_entry_points(group):
|
||||
if group == 'novaclient.extension':
|
||||
fake_ep = mock.Mock()
|
||||
fake_ep.name = 'foo'
|
||||
fake_ep.module = imp.new_module('foo')
|
||||
fake_ep.load.return_value = fake_ep.module
|
||||
return [fake_ep]
|
||||
|
||||
@mock.patch.object(pkg_resources, 'iter_entry_points',
|
||||
mock_iter_entry_points)
|
||||
def test():
|
||||
shell = novaclient.shell.OpenStackComputeShell()
|
||||
for name, module in shell._discover_via_entry_points():
|
||||
self.assertEqual(name, 'foo')
|
||||
self.assertTrue(inspect.ismodule(module))
|
||||
|
||||
test()
|
||||
|
||||
def test_discover_extensions(self):
|
||||
|
||||
def mock_discover_via_python_path(self):
|
||||
yield 'foo', imp.new_module('foo')
|
||||
|
||||
def mock_discover_via_contrib_path(self, version):
|
||||
yield 'bar', imp.new_module('bar')
|
||||
|
||||
def mock_discover_via_entry_points(self):
|
||||
yield 'baz', imp.new_module('baz')
|
||||
|
||||
@mock.patch.object(novaclient.shell.OpenStackComputeShell,
|
||||
'_discover_via_python_path',
|
||||
mock_discover_via_python_path)
|
||||
@mock.patch.object(novaclient.shell.OpenStackComputeShell,
|
||||
'_discover_via_contrib_path',
|
||||
mock_discover_via_contrib_path)
|
||||
@mock.patch.object(novaclient.shell.OpenStackComputeShell,
|
||||
'_discover_via_entry_points',
|
||||
mock_discover_via_entry_points)
|
||||
def test():
|
||||
shell = novaclient.shell.OpenStackComputeShell()
|
||||
extensions = shell._discover_extensions('1.1')
|
||||
self.assertEqual(len(extensions), 3)
|
||||
names = sorted(['foo', 'bar', 'baz'])
|
||||
sorted_extensions = sorted(extensions, key=lambda ext: ext.name)
|
||||
for i in range(len(names)):
|
||||
ext = sorted_extensions[i]
|
||||
name = names[i]
|
||||
self.assertEqual(ext.name, name)
|
||||
self.assertTrue(inspect.ismodule(ext.module))
|
||||
|
||||
test()
|
Loading…
Reference in New Issue
Block a user