Author xtreak
Recipients Phil Kang, inada.naoki, lukasz.langa, xtreak
Date 2019-01-28.14:27:27
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1548685648.21.0.13907746587.issue35838@roundup.psfhosted.org>
In-reply-to
Content
This seems to be a bug with read_dict which is used internally when a dictionary is directly assigned. In read_dict optionxform is called with key [0] to check for duplicate and the transformed value is again passed to self.set which also calls optionxform [1] causing optionxform to be applied twice. A possible fix would be to assign the transformed key to a temporary variable to check for duplicate and then pass the original key to self.set ? My patch gives correct value and no tests fail on master. I can make a PR with test for this if my analysis is correct.

This fixes the below since the key is stored correctly now. 

print(ini['section A']['key 1'])    # OK
print(ini['section A']['(key 1)'])  # Raises KeyError

I think for iterating over the section items [2] need to be used and the reported code can be written as below

for key, value in ini.items('section A'):
    print(key + ', ' + value)

[0] https://github.com/python/cpython/blob/ea446409cd5f1364beafd5e5255da6799993f285/Lib/configparser.py#L748
[1] https://github.com/python/cpython/blob/ea446409cd5f1364beafd5e5255da6799993f285/Lib/configparser.py#L903
[2] https://docs.python.org/3.8/library/configparser.html#configparser.ConfigParser.items

# sample reproducer

import io
import configparser

ini = configparser.ConfigParser()
ini.optionxform = lambda x: '(' + x + ')'
ini.read_dict({'section A': {'key 1': 'value 1'}})

inifile = io.StringIO()
ini.write(inifile)
print(inifile.getvalue())

$ ./python.exe ../backups/bpo35838_1.py
[section A]
((key 1)) = value 1

# Possible patch

$ git diff -w | cat
diff --git a/Lib/configparser.py b/Lib/configparser.py
index 79a991084b..1389f4ac08 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -745,13 +745,13 @@ class RawConfigParser(MutableMapping):
                     raise
             elements_added.add(section)
             for key, value in keys.items():
-                key = self.optionxform(str(key))
+                option_key = self.optionxform(str(key))
                 if value is not None:
                     value = str(value)
-                if self._strict and (section, key) in elements_added:
-                    raise DuplicateOptionError(section, key, source)
-                elements_added.add((section, key))
-                self.set(section, key, value)
+                if self._strict and (section, option_key) in elements_added:
+                    raise DuplicateOptionError(section, option_key, source)
+                elements_added.add((section, option_key))
+                self.set(section, str(key), value)

     def readfp(self, fp, filename=None):
         """Deprecated, use read_file instead."""


$ ./python.exe ../backups/bpo35838_1.py
[section A]
(key 1) = value 1
History
Date User Action Args
2019-01-28 14:27:29xtreaksetrecipients: + xtreak, inada.naoki, lukasz.langa, Phil Kang
2019-01-28 14:27:28xtreaksetmessageid: <1548685648.21.0.13907746587.issue35838@roundup.psfhosted.org>
2019-01-28 14:27:28xtreaklinkissue35838 messages
2019-01-28 14:27:27xtreakcreate