Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: chainedconfigparser.py

Issue 29319007: Issue 2711 - Refactored ChainedConfigParser, allowing manipulation of list items (Closed)
Left Patch Set: Don't convert options to lowercase and decode config files as UTF-8 Created July 7, 2015, 1:06 p.m.
Right Patch Set: Addressed comments Created July 7, 2015, 3:18 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | packager.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # coding: utf-8 1 # coding: utf-8
2 2
3 # This Source Code Form is subject to the terms of the Mozilla Public 3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 6
7 import os 7 import os
8 import io 8 import io
9 import ConfigParser 9 import ConfigParser
10 from StringIO import StringIO 10 from StringIO import StringIO
(...skipping 26 matching lines...) Expand all
37 whitespace-separated lists given by an inherited option: 37 whitespace-separated lists given by an inherited option:
38 38
39 [section] 39 [section]
40 opt1 += foo 40 opt1 += foo
41 opt2 -= bar 41 opt2 -= bar
42 42
43 The value of the inherit option has to be a relative path with forward 43 The value of the inherit option has to be a relative path with forward
44 slashes as delimiters. Up to 5 configuration files can be chained this way, 44 slashes as delimiters. Up to 5 configuration files can be chained this way,
45 longer chains are disallowed to deal with circular references. 45 longer chains are disallowed to deal with circular references.
46 46
47 As opposed to ChainedConfigParser, files are decoded as UTF-8 while reading. 47 As opposed to SafeConfigParser, files are decoded as UTF-8 while
Wladimir Palant 2015/07/07 14:53:17 Did you mean SafeConfigParser?
Sebastian Noack 2015/07/07 15:20:43 Yes, corrected.
48 Also, ChainedConfigParser data is read-only and the options are case-sensiti ve. 48 reading. Also, ChainedConfigParser data is read-only. An additional
Wladimir Palant 2015/07/07 14:53:17 Nit: "case-sensitive by default" (it's configurabl
Sebastian Noack 2015/07/07 15:20:43 Not really. There were some code assumptions, rely
49 An additional option_source(section, option) method is provided to get the 49 option_source(section, option) method is provided to get the path
50 path of the configuration file defining this option (for relative paths). 50 of the configuration file defining this option (for relative paths).
51 Items returned by the items() function also have a source attribute serving 51 Items returned by the items() function also have a source attribute
52 the same purpose. 52 serving the same purpose.
53 ''' 53 '''
54 54
55 def __init__(self): 55 def __init__(self):
56 ConfigParser.SafeConfigParser.__init__(self) 56 ConfigParser.SafeConfigParser.__init__(self)
57 self._origin = {} 57 self._origin = {}
58 58
59 def _make_parser(self, filename): 59 def _make_parser(self, filename):
60 parser = ConfigParser.SafeConfigParser() 60 parser = ConfigParser.SafeConfigParser()
61 parser.optionxform = self.optionxform 61 parser.optionxform = lambda option: option
62 62
63 with io.open(filename, encoding='utf-8') as file: 63 with io.open(filename, encoding='utf-8') as file:
64 parser.readfp(file, filename) 64 parser.readfp(file, filename)
65 65
66 return parser 66 return parser
67 67
68 def _get_parser_chain(self, parser, filename): 68 def _get_parser_chain(self, parser, filename):
69 parsers = [] 69 parsers = []
70 70
71 while True: 71 while True:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 # add_section() hardcodes 'default' and raises a ValueError if 112 # add_section() hardcodes 'default' and raises a ValueError if
113 # you try to add a section called like that (case insensitive). 113 # you try to add a section called like that (case insensitive).
114 # This bug has been fixed in Python 3. 114 # This bug has been fixed in Python 3.
115 ConfigParser.SafeConfigParser.readfp(self, StringIO('[%s]' % section )) 115 ConfigParser.SafeConfigParser.readfp(self, StringIO('[%s]' % section ))
116 116
117 for option, value in parser.items(section): 117 for option, value in parser.items(section):
118 is_diff, option, value = self._apply_diff(section, option, value) 118 is_diff, option, value = self._apply_diff(section, option, value)
119 ConfigParser.SafeConfigParser.set(self, section, option, value) 119 ConfigParser.SafeConfigParser.set(self, section, option, value)
120 120
121 if not is_diff: 121 if not is_diff:
122 self._origin[(section, option)] = filename 122 self._origin[(section, self.optionxform(option))] = filename
123 123
124 def read(self, filenames): 124 def read(self, filenames):
125 if isinstance(filenames, basestring): 125 if isinstance(filenames, basestring):
126 filenames = [filenames] 126 filenames = [filenames]
127 127
128 read_ok = [] 128 read_ok = []
129 for filename in filenames: 129 for filename in filenames:
130 try: 130 try:
131 parser = self._make_parser(filename) 131 parser = self._make_parser(filename)
132 except IOError: 132 except IOError:
133 continue 133 continue
134 self._process_parsers(self._get_parser_chain(parser, filename)) 134 self._process_parsers(self._get_parser_chain(parser, filename))
135 read_ok.append(filename) 135 read_ok.append(filename)
136 136
137 return read_ok 137 return read_ok
138 138
139 def items(self, section, *args, **kwargs): 139 def items(self, section, *args, **kwargs):
140 items = [] 140 items = []
141 for option, value in ConfigParser.SafeConfigParser.items(self, section, *arg s, **kwargs): 141 for option, value in ConfigParser.SafeConfigParser.items(self, section, *arg s, **kwargs):
142 items.append(Item(option, value, self._origin[(section, option)])) 142 items.append(Item(
143 option, value,
144 self._origin[(section, self.optionxform(option))]
145 ))
143 return items 146 return items
144 147
145 def option_source(self, section, option): 148 def option_source(self, section, option):
149 option = self.optionxform(option)
146 try: 150 try:
147 return self._origin[(section, option)] 151 return self._origin[(section, option)]
148 except KeyError: 152 except KeyError:
149 if not self.has_section(section): 153 if not self.has_section(section):
150 raise ConfigParser.NoSectionError(section) 154 raise ConfigParser.NoSectionError(section)
151 raise ConfigParser.NoOptionError(option, section) 155 raise ConfigParser.NoOptionError(option, section)
152
153 def optionxform(self, option):
154 return option
155 156
156 def readfp(self, fp, filename=None): 157 def readfp(self, fp, filename=None):
157 raise NotImplementedError 158 raise NotImplementedError
158 159
159 def set(self, section, option, value=None): 160 def set(self, section, option, value=None):
160 raise NotImplementedError 161 raise NotImplementedError
161 162
162 def add_section(self, section): 163 def add_section(self, section):
163 raise NotImplementedError 164 raise NotImplementedError
164 165
165 def remove_option(self, section, option): 166 def remove_option(self, section, option):
166 raise NotImplementedError 167 raise NotImplementedError
167 168
168 def remove_section(self, section): 169 def remove_section(self, section):
169 raise NotImplementedError 170 raise NotImplementedError
LEFTRIGHT
« no previous file | packager.py » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld