OLD | NEW |
---|---|
(Empty) | |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 import collections | |
6 import json | |
7 | |
8 | |
9 def _NameForNode(node): | |
10 '''Creates a unique id for an object in an API schema, depending on | |
11 what type of attribute the object is a member of. | |
12 ''' | |
13 if 'namespace' in node: return node['namespace'] | |
14 if 'name' in node: return node['name'] | |
15 if 'id' in node: return node['id'] | |
16 if 'type' in node: return node['type'] | |
17 assert False, 'Problems with naming node: %s' % json.dumps(node, indent=3) | |
18 | |
19 | |
20 def _IsObjectList(value): | |
21 '''Determines whether or not |value| is a list made up entirely of | |
22 dict-like objects. | |
23 ''' | |
24 return (isinstance(value, collections.Iterable) and | |
25 all(isinstance(node, collections.Mapping) for node in value)) | |
26 | |
27 | |
28 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.
| |
29 '''Recursively moves through an API schema, replacing lists of objects | |
30 for each attribute listed in |attributes| with a dict containing a | |
31 key for each object in the list. | |
32 ''' | |
33 api_schema_map = {} | |
34 if _IsObjectList(root): | |
35 for node in root: | |
36 name = _NameForNode(node) | |
37 assert name not in api_schema_map, 'Duplicate name in availability map.' | |
38 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
| |
39 for key, value in node.iteritems(): | |
40 # Recur on each (key, value) pair. The key becomes |node_type| and the | |
41 # value becomes the next |root|. The value will only pass the if/elif | |
42 # guard if it is a list or dict. | |
43 if isinstance(value, collections.Mapping) or _IsObjectList(value): | |
44 # Keep track of availability for 'objects' only. | |
45 api_schema_map[name][key] = _CreateMap(value, node_type=key) | |
46 elif isinstance(root, collections.Mapping): | |
47 for name, node in root.iteritems(): | |
48 api_schema_map[name] = {} | |
49 for key, value in node.iteritems(): | |
50 if isinstance(value, collections.Mapping) or _IsObjectList(value): | |
51 api_schema_map[name][key] = _CreateMap(value, node_type=key) | |
52 | |
53 return api_schema_map | |
54 | |
55 | |
56 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 "
| |
57 ''' A Set Difference adaptation for dicts. Returns a |difference|, | |
58 which contains key-value pairs found in |minuend| but not in | |
59 |subtrahend|. | |
60 ''' | |
61 difference = {} | |
62 for key in minuend: | |
63 if key not in subtrahend: | |
64 # Record all of this key's children as being part of the difference. | |
65 difference[key] = _Subtract(minuend[key], {}) | |
66 else: | |
67 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
| |
68 if rest: | |
69 # Record a difference if children of this key differed at some point. | |
70 difference[key] = rest | |
71 return difference | |
72 | |
73 | |
74 class APISchemaMap(object): | |
75 '''Represents an API schema as a nested dict structure, where lists of | |
76 schema nodes are converted to dicts with a key representing each node. | |
77 ''' | |
78 | |
79 def __init__(self, api_schema): | |
80 self._map = _CreateMap(api_schema) | |
81 | |
82 def Subtract(self, other_map): | |
83 '''Returns an APISchemaMap instance representing keys that are in | |
84 this map but not in the |other_map|. | |
85 ''' | |
86 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
| |
87 | |
88 def Lookup(self, *path): | |
89 '''Given a list of path components, |path|, checks if the | |
90 APISchemaMap instance contains |path|. | |
91 ''' | |
92 node = self._map | |
93 for path_piece in path: | |
94 node = node.get(path_piece) | |
95 if node is None: | |
96 return False | |
97 return True | |
OLD | NEW |