Left: | ||
Right: |
OLD | NEW |
---|---|
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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 as_json_object(self, section): | |
161 r"""Parse a given section into a JSON object. | |
162 | |
163 Parse arbitrary key/value pairs from 'section' of the current | |
164 configuration into a nested JSON object. | |
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 * An option's key must end with '[]', to mark this option as an array | |
171 * When an option is marked as an array, no other nested objects may | |
172 follow | |
173 * An array is expandable by the ConfigParser's '+=' token. | |
174 * Values may be marked as special types by appending '\{code}': | |
175 * \b - boolean | |
176 * \i - integer | |
177 * \f - float | |
178 | |
179 Example: | |
180 | |
181 { | |
182 "good": false, | |
183 "bar": { | |
184 "baz": ["bar", "bazinga"] | |
185 foo = foo }, | |
186 bar.baz[] = bar "is": { | |
187 baz.foo = a "integer": 1, | |
188 baz.z[] = b "float": 1.4 | |
189 bar.baz[] += bazinga ==> }, | |
190 bad = true\b "baz": { | |
191 good = f\b "foo": "a", | |
192 is.integer = 1\i "z": ["b"] | |
193 is.float = 1.4\f }, | |
194 "bad": true | |
195 "foo": "foo" | |
196 } | |
197 """ | |
198 def parse_values(v): | |
199 import distutils | |
200 if isinstance(v, list): | |
201 return [parse_values(x) for x in v] | |
202 | |
203 mapping = { | |
204 '\\b': lambda x: bool(distutils.util.strtobool(x)), | |
205 '\\i': int, | |
206 '\\f': float, | |
207 } | |
208 if '\\' in v: | |
209 return mapping[v[-2:]](v[:-2]) | |
210 return v | |
Sebastian Noack
2018/04/12 12:19:23
* I cannot think of any relevant manifest key wher
tlucas
2018/04/12 13:47:39
I do not fully oppose your thoughts, but what abou
Sebastian Noack
2018/04/12 14:39:29
I was thinking about the version number, but its n
tlucas
2018/04/13 09:14:59
Done.
| |
211 | |
212 def setdefault_recursive(target, arr): | |
213 if len(arr) == 2: | |
214 target.setdefault(arr[0], parse_values(arr[1])) | |
215 else: | |
216 current = target.setdefault(arr[0], {}) | |
Sebastian Noack
2018/04/12 12:19:23
You might want to use an OrderedDict to make sure
tlucas
2018/04/12 13:47:38
Good point, done.
| |
217 setdefault_recursive(current, arr[1:]) | |
218 | |
219 data = self.items(section) | |
220 result = {} | |
Sebastian Noack
2018/04/12 12:19:23
Same here.
tlucas
2018/04/12 13:47:38
See above, done.
| |
221 | |
222 for k, v in data: | |
223 is_array = k.endswith('[]') | |
224 | |
225 sub_keys = (k if not is_array else k[:-2]).split('.') | |
226 value = v.split() if is_array else v | |
Sebastian Noack
2018/04/12 12:19:23
It seems the logic here can be simplified:
if k
tlucas
2018/04/12 13:47:39
Done.
| |
227 | |
228 setdefault_recursive(result, sub_keys + [value]) | |
229 | |
230 return result | |
231 | |
160 def readfp(self, fp, filename=None): | 232 def readfp(self, fp, filename=None): |
161 raise NotImplementedError | 233 raise NotImplementedError |
162 | 234 |
163 def set(self, section, option, value=None): | 235 def set(self, section, option, value=None): |
164 raise NotImplementedError | 236 raise NotImplementedError |
165 | 237 |
166 def add_section(self, section): | 238 def add_section(self, section): |
167 raise NotImplementedError | 239 raise NotImplementedError |
168 | 240 |
169 def remove_option(self, section, option): | 241 def remove_option(self, section, option): |
170 raise NotImplementedError | 242 raise NotImplementedError |
171 | 243 |
172 def remove_section(self, section): | 244 def remove_section(self, section): |
173 raise NotImplementedError | 245 raise NotImplementedError |
OLD | NEW |