add property methods to extension for more entry point values

The underlying EntryPoint class has some similar methods to fetch
these values, but they depend on the version of importlib.metadata
that is installed, so this provides a consistent API

Change-Id: I7a1b9541f0e4042a224e49c890ba3c63e8a5a259
Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
Doug Hellmann 2020-07-12 15:26:07 -04:00
parent bc04ca91e0
commit e9204ee7b7
No known key found for this signature in database
GPG Key ID: 3B6D06A0C428437A
3 changed files with 73 additions and 0 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
Add `extras` and `attr` properties to the `Extension` class to
make it easier for consumers to access the underlying properties,
regardless of the version of `importlib.metadata` being used.

View File

@ -58,6 +58,27 @@ class Extension(object):
match = self.entry_point.pattern.match(self.entry_point.value)
return match.group('module')
@property
def extras(self):
"""The 'extras' settings for the plugin."""
# NOTE: The underlying package returns re.Match objects for
# some reason. Translate those to the matched strings, which
# seem more useful.
return [
# Python 3.6 returns _sre.SRE_Match objects. Later
# versions of python return re.Match objects. Both types
# have a 'string' attribute containing the text that
# matched the pattern.
getattr(e, 'string', e)
for e in self.entry_point.extras
]
@property
def attr(self):
"""The attribute of the module to be loaded."""
match = self.entry_point.pattern.match(self.entry_point.value)
return match.group('attr')
@property
def entry_point_target(self):
"""The module and attribute referenced by this extension's entry_point.

View File

@ -16,6 +16,13 @@
import operator
from unittest import mock
try:
# For python 3.8 and later
import importlib.metadata as importlib_metadata
except ImportError:
# For everyone else
import importlib_metadata
from stevedore import exception
from stevedore import extension
from stevedore.tests import utils
@ -241,3 +248,42 @@ class TestLoadRequirementsOldSetuptools(utils.TestCase):
self.em._load_one_plugin(self.mock_ep, False, (), {},
verify_requirements=False)
self.mock_ep.load.assert_called_once_with()
class TestExtensionProperties(utils.TestCase):
def setUp(self):
self.ext1 = extension.Extension(
'name',
importlib_metadata.EntryPoint(
'name', 'module.name:attribute.name [extra]', 'group_name',
),
mock.Mock(),
None,
)
self.ext2 = extension.Extension(
'name',
importlib_metadata.EntryPoint(
'name', 'module:attribute', 'group_name',
),
mock.Mock(),
None,
)
def test_module_name(self):
self.assertEqual('module.name', self.ext1.module_name)
self.assertEqual('module', self.ext2.module_name)
def test_extras(self):
self.assertEqual(['[extra]'], self.ext1.extras)
self.assertEqual([], self.ext2.extras)
def test_attr(self):
self.assertEqual('attribute.name', self.ext1.attr)
self.assertEqual('attribute', self.ext2.attr)
def test_entry_point_target(self):
self.assertEqual('module.name:attribute.name [extra]',
self.ext1.entry_point_target)
self.assertEqual('module:attribute',
self.ext2.entry_point_target)