Index: Doc/library/configparser.rst =================================================================== --- Doc/library/configparser.rst (revision 86636) +++ Doc/library/configparser.rst (working copy) @@ -333,10 +333,6 @@ 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 -`_. Customizing Parser Behaviour @@ -947,8 +943,7 @@ 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 Index: Lib/configparser.py =================================================================== --- Lib/configparser.py (revision 86636) +++ Lib/configparser.py (working copy) @@ -29,8 +29,7 @@ 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 @@ -474,8 +473,6 @@ 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): @@ -593,8 +590,6 @@ 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): @@ -675,8 +670,6 @@ """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: @@ -812,7 +805,6 @@ cursect = self._defaults else: cursect = self._dict() - cursect['__name__'] = sectname self._sections[sectname] = cursect self._proxies[sectname] = SectionProxy(self, sectname) elements_added.add(sectname) @@ -1008,8 +1000,6 @@ 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] @@ -1112,9 +1102,6 @@ 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 @@ -1130,37 +1117,27 @@ return ''.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__() Index: Lib/test/test_cfgparser.py =================================================================== --- Lib/test/test_cfgparser.py (revision 86636) +++ Lib/test/test_cfgparser.py (working copy) @@ -146,22 +146,6 @@ 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: @@ -640,17 +624,15 @@ "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": ""}) L = list(cf.items("section")) L.sort() @@ -673,7 +655,6 @@ } 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)") @@ -699,7 +680,6 @@ def test_items(self): self.check_items_config([('default', ''), ('getdefault', '||'), - ('getname', '|section|'), ('key', '|value|'), ('name', 'value')]) @@ -765,7 +745,6 @@ 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"), @@ -778,7 +757,6 @@ def test_items(self): self.check_items_config([('default', ''), ('getdefault', '|%(default)s|'), - ('getname', '|%(__name__)s|'), ('key', '|%(name)s|'), ('name', 'value')])