summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2011-02-02 21:35:48 (GMT)
committerRaymond Hettinger <python@rcn.com>2011-02-02 21:35:48 (GMT)
commit65548873cfdef1fbd99a71e84a81283558342d64 (patch)
tree6d236a45c12552e357c46f18d7669dbbffd9c40b /Lib
parent9f1ab8530c20d38f66afbc55cf96d144681464f8 (diff)
downloadcpython-65548873cfdef1fbd99a71e84a81283558342d64.zip
cpython-65548873cfdef1fbd99a71e84a81283558342d64.tar.gz
cpython-65548873cfdef1fbd99a71e84a81283558342d64.tar.bz2
Issue #11089: Fix performance issue limiting the use of ConfigParser()
with large config files.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/configparser.py42
1 files changed, 38 insertions, 4 deletions
diff --git a/Lib/configparser.py b/Lib/configparser.py
index 14ddd85..edd3ac3 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -88,7 +88,7 @@ ConfigParser -- responsible for parsing a list of
"""
try:
- from collections import OrderedDict as _default_dict
+ from collections import Mapping, OrderedDict as _default_dict
except ImportError:
# fallback for setup.py which hasn't yet built _collections
_default_dict = dict
@@ -515,6 +515,38 @@ class RawConfigParser:
if e:
raise e
+class _Chainmap(Mapping):
+ """Combine multiple mappings for successive lookups.
+
+ For example, to emulate Python's normal lookup sequence:
+
+ import __builtin__
+ pylookup = _Chainmap(locals(), globals(), vars(__builtin__))
+ """
+
+ def __init__(self, *maps):
+ self.maps = maps
+
+ def __getitem__(self, key):
+ for mapping in self.maps:
+ try:
+ return mapping[key]
+ except KeyError:
+ pass
+ raise KeyError(key)
+
+ def __iter__(self):
+ seen = set()
+ for mapping in self.maps:
+ s = set(mapping) - seen
+ for elem in s:
+ yield elem
+ seen.update(s)
+
+ def __len__(self):
+ s = set()
+ s.update(*self.maps)
+ return len(s)
class ConfigParser(RawConfigParser):
@@ -530,16 +562,18 @@ class ConfigParser(RawConfigParser):
The section DEFAULT is special.
"""
- d = self._defaults.copy()
+ sectiondict = {}
try:
- d.update(self._sections[section])
+ sectiondict = self._sections[section]
except KeyError:
if section != DEFAULTSECT:
raise NoSectionError(section)
# Update with the entry specific variables
+ vardict = {}
if vars:
for key, value in vars.items():
- d[self.optionxform(key)] = value
+ vardict[self.optionxform(key)] = value
+ d = _Chainmap(vardict, sectiondict, self._defaults)
option = self.optionxform(option)
try:
value = d[option]