mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	Patch #1371075: Make ConfigParser accept optional dict type
for ordering, sorting, etc.
This commit is contained in:
		
							parent
							
								
									046c4d13be
								
							
						
					
					
						commit
						a00bcac003
					
				
					 4 changed files with 68 additions and 11 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Martin v. Löwis
						Martin v. Löwis