summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Hellmann <doug@doughellmann.com>2016-02-10 12:42:57 -0500
committerDoug Hellmann <doug@doughellmann.com>2016-02-10 15:19:02 -0500
commit1a64804a9a2513e89d4ccd2e2524f54838651d96 (patch)
treec52f18d76be7fa0ff91b2231da26abe0a8d7ae7c
parent04437d5b4f279bea0de31c78a32f907c128f0df0 (diff)
downloadoslo-config-1a64804a9a2513e89d4ccd2e2524f54838651d96.tar.gz
refactor generator._list_opts for further enhancement
The _list_opts() function combines the behavior for loading the options and the behavior for cleaning and filtering them. This patch breaks it up a bit and updates the relevant tests, to prepare for the next patch which will add some new behavior to _list_opts(). Change-Id: Ie6616e76bf0c23a6303cdb1e441754ccba37a9c3 Signed-off-by: Doug Hellmann <doug@doughellmann.com>
-rw-r--r--oslo_config/generator.py19
-rw-r--r--oslo_config/tests/test_generator.py52
2 files changed, 40 insertions, 31 deletions
diff --git a/oslo_config/generator.py b/oslo_config/generator.py
index 3e801d0..00de370 100644
--- a/oslo_config/generator.py
+++ b/oslo_config/generator.py
@@ -267,7 +267,7 @@ def _cleanup_opts(read_opts):
return cleaned_opts
-def _list_opts(namespaces):
+def _get_raw_opts_loaders(namespaces):
"""List the options available via the given namespaces.
:param namespaces: a list of namespaces registered under 'oslo.config.opts'
@@ -277,9 +277,22 @@ def _list_opts(namespaces):
'oslo.config.opts',
names=namespaces,
on_load_failure_callback=on_load_failure_callback,
- invoke_on_load=True)
- opts = [(ep.name, ep.obj) for ep in mgr]
+ invoke_on_load=False)
+ return [(e.name, e.plugin) for e in mgr]
+
+
+def _list_opts(namespaces):
+ """List the options available via the given namespaces.
+ Duplicate options from a namespace are removed.
+
+ :param namespaces: a list of namespaces registered under 'oslo.config.opts'
+ :returns: a list of (namespace, [(group, [opt_1, opt_2])]) tuples
+ """
+ opts = [
+ (namespace, loader())
+ for namespace, loader in _get_raw_opts_loaders(namespaces)
+ ]
return _cleanup_opts(opts)
diff --git a/oslo_config/tests/test_generator.py b/oslo_config/tests/test_generator.py
index 152c59a..263c8fa 100644
--- a/oslo_config/tests/test_generator.py
+++ b/oslo_config/tests/test_generator.py
@@ -729,9 +729,9 @@ class GeneratorTestCase(base.BaseTestCase):
def _capture_stdout(self):
return self._capture_stream('stdout')
- @mock.patch('stevedore.named.NamedExtensionManager')
+ @mock.patch.object(generator, '_get_raw_opts_loaders')
@mock.patch.object(generator, 'LOG')
- def test_generate(self, mock_log, named_mgr):
+ def test_generate(self, mock_log, raw_opts_loader):
generator.register_cli_opts(self.conf)
namespaces = [i[0] for i in self.opts]
@@ -750,12 +750,17 @@ class GeneratorTestCase(base.BaseTestCase):
output_file = self.tempdir.join(self.output_file)
self.config(output_file=output_file)
- mock_eps = []
- for name, opts in self.opts:
- mock_ep = mock.Mock()
- mock_ep.configure_mock(name=name, obj=opts)
- mock_eps.append(mock_ep)
- named_mgr.return_value = mock_eps
+ # We have a static data structure matching what should be
+ # returned by _list_opts() but we're mocking out a lower level
+ # function that needs to return a namespace and a callable to
+ # return options from that namespace. We have to pass opts to
+ # the lambda to cache a reference to the name because the list
+ # comprehension changes the thing pointed to by the name each
+ # time through the loop.
+ raw_opts_loader.return_value = [
+ (ns, lambda opts=opts: opts)
+ for ns, opts in self.opts
+ ]
generator.generate(self.conf)
@@ -765,12 +770,6 @@ class GeneratorTestCase(base.BaseTestCase):
content = open(output_file).read()
self.assertEqual(self.expected, content)
- named_mgr.assert_called_once_with(
- 'oslo.config.opts',
- names=namespaces,
- on_load_failure_callback=generator.on_load_failure_callback,
- invoke_on_load=True)
-
log_warning = getattr(self, 'log_warning', None)
if log_warning is not None:
mock_log.warning.assert_called_once_with(*log_warning)
@@ -825,28 +824,25 @@ class IgnoreDoublesTestCase(base.BaseTestCase):
("group2", self.opts)])]
self.assertEqual(e, generator._cleanup_opts(o))
- @mock.patch('stevedore.named.NamedExtensionManager')
- def test_list_ignores_doubles(self, named_mgr):
- config_opts = [cfg.StrOpt('foo'),
- cfg.StrOpt('bar'),
- ]
- mock_ep1 = mock.Mock()
- mock_ep1.configure_mock(name="namespace",
- obj=[("group", config_opts)])
- mock_ep2 = mock.Mock()
- mock_ep2.configure_mock(name="namespace",
- obj=[("group", config_opts)])
+ @mock.patch.object(generator, '_get_raw_opts_loaders')
+ def test_list_ignores_doubles(self, raw_opts_loaders):
+ config_opts = [
+ (None, [cfg.StrOpt('foo'), cfg.StrOpt('bar')]),
+ ]
+
# These are the very same config options, but read twice.
# This is possible if one misconfigures the entry point for the
# sample config generator.
- mock_eps = [mock_ep1, mock_ep2]
- named_mgr.return_value = mock_eps
+ raw_opts_loaders.return_value = [
+ ('namespace', lambda: config_opts),
+ ('namespace', lambda: config_opts),
+ ]
slurped_opts = 0
for _, listing in generator._list_opts(None):
for _, opts in listing:
slurped_opts += len(opts)
- self.assertEqual(len(config_opts), slurped_opts)
+ self.assertEqual(2, slurped_opts)
class GeneratorRaiseErrorTestCase(base.BaseTestCase):