The mapping protocol is implemented on top of the existing legacy API so that
subclassing the original interface makes the mappings work as expected as well.
-One difference is the explicit lack of support for the ``'__name__'`` special
-key. This is because the existing behavior of ``'__name__'`` is very
-inconsistent and supporting it would only lead to problems. Details `here
-<http://mail.python.org/pipermail/python-dev/2010-July/102556.html>`_.
Customizing Parser Behaviour
need interpolation.
The values in *defaults* must be appropriate for the ``%()s`` string
- interpolation. Note that ``'__name__'`` is an intrinsic default; its value
- is the section name, and will override any value provided in *defaults*.
+ interpolation.
All option names used in interpolation will be passed through the
:meth:`optionxform` method just like any other option name reference. For
strict=False, empty_lines_in_values=True):
Create the parser. When `defaults' is given, it is initialized into the
dictionary or intrinsic defaults. The keys must be strings, the values
- must be appropriate for %()s string interpolation. Note that `__name__'
- is always an intrinsic default; its value is the section's name.
+ must be appropriate for %()s string interpolation.
When `dict_type' is given, it will be used to create the dictionary
objects for the list of sections, for the options within a section, and
except KeyError:
raise NoSectionError(section)
opts.update(self._defaults)
- if '__name__' in opts:
- del opts['__name__']
return list(opts.keys())
def read(self, filenames, encoding=None):
d2 = self._dict()
d = self._defaults.copy()
d.update(d2)
- if "__name__" in d:
- del d["__name__"]
return d.items()
def _get(self, section, conv, option, **kwargs):
"""Write a single section to the specified `fp'."""
fp.write("[{}]\n".format(section_name))
for key, value in section_items:
- if key == "__name__":
- continue
if value is not None or not self._allow_no_value:
value = delimiter + str(value).replace('\n', '\n\t')
else:
cursect = self._defaults
else:
cursect = self._dict()
- cursect['__name__'] = sectname
self._sections[sectname] = cursect
self._proxies[sectname] = SectionProxy(self, sectname)
elements_added.add(sectname)
for key, value in vars.items():
d[self.optionxform(key)] = value
options = list(d.keys())
- if "__name__" in options:
- options.remove("__name__")
if raw:
return [(option, d[option])
for option in options]
class SectionProxy(MutableMapping):
"""A proxy for a single section from a parser."""
- _noname = ("__name__ special key access and modification "
- "not supported through the mapping interface.")
-
def __init__(self, parser, section_name):
"""Creates a view on a section named `section_name` in `parser`."""
self._parser = parser
return '<Section: {}>'.format(self._section)
def __getitem__(self, key):
- if key == '__name__':
- raise ValueError(self._noname)
if not self._parser.has_option(self._section, key):
raise KeyError(key)
return self._parser.get(self._section, key)
def __setitem__(self, key, value):
- if key == '__name__':
- raise ValueError(self._noname)
self._parser._validate_value_type(value)
return self._parser.set(self._section, key, value)
def __delitem__(self, key):
- if key == '__name__':
- raise ValueError(self._noname)
if not self._parser.has_option(self._section, key):
raise KeyError(key)
return self._parser.remove_option(self._section, key)
def __contains__(self, key):
- if key == '__name__':
- return False
return self._parser.has_option(self._section, key)
def __len__(self):
- # __name__ is properly hidden by .options()
# XXX weak performance
return len(self._parser.options(self._section))
def __iter__(self):
- # __name__ is properly hidden by .options()
# XXX weak performance
# XXX does not break when underlying container state changed
return self._parser.options(self._section).__iter__()
if self.allow_no_value:
eq(cf['NoValue']['option-without-value'], None)
- # API access
- self.assertNotIn('__name__', cf.options("Foo Bar"),
- '__name__ "option" should not be exposed by the API!')
-
- # mapping access
- self.assertNotIn('__name__', cf['Foo Bar'],
- '__name__ "option" should not be exposed by '
- 'mapping protocol access')
- self.assertFalse('__name__' in cf['Foo Bar'])
- with self.assertRaises(ValueError):
- cf['Foo Bar']['__name__']
- with self.assertRaises(ValueError):
- del cf['Foo Bar']['__name__']
- with self.assertRaises(ValueError):
- cf['Foo Bar']['__name__'] = "can't write to this special name"
-
# Make sure the right things happen for remove_option();
# added to include check for SourceForge bug #123324:
"bar{equals}%(foo)s\n"
"\n"
"[Interpolation Error]\n"
- "name{equals}%(reference)s\n".format(equals=self.delimiters[0]),
# no definition for 'reference'
- defaults={"getname": "%(__name__)s"})
+ "name{equals}%(reference)s\n".format(equals=self.delimiters[0]))
def check_items_config(self, expected):
cf = self.fromstring(
"[section]\n"
"name {0[0]} value\n"
"key{0[1]} |%(name)s| \n"
- "getdefault{0[1]} |%(default)s|\n"
- "getname{0[1]} |%(__name__)s|".format(self.delimiters),
+ "getdefault{0[1]} |%(default)s|\n".format(self.delimiters),
defaults={"default": "<default>"})
L = list(cf.items("section"))
L.sort()
}
cf = self.get_interpolation_config()
eq = self.assertEqual
- eq(cf.get("Foo", "getname"), "Foo")
eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
eq(cf.get("Foo", "bar9"),
"something with lots of interpolation (9 steps)")
def test_items(self):
self.check_items_config([('default', '<default>'),
('getdefault', '|<default>|'),
- ('getname', '|section|'),
('key', '|value|'),
('name', 'value')])
def test_interpolation(self):
cf = self.get_interpolation_config()
eq = self.assertEqual
- eq(cf.get("Foo", "getname"), "%(__name__)s")
eq(cf.get("Foo", "bar"),
"something %(with1)s interpolation (1 step)")
eq(cf.get("Foo", "bar9"),
def test_items(self):
self.check_items_config([('default', '<default>'),
('getdefault', '|%(default)s|'),
- ('getname', '|%(__name__)s|'),
('key', '|%(name)s|'),
('name', 'value')])