зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1255450 - [mach] Implement 'wildcard' settings for enabling sections with user-defined options, r=gps
Some sections should support user-defined options. For example, in an [alias] section, the option names are not well-defined, rather specified by the user. This patch allows user-defined option names for any section that has a 'section.*' option defined. Even with 'section.*', option types are still well-defined. MozReview-Commit-ID: L34W9v9Fy28 --HG-- extra : rebase_source : 9333f552edead9bf1cf464e28ef8fbbb9bed5597
This commit is contained in:
Родитель
5167efa8e4
Коммит
c105e8a3b4
|
@ -54,6 +54,26 @@ pairs to add to the setting's metadata. The following keys may be specified
|
|||
in the ``extra`` dict:
|
||||
* ``choices`` - A set of allowed values for the setting.
|
||||
|
||||
Wildcards
|
||||
---------
|
||||
|
||||
Sometimes a section should allow arbitrarily defined options from the user, such
|
||||
as the ``alias`` section mentioned above. To define a section like this, use ``*``
|
||||
as the option name. For example:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
('foo.*', 'string')
|
||||
|
||||
This allows configuration files like this:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[foo]
|
||||
arbitrary1 = some string
|
||||
arbitrary2 = some other string
|
||||
|
||||
|
||||
|
||||
Accessing Settings
|
||||
==================
|
||||
|
|
|
@ -213,6 +213,9 @@ class ConfigSettings(collections.Mapping):
|
|||
object.__setattr__(self, '_name', name)
|
||||
object.__setattr__(self, '_settings', settings)
|
||||
|
||||
wildcard = any(s == '*' for s in self._settings)
|
||||
object.__setattr__(self, '_wildcard', wildcard)
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
try:
|
||||
|
@ -220,11 +223,15 @@ class ConfigSettings(collections.Mapping):
|
|||
except NoSectionError:
|
||||
return []
|
||||
|
||||
def _validate(self, option, value):
|
||||
if option not in self._settings:
|
||||
raise KeyError('Option not registered with provider: %s' % option)
|
||||
def get_meta(self, option):
|
||||
if option in self._settings:
|
||||
return self._settings[option]
|
||||
if self._wildcard:
|
||||
return self._settings['*']
|
||||
raise KeyError('Option not registered with provider: %s' % option)
|
||||
|
||||
meta = self._settings[option]
|
||||
def _validate(self, option, value):
|
||||
meta = self.get_meta(option)
|
||||
meta['type_cls'].validate(value)
|
||||
|
||||
if 'choices' in meta and value not in meta['choices']:
|
||||
|
@ -242,7 +249,7 @@ class ConfigSettings(collections.Mapping):
|
|||
return self._config.has_option(self._name, k)
|
||||
|
||||
def __getitem__(self, k):
|
||||
meta = self._settings[k]
|
||||
meta = self.get_meta(k)
|
||||
|
||||
if self._config.has_option(self._name, k):
|
||||
v = meta['type_cls'].from_config(self._config, self._name, k)
|
||||
|
@ -255,11 +262,10 @@ class ConfigSettings(collections.Mapping):
|
|||
self._validate(k, v)
|
||||
return v
|
||||
|
||||
|
||||
def __setitem__(self, k, v):
|
||||
self._validate(k, v)
|
||||
meta = self.get_meta(k)
|
||||
|
||||
meta = self._settings[k]
|
||||
if not self._config.has_section(self._name):
|
||||
self._config.add_section(self._name)
|
||||
|
||||
|
@ -416,7 +422,7 @@ class ConfigSettings(collections.Mapping):
|
|||
def option_help(self, section, option):
|
||||
"""Obtain the translated help messages for an option."""
|
||||
|
||||
meta = self[section]._settings[option]
|
||||
meta = self[section].get_meta(option)
|
||||
|
||||
# Providers should always have an en-US translation. If they don't,
|
||||
# they are coded wrong and this will raise.
|
||||
|
|
|
@ -88,6 +88,14 @@ class Provider4(object):
|
|||
]
|
||||
|
||||
|
||||
@SettingsProvider
|
||||
class Provider5(object):
|
||||
config_settings = [
|
||||
('foo.*', 'string'),
|
||||
('foo.bar', 'string'),
|
||||
]
|
||||
|
||||
|
||||
class TestConfigSettings(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
s = ConfigSettings()
|
||||
|
@ -211,6 +219,24 @@ class TestConfigSettings(unittest.TestCase):
|
|||
foo.abc = 'b'
|
||||
foo.xyz = 'y'
|
||||
|
||||
def test_wildcard_options(self):
|
||||
s = ConfigSettings()
|
||||
s.register_provider(Provider5)
|
||||
|
||||
foo = s.foo
|
||||
|
||||
self.assertIn('*', foo._settings)
|
||||
self.assertNotIn('*', foo)
|
||||
|
||||
foo.baz = 'value1'
|
||||
foo.bar = 'value2'
|
||||
|
||||
self.assertIn('baz', foo)
|
||||
self.assertEqual(foo.baz, 'value1')
|
||||
|
||||
self.assertIn('bar', foo)
|
||||
self.assertEqual(foo.bar, 'value2')
|
||||
|
||||
def test_file_reading_single(self):
|
||||
temp = NamedTemporaryFile(mode='wt')
|
||||
temp.write(CONFIG1)
|
||||
|
|
Загрузка…
Ссылка в новой задаче