| Index: chrome/common/extensions/docs/server2/api_schema_graph.py
|
| diff --git a/chrome/common/extensions/docs/server2/api_schema_graph.py b/chrome/common/extensions/docs/server2/api_schema_graph.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..03d3744dd3247c0ecb26e71fde35a72760990835
|
| --- /dev/null
|
| +++ b/chrome/common/extensions/docs/server2/api_schema_graph.py
|
| @@ -0,0 +1,94 @@
|
| +# Copyright 2013 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import collections
|
| +import json
|
| +
|
| +
|
| +def _NameForNode(node):
|
| + '''Creates a unique id for an object in an API schema, depending on
|
| + what type of attribute the object is a member of.
|
| + '''
|
| + if 'namespace' in node: return node['namespace']
|
| + if 'name' in node: return node['name']
|
| + if 'id' in node: return node['id']
|
| + if 'type' in node: return node['type']
|
| + assert False, 'Problems with naming node: %s' % json.dumps(node, indent=3)
|
| +
|
| +
|
| +def _IsObjectList(value):
|
| + '''Determines whether or not |value| is a list made up entirely of
|
| + dict-like objects.
|
| + '''
|
| + return (isinstance(value, collections.Iterable) and
|
| + all(isinstance(node, collections.Mapping) for node in value))
|
| +
|
| +
|
| +def _CreateGraph(root):
|
| + '''Recursively moves through an API schema, replacing lists of objects
|
| + and non-object values with objects.
|
| + '''
|
| + schema_graph = {}
|
| + if _IsObjectList(root):
|
| + for node in root:
|
| + name = _NameForNode(node)
|
| + assert name not in schema_graph, 'Duplicate name in availability graph.'
|
| + schema_graph[name] = dict((key, _CreateGraph(value)) for key, value
|
| + in node.iteritems())
|
| + elif isinstance(root, collections.Mapping):
|
| + for name, node in root.iteritems():
|
| + schema_graph[name] = dict((key, _CreateGraph(value)) for key, value
|
| + in node.iteritems())
|
| + return schema_graph
|
| +
|
| +
|
| +def _Subtract(minuend, subtrahend):
|
| + ''' A Set Difference adaptation for graphs. Returns a |difference|,
|
| + which contains key-value pairs found in |minuend| but not in
|
| + |subtrahend|.
|
| + '''
|
| + difference = {}
|
| + for key in minuend:
|
| + if key not in subtrahend:
|
| + # Record all of this key's children as being part of the difference.
|
| + difference[key] = _Subtract(minuend[key], {})
|
| + else:
|
| + # Note that |minuend| and |subtrahend| are assumed to be graphs, and
|
| + # therefore should have no lists present, only keys and nodes.
|
| + rest = _Subtract(minuend[key], subtrahend[key])
|
| + if rest:
|
| + # Record a difference if children of this key differed at some point.
|
| + difference[key] = rest
|
| + return difference
|
| +
|
| +
|
| +class APISchemaGraph(object):
|
| + '''Provides an interface for interacting with an API schema graph, a
|
| + nested dict structure that allows for simpler lookups of schema data.
|
| + '''
|
| +
|
| + def __init__(self, api_schema):
|
| + self._graph = _CreateGraph(api_schema)
|
| +
|
| + def Subtract(self, other):
|
| + '''Returns an APISchemaGraph instance representing keys that are in
|
| + this graph but not in |other|.
|
| + '''
|
| + return APISchemaGraph(_Subtract(self._graph, other._graph))
|
| +
|
| + def Lookup(self, *path):
|
| + '''Given a list of path components, |path|, checks if the
|
| + APISchemaGraph instance contains |path|.
|
| + '''
|
| + node = self._graph
|
| + for path_piece in path:
|
| + node = node.get(path_piece)
|
| + if node is None:
|
| + return False
|
| + return True
|
| +
|
| + def IsEmpty(self):
|
| + '''Checks for an empty schema graph.
|
| + '''
|
| + return not self._graph
|
|
|