Remove MultiConfigParser

This has been deprecated for quite a while and some of the upcoming
work to be done in oslo.config will be easier if we don't have to
deal with this unused parser too.

The class is still currently in use in networking-cisco, but in
change https://review.openstack.org/554617 we have provided a fix
that removes their reliance on it.  They are planning to remove it
entirely in Rocky and are only testing against a capped version in
Queens so we are not going to wait on them.

Change-Id: Id6ae40311f967e172e45bcb0e61812365a72618b
This commit is contained in:
Ben Nemec 2018-03-20 16:34:06 +00:00
parent 8d406fe925
commit 3a9d653b09
3 changed files with 7 additions and 200 deletions

View File

@ -6,6 +6,3 @@ File Parsing
.. autoclass:: oslo_config.cfg.ConfigParser
:members: parse
.. autoclass:: oslo_config.cfg.MultiConfigParser
:members: read, get

View File

@ -496,11 +496,9 @@ import os
import string
import sys
from debtcollector import removals
import enum
import six
from oslo_config import iniparser
from oslo_config import types
@ -2009,116 +2007,6 @@ class ConfigParser(iniparser.BaseParser):
config_file, sections, normalized)
@removals.remove(version='3.4', removal_version='4.0')
class MultiConfigParser(object):
"""A ConfigParser which handles multi-opts.
All methods in this class which accept config names should treat a section
name of None as 'DEFAULT'.
This class was deprecated in Mitaka and should be removed in Ocata.
_Namespace holds values, ConfigParser._parse_file reads one file into a
_Namespace and ConfigOpts._parse_config_files reads multiple files into a
_Namespace.
"""
_deprecated_opt_message = ('Option "%(dep_option)s" from group '
'"%(dep_group)s" is deprecated. Use option '
'"%(option)s" from group "%(group)s".')
def __init__(self):
self.parsed = []
self._normalized = []
self._emitted_deprecations = set()
def read(self, config_files):
read_ok = []
for filename in config_files:
sections = {}
normalized = {}
parser = ConfigParser(filename, sections)
parser._add_normalized(normalized)
try:
parser.parse()
except IOError:
continue
self._add_parsed_config_file(filename, sections, normalized)
read_ok.append(filename)
return read_ok
def _add_parsed_config_file(self, filename, sections, normalized):
"""Add a parsed config file to the list of parsed files.
:param sections: a mapping of section name to dicts of config values
:param normalized: sections mapping with section names normalized
:raises: ConfigFileValueError
"""
self.parsed.insert(0, sections)
self._normalized.insert(0, normalized)
def get(self, names, multi=False):
return self._get(names, multi=multi)
def _get(self, names, multi=False, normalized=False, current_name=None):
"""Fetch a config file value from the parsed files.
:param names: a list of (section, name) tuples
:param multi: a boolean indicating whether to return multiple values
:param normalized: whether to normalize group names to lowercase
:param current_name: current name in tuple being checked
"""
rvalue = []
def normalize(name):
if name is None:
name = 'DEFAULT'
return _normalize_group_name(name) if normalized else name
names = [(normalize(section), name) for section, name in names]
for sections in (self._normalized if normalized else self.parsed):
for section, name in names:
if section not in sections:
continue
if name in sections[section]:
current_name = current_name or names[0]
self._check_deprecated((section, name), current_name,
names[1:])
val = sections[section][name]
if multi:
rvalue = val + rvalue
else:
return val
if multi and rvalue != []:
return rvalue
raise KeyError
def _check_deprecated(self, name, current, deprecated):
"""Check for usage of deprecated names.
:param name: A tuple of the form (group, name) representing the group
and name where an opt value was found.
:param current: A tuple of the form (group, name) representing the
current name for an option.
:param deprecated: A list of tuples with the same format as the name
param which represent any deprecated names for an option.
If the name param matches any entries in this list a
deprecation warning will be logged.
"""
if name in deprecated and name not in self._emitted_deprecations:
self._emitted_deprecations.add(name)
current = (current[0] or 'DEFAULT', current[1])
# NOTE(bnemec): Not using versionutils for this to avoid a
# circular dependency between oslo.config and whatever library
# versionutils ends up in.
LOG.warning(self._deprecated_opt_message,
{'dep_option': name[1], 'dep_group': name[0],
'option': current[1], 'group': current[0]})
class _Namespace(argparse.Namespace):
"""An argparse namespace which also stores config file values.

View File

@ -3964,84 +3964,6 @@ class ConfigParserTestCase(BaseTestCase):
namespace)
class MultiConfigParserTestCase(BaseTestCase):
def test_parse_single_file(self):
paths = self.create_tempfiles([('test',
'[DEFAULT]\n'
'foo = bar\n'
'[BLAA]\n'
'bar = foo\n')])
parser = cfg.MultiConfigParser()
read_ok = parser.read(paths)
self.assertEqual(read_ok, paths)
self.assertIn('DEFAULT', parser.parsed[0])
self.assertEqual(parser.parsed[0]['DEFAULT']['foo'], ['bar'])
self.assertEqual(parser.get([('DEFAULT', 'foo')]), ['bar'])
self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True),
['bar'])
self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True),
['bar'])
self.assertEqual(parser.get([(None, 'foo')], multi=True),
['bar'])
self.assertEqual(parser._get([('DEFAULT', 'foo')],
multi=True, normalized=True),
['bar'])
self.assertIn('BLAA', parser.parsed[0])
self.assertEqual(parser.parsed[0]['BLAA']['bar'], ['foo'])
self.assertEqual(parser.get([('BLAA', 'bar')]), ['foo'])
self.assertEqual(parser.get([('BLAA', 'bar')], multi=True),
['foo'])
self.assertEqual(parser._get([('blaa', 'bar')],
multi=True, normalized=True),
['foo'])
def test_parse_multiple_files(self):
paths = self.create_tempfiles([('test1',
'[DEFAULT]\n'
'foo = bar\n'
'[BLAA]\n'
'bar = foo'),
('test2',
'[DEFAULT]\n'
'foo = barbar\n'
'[BLAA]\n'
'bar = foofoo\n'
'[bLAa]\n'
'bar = foofoofoo\n')])
parser = cfg.MultiConfigParser()
read_ok = parser.read(paths)
self.assertEqual(read_ok, paths)
self.assertIn('DEFAULT', parser.parsed[0])
self.assertEqual(parser.parsed[0]['DEFAULT']['foo'], ['barbar'])
self.assertIn('DEFAULT', parser.parsed[1])
self.assertEqual(parser.parsed[1]['DEFAULT']['foo'], ['bar'])
self.assertEqual(parser.get([('DEFAULT', 'foo')]), ['barbar'])
self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True),
['bar', 'barbar'])
self.assertIn('BLAA', parser.parsed[0])
self.assertIn('bLAa', parser.parsed[0])
self.assertEqual(parser.parsed[0]['BLAA']['bar'], ['foofoo'])
self.assertEqual(parser.parsed[0]['bLAa']['bar'], ['foofoofoo'])
self.assertIn('BLAA', parser.parsed[1])
self.assertEqual(parser.parsed[1]['BLAA']['bar'], ['foo'])
self.assertEqual(parser.get([('BLAA', 'bar')]), ['foofoo'])
self.assertEqual(parser.get([('bLAa', 'bar')]), ['foofoofoo'])
self.assertEqual(parser.get([('BLAA', 'bar')], multi=True),
['foo', 'foofoo'])
self.assertEqual(parser._get([('BLAA', 'bar')],
multi=True, normalized=True),
['foo', 'foofoo', 'foofoofoo'])
class NamespaceTestCase(BaseTestCase):
def setUp(self):
super(NamespaceTestCase, self).setUp()
@ -4909,7 +4831,7 @@ class DeprecationWarningTestBase(BaseTestCase):
def setUp(self):
super(DeprecationWarningTestBase, self).setUp()
self.log_fixture = self.useFixture(fixtures.FakeLogger())
self._parser_class = cfg.MultiConfigParser
self._parser_class = cfg.ConfigParser
class DeprecationWarningTestScenarios(DeprecationWarningTestBase):
@ -4945,7 +4867,7 @@ class DeprecationWarningTestScenarios(DeprecationWarningTestBase):
self.assertEqual('baz', self.conf.other.foo)
self.assertEqual('baz', self.conf.other.foo)
if self.deprecated:
expected = (self._parser_class._deprecated_opt_message %
expected = (cfg._Namespace._deprecated_opt_message %
{'dep_option': 'bar',
'dep_group': self.group,
'option': 'foo',
@ -4979,15 +4901,15 @@ class DeprecationWarningTests(DeprecationWarningTestBase):
self.log_fixture.output)
def test_check_deprecated(self):
parser = self._parser_class()
namespace = cfg._Namespace(None)
deprecated_list = [('DEFAULT', 'bar')]
parser._check_deprecated(('DEFAULT', 'bar'), (None, 'foo'),
deprecated_list)
namespace._check_deprecated(('DEFAULT', 'bar'), (None, 'foo'),
deprecated_list)
self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT')
def assert_message_logged(self, deprecated_name, deprecated_group,
current_name, current_group):
expected = (self._parser_class._deprecated_opt_message %
expected = (cfg._Namespace._deprecated_opt_message %
{'dep_option': deprecated_name,
'dep_group': deprecated_group,
'option': current_name,
@ -5048,7 +4970,7 @@ class DeprecationWarningTests(DeprecationWarningTestBase):
self.conf(['--config-file', paths[0]])
self.assertEqual('baz', self.conf.other.foo)
expected = (self._parser_class._deprecated_opt_message %
expected = (cfg._Namespace._deprecated_opt_message %
{'dep_option': 'bar',
'dep_group': 'other',
'option': 'foo-bar',