use stevedore to load extensions

Importing pkg_resources causes the app to scan the entire import path
for all distributions, not just those providing entry points. The
scanner in stevedore will have a cache of the entry point data, making
it significantly faster. This will be especially useful in command
line programs like python-openstackclient.

Change-Id: Ic5eb9401c8ea3bd9624b818e0ffb8dcc13f61559
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann 2020-07-04 15:10:29 -04:00
parent 600384fa3b
commit 109d41e722
4 changed files with 26 additions and 17 deletions

View File

@ -92,7 +92,7 @@ Routes==2.3.1
simplejson==3.5.1 simplejson==3.5.1
smmap==0.9.0 smmap==0.9.0
statsd==3.2.1 statsd==3.2.1
stevedore==1.20.0 stevedore==2.0.1
tempest==17.1.0 tempest==17.1.0
tenacity==3.2.1 tenacity==3.2.1
stestr==2.0.0 stestr==2.0.0

View File

@ -28,7 +28,7 @@ from keystoneauth1 import adapter
from keystoneauth1 import identity from keystoneauth1 import identity
from keystoneauth1 import session as ksession from keystoneauth1 import session as ksession
from oslo_utils import importutils from oslo_utils import importutils
import pkg_resources import stevedore
import novaclient import novaclient
from novaclient import api_versions from novaclient import api_versions
@ -176,12 +176,15 @@ def _discover_via_python_path():
yield name, module yield name, module
def _discover_via_entry_points(): def _make_discovery_manager():
for ep in pkg_resources.iter_entry_points('novaclient.extension'): # This function provides a place to mock out the entry point scan
name = ep.name return stevedore.ExtensionManager('novaclient.extension')
module = ep.load()
yield name, module
def _discover_via_entry_points():
mgr = _make_discovery_manager()
for extension in mgr:
yield extension.name, extension.plugin
def _get_client_class_and_version(version): def _get_client_class_and_version(version):

View File

@ -17,7 +17,8 @@ import imp
import inspect import inspect
from unittest import mock from unittest import mock
import pkg_resources import stevedore
from stevedore import extension
from novaclient import client from novaclient import client
from novaclient.tests.unit import utils from novaclient.tests.unit import utils
@ -27,16 +28,20 @@ class DiscoverTest(utils.TestCase):
def test_discover_via_entry_points(self): def test_discover_via_entry_points(self):
def mock_iter_entry_points(group): def mock_mgr():
if group == 'novaclient.extension': fake_ep = mock.Mock()
fake_ep = mock.Mock() fake_ep.name = 'foo'
fake_ep.name = 'foo' fake_ep.module = imp.new_module('foo')
fake_ep.module = imp.new_module('foo') fake_ep.load.return_value = fake_ep.module
fake_ep.load.return_value = fake_ep.module fake_ext = extension.Extension(
return [fake_ep] name='foo',
entry_point=fake_ep,
plugin=fake_ep.module,
obj=None,
)
return stevedore.ExtensionManager.make_test_instance([fake_ext])
@mock.patch.object(pkg_resources, 'iter_entry_points', @mock.patch.object(client, '_make_discovery_manager', mock_mgr)
mock_iter_entry_points)
def test(): def test():
for name, module in client._discover_via_entry_points(): for name, module in client._discover_via_entry_points():
self.assertEqual('foo', name) self.assertEqual('foo', name)

View File

@ -9,3 +9,4 @@ oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
PrettyTable<0.8,>=0.7.2 # BSD PrettyTable<0.8,>=0.7.2 # BSD
simplejson>=3.5.1 # MIT simplejson>=3.5.1 # MIT
stevedore>=2.0.1 # Apache-2.0