Chromium Code Reviews| Index: chrome/common/extensions/docs/server2/availability_graph.py |
| diff --git a/chrome/common/extensions/docs/server2/availability_graph.py b/chrome/common/extensions/docs/server2/availability_graph.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3d3133deb8aa1caefe986f12a31e76652f87d6ee |
| --- /dev/null |
| +++ b/chrome/common/extensions/docs/server2/availability_graph.py |
| @@ -0,0 +1,102 @@ |
| +# 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. |
| + |
| +_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.
|
| + |
| + |
| +def _NameForNode(node, node_type): |
| + '''Creates a unique id for an object in an API schema, depending on |
| + what type of attribute the object is a member of. |
| + ''' |
| + if node_type == 'properties': return node |
| + if node_type == 'types': return node['id'] |
| + if node_type is None: return node['namespace'] |
| + if 'name' in node: |
| + return node['name'] |
| + # The API Schema probably had an error here. Fall back to the 'type' field to |
| + # avoid raising an error. |
| + return node['type'] |
| + |
| + |
| +def _CreateGraph(api_schema, node_type=None): |
| + '''Recursively move 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. |
| + ''' |
| + availability_graph = {} |
| + 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.
|
| + 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.
|
| + availability_graph[name] = { 'availability': None } |
| + if node_type == 'properties': |
| + # The 'properties' attribute is a key -> value mapping. Grab the value. |
| + node = api_schema[node] |
| + for attribute in _ATTRIBUTES: |
| + if attribute in node: |
| + availability_graph[name][attribute] = _CreateGraph(node[attribute], |
| + node_type=attribute) |
| + return availability_graph |
| + |
| + |
| +class AvailabilityGraph(object): |
| + '''Represents an API schema as a nested dict structure, where lists of |
| + schema nodes (falling under one of |_ATTRIBUTES|) are converted to |
| + dicts with a key representing each node. Availability information for |
| + schema nodes is tracked as the graph is created and processed. |
| + ''' |
| + |
| + def __init__(self, api_schema, channel_info): |
| + self.graph = _CreateGraph(api_schema) |
| + 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.
|
| + self._paths = [] |
| + |
| + def SetPaths(self, other): |
| + '''Sets a list of '/'-delimited dictionary-keys, or 'paths', that |
| + exist in this object's |graph| but not in |other|'s graph. Update |
| + 'availability' for keys based on which graphs they are initially |
| + found in. |
| + ''' |
| + def get_missing_paths(this_graph, other_graph, path=''): |
| + paths = [] |
| + for key in this_graph: |
| + if key == 'availability': |
| + continue |
| + current_path = '%s/%s' % (path, key) if path else key |
| + paths.extend(get_missing_paths(this_graph[key], |
| + other_graph.get(key, {}), |
| + current_path)) |
| + if key not in _ATTRIBUTES: |
| + # Add the path if the value was not available upon the API's release. |
| + if key not in other_graph: |
| + this_graph[key]['availability'] = self.channel_info |
| + paths.append(current_path) |
| + else: |
| + this_graph[key]['availability'] = other.channel_info |
| + return paths |
| + |
| + self._paths = get_missing_paths(self.graph, other.graph) |
| + |
| + def UpdatePaths(self, other): |
| + '''Check each path in |_paths|, removing a path if it has become |
| + available and updating that path's availability in the |graph|. |
| + ''' |
| + for path in self._paths[:]: |
| + path_pieces = path.split('/') |
| + if other.Lookup(*path_pieces) is not None: |
| + node = self.graph |
| + for path_piece in path_pieces: |
| + node = node[path_piece] |
| + node['availability'] = other.channel_info |
| + self._paths.remove(path) |
| + 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.
|
| + |
| + def Lookup(self, *path): |
| + '''Given a list of path components, |path|, checks if |graph| |
| + contains |path| and returns its availability if found. |
| + ''' |
| + node = self.graph |
| + for path_piece in path: |
| + node = node.get(path_piece) |
| + if node is None: |
| + return None |
| + return node.get('availability') |