From 109d41e722aec8df1a2325ea31630dc54e88e957 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Sat, 4 Jul 2020 15:10:29 -0400 Subject: [PATCH] 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 --- lower-constraints.txt | 2 +- novaclient/client.py | 15 +++++++++------ novaclient/tests/unit/test_discover.py | 25 +++++++++++++++---------- requirements.txt | 1 + 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index cd722665d..d40bb1752 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -92,7 +92,7 @@ Routes==2.3.1 simplejson==3.5.1 smmap==0.9.0 statsd==3.2.1 -stevedore==1.20.0 +stevedore==2.0.1 tempest==17.1.0 tenacity==3.2.1 stestr==2.0.0 diff --git a/novaclient/client.py b/novaclient/client.py index 4b3e22819..6c15f04d1 100644 --- a/novaclient/client.py +++ b/novaclient/client.py @@ -28,7 +28,7 @@ from keystoneauth1 import adapter from keystoneauth1 import identity from keystoneauth1 import session as ksession from oslo_utils import importutils -import pkg_resources +import stevedore import novaclient from novaclient import api_versions @@ -176,12 +176,15 @@ def _discover_via_python_path(): yield name, module -def _discover_via_entry_points(): - for ep in pkg_resources.iter_entry_points('novaclient.extension'): - name = ep.name - module = ep.load() +def _make_discovery_manager(): + # This function provides a place to mock out the entry point scan + return stevedore.ExtensionManager('novaclient.extension') - 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): diff --git a/novaclient/tests/unit/test_discover.py b/novaclient/tests/unit/test_discover.py index 9bbbe3917..d5fa54000 100644 --- a/novaclient/tests/unit/test_discover.py +++ b/novaclient/tests/unit/test_discover.py @@ -17,7 +17,8 @@ import imp import inspect from unittest import mock -import pkg_resources +import stevedore +from stevedore import extension from novaclient import client from novaclient.tests.unit import utils @@ -27,16 +28,20 @@ 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] + def mock_mgr(): + fake_ep = mock.Mock() + fake_ep.name = 'foo' + fake_ep.module = imp.new_module('foo') + fake_ep.load.return_value = fake_ep.module + fake_ext = extension.Extension( + 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_iter_entry_points) + @mock.patch.object(client, '_make_discovery_manager', mock_mgr) def test(): for name, module in client._discover_via_entry_points(): self.assertEqual('foo', name) diff --git a/requirements.txt b/requirements.txt index 682f6b94a..3f6c92808 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 PrettyTable<0.8,>=0.7.2 # BSD simplejson>=3.5.1 # MIT +stevedore>=2.0.1 # Apache-2.0