Patch #1371075: Make ConfigParser accept optional dict type
for ordering, sorting, etc.
This commit is contained in:
parent
046c4d13be
commit
a00bcac003
|
@ -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}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__":
|
||||
|
|
Loading…
Reference in New Issue