From 7683c9676656198517311c7a875a954a3a6a6409 Mon Sep 17 00:00:00 2001 From: Andrey Efremov Date: Sun, 24 Nov 2024 22:07:42 +0700 Subject: [PATCH 1/2] Do not recreate unnamed section on every read in ConfigParser --- Lib/configparser.py | 10 ++++++---- Lib/test/test_configparser.py | 9 +++++++++ .../2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst diff --git a/Lib/configparser.py b/Lib/configparser.py index 420dce77c234e1..b978c67b500a59 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -1106,10 +1106,12 @@ def _handle_rest(self, st, line, fpname): # a section header or option header? if self._allow_unnamed_section and st.cursect is None: st.sectname = UNNAMED_SECTION - st.cursect = self._dict() - self._sections[st.sectname] = st.cursect - self._proxies[st.sectname] = SectionProxy(self, st.sectname) - st.elements_added.add(st.sectname) + if st.sectname in self._sections: + st.cursect = self._sections[st.sectname] + else: + st.cursect = self._dict() + self._sections[st.sectname] = st.cursect + self._proxies[st.sectname] = SectionProxy(self, st.sectname) st.indent_level = st.cur_indent_level # is it a section header? diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index e3c5d08dd1e7d1..bde805eb741c33 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -2174,6 +2174,15 @@ def test_disabled_error(self): with self.assertRaises(configparser.UnnamedSectionDisabledError): configparser.ConfigParser().add_section(configparser.UNNAMED_SECTION) + def test_multiple_configs(self): + cfg = configparser.ConfigParser(allow_unnamed_section=True) + cfg.read_string('a = 1') + cfg.read_string('b = 2') + + self.assertEqual([configparser.UNNAMED_SECTION], cfg.sections()) + self.assertEqual('1', cfg[configparser.UNNAMED_SECTION]['a']) + self.assertEqual('2', cfg[configparser.UNNAMED_SECTION]['b']) + class MiscTestCase(unittest.TestCase): def test__all__(self): diff --git a/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst b/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst new file mode 100644 index 00000000000000..8619296143b7d7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst @@ -0,0 +1,2 @@ +Do not recreate unnamed section on every read in +:class:`configparser.ConfigParser`. Patch by Andrey Efremov. From ffa2ea900d293c14f040c16c484c8feccba8a934 Mon Sep 17 00:00:00 2001 From: Andrey Efremov Date: Mon, 25 Nov 2024 00:13:17 +0700 Subject: [PATCH 2/2] Remove duplicate section creation code --- Lib/configparser.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py index b978c67b500a59..9dc4fa515cfcbe 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -1105,13 +1105,7 @@ def _handle_continuation_line(self, st, line, fpname): def _handle_rest(self, st, line, fpname): # a section header or option header? if self._allow_unnamed_section and st.cursect is None: - st.sectname = UNNAMED_SECTION - if st.sectname in self._sections: - st.cursect = self._sections[st.sectname] - else: - st.cursect = self._dict() - self._sections[st.sectname] = st.cursect - self._proxies[st.sectname] = SectionProxy(self, st.sectname) + self._handle_header(st, UNNAMED_SECTION, fpname) st.indent_level = st.cur_indent_level # is it a section header? @@ -1120,10 +1114,10 @@ def _handle_rest(self, st, line, fpname): if not mo and st.cursect is None: raise MissingSectionHeaderError(fpname, st.lineno, line) - self._handle_header(st, mo, fpname) if mo else self._handle_option(st, line, fpname) + self._handle_header(st, mo.group('header'), fpname) if mo else self._handle_option(st, line, fpname) - def _handle_header(self, st, mo, fpname): - st.sectname = mo.group('header') + def _handle_header(self, st, sectname, fpname): + st.sectname = sectname if st.sectname in self._sections: if self._strict and st.sectname in st.elements_added: raise DuplicateSectionError(st.sectname, fpname,