bpo-33504: Migrate configparser from OrderedDict to dict. (#6819)
With 3.7+, dictionary are ordered by design. Configparser still uses collections.OrderedDict, which is unnecessary. This updates the module to use the standard dict implementation by default, and changes the docs and tests to match.
This commit is contained in:
parent
5f3d04fa4e
commit
3a5b0d8988
|
@ -445,20 +445,19 @@ the :meth:`__init__` options:
|
||||||
Hint: if you want to specify default values for a specific section, use
|
Hint: if you want to specify default values for a specific section, use
|
||||||
:meth:`read_dict` before you read the actual file.
|
:meth:`read_dict` before you read the actual file.
|
||||||
|
|
||||||
* *dict_type*, default value: :class:`collections.OrderedDict`
|
* *dict_type*, default value: :class:`dict`
|
||||||
|
|
||||||
This option has a major impact on how the mapping protocol will behave and how
|
This option has a major impact on how the mapping protocol will behave and how
|
||||||
the written configuration files look. With the default ordered
|
the written configuration files look. With the standard dictionary, every
|
||||||
dictionary, every section is stored in the order they were added to the
|
section is stored in the order they were added to the parser. Same goes for
|
||||||
parser. Same goes for options within sections.
|
options within sections.
|
||||||
|
|
||||||
An alternative dictionary type can be used for example to sort sections and
|
An alternative dictionary type can be used for example to sort sections and
|
||||||
options on write-back. You can also use a regular dictionary for performance
|
options on write-back.
|
||||||
reasons.
|
|
||||||
|
|
||||||
Please note: there are ways to add a set of key-value pairs in a single
|
Please note: there are ways to add a set of key-value pairs in a single
|
||||||
operation. When you use a regular dictionary in those operations, the order
|
operation. When you use a regular dictionary in those operations, the order
|
||||||
of the keys may be random. For example:
|
of the keys will be ordered. For example:
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
|
|
||||||
|
@ -474,40 +473,9 @@ the :meth:`__init__` options:
|
||||||
... 'baz': 'z'}
|
... 'baz': 'z'}
|
||||||
... })
|
... })
|
||||||
>>> parser.sections() # doctest: +SKIP
|
>>> parser.sections() # doctest: +SKIP
|
||||||
['section3', 'section2', 'section1']
|
['section1', 'section2', 'section3']
|
||||||
>>> [option for option in parser['section3']] # doctest: +SKIP
|
>>> [option for option in parser['section3']] # doctest: +SKIP
|
||||||
['baz', 'foo', 'bar']
|
['foo', 'bar', 'baz']
|
||||||
|
|
||||||
In these operations you need to use an ordered dictionary as well:
|
|
||||||
|
|
||||||
.. doctest::
|
|
||||||
|
|
||||||
>>> from collections import OrderedDict
|
|
||||||
>>> parser = configparser.ConfigParser()
|
|
||||||
>>> parser.read_dict(
|
|
||||||
... OrderedDict((
|
|
||||||
... ('s1',
|
|
||||||
... OrderedDict((
|
|
||||||
... ('1', '2'),
|
|
||||||
... ('3', '4'),
|
|
||||||
... ('5', '6'),
|
|
||||||
... ))
|
|
||||||
... ),
|
|
||||||
... ('s2',
|
|
||||||
... OrderedDict((
|
|
||||||
... ('a', 'b'),
|
|
||||||
... ('c', 'd'),
|
|
||||||
... ('e', 'f'),
|
|
||||||
... ))
|
|
||||||
... ),
|
|
||||||
... ))
|
|
||||||
... )
|
|
||||||
>>> parser.sections() # doctest: +SKIP
|
|
||||||
['s1', 's2']
|
|
||||||
>>> [option for option in parser['s1']] # doctest: +SKIP
|
|
||||||
['1', '3', '5']
|
|
||||||
>>> [option for option in parser['s2'].values()] # doctest: +SKIP
|
|
||||||
['b', 'd', 'f']
|
|
||||||
|
|
||||||
* *allow_no_value*, default value: ``False``
|
* *allow_no_value*, default value: ``False``
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ ConfigParser -- responsible for parsing a list of
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections.abc import MutableMapping
|
from collections.abc import MutableMapping
|
||||||
from collections import OrderedDict as _default_dict, ChainMap as _ChainMap
|
from collections import ChainMap as _ChainMap
|
||||||
import functools
|
import functools
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
|
@ -157,6 +157,7 @@ __all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError",
|
||||||
"LegacyInterpolation", "SectionProxy", "ConverterMapping",
|
"LegacyInterpolation", "SectionProxy", "ConverterMapping",
|
||||||
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
|
"DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"]
|
||||||
|
|
||||||
|
_default_dict = dict
|
||||||
DEFAULTSECT = "DEFAULT"
|
DEFAULTSECT = "DEFAULT"
|
||||||
|
|
||||||
MAX_INTERPOLATION_DEPTH = 10
|
MAX_INTERPOLATION_DEPTH = 10
|
||||||
|
|
|
@ -1109,7 +1109,7 @@ class RawConfigParserTestCase(BasicTestCase, unittest.TestCase):
|
||||||
self.assertEqual(cf.get(123, 'this is sick'), True)
|
self.assertEqual(cf.get(123, 'this is sick'), True)
|
||||||
if cf._dict is configparser._default_dict:
|
if cf._dict is configparser._default_dict:
|
||||||
# would not work for SortedDict; only checking for the most common
|
# would not work for SortedDict; only checking for the most common
|
||||||
# default dictionary (OrderedDict)
|
# default dictionary (dict)
|
||||||
cf.optionxform = lambda x: x
|
cf.optionxform = lambda x: x
|
||||||
cf.set('non-string', 1, 1)
|
cf.set('non-string', 1, 1)
|
||||||
self.assertEqual(cf.get('non-string', 1), 1)
|
self.assertEqual(cf.get('non-string', 1), 1)
|
||||||
|
|
|
@ -1315,6 +1315,7 @@ Marc Recht
|
||||||
John Redford
|
John Redford
|
||||||
Terry J. Reedy
|
Terry J. Reedy
|
||||||
Gareth Rees
|
Gareth Rees
|
||||||
|
John Reese
|
||||||
Steve Reeves
|
Steve Reeves
|
||||||
Lennart Regebro
|
Lennart Regebro
|
||||||
John Regehr
|
John Regehr
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Switch the default dictionary implementation for :mod:`configparser` from
|
||||||
|
:class:`collections.OrderedDict` to the standard :class:`dict` type.
|
Loading…
Reference in New Issue