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 _ATTRIBUTES = ('events', 'functions', 'parameters', 'properties', 'types') | |
not at google - send to devlin
2013/09/06 23:29:38
I'm thinking this shouldn't care about what the co
epeterson
2013/09/12 00:32:01
Done.
| |
6 | |
7 | |
8 def _NameForNode(node, node_type): | |
9 '''Creates a unique id for an object in an API schema, depending on | |
10 what type of attribute the object is a member of. | |
11 ''' | |
12 if node_type == 'properties': return node | |
13 if node_type == 'types': return node['id'] | |
14 if node_type is None: return node['namespace'] | |
15 if 'name' in node: | |
16 return node['name'] | |
17 # The API Schema probably had an error here. Fall back to the 'type' field to | |
18 # avoid raising an error. | |
19 return node['type'] | |
20 | |
21 | |
22 def _CreateGraph(api_schema, node_type=None): | |
23 '''Recursively move through an API schema, replacing lists of objects | |
24 for each attribute listed in |attributes| with a dict containing a | |
25 key for each object in the list. | |
26 ''' | |
27 availability_graph = {} | |
28 for node in api_schema: | |
not at google - send to devlin
2013/09/06 23:29:38
confusing dicts and lists here is.. odd. And I can
epeterson
2013/09/12 00:32:01
Done.
| |
29 name = _NameForNode(node, node_type) | |
not at google - send to devlin
2013/09/06 23:29:38
how about asserting "name not in graph" here.
epeterson
2013/09/12 00:32:01
Done.
| |
30 availability_graph[name] = { 'availability': None } | |
31 if node_type == 'properties': | |
32 # The 'properties' attribute is a key -> value mapping. Grab the value. | |
33 node = api_schema[node] | |
34 for attribute in _ATTRIBUTES: | |
35 if attribute in node: | |
36 availability_graph[name][attribute] = _CreateGraph(node[attribute], | |
37 node_type=attribute) | |
38 return availability_graph | |
39 | |
40 | |
41 class AvailabilityGraph(object): | |
42 '''Represents an API schema as a nested dict structure, where lists of | |
43 schema nodes (falling under one of |_ATTRIBUTES|) are converted to | |
44 dicts with a key representing each node. Availability information for | |
45 schema nodes is tracked as the graph is created and processed. | |
46 ''' | |
47 | |
48 def __init__(self, api_schema, channel_info): | |
49 self.graph = _CreateGraph(api_schema) | |
50 self.channel_info = channel_info | |
not at google - send to devlin
2013/09/06 23:29:38
these need to be private.
epeterson
2013/09/12 00:32:01
Done.
| |
51 self._paths = [] | |
52 | |
53 def SetPaths(self, other): | |
54 '''Sets a list of '/'-delimited dictionary-keys, or 'paths', that | |
55 exist in this object's |graph| but not in |other|'s graph. Update | |
56 'availability' for keys based on which graphs they are initially | |
57 found in. | |
58 ''' | |
59 def get_missing_paths(this_graph, other_graph, path=''): | |
60 paths = [] | |
61 for key in this_graph: | |
62 if key == 'availability': | |
63 continue | |
64 current_path = '%s/%s' % (path, key) if path else key | |
65 paths.extend(get_missing_paths(this_graph[key], | |
66 other_graph.get(key, {}), | |
67 current_path)) | |
68 if key not in _ATTRIBUTES: | |
69 # Add the path if the value was not available upon the API's release. | |
70 if key not in other_graph: | |
71 this_graph[key]['availability'] = self.channel_info | |
72 paths.append(current_path) | |
73 else: | |
74 this_graph[key]['availability'] = other.channel_info | |
75 return paths | |
76 | |
77 self._paths = get_missing_paths(self.graph, other.graph) | |
78 | |
79 def UpdatePaths(self, other): | |
80 '''Check each path in |_paths|, removing a path if it has become | |
81 available and updating that path's availability in the |graph|. | |
82 ''' | |
83 for path in self._paths[:]: | |
84 path_pieces = path.split('/') | |
85 if other.Lookup(*path_pieces) is not None: | |
86 node = self.graph | |
87 for path_piece in path_pieces: | |
88 node = node[path_piece] | |
89 node['availability'] = other.channel_info | |
90 self._paths.remove(path) | |
91 return bool(self._paths) | |
not at google - send to devlin
2013/09/06 23:29:38
Would a better set of methods on this class be som
epeterson
2013/09/12 00:32:01
Done.
| |
92 | |
93 def Lookup(self, *path): | |
94 '''Given a list of path components, |path|, checks if |graph| | |
95 contains |path| and returns its availability if found. | |
96 ''' | |
97 node = self.graph | |
98 for path_piece in path: | |
99 node = node.get(path_piece) | |
100 if node is None: | |
101 return None | |
102 return node.get('availability') | |
OLD | NEW |