Do not check requirements when loading entry points

Update the calls to pkg_resources to avoid forcing a requirements check
when the plugins are being loaded.

There are 2 versions of the entry point API in different releases of
setuptools. In one version, the require keyword argument can be passed
to load(). In the other, separate methods resolve() and require() need
to be used. This change updates the mock and fake objects to support
either, since the fakes are subclasses of the EntryPoint class in
pkg_resources.

It would be better to replace the calls to pkg_resources with stevedore,
which provides a more stable API, abstracts away this difference, and
provides an API for creating test managers directly. That change would
have required more extensive updates to the test suite, though, and
since I'm not as familiar with this code base as others will be, I will
leave those changes for someone else.

Change-Id: I2a9aeb53ccad04c7fa687f25340306b84218f9ff
Partial-bug: #1457100
This commit is contained in:
Doug Hellmann 2015-05-27 18:08:02 +00:00
parent 0a327ce375
commit e649cea843
3 changed files with 62 additions and 18 deletions

View File

@ -37,7 +37,14 @@ def discover_auth_systems():
ep_name = 'openstack.client.auth_plugin'
for ep in pkg_resources.iter_entry_points(ep_name):
try:
auth_plugin = ep.load()
# FIXME(dhellmann): It would be better to use stevedore
# here, since it abstracts this difference in behavior
# between versions of setuptools, but this seemed like a
# more expedient fix.
if hasattr(ep, 'resolve') and hasattr(ep, 'require'):
auth_plugin = ep.resolve()
else:
auth_plugin = ep.load(require=False)
except (ImportError, pkg_resources.UnknownExtra, AttributeError) as e:
logger.debug("ERROR: Cannot load auth plugin %s" % ep.name)
logger.debug(e, exc_info=1)

View File

@ -58,7 +58,10 @@ def requested_headers(cs):
class DeprecatedAuthPluginTest(utils.TestCase):
def test_auth_system_success(self):
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return self.authenticate
def resolve(self):
return self.authenticate
def authenticate(self, cls, auth_url):
@ -117,14 +120,20 @@ class DeprecatedAuthPluginTest(utils.TestCase):
def test_auth_system_defining_auth_url(self):
class MockAuthUrlEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return self.auth_url
def resolve(self):
return self.auth_url
def auth_url(self):
return "http://faked/v2.0"
class MockAuthenticateEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return self.authenticate
def resolve(self):
return self.authenticate
def authenticate(self, cls, auth_url):
@ -160,7 +169,10 @@ class DeprecatedAuthPluginTest(utils.TestCase):
@mock.patch.object(pkg_resources, "iter_entry_points")
def test_client_raises_exc_without_auth_url(self, mock_iter_entry_points):
class MockAuthUrlEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return self.auth_url
def resolve(self):
return self.auth_url
def auth_url(self):
@ -184,14 +196,17 @@ class AuthPluginTest(utils.TestCase):
def test_auth_system_success(self, mock_iter_entry_points, mock_request):
"""Test that we can authenticate using the auth system."""
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
def resolve(self):
return FakePlugin
class FakePlugin(auth_plugin.BaseAuthPlugin):
def authenticate(self, cls, auth_url):
cls._authenticate(auth_url, {"fake": "me"})
mock_iter_entry_points.side_effect = lambda _t: [
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
mock_request.side_effect = mock_http_request()
@ -227,10 +242,13 @@ class AuthPluginTest(utils.TestCase):
return parser
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
mock_iter_entry_points.side_effect = lambda _t: [
def resolve(self):
return FakePlugin
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
parser = argparse.ArgumentParser()
@ -244,7 +262,10 @@ class AuthPluginTest(utils.TestCase):
def test_parse_auth_system_options(self, mock_iter_entry_points):
"""Test that we can parse the auth system options."""
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
def resolve(self):
return FakePlugin
class FakePlugin(auth_plugin.BaseAuthPlugin):
@ -254,7 +275,7 @@ class AuthPluginTest(utils.TestCase):
def parse_opts(self, args):
return self.opts
mock_iter_entry_points.side_effect = lambda _t: [
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
auth_plugin.discover_auth_systems()
@ -267,14 +288,17 @@ class AuthPluginTest(utils.TestCase):
def test_auth_system_defining_url(self, mock_iter_entry_points):
"""Test the auth_system defining an url."""
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
def resolve(self):
return FakePlugin
class FakePlugin(auth_plugin.BaseAuthPlugin):
def get_auth_url(self):
return "http://faked/v2.0"
mock_iter_entry_points.side_effect = lambda _t: [
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
auth_plugin.discover_auth_systems()
@ -289,13 +313,16 @@ class AuthPluginTest(utils.TestCase):
def test_exception_if_no_authenticate(self, mock_iter_entry_points):
"""Test that no authenticate raises a proper exception."""
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
def resolve(self):
return FakePlugin
class FakePlugin(auth_plugin.BaseAuthPlugin):
pass
mock_iter_entry_points.side_effect = lambda _t: [
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
auth_plugin.discover_auth_systems()
@ -310,13 +337,16 @@ class AuthPluginTest(utils.TestCase):
def test_exception_if_no_url(self, mock_iter_entry_points):
"""Test that no auth_url at all raises exception."""
class MockEntrypoint(pkg_resources.EntryPoint):
def load(self):
def load(self, require=False):
return FakePlugin
def resolve(self):
return FakePlugin
class FakePlugin(auth_plugin.BaseAuthPlugin):
pass
mock_iter_entry_points.side_effect = lambda _t: [
mock_iter_entry_points.side_effect = lambda _t, name=None: [
MockEntrypoint("fake", "fake", ["FakePlugin"])]
auth_plugin.discover_auth_systems()

View File

@ -319,7 +319,14 @@ def _load_entry_point(ep_name, name=None):
"""Try to load the entry point ep_name that matches name."""
for ep in pkg_resources.iter_entry_points(ep_name, name=name):
try:
return ep.load()
# FIXME(dhellmann): It would be better to use stevedore
# here, since it abstracts this difference in behavior
# between versions of setuptools, but this seemed like a
# more expedient fix.
if hasattr(ep, 'resolve') and hasattr(ep, 'require'):
return ep.resolve()
else:
return ep.load(require=False)
except (ImportError, pkg_resources.UnknownExtra, AttributeError):
continue