]> granicus.if.org Git - python/commitdiff
Issue #11089: Fix performance issue limiting the use of ConfigParser()
authorRaymond Hettinger <python@rcn.com>
Wed, 2 Feb 2011 21:35:48 +0000 (21:35 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 2 Feb 2011 21:35:48 +0000 (21:35 +0000)
with large config files.

Lib/configparser.py
Misc/NEWS

index 14ddd8576753f0c9132c2e2aa705e7f3f8e1c218..edd3ac3bb5565ee8d53c5c19c9b4448fb475ae8e 100644 (file)
@@ -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]
index 362e52ce22313bdf167b6a3b3fe5ae1e1cecaf18..ba75e82d7a6c361118f28f39077bf0deb05e0ff0 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -37,6 +37,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #11089: Fix performance issue limiting the use of ConfigParser()
+  with large config files.
+
 - Issue #8275: Fix passing of callback arguments with ctypes under Win64.
   Patch by Stan Mihai.