Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Unified Diff: components/policy/tools/generate_policy_source.py

Issue 228423002: Add $ref support to policy schema (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@policy-schema-regex
Patch Set: fixes Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/policy/resources/policy_templates.json ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/policy/tools/generate_policy_source.py
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py
index 9ccf881d17137a2ecd5b98f6e3ea77f21a44cda8..0be012abf272e7c6998a84d851e007416443d5ec 100755
--- a/components/policy/tools/generate_policy_source.py
+++ b/components/policy/tools/generate_policy_source.py
@@ -11,11 +11,13 @@ chromium_os_flag should be 1 if this is a Chromium OS build
template is the path to a .json policy template file.'''
from __future__ import with_statement
+from functools import partial
import json
from optparse import OptionParser
import re
import sys
import textwrap
+import types
CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome'
@@ -282,6 +284,7 @@ class SchemaNodesGenerator:
}
self.stringlist_type = None
self.ranges = {}
+ self.id_map = {}
def GetString(self, s):
if s in self.shared_strings:
@@ -398,6 +401,12 @@ class SchemaNodesGenerator:
|schema|: a valid JSON schema in a dictionary.
|name|: the name of the current node, for the generated comments."""
+ if schema.has_key('$ref'):
+ if schema.has_key('id'):
+ raise RuntimeError("Schemas with a $ref can't have an id")
+ if not isinstance(schema['$ref'], types.StringTypes):
+ raise RuntimeError("$ref attribute must be a string")
+ return schema['$ref']
if schema['type'] in self.simple_types:
if not self.SchemaHaveRestriction(schema):
# Simple types use shared nodes.
@@ -413,9 +422,8 @@ class SchemaNodesGenerator:
# Special case for lists of strings, which is a common policy type.
if schema['items']['type'] == 'string':
return self.GetStringList()
- return self.AppendSchema(
- 'TYPE_LIST',
- self.Generate(schema['items'], 'items of ' + name))
+ return self.AppendSchema('TYPE_LIST',
+ self.GenerateAndCollectID(schema['items'], 'items of ' + name))
elif schema['type'] == 'object':
# Reserve an index first, so that dictionaries come before their
# properties. This makes sure that the root node is the first in the
@@ -423,7 +431,7 @@ class SchemaNodesGenerator:
index = self.AppendSchema('TYPE_DICTIONARY', -1)
if 'additionalProperties' in schema:
- additionalProperties = self.Generate(
+ additionalProperties = self.GenerateAndCollectID(
schema['additionalProperties'],
'additionalProperties of ' + name)
else:
@@ -434,13 +442,14 @@ class SchemaNodesGenerator:
# recursive calls to Generate() append the necessary child nodes; if
# |properties| were a generator then this wouldn't work.
sorted_properties = sorted(schema.get('properties', {}).items())
- properties = [ (self.GetString(key), self.Generate(subschema, key))
- for key, subschema in sorted_properties ]
+ properties = [
+ (self.GetString(key), self.GenerateAndCollectID(subschema, key))
+ for key, subschema in sorted_properties ]
pattern_properties = []
for pattern, subschema in schema.get('patternProperties', {}).items():
pattern_properties.append((self.GetString(pattern),
- self.Generate(subschema, pattern)));
+ self.GenerateAndCollectID(subschema, pattern)));
begin = len(self.property_nodes)
self.property_nodes += properties
@@ -462,6 +471,20 @@ class SchemaNodesGenerator:
else:
assert False
+ def GenerateAndCollectID(self, schema, name):
+ """A wrapper of Generate(), will take the return value, check and add 'id'
+ attribute to self.id_map. The wrapper needs to be used for every call to
+ Generate().
+ """
+ index = self.Generate(schema, name)
+ if not schema.has_key('id'):
+ return index
+ id_str = schema['id']
+ if self.id_map.has_key(id_str):
+ raise RuntimeError('Duplicated id: ' + id_str)
+ self.id_map[id_str] = index
+ return index
+
def Write(self, f):
"""Writes the generated structs to the given file.
@@ -516,6 +539,29 @@ class SchemaNodesGenerator:
f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n')
f.write('};\n\n')
+ def GetByID(self, id_str):
+ if not isinstance(id_str, types.StringTypes):
+ return id_str
+ if not self.id_map.has_key(id_str):
+ raise RuntimeError('Invalid $ref: ' + id_str)
+ return self.id_map[id_str]
+
+ def ResolveID(self, index, params):
+ return params[:index] + (self.GetByID(params[index]),) + params[index+1:]
+
+ def ResolveReferences(self):
+ """Resolve reference mapping, required to be called after Generate()
+
+ After calling Generate(), the type of indices used in schema structures
+ might be either int or string. An int type suggests that it's a resolved
+ index, but for string type it's unresolved. Resolving a reference is as
+ simple as looking up for corresponding ID in self.id_map, and replace the
+ old index with the mapped index.
+ """
+ self.schema_nodes = map(partial(self.ResolveID, 1), self.schema_nodes)
+ self.property_nodes = map(partial(self.ResolveID, 1), self.property_nodes)
+ self.properties_nodes = map(partial(self.ResolveID, 3),
+ self.properties_nodes)
def _WritePolicyConstantSource(policies, os, f):
f.write('#include "policy/policy_constants.h"\n'
@@ -558,7 +604,8 @@ def _WritePolicyConstantSource(policies, os, f):
f.write('};\n\n')
schema_generator = SchemaNodesGenerator(shared_strings)
- schema_generator.Generate(chrome_schema, 'root node')
+ schema_generator.GenerateAndCollectID(chrome_schema, 'root node')
+ schema_generator.ResolveReferences()
schema_generator.Write(f)
f.write('bool CompareKeys(const internal::PropertyNode& node,\n'
« no previous file with comments | « components/policy/resources/policy_templates.json ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698