Chromium Code Reviews| Index: chrome/common/extensions/docs/server2/api_schema_map.py |
| diff --git a/chrome/common/extensions/docs/server2/api_schema_map.py b/chrome/common/extensions/docs/server2/api_schema_map.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..705c9af0d2735ae8e8c721e0266e0e017b20238d |
| --- /dev/null |
| +++ b/chrome/common/extensions/docs/server2/api_schema_map.py |
| @@ -0,0 +1,97 @@ |
| +# 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 _CreateMap(root, node_type=None): |
|
not at google - send to devlin
2013/09/12 20:34:23
node_type is never used
epeterson
2013/09/12 22:39:10
Done.
|
| + '''Recursively moves through an API schema, replacing lists of objects |
| + for each attribute listed in |attributes| with a dict containing a |
| + key for each object in the list. |
| + ''' |
| + api_schema_map = {} |
| + if _IsObjectList(root): |
| + for node in root: |
| + name = _NameForNode(node) |
| + assert name not in api_schema_map, 'Duplicate name in availability map.' |
| + api_schema_map[name] = {} |
|
not at google - send to devlin
2013/09/12 20:34:23
Is/can this be written similar to:
api_schema_map
epeterson
2013/09/12 22:39:10
I do want that check, but I tried to make it neate
|
| + for key, value in node.iteritems(): |
| + # Recur on each (key, value) pair. The key becomes |node_type| and the |
| + # value becomes the next |root|. The value will only pass the if/elif |
| + # guard if it is a list or dict. |
| + if isinstance(value, collections.Mapping) or _IsObjectList(value): |
| + # Keep track of availability for 'objects' only. |
| + api_schema_map[name][key] = _CreateMap(value, node_type=key) |
| + elif isinstance(root, collections.Mapping): |
| + for name, node in root.iteritems(): |
| + api_schema_map[name] = {} |
| + for key, value in node.iteritems(): |
| + if isinstance(value, collections.Mapping) or _IsObjectList(value): |
| + api_schema_map[name][key] = _CreateMap(value, node_type=key) |
| + |
| + return api_schema_map |
| + |
| + |
| +def _Subtract(minuend, subtrahend): |
|
not at google - send to devlin
2013/09/12 20:34:23
I've never heard the terms "minuend" and "subtrahe
epeterson
2013/09/12 22:39:10
I hadn't either.
not at google - send to devlin
2013/09/13 17:00:34
Btw another convention I see sometimes is to use "
|
| + ''' A Set Difference adaptation for dicts. 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: |
| + rest = _Subtract(minuend[key], subtrahend[key]) |
|
not at google - send to devlin
2013/09/12 20:34:23
won't this break if minuend[key] or subtrahend[key
epeterson
2013/09/12 22:39:10
Updated the comment -- but the parameters here nee
not at google - send to devlin
2013/09/13 17:00:34
I'm.. not totally convinced. Why do they "need" to
not at google - send to devlin
2013/09/13 17:16:30
Ah, because you create |_map| yourself. Never mind
|
| + if rest: |
| + # Record a difference if children of this key differed at some point. |
| + difference[key] = rest |
| + return difference |
| + |
| + |
| +class APISchemaMap(object): |
| + '''Represents an API schema as a nested dict structure, where lists of |
| + schema nodes are converted to dicts with a key representing each node. |
| + ''' |
| + |
| + def __init__(self, api_schema): |
| + self._map = _CreateMap(api_schema) |
| + |
| + def Subtract(self, other_map): |
| + '''Returns an APISchemaMap instance representing keys that are in |
| + this map but not in the |other_map|. |
| + ''' |
| + return APISchemaMap(_Subtract(self._map, other_map)) |
|
not at google - send to devlin
2013/09/12 20:34:23
|other_map| should be an APISchemaMap, not... what
epeterson
2013/09/12 22:39:10
Great, this makes things simpler for actually usin
not at google - send to devlin
2013/09/13 17:00:34
This is fine here because it's private data that t
|
| + |
| + def Lookup(self, *path): |
| + '''Given a list of path components, |path|, checks if the |
| + APISchemaMap instance contains |path|. |
| + ''' |
| + node = self._map |
| + for path_piece in path: |
| + node = node.get(path_piece) |
| + if node is None: |
| + return False |
| + return True |