summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2006-12-03 12:01:53 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2006-12-03 12:01:53 (GMT)
commita00bcac00382be7f99ef30e24ec029268efa0cbf (patch)
tree5b7e4f5aadf7a7eaa371d3cb898833bbf9ab009c
parent046c4d13beea45c2b89b7b80f2654dff5a38eac8 (diff)
downloadcpython-a00bcac00382be7f99ef30e24ec029268efa0cbf.zip
cpython-a00bcac00382be7f99ef30e24ec029268efa0cbf.tar.gz
cpython-a00bcac00382be7f99ef30e24ec029268efa0cbf.tar.bz2
Patch #1371075: Make ConfigParser accept optional dict type
for ordering, sorting, etc.
-rw-r--r--Doc/lib/libcfgparser.tex15
-rw-r--r--Lib/ConfigParser.py15
-rw-r--r--Lib/test/test_cfgparser.py46
-rw-r--r--Misc/NEWS3
4 files changed, 68 insertions, 11 deletions
diff --git a/Doc/lib/libcfgparser.tex b/Doc/lib/libcfgparser.tex
index 42a362e..b0680d2 100644
--- a/Doc/lib/libcfgparser.tex
+++ b/Doc/lib/libcfgparser.tex
@@ -48,11 +48,20 @@ Default values can be specified by passing them into the
may be passed into the \method{get()} method which will override all
others.
-\begin{classdesc}{RawConfigParser}{\optional{defaults}}
+Sections are normally stored in a builtin dictionary. An alternative
+dictionary type can be passed to the \class{ConfigParser} constructor.
+For example, if a dictionary type is passed that sorts is keys,
+the sections will be sorted on write-back, as will be the keys within
+each section.
+
+\begin{classdesc}{RawConfigParser}{\optional{defaults\optional{, dict_type}}}
The basic configuration object. When \var{defaults} is given, it is
-initialized into the dictionary of intrinsic defaults. This class
-does not support the magical interpolation behavior.
+initialized into the dictionary of intrinsic defaults. When \var{dict_type}
+is given, it will be used to create the dictionary objects for the list
+of sections, for the options within a section, and for the default values.
+This class does not support the magical interpolation behavior.
\versionadded{2.3}
+\versionchanged{\var{dict_type} was added}[2.6]
\end{classdesc}
\begin{classdesc}{ConfigParser}{\optional{defaults}}
diff --git a/Lib/ConfigParser.py b/Lib/ConfigParser.py
index 6dc53b9..65c8ce5 100644
--- a/Lib/ConfigParser.py
+++ b/Lib/ConfigParser.py
@@ -199,11 +199,11 @@ class MissingSectionHeaderError(ParsingError):
self.line = line
-
class RawConfigParser:
- def __init__(self, defaults=None):
- self._sections = {}
- self._defaults = {}
+ def __init__(self, defaults=None, dict_type=dict):
+ self._dict = dict_type
+ self._sections = self._dict()
+ self._defaults = self._dict()
if defaults:
for key, value in defaults.items():
self._defaults[self.optionxform(key)] = value
@@ -224,7 +224,7 @@ class RawConfigParser:
"""
if section in self._sections:
raise DuplicateSectionError(section)
- self._sections[section] = {}
+ self._sections[section] = self._dict()
def has_section(self, section):
"""Indicate whether the named section is present in the configuration.
@@ -307,7 +307,7 @@ class RawConfigParser:
except KeyError:
if section != DEFAULTSECT:
raise NoSectionError(section)
- d2 = {}
+ d2 = self._dict()
d = self._defaults.copy()
d.update(d2)
if "__name__" in d:
@@ -453,7 +453,8 @@ class RawConfigParser:
elif sectname == DEFAULTSECT:
cursect = self._defaults
else:
- cursect = {'__name__': sectname}
+ cursect = self._dict()
+ cursect['__name__'] = sectname
self._sections[sectname] = cursect
# So sections can't start with a continuation line
optname = None
diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py
index 66fecf1..3979f15 100644
--- a/Lib/test/test_cfgparser.py
+++ b/Lib/test/test_cfgparser.py
@@ -1,9 +1,29 @@
import ConfigParser
import StringIO
import unittest
+import UserDict
from test import test_support
+class SortedDict(UserDict.UserDict):
+ def items(self):
+ result = self.data.items()
+ result.sort()
+ return result
+
+ def keys(self):
+ result = self.data.keys()
+ result.sort()
+ return result
+
+ def values(self):
+ result = self.items()
+ return [i[1] for i in values]
+
+ def iteritems(self): return iter(self.items())
+ def iterkeys(self): return iter(self.keys())
+ __iter__ = iterkeys
+ def itervalues(self): return iter(self.values())
class TestCaseBase(unittest.TestCase):
def newconfig(self, defaults=None):
@@ -414,12 +434,36 @@ class SafeConfigParserTestCase(ConfigParserTestCase):
self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
self.assertRaises(TypeError, cf.set, "sect", "option2", object())
+class SortedTestCase(RawConfigParserTestCase):
+ def newconfig(self, defaults=None):
+ self.cf = self.config_class(defaults=defaults, dict_type=SortedDict)
+ return self.cf
+
+ def test_sorted(self):
+ self.fromstring("[b]\n"
+ "o4=1\n"
+ "o3=2\n"
+ "o2=3\n"
+ "o1=4\n"
+ "[a]\n"
+ "k=v\n")
+ output = StringIO.StringIO()
+ self.cf.write(output)
+ self.assertEquals(output.getvalue(),
+ "[a]\n"
+ "k = v\n\n"
+ "[b]\n"
+ "o1 = 4\n"
+ "o2 = 3\n"
+ "o3 = 2\n"
+ "o4 = 1\n\n")
def test_main():
test_support.run_unittest(
ConfigParserTestCase,
RawConfigParserTestCase,
- SafeConfigParserTestCase
+ SafeConfigParserTestCase,
+ SortedTestCase
)
if __name__ == "__main__":
diff --git a/Misc/NEWS b/Misc/NEWS
index 0ce50ed..ef6f951 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -101,6 +101,9 @@ Core and builtins
Library
-------
+- Patch #1371075: Make ConfigParser accept optional dict type
+ for ordering, sorting, etc.
+
- Bug #1563807: _ctypes built on AIX fails with ld ffi error.
- Bug #1598620: A ctypes Structure cannot contain itself.