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 13, 2018, 9:13 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') | packagerChrome.py » ('J')
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 from collections import OrderedDict
9 10
10 11
11 class Item(tuple): 12 class Item(tuple):
12 def __new__(cls, name, value, source): 13 def __new__(cls, name, value, source):
13 result = super(Item, cls).__new__(cls, (name, value)) 14 result = super(Item, cls).__new__(cls, (name, value))
14 result.source = source 15 result.source = source
15 return result 16 return result
16 17
17 18
18 class DiffForUnknownOptionError(ConfigParser.Error): 19 class DiffForUnknownOptionError(ConfigParser.Error):
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 151
151 def option_source(self, section, option): 152 def option_source(self, section, option):
152 option = self.optionxform(option) 153 option = self.optionxform(option)
153 try: 154 try:
154 return self._origin[(section, option)] 155 return self._origin[(section, option)]
155 except KeyError: 156 except KeyError:
156 if not self.has_section(section): 157 if not self.has_section(section):
157 raise ConfigParser.NoSectionError(section) 158 raise ConfigParser.NoSectionError(section)
158 raise ConfigParser.NoOptionError(option, section) 159 raise ConfigParser.NoOptionError(option, section)
159 160
161 def as_json_object(self, section):
Sebastian Noack 2018/04/14 00:33:07 Actually there isn't anything specific to JSON in
tlucas 2018/04/14 08:36:23 You are right - what would you suggest? How about
Sebastian Noack 2018/04/14 08:54:26 Maybe section_as_dict()?
tlucas 2018/04/18 14:46:04 Done.
162 r"""Parse a given section into a JSON object.
163
164 Parse arbitrary key/value pairs from 'section' of the current
165 configuration into a nested JSON object.
166
167 The following rules need to be considered:
168
169 * An option's key may be declared as a series of nested dictionary keys,
170 seperated by '.'.
171 * An option's key must end with '[]', to mark this option as an array
Sebastian Noack 2018/04/14 00:33:06 Nit: Please make all bullet point end with punctat
Sebastian Noack 2018/04/14 00:33:07 I just noticed, we could identify arrays by the pr
tlucas 2018/04/14 08:36:23 The bullet points: ack The newlines: Nice idea, w
tlucas 2018/04/18 14:46:04 Done.
172 * When an option is marked as an array, no other nested objects may
173 follow
174 * An array is expandable by the ConfigParser's '+=' token.
175 * Values may be marked as `number` or `bool` by prefixing them
176 accordingly:
177 * bool:<value>
178 * number:<value>
179
180 Example:
181
182 {
183 "good": false,
184 "bar": {
185 "baz": ["bar", "bazinga"]
186 foo = foo },
187 bar.baz[] = bar "is": {
188 baz.foo = a "integer": 1,
189 baz.z[] = b bool:true "float": 1.4
190 bar.baz[] += bazinga ==> },
191 bad = bool:true "baz": {
192 good = bool:false "foo": "a",
193 is.integer = number:1 "z": ["b", true]
194 is.float = number:1.4 },
195 "bad": true
196 "foo": "foo"
197 }
198 """
199 def parse_values(v):
200 if isinstance(v, list):
201 return [parse_values(x) for x in v]
202
203 if v.startswith('number:'):
204 v = v.split(':', 1)[1]
205 try:
206 v = int(v)
207 except ValueError:
208 v = float(v)
209 elif v == 'bool:true':
210 v = True
211 elif v == 'bool:false':
212 v = False
213 return v
214
215 def setdefault_recursive(target, arr):
216 if len(arr) == 2:
217 target.setdefault(arr[0], parse_values(arr[1]))
218 else:
219 current = target.setdefault(arr[0], OrderedDict())
220 setdefault_recursive(current, arr[1:])
221
222 data = self.items(section)
223 result = OrderedDict()
224
225 for k, v in data:
226 if k.endswith('[]'):
227 k = k[:-2]
228 v = v.split()
Sebastian Noack 2018/04/14 00:33:06 We might want to strip by newlines, so that array
tlucas 2018/04/14 08:36:23 Acknowledged.
tlucas 2018/04/18 14:46:04 Done.
229
230 setdefault_recursive(result, k.split('.') + [v])
Sebastian Noack 2018/04/14 00:33:06 It seems weird/unnecessary to merge the key segmen
tlucas 2018/04/14 08:36:23 Not at all, will change.
tlucas 2018/04/18 14:46:04 Done.
231
232 return result
233
160 def readfp(self, fp, filename=None): 234 def readfp(self, fp, filename=None):
161 raise NotImplementedError 235 raise NotImplementedError
162 236
163 def set(self, section, option, value=None): 237 def set(self, section, option, value=None):
164 raise NotImplementedError 238 raise NotImplementedError
165 239
166 def add_section(self, section): 240 def add_section(self, section):
167 raise NotImplementedError 241 raise NotImplementedError
168 242
169 def remove_option(self, section, option): 243 def remove_option(self, section, option):
170 raise NotImplementedError 244 raise NotImplementedError
171 245
172 def remove_section(self, section): 246 def remove_section(self, section):
173 raise NotImplementedError 247 raise NotImplementedError
OLDNEW
« no previous file with comments | « no previous file | packagerChrome.py » ('j') | packagerChrome.py » ('J')

Powered by Google App Engine
This is Rietveld