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

Unified 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 12, 2018, 1:46 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | packagerChrome.py » ('j') | templates/manifest.json.tmpl » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chainedconfigparser.py
diff --git a/chainedconfigparser.py b/chainedconfigparser.py
index ce26b04b50e175e1cbd99a772f2a589acd1ac64c..0dcff30c4671eaf4f358e056fbf0af5545979eb7 100644
--- a/chainedconfigparser.py
+++ b/chainedconfigparser.py
@@ -6,6 +6,7 @@ import os
import io
import ConfigParser
from StringIO import StringIO
+from collections import OrderedDict
class Item(tuple):
@@ -157,6 +158,77 @@ class ChainedConfigParser(ConfigParser.SafeConfigParser):
raise ConfigParser.NoSectionError(section)
raise ConfigParser.NoOptionError(option, section)
+ def as_json_object(self, section):
+ r"""Parse a given section into a JSON object.
+
+ Parse arbitrary key/value pairs from 'section' of the current
+ configuration into a nested JSON object.
+
+ The following rules need to be considered:
+
+ * An option's key may be declared as a series of nested dictionary keys,
+ seperated by '.'.
+ * An option's key must end with '[]', to mark this option as an array
+ * When an option is marked as an array, no other nested objects may
+ follow
+ * An array is expandable by the ConfigParser's '+=' token.
+ * Values may be marked as special types by appending '\{code}':
+ * \b - boolean
+ * \i - integer
+ * \f - float
+
+ Example:
+
+ {
+ "good": false,
+ "bar": {
+ "baz": ["bar", "bazinga"]
+ foo = foo },
+ bar.baz[] = bar "is": {
+ baz.foo = a "integer": 1,
+ baz.z[] = b "float": 1.4
+ bar.baz[] += bazinga ==> },
+ bad = true\b "baz": {
+ good = f\b "foo": "a",
+ is.integer = 1\i "z": ["b"]
+ is.float = 1.4\f },
+ "bad": true
+ "foo": "foo"
+ }
+ """
+ def parse_values(v):
+ import distutils
+ if isinstance(v, list):
+ return [parse_values(x) for x in v]
+
+ mapping = {
+ '\\b': lambda x: bool(distutils.util.strtobool(x)),
+ '\\i': int,
+ '\\f': float,
+ }
+ if '\\' in v:
+ return mapping[v[-2:]](v[:-2])
+ return v
+
+ def setdefault_recursive(target, arr):
+ if len(arr) == 2:
+ target.setdefault(arr[0], parse_values(arr[1]))
+ else:
+ current = target.setdefault(arr[0], OrderedDict())
+ setdefault_recursive(current, arr[1:])
+
+ data = self.items(section)
+ result = OrderedDict()
+
+ for k, v in data:
+ if k.endswith('[]'):
+ k = k[:-2]
+ v = v.split()
+
+ setdefault_recursive(result, k.split('.') + [v])
+
+ return result
+
def readfp(self, fp, filename=None):
raise NotImplementedError
« no previous file with comments | « no previous file | packagerChrome.py » ('j') | templates/manifest.json.tmpl » ('J')

Powered by Google App Engine
This is Rietveld