mirror of https://github.com/python/cpython.git
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
|
may be passed into the \method{get()} method which will override all
|
||||||
others.
|
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
|
The basic configuration object. When \var{defaults} is given, it is
|
||||||
initialized into the dictionary of intrinsic defaults. This class
|
initialized into the dictionary of intrinsic defaults. When \var{dict_type}
|
||||||
does not support the magical interpolation behavior.
|
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}
|
\versionadded{2.3}
|
||||||
|
\versionchanged{\var{dict_type} was added}[2.6]
|
||||||
\end{classdesc}
|
\end{classdesc}
|
||||||
|
|
||||||
\begin{classdesc}{ConfigParser}{\optional{defaults}}
|
\begin{classdesc}{ConfigParser}{\optional{defaults}}
|
||||||
|
|
|
@ -199,11 +199,11 @@ def __init__(self, filename, lineno, line):
|
||||||
self.line = line
|
self.line = line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RawConfigParser:
|
class RawConfigParser:
|
||||||
def __init__(self, defaults=None):
|
def __init__(self, defaults=None, dict_type=dict):
|
||||||
self._sections = {}
|
self._dict = dict_type
|
||||||
self._defaults = {}
|
self._sections = self._dict()
|
||||||
|
self._defaults = self._dict()
|
||||||
if defaults:
|
if defaults:
|
||||||
for key, value in defaults.items():
|
for key, value in defaults.items():
|
||||||
self._defaults[self.optionxform(key)] = value
|
self._defaults[self.optionxform(key)] = value
|
||||||
|
@ -224,7 +224,7 @@ def add_section(self, section):
|
||||||
"""
|
"""
|
||||||
if section in self._sections:
|
if section in self._sections:
|
||||||
raise DuplicateSectionError(section)
|
raise DuplicateSectionError(section)
|
||||||
self._sections[section] = {}
|
self._sections[section] = self._dict()
|
||||||
|
|
||||||
def has_section(self, section):
|
def has_section(self, section):
|
||||||
"""Indicate whether the named section is present in the configuration.
|
"""Indicate whether the named section is present in the configuration.
|
||||||
|
@ -307,7 +307,7 @@ def items(self, section):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if section != DEFAULTSECT:
|
if section != DEFAULTSECT:
|
||||||
raise NoSectionError(section)
|
raise NoSectionError(section)
|
||||||
d2 = {}
|
d2 = self._dict()
|
||||||
d = self._defaults.copy()
|
d = self._defaults.copy()
|
||||||
d.update(d2)
|
d.update(d2)
|
||||||
if "__name__" in d:
|
if "__name__" in d:
|
||||||
|
@ -453,7 +453,8 @@ def _read(self, fp, fpname):
|
||||||
elif sectname == DEFAULTSECT:
|
elif sectname == DEFAULTSECT:
|
||||||
cursect = self._defaults
|
cursect = self._defaults
|
||||||
else:
|
else:
|
||||||
cursect = {'__name__': sectname}
|
cursect = self._dict()
|
||||||
|
cursect['__name__'] = sectname
|
||||||
self._sections[sectname] = cursect
|
self._sections[sectname] = cursect
|
||||||
# So sections can't start with a continuation line
|
# So sections can't start with a continuation line
|
||||||
optname = None
|
optname = None
|
||||||
|
|
|
@ -1,9 +1,29 @@
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
import StringIO
|
import StringIO
|
||||||
import unittest
|
import unittest
|
||||||
|
import UserDict
|
||||||
|
|
||||||
from test import test_support
|
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):
|
class TestCaseBase(unittest.TestCase):
|
||||||
def newconfig(self, defaults=None):
|
def newconfig(self, defaults=None):
|
||||||
|
@ -414,12 +434,36 @@ def test_set_nonstring_types(self):
|
||||||
self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
|
self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0)
|
||||||
self.assertRaises(TypeError, cf.set, "sect", "option2", object())
|
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():
|
def test_main():
|
||||||
test_support.run_unittest(
|
test_support.run_unittest(
|
||||||
ConfigParserTestCase,
|
ConfigParserTestCase,
|
||||||
RawConfigParserTestCase,
|
RawConfigParserTestCase,
|
||||||
SafeConfigParserTestCase
|
SafeConfigParserTestCase,
|
||||||
|
SortedTestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -101,6 +101,9 @@ Core and builtins
|
||||||
Library
|
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 #1563807: _ctypes built on AIX fails with ld ffi error.
|
||||||
|
|
||||||
- Bug #1598620: A ctypes Structure cannot contain itself.
|
- Bug #1598620: A ctypes Structure cannot contain itself.
|
||||||
|
|
Loading…
Reference in New Issue