From 42664c5a2172973840f4b9b928cce2dc1bbfd185 Mon Sep 17 00:00:00 2001 From: John Reese Date: Mon, 14 May 2018 14:19:16 -0400 Subject: [PATCH] bpo-33504: Migrate configparser from OrderedDict to dict. 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. --- Doc/library/configparser.rst | 50 ++++--------------- Lib/configparser.py | 3 +- Lib/test/test_configparser.py | 2 +- Misc/ACKS | 1 + .../2018-05-15-12-11-13.bpo-33504.czsHFg.rst | 2 + 5 files changed, 15 insertions(+), 43 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-05-15-12-11-13.bpo-33504.czsHFg.rst diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index f51c580c0de1c0..5a2178f11b0e0f 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -445,20 +445,19 @@ the :meth:`__init__` options: Hint: if you want to specify default values for a specific section, use :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 - the written configuration files look. With the default ordered - dictionary, every section is stored in the order they were added to the - parser. Same goes for options within sections. + the written configuration files look. With the standard dictionary, every + section is stored in the order they were added to the parser. Same goes for + options within sections. 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 - reasons. + options on write-back. 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 - of the keys may be random. For example: + of the keys will be ordered. For example: .. doctest:: @@ -474,40 +473,9 @@ the :meth:`__init__` options: ... 'baz': 'z'} ... }) >>> parser.sections() # doctest: +SKIP - ['section3', 'section2', 'section1'] - >>> [option for option in parser['section3']] # doctest: +SKIP - ['baz', 'foo', 'bar'] - - 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'] + ['section1', 'section2', 'section3'] + >>> [option for option in parser['section3']] # doctest: +SKIP + ['foo', 'bar', 'baz'] * *allow_no_value*, default value: ``False`` diff --git a/Lib/configparser.py b/Lib/configparser.py index a681d3990e7261..c88605feff7877 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -139,7 +139,7 @@ """ from collections.abc import MutableMapping -from collections import OrderedDict as _default_dict, ChainMap as _ChainMap +from collections import ChainMap as _ChainMap import functools import io import itertools @@ -157,6 +157,7 @@ "LegacyInterpolation", "SectionProxy", "ConverterMapping", "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] +_default_dict = dict DEFAULTSECT = "DEFAULT" MAX_INTERPOLATION_DEPTH = 10 diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 87b811f09b6ead..f4df622050b911 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1109,7 +1109,7 @@ def test_set_nonstring_types(self): self.assertEqual(cf.get(123, 'this is sick'), True) if cf._dict is configparser._default_dict: # would not work for SortedDict; only checking for the most common - # default dictionary (OrderedDict) + # default dictionary (dict) cf.optionxform = lambda x: x cf.set('non-string', 1, 1) self.assertEqual(cf.get('non-string', 1), 1) diff --git a/Misc/ACKS b/Misc/ACKS index 587bbecbc36a3a..e578f1f35f517f 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1310,6 +1310,7 @@ Marc Recht John Redford Terry J. Reedy Gareth Rees +John Reese Steve Reeves Lennart Regebro John Regehr diff --git a/Misc/NEWS.d/next/Library/2018-05-15-12-11-13.bpo-33504.czsHFg.rst b/Misc/NEWS.d/next/Library/2018-05-15-12-11-13.bpo-33504.czsHFg.rst new file mode 100644 index 00000000000000..d5065d9224e7e4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-12-11-13.bpo-33504.czsHFg.rst @@ -0,0 +1,2 @@ +Switch the default dictionary implementation for :mod:`configparser` from +:class:`collections.OrderedDict` to the standard :class:`dict` type.