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

Side by Side Diff: chainedconfigparser.py

Issue 29743581: Issue 6552 - Support arbitrary manifest values (Closed) Base URL: https://hg.adblockplus.org/buildtools/file/a3db4a1a49e8
Patch Set: Created April 19, 2018, 9:59 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | packagerChrome.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This Source Code Form is subject to the terms of the Mozilla Public 1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 4
5 import os 5 import os
6 import io 6 import io
7 import ConfigParser 7 import ConfigParser
8 from StringIO import StringIO 8 from StringIO import StringIO
9 9
10 10
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 is_addition = option.endswith('+') 86 is_addition = option.endswith('+')
87 is_diff = is_addition or option.endswith('-') 87 is_diff = is_addition or option.endswith('-')
88 88
89 if is_diff: 89 if is_diff:
90 option = option[:-1].rstrip() 90 option = option[:-1].rstrip()
91 try: 91 try:
92 orig_value = self.get(section, option) 92 orig_value = self.get(section, option)
93 except ConfigParser.NoOptionError: 93 except ConfigParser.NoOptionError:
94 raise DiffForUnknownOptionError(option, section) 94 raise DiffForUnknownOptionError(option, section)
95 95
96 orig_values = orig_value.split() 96 orig_values = orig_value.splitlines()
97 diff_values = value.split() 97 diff_values = value.splitlines()
98 98
99 if is_addition: 99 if is_addition:
100 new_values = orig_values + [v for v in diff_values if v not in o rig_values] 100 new_values = orig_values + [v for v in diff_values if v not in o rig_values]
101 else: 101 else:
102 new_values = [v for v in orig_values if v not in diff_values] 102 new_values = [v for v in orig_values if v not in diff_values]
103 103
104 value = ' '.join(new_values) 104 value = '\n'.join(new_values)
105 105
106 return is_diff, option, value 106 return is_diff, option, value
107 107
108 def _process_parsers(self, parsers): 108 def _process_parsers(self, parsers):
109 for parser, filename in parsers: 109 for parser, filename in parsers:
110 for section in parser.sections(): 110 for section in parser.sections():
111 if not self.has_section(section): 111 if not self.has_section(section):
112 try: 112 try:
113 ConfigParser.SafeConfigParser.add_section(self, section) 113 ConfigParser.SafeConfigParser.add_section(self, section)
114 except ValueError: 114 except ValueError:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 150
151 def option_source(self, section, option): 151 def option_source(self, section, option):
152 option = self.optionxform(option) 152 option = self.optionxform(option)
153 try: 153 try:
154 return self._origin[(section, option)] 154 return self._origin[(section, option)]
155 except KeyError: 155 except KeyError:
156 if not self.has_section(section): 156 if not self.has_section(section):
157 raise ConfigParser.NoSectionError(section) 157 raise ConfigParser.NoSectionError(section)
158 raise ConfigParser.NoOptionError(option, section) 158 raise ConfigParser.NoOptionError(option, section)
159 159
160 def section_as_dict(self, section, base):
161 """Parse a given section into a dictionary.
162
163 Parse arbitrary key/value pairs from 'section' of the current
164 configuration into a dictionary and deep merge it into `base`.
165
166 The following rules need to be considered:
167
168 * An option's key may be declared as a series of nested dictionary keys,
169 seperated by '.'.
170 * Declaring an option's value in a new line (even if only one is given)
171 will define the option's value as an array.
Sebastian Noack 2018/04/19 10:50:56 Nit: Talking about "arrays" made sense initially w
tlucas 2018/04/19 11:08:13 Done.
172 * When an option's value is defined as an array, no other nested
173 objects may follow.
174 * An array is expandable by the ConfigParser's '+=' token (Note: A
175 previously declared string will be converted into an array).
176 * Values may be marked as `number` or `bool` by prefixing them
177 accordingly (this also applies to values in an array):
178 * bool:<value>
179 * number:<value>
180
181 Example:
182 {
183 foo = foo "foo": "foo",
184 asd = "asd": ["asd"],
185 asd "bar": {
Sebastian Noack 2018/04/19 10:50:57 Nit: For consistency, we might want to use two spa
tlucas 2018/04/19 11:08:14 Done.
186 bar.baz = a "baz": ["a", "c", "d"]
187 baz.foo = a },
188 baz.z = "baz": {
189 bar "foo": "a",
190 bool:true ===> "z": ["bar", true]
191 bar.baz += },
192 c "bad": true,
193 d "good": false,
194 bad = bool:true "is": {
195 good = bool:false "integer": 1,
196 is.integer = number:1 "float": 1.4
197 is.float = number:1.4 }
198 }
199 """
200 def parse_values(v):
Sebastian Noack 2018/04/19 10:50:57 Nit; since this function is only called with a sin
tlucas 2018/04/19 11:08:13 Done.
201 if isinstance(v, list):
202 return [parse_values(x) for x in v]
Sebastian Noack 2018/04/19 10:50:57 This code path can be removed now, since we no lon
tlucas 2018/04/19 11:08:14 Done.
203
204 if v.startswith('number:'):
205 v = v.split(':', 1)[1]
206 try:
207 return int(v)
208 except ValueError:
209 return float(v)
210 if v == 'bool:true':
211 return True
212 if v == 'bool:false':
213 return False
214 return v
215
216 data = self.items(section)
Sebastian Noack 2018/04/19 10:50:56 Nit: this variable is only used once, perhaps inli
tlucas 2018/04/19 11:08:14 Done. One note: Not catching a NoSectionError her
tlucas 2018/04/19 11:45:15 Done.
217
218 for k, v in data:
219
Sebastian Noack 2018/04/19 10:50:58 Nit: Is the blank line here intended? It looks wei
tlucas 2018/04/19 11:08:15 Done.
220 parents = k.split('.')
221 tail = parents.pop()
222 current = base
223 for name in parents:
224 current = base.setdefault(name, {})
225
226 if '\n' in v:
227 current[tail] = [parse_values(x) for x in v.splitlines() if x]
228 else:
229 current[tail] = parse_values(v)
230
231 return base
Sebastian Noack 2018/04/19 10:50:57 Nit: Returning the dictionary seems redundant. It'
tlucas 2018/04/19 11:08:14 I wouldn't mind either solution - but we also migh
Sebastian Noack 2018/04/19 11:12:41 That is exactly what I said. My suggestions above
tlucas 2018/04/19 11:45:15 Done.
232
160 def readfp(self, fp, filename=None): 233 def readfp(self, fp, filename=None):
161 raise NotImplementedError 234 raise NotImplementedError
162 235
163 def set(self, section, option, value=None): 236 def set(self, section, option, value=None):
164 raise NotImplementedError 237 raise NotImplementedError
165 238
166 def add_section(self, section): 239 def add_section(self, section):
167 raise NotImplementedError 240 raise NotImplementedError
168 241
169 def remove_option(self, section, option): 242 def remove_option(self, section, option):
170 raise NotImplementedError 243 raise NotImplementedError
171 244
172 def remove_section(self, section): 245 def remove_section(self, section):
173 raise NotImplementedError 246 raise NotImplementedError
OLDNEW
« no previous file with comments | « no previous file | packagerChrome.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld