Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be | 
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. | 
| 4 | 4 | 
| 5 import copy | 5 import copy | 
| 6 import json | 6 import json | 
| 7 import logging | |
| 7 import os | 8 import os | 
| 8 | 9 | 
| 9 from docs_server_utils import GetLinkToRefType | |
| 10 import compiled_file_system as compiled_fs | 10 import compiled_file_system as compiled_fs | 
| 11 from file_system import FileNotFoundError | 11 from file_system import FileNotFoundError | 
| 12 from reference_resolver import ReferenceResolver | |
| 12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater | 13 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater | 
| 13 import third_party.json_schema_compiler.model as model | 14 import third_party.json_schema_compiler.model as model | 
| 14 import third_party.json_schema_compiler.idl_schema as idl_schema | 15 import third_party.json_schema_compiler.idl_schema as idl_schema | 
| 15 import third_party.json_schema_compiler.idl_parser as idl_parser | 16 import third_party.json_schema_compiler.idl_parser as idl_parser | 
| 16 | 17 | 
| 17 # Increment this version when there are changes to the data stored in any of | 18 # Increment this version when there are changes to the data stored in any of | 
| 18 # the caches used by APIDataSource. This allows the cache to be invalidated | 19 # the caches used by APIDataSource. This allows the cache to be invalidated | 
| 19 # without having to flush memcache on the production server. | 20 # without having to flush memcache on the production server. | 
| 20 _VERSION = 2 | 21 _VERSION = 3 | 
| 21 | 22 | 
| 22 def _RemoveNoDocs(item): | 23 def _RemoveNoDocs(item): | 
| 23 if type(item) == dict: | 24 if type(item) == dict: | 
| 24 if item.get('nodoc', False): | 25 if item.get('nodoc', False): | 
| 25 return True | 26 return True | 
| 26 to_remove = [] | 27 to_remove = [] | 
| 27 for key, value in item.items(): | 28 for key, value in item.items(): | 
| 28 if _RemoveNoDocs(value): | 29 if _RemoveNoDocs(value): | 
| 29 to_remove.append(key) | 30 to_remove.append(key) | 
| 30 for k in to_remove: | 31 for k in to_remove: | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 42 if node.parent is not None and not isinstance(node.parent, model.Namespace): | 43 if node.parent is not None and not isinstance(node.parent, model.Namespace): | 
| 43 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) | 44 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) | 
| 44 return '-'.join([prefix, node.simple_name]) | 45 return '-'.join([prefix, node.simple_name]) | 
| 45 | 46 | 
| 46 def _FormatValue(value): | 47 def _FormatValue(value): | 
| 47 """Inserts commas every three digits for integer values. It is magic. | 48 """Inserts commas every three digits for integer values. It is magic. | 
| 48 """ | 49 """ | 
| 49 s = str(value) | 50 s = str(value) | 
| 50 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) | 51 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) | 
| 51 | 52 | 
| 52 class _JscModel(object): | 53 class _JSCModel(object): | 
| 53 """Uses a Model from the JSON Schema Compiler and generates a dict that | 54 """Uses a Model from the JSON Schema Compiler and generates a dict that | 
| 54 a Handlebar template can use for a data source. | 55 a Handlebar template can use for a data source. | 
| 55 """ | 56 """ | 
| 56 def __init__(self, json): | 57 def __init__(self, json): | 
| 57 clean_json = copy.deepcopy(json) | 58 clean_json = copy.deepcopy(json) | 
| 58 if _RemoveNoDocs(clean_json): | 59 if _RemoveNoDocs(clean_json): | 
| 59 self._namespace = None | 60 self._namespace = None | 
| 60 else: | 61 else: | 
| 61 self._namespace = model.Namespace(clean_json, clean_json['namespace']) | 62 self._namespace = model.Namespace(clean_json, clean_json['namespace']) | 
| 62 | 63 | 
| 63 def _FormatDescription(self, description): | 64 def _GetLinkToRefType(self, ref, ref_resolver): | 
| 
 
not at google - send to devlin
2012/11/02 17:26:48
Rename method similar to rename suggestion in Refe
 
cduvall
2012/11/03 01:30:05
Done.
 
 | |
| 64 if description is None or '$ref:' not in description: | 65 ref_data = ref_resolver.GetLinkToRefType(self._namespace.name, ref) | 
| 66 if ref_data is None: | |
| 
 
not at google - send to devlin
2012/11/02 17:26:48
nit: invert condition.
 
cduvall
2012/11/03 01:30:05
Done.
 
 | |
| 67 logging.error('$ref %s could not be resolved.' % ref) | |
| 68 if '.' in ref: | |
| 69 type_name = ref.rsplit('.', 1)[-1] | |
| 70 else: | |
| 71 type_name = ref | |
| 72 return { 'href': '#type-%s' % type_name, 'text': ref } | |
| 73 return ref_data | |
| 74 | |
| 75 def _FormatDescription(self, description, ref_resolver): | |
| 76 if (description is None or | |
| 77 '$ref:' not in description or | |
| 78 ref_resolver is None): | |
| 65 return description | 79 return description | 
| 66 refs = description.split('$ref:') | 80 refs = description.split('$ref:') | 
| 67 formatted_description = [refs[0]] | 81 formatted_description = [refs[0]] | 
| 68 for ref in refs[1:]: | 82 for ref in refs[1:]: | 
| 69 parts = ref.split(' ', 1) | 83 parts = ref.split(' ', 1) | 
| 70 if len(parts) == 1: | 84 if len(parts) == 1: | 
| 71 ref = parts[0] | 85 ref = parts[0] | 
| 72 rest = '' | 86 rest = '' | 
| 73 else: | 87 else: | 
| 74 ref, rest = parts | 88 ref, rest = parts | 
| 75 rest = ' ' + rest | 89 rest = ' ' + rest | 
| 76 if not ref[-1].isalnum(): | 90 if not ref[-1].isalnum(): | 
| 77 rest = ref[-1] + rest | 91 rest = ref[-1] + rest | 
| 78 ref = ref[:-1] | 92 ref = ref[:-1] | 
| 79 ref_dict = GetLinkToRefType(self._namespace.name, ref) | 93 ref_dict = self._GetLinkToRefType(ref, ref_resolver) | 
| 80 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % | 94 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % | 
| 81 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) | 95 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) | 
| 82 return ''.join(formatted_description) | 96 return ''.join(formatted_description) | 
| 83 | 97 | 
| 84 def ToDict(self): | 98 def ToDict(self, ref_resolver): | 
| 
 
not at google - send to devlin
2012/11/02 17:26:48
Consider introducing a DictBuilder class that is c
 
cduvall
2012/11/03 01:30:05
I redid JSCModel so that it acts as a DictBuilder.
 
 | |
| 85 if self._namespace is None: | 99 if self._namespace is None: | 
| 86 return {} | 100 return {} | 
| 87 return { | 101 return { | 
| 88 'name': self._namespace.name, | 102 'name': self._namespace.name, | 
| 89 'types': [self._GenerateType(t) for t in self._namespace.types.values() | 103 'types': [self._GenerateType(t, ref_resolver) | 
| 104 for t in self._namespace.types.values() | |
| 90 if t.type_ != model.PropertyType.ADDITIONAL_PROPERTIES], | 105 if t.type_ != model.PropertyType.ADDITIONAL_PROPERTIES], | 
| 91 'functions': self._GenerateFunctions(self._namespace.functions), | 106 'functions': self._GenerateFunctions(self._namespace.functions, | 
| 92 'events': self._GenerateEvents(self._namespace.events), | 107 ref_resolver), | 
| 93 'properties': self._GenerateProperties(self._namespace.properties) | 108 'events': self._GenerateEvents(self._namespace.events, | 
| 109 ref_resolver), | |
| 110 'properties': self._GenerateProperties(self._namespace.properties, | |
| 111 ref_resolver) | |
| 94 } | 112 } | 
| 95 | 113 | 
| 96 def _GenerateType(self, type_): | 114 def _GenerateType(self, type_, ref_resolver): | 
| 97 type_dict = { | 115 type_dict = { | 
| 98 'name': type_.simple_name, | 116 'name': type_.simple_name, | 
| 99 'description': self._FormatDescription(type_.description), | 117 'description': self._FormatDescription(type_.description, ref_resolver), | 
| 100 'properties': self._GenerateProperties(type_.properties), | 118 'properties': self._GenerateProperties(type_.properties, ref_resolver), | 
| 101 'functions': self._GenerateFunctions(type_.functions), | 119 'functions': self._GenerateFunctions(type_.functions, ref_resolver), | 
| 102 'events': self._GenerateEvents(type_.events), | 120 'events': self._GenerateEvents(type_.events, ref_resolver), | 
| 103 'id': _CreateId(type_, 'type') | 121 'id': _CreateId(type_, 'type') | 
| 104 } | 122 } | 
| 105 self._RenderTypeInformation(type_, type_dict) | 123 self._RenderTypeInformation(type_, type_dict, ref_resolver) | 
| 106 return type_dict | 124 return type_dict | 
| 107 | 125 | 
| 108 def _GenerateFunctions(self, functions): | 126 def _GenerateFunctions(self, functions, ref_resolver): | 
| 109 return [self._GenerateFunction(f) for f in functions.values()] | 127 return [self._GenerateFunction(f, ref_resolver) for f in functions.values()] | 
| 110 | 128 | 
| 111 def _GenerateFunction(self, function): | 129 def _GenerateFunction(self, function, ref_resolver): | 
| 112 function_dict = { | 130 function_dict = { | 
| 113 'name': function.simple_name, | 131 'name': function.simple_name, | 
| 114 'description': self._FormatDescription(function.description), | 132 'description': self._FormatDescription(function.description, | 
| 115 'callback': self._GenerateCallback(function.callback), | 133 ref_resolver), | 
| 134 'callback': self._GenerateCallback(function.callback, ref_resolver), | |
| 116 'parameters': [], | 135 'parameters': [], | 
| 117 'returns': None, | 136 'returns': None, | 
| 118 'id': _CreateId(function, 'method') | 137 'id': _CreateId(function, 'method') | 
| 119 } | 138 } | 
| 120 if (function.parent is not None and | 139 if (function.parent is not None and | 
| 121 not isinstance(function.parent, model.Namespace)): | 140 not isinstance(function.parent, model.Namespace)): | 
| 122 function_dict['parent_name'] = function.parent.simple_name | 141 function_dict['parent_name'] = function.parent.simple_name | 
| 123 else: | 142 else: | 
| 124 function_dict['parent_name'] = None | 143 function_dict['parent_name'] = None | 
| 125 if function.returns: | 144 if function.returns: | 
| 126 function_dict['returns'] = self._GenerateProperty(function.returns) | 145 function_dict['returns'] = self._GenerateProperty(function.returns, | 
| 146 ref_resolver) | |
| 127 for param in function.params: | 147 for param in function.params: | 
| 128 function_dict['parameters'].append(self._GenerateProperty(param)) | 148 function_dict['parameters'].append(self._GenerateProperty(param, | 
| 149 ref_resolver)) | |
| 129 if function_dict['callback']: | 150 if function_dict['callback']: | 
| 130 function_dict['parameters'].append(function_dict['callback']) | 151 function_dict['parameters'].append(function_dict['callback']) | 
| 131 if len(function_dict['parameters']) > 0: | 152 if len(function_dict['parameters']) > 0: | 
| 132 function_dict['parameters'][-1]['last'] = True | 153 function_dict['parameters'][-1]['last'] = True | 
| 133 return function_dict | 154 return function_dict | 
| 134 | 155 | 
| 135 def _GenerateEvents(self, events): | 156 def _GenerateEvents(self, events, ref_resolver): | 
| 136 return [self._GenerateEvent(e) for e in events.values()] | 157 return [self._GenerateEvent(e, ref_resolver) for e in events.values()] | 
| 137 | 158 | 
| 138 def _GenerateEvent(self, event): | 159 def _GenerateEvent(self, event, ref_resolver): | 
| 139 event_dict = { | 160 event_dict = { | 
| 140 'name': event.simple_name, | 161 'name': event.simple_name, | 
| 141 'description': self._FormatDescription(event.description), | 162 'description': self._FormatDescription(event.description, | 
| 142 'parameters': map(self._GenerateProperty, event.params), | 163 ref_resolver), | 
| 143 'callback': self._GenerateCallback(event.callback), | 164 'parameters': [self._GenerateProperty(p, ref_resolver) | 
| 144 'conditions': [GetLinkToRefType(self._namespace.name, c) | 165 for p in event.params], | 
| 145 for c in event.conditions], | 166 'callback': self._GenerateCallback(event.callback, ref_resolver), | 
| 146 'actions': [GetLinkToRefType(self._namespace.name, a) | 167 'filters': [self._GenerateProperty(f, ref_resolver) | 
| 147 for a in event.actions], | 168 for f in event.filters], | 
| 148 'filters': map(self._GenerateProperty, event.filters), | |
| 149 'supportsRules': event.supports_rules, | 169 'supportsRules': event.supports_rules, | 
| 150 'id': _CreateId(event, 'event') | 170 'id': _CreateId(event, 'event') | 
| 151 } | 171 } | 
| 172 if ref_resolver is not None: | |
| 173 event_dict['conditions'] = [self._GetLinkToRefType(condition, | |
| 174 ref_resolver) | |
| 175 for condition in event.conditions] | |
| 176 event_dict['actions'] = [self._GetLinkToRefType(action, ref_resolver) | |
| 177 for action in event.actions] | |
| 152 if (event.parent is not None and | 178 if (event.parent is not None and | 
| 153 not isinstance(event.parent, model.Namespace)): | 179 not isinstance(event.parent, model.Namespace)): | 
| 154 event_dict['parent_name'] = event.parent.simple_name | 180 event_dict['parent_name'] = event.parent.simple_name | 
| 155 else: | 181 else: | 
| 156 event_dict['parent_name'] = None | 182 event_dict['parent_name'] = None | 
| 157 if event_dict['callback']: | 183 if event_dict['callback']: | 
| 158 event_dict['parameters'].append(event_dict['callback']) | 184 event_dict['parameters'].append(event_dict['callback']) | 
| 159 if len(event_dict['parameters']) > 0: | 185 if len(event_dict['parameters']) > 0: | 
| 160 event_dict['parameters'][-1]['last'] = True | 186 event_dict['parameters'][-1]['last'] = True | 
| 161 return event_dict | 187 return event_dict | 
| 162 | 188 | 
| 163 def _GenerateCallback(self, callback): | 189 def _GenerateCallback(self, callback, ref_resolver): | 
| 164 if not callback: | 190 if not callback: | 
| 165 return None | 191 return None | 
| 166 callback_dict = { | 192 callback_dict = { | 
| 167 'name': callback.simple_name, | 193 'name': callback.simple_name, | 
| 168 'description': self._FormatDescription(callback.description), | 194 'description': self._FormatDescription(callback.description, | 
| 195 ref_resolver), | |
| 169 'simple_type': {'simple_type': 'function'}, | 196 'simple_type': {'simple_type': 'function'}, | 
| 170 'optional': callback.optional, | 197 'optional': callback.optional, | 
| 171 'parameters': [] | 198 'parameters': [] | 
| 172 } | 199 } | 
| 173 for param in callback.params: | 200 for param in callback.params: | 
| 174 callback_dict['parameters'].append(self._GenerateProperty(param)) | 201 callback_dict['parameters'].append( | 
| 202 self._GenerateProperty(param, ref_resolver)) | |
| 175 if (len(callback_dict['parameters']) > 0): | 203 if (len(callback_dict['parameters']) > 0): | 
| 176 callback_dict['parameters'][-1]['last'] = True | 204 callback_dict['parameters'][-1]['last'] = True | 
| 177 return callback_dict | 205 return callback_dict | 
| 178 | 206 | 
| 179 def _GenerateProperties(self, properties): | 207 def _GenerateProperties(self, properties, ref_resolver): | 
| 180 return [self._GenerateProperty(v) for v in properties.values() | 208 return [self._GenerateProperty(v, ref_resolver) for v in properties.values() | 
| 181 if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] | 209 if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] | 
| 182 | 210 | 
| 183 def _GenerateProperty(self, property_): | 211 def _GenerateProperty(self, property_, ref_resolver): | 
| 184 property_dict = { | 212 property_dict = { | 
| 185 'name': property_.simple_name, | 213 'name': property_.simple_name, | 
| 186 'optional': property_.optional, | 214 'optional': property_.optional, | 
| 187 'description': self._FormatDescription(property_.description), | 215 'description': self._FormatDescription(property_.description, | 
| 188 'properties': self._GenerateProperties(property_.properties), | 216 ref_resolver), | 
| 217 'properties': self._GenerateProperties(property_.properties, | |
| 218 ref_resolver), | |
| 219 'functions': self._GenerateFunctions(property_.functions, ref_resolver), | |
| 189 'parameters': [], | 220 'parameters': [], | 
| 190 'functions': self._GenerateFunctions(property_.functions), | |
| 191 'returns': None, | 221 'returns': None, | 
| 192 'id': _CreateId(property_, 'property') | 222 'id': _CreateId(property_, 'property') | 
| 193 } | 223 } | 
| 194 for param in property_.params: | 224 for param in property_.params: | 
| 195 property_dict['parameters'].append(self._GenerateProperty(param)) | 225 property_dict['parameters'].append(self._GenerateProperty(param, | 
| 226 ref_resolver)) | |
| 196 if property_.returns: | 227 if property_.returns: | 
| 197 property_dict['returns'] = self._GenerateProperty(property_.returns) | 228 property_dict['returns'] = self._GenerateProperty(property_.returns) | 
| 198 if (property_.parent is not None and | 229 if (property_.parent is not None and | 
| 199 not isinstance(property_.parent, model.Namespace)): | 230 not isinstance(property_.parent, model.Namespace)): | 
| 200 property_dict['parent_name'] = property_.parent.simple_name | 231 property_dict['parent_name'] = property_.parent.simple_name | 
| 201 else: | 232 else: | 
| 202 property_dict['parent_name'] = None | 233 property_dict['parent_name'] = None | 
| 203 if property_.has_value: | 234 if property_.has_value: | 
| 204 if isinstance(property_.value, int): | 235 if isinstance(property_.value, int): | 
| 205 property_dict['value'] = _FormatValue(property_.value) | 236 property_dict['value'] = _FormatValue(property_.value) | 
| 206 else: | 237 else: | 
| 207 property_dict['value'] = property_.value | 238 property_dict['value'] = property_.value | 
| 208 else: | 239 else: | 
| 209 self._RenderTypeInformation(property_, property_dict) | 240 self._RenderTypeInformation(property_, property_dict, ref_resolver) | 
| 210 return property_dict | 241 return property_dict | 
| 211 | 242 | 
| 212 def _RenderTypeInformation(self, property_, dst_dict): | 243 def _RenderTypeInformation(self, property_, dst_dict, ref_resolver): | 
| 213 if property_.type_ == model.PropertyType.CHOICES: | 244 if property_.type_ == model.PropertyType.CHOICES: | 
| 214 dst_dict['choices'] = map(self._GenerateProperty, | 245 dst_dict['choices'] = [self._GenerateProperty(c, ref_resolver) | 
| 215 property_.choices.values()) | 246 for c in property_.choices.values()] | 
| 216 # We keep track of which is last for knowing when to add "or" between | 247 # We keep track of which is last for knowing when to add "or" between | 
| 217 # choices in templates. | 248 # choices in templates. | 
| 218 if len(dst_dict['choices']) > 0: | 249 if len(dst_dict['choices']) > 0: | 
| 219 dst_dict['choices'][-1]['last'] = True | 250 dst_dict['choices'][-1]['last'] = True | 
| 220 elif property_.type_ == model.PropertyType.REF: | 251 elif property_.type_ == model.PropertyType.REF: | 
| 221 dst_dict['link'] = GetLinkToRefType(self._namespace.name, | 252 if ref_resolver is not None: | 
| 222 property_.ref_type) | 253 dst_dict['link'] = self._GetLinkToRefType(property_.ref_type, | 
| 254 ref_resolver) | |
| 223 elif property_.type_ == model.PropertyType.ARRAY: | 255 elif property_.type_ == model.PropertyType.ARRAY: | 
| 224 dst_dict['array'] = self._GenerateProperty(property_.item_type) | 256 dst_dict['array'] = self._GenerateProperty(property_.item_type, | 
| 257 ref_resolver) | |
| 225 elif property_.type_ == model.PropertyType.ENUM: | 258 elif property_.type_ == model.PropertyType.ENUM: | 
| 226 dst_dict['enum_values'] = [] | 259 dst_dict['enum_values'] = [] | 
| 227 for enum_value in property_.enum_values: | 260 for enum_value in property_.enum_values: | 
| 228 dst_dict['enum_values'].append({'name': enum_value}) | 261 dst_dict['enum_values'].append({'name': enum_value}) | 
| 229 if len(dst_dict['enum_values']) > 0: | 262 if len(dst_dict['enum_values']) > 0: | 
| 230 dst_dict['enum_values'][-1]['last'] = True | 263 dst_dict['enum_values'][-1]['last'] = True | 
| 231 elif property_.instance_of is not None: | 264 elif property_.instance_of is not None: | 
| 232 dst_dict['simple_type'] = property_.instance_of.lower() | 265 dst_dict['simple_type'] = property_.instance_of.lower() | 
| 233 else: | 266 else: | 
| 234 dst_dict['simple_type'] = property_.type_.name.lower() | 267 dst_dict['simple_type'] = property_.type_.name.lower() | 
| 235 | 268 | 
| 236 class _LazySamplesGetter(object): | 269 class _LazySamplesGetter(object): | 
| 237 """This class is needed so that an extensions API page does not have to fetch | 270 """This class is needed so that an extensions API page does not have to fetch | 
| 238 the apps samples page and vice versa. | 271 the apps samples page and vice versa. | 
| 239 """ | 272 """ | 
| 240 def __init__(self, api_name, samples): | 273 def __init__(self, api_name, samples): | 
| 241 self._api_name = api_name | 274 self._api_name = api_name | 
| 242 self._samples = samples | 275 self._samples = samples | 
| 243 | 276 | 
| 244 def get(self, key): | 277 def get(self, key): | 
| 245 return self._samples.FilterSamples(key, self._api_name) | 278 return self._samples.FilterSamples(key, self._api_name) | 
| 246 | 279 | 
| 247 class APIDataSource(object): | 280 class APIDataSource(object): | 
| 248 """This class fetches and loads JSON APIs from the FileSystem passed in with | 281 """This class fetches and loads JSON APIs from the FileSystem passed in with | 
| 249 |cache_factory|, so the APIs can be plugged into templates. | 282 |cache_factory|, so the APIs can be plugged into templates. | 
| 250 """ | 283 """ | 
| 251 class Factory(object): | 284 class Factory(object): | 
| 252 def __init__(self, cache_factory, base_path, samples_factory): | 285 def __init__(self, | 
| 286 cache_factory, | |
| 287 base_path, | |
| 288 api_list_data_source): | |
| 
 
not at google - send to devlin
2012/11/02 17:26:48
As I mentioned in handler, should be passing the f
 
cduvall
2012/11/03 01:30:05
Done.
 
 | |
| 253 self._permissions_cache = cache_factory.Create(self._LoadPermissions, | 289 self._permissions_cache = cache_factory.Create(self._LoadPermissions, | 
| 254 compiled_fs.PERMS, | 290 compiled_fs.PERMS, | 
| 255 version=_VERSION) | 291 version=_VERSION) | 
| 256 self._json_cache = cache_factory.Create(self._LoadJsonAPI, | 292 self._json_cache = cache_factory.Create(self._LoadJsonAPI, | 
| 257 compiled_fs.JSON, | 293 compiled_fs.JSON, | 
| 258 version=_VERSION) | 294 version=_VERSION) | 
| 259 self._idl_cache = cache_factory.Create(self._LoadIdlAPI, | 295 self._idl_cache = cache_factory.Create(self._LoadIdlAPI, | 
| 260 compiled_fs.IDL, | 296 compiled_fs.IDL, | 
| 261 version=_VERSION) | 297 version=_VERSION) | 
| 262 self._idl_names_cache = cache_factory.Create(self._GetIDLNames, | 298 self._idl_names_cache = cache_factory.Create(self._GetIDLNames, | 
| 263 compiled_fs.IDL_NAMES, | 299 compiled_fs.IDL_NAMES, | 
| 264 version=_VERSION) | 300 version=_VERSION) | 
| 265 self._samples_factory = samples_factory | 301 self._names_cache = cache_factory.Create(self._GetAllNames, | 
| 302 compiled_fs.NAMES, | |
| 303 version=_VERSION) | |
| 266 self._base_path = base_path | 304 self._base_path = base_path | 
| 305 self._ref_resolver = ReferenceResolver( | |
| 306 self.Create(None, None, resolve_refs=False), | |
| 307 api_list_data_source) | |
| 267 | 308 | 
| 268 def Create(self, request): | 309 def Create(self, request, samples_data_source, resolve_refs=True): | 
| 
 
not at google - send to devlin
2012/11/02 17:26:48
It's nice for optional arguments to be False by de
 
not at google - send to devlin
2012/11/02 17:26:48
Having a separate SetSamplesDataSourceFactory meth
 
cduvall
2012/11/03 01:30:05
Done.
 
cduvall
2012/11/03 01:30:05
Done.
 
 | |
| 310 """Create an APIDataSource. |resolve_refs| specifies whether $ref's in | |
| 311 APIs being processed by the |ToDict| method of _JSCModel follows $ref's | |
| 312 in the API. This prevents endless recursion in ReferenceResolver. | |
| 313 """ | |
| 269 return APIDataSource(self._permissions_cache, | 314 return APIDataSource(self._permissions_cache, | 
| 270 self._json_cache, | 315 self._json_cache, | 
| 271 self._idl_cache, | 316 self._idl_cache, | 
| 317 self._names_cache, | |
| 272 self._idl_names_cache, | 318 self._idl_names_cache, | 
| 273 self._base_path, | 319 self._base_path, | 
| 274 self._samples_factory.Create(request)) | 320 samples_data_source, | 
| 321 self._ref_resolver if resolve_refs else None) | |
| 
 
not at google - send to devlin
2012/11/02 17:26:48
nit: push this logic into where ToDict is called (
 
cduvall
2012/11/03 01:30:05
Done.
 
 | |
| 275 | 322 | 
| 276 def _LoadPermissions(self, json_str): | 323 def _LoadPermissions(self, json_str): | 
| 277 return json.loads(json_comment_eater.Nom(json_str)) | 324 return json.loads(json_comment_eater.Nom(json_str)) | 
| 278 | 325 | 
| 279 def _LoadJsonAPI(self, api): | 326 def _LoadJsonAPI(self, api): | 
| 280 return _JscModel(json.loads(json_comment_eater.Nom(api))[0]) | 327 return _JSCModel(json.loads(json_comment_eater.Nom(api))[0]) | 
| 281 | 328 | 
| 282 def _LoadIdlAPI(self, api): | 329 def _LoadIdlAPI(self, api): | 
| 283 idl = idl_parser.IDLParser().ParseData(api) | 330 idl = idl_parser.IDLParser().ParseData(api) | 
| 284 return _JscModel(idl_schema.IDLSchema(idl).process()[0]) | 331 return _JSCModel(idl_schema.IDLSchema(idl).process()[0]) | 
| 285 | 332 | 
| 286 def _GetIDLNames(self, apis): | 333 def _GetIDLNames(self, apis): | 
| 287 return [model.UnixName(os.path.splitext(api.split('/')[-1])[0]) | 334 return [ | 
| 288 for api in apis if api.endswith('.idl')] | 335 model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0]) | 
| 336 for api in apis if api.endswith('.idl') | |
| 337 ] | |
| 338 | |
| 339 def _GetAllNames(self, apis): | |
| 340 return [ | |
| 341 model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0]) | |
| 342 for api in apis | |
| 343 ] | |
| 289 | 344 | 
| 290 def __init__(self, | 345 def __init__(self, | 
| 291 permissions_cache, | 346 permissions_cache, | 
| 292 json_cache, | 347 json_cache, | 
| 293 idl_cache, | 348 idl_cache, | 
| 349 names_cache, | |
| 294 idl_names_cache, | 350 idl_names_cache, | 
| 295 base_path, | 351 base_path, | 
| 296 samples): | 352 samples, | 
| 353 ref_resolver): | |
| 297 self._base_path = base_path | 354 self._base_path = base_path | 
| 298 self._permissions_cache = permissions_cache | 355 self._permissions_cache = permissions_cache | 
| 299 self._json_cache = json_cache | 356 self._json_cache = json_cache | 
| 300 self._idl_cache = idl_cache | 357 self._idl_cache = idl_cache | 
| 358 self._names_cache = names_cache | |
| 301 self._idl_names_cache = idl_names_cache | 359 self._idl_names_cache = idl_names_cache | 
| 302 self._samples = samples | 360 self._samples = samples | 
| 361 self._ref_resolver = ref_resolver | |
| 303 | 362 | 
| 304 def _GetPermsFromFile(self, filename): | 363 def _GetPermsFromFile(self, filename): | 
| 305 try: | 364 try: | 
| 306 perms = self._permissions_cache.GetFromFile('%s/%s' % | 365 perms = self._permissions_cache.GetFromFile('%s/%s' % | 
| 307 (self._base_path, filename)) | 366 (self._base_path, filename)) | 
| 308 return dict((model.UnixName(k), v) for k, v in perms.iteritems()) | 367 return dict((model.UnixName(k), v) for k, v in perms.iteritems()) | 
| 309 except FileNotFoundError: | 368 except FileNotFoundError: | 
| 310 return {} | 369 return {} | 
| 311 | 370 | 
| 312 def _GetFeature(self, path): | 371 def _GetFeature(self, path): | 
| 313 # Remove 'experimental_' from path name to match the keys in | 372 # Remove 'experimental_' from path name to match the keys in | 
| 314 # _permissions_features.json. | 373 # _permissions_features.json. | 
| 315 path = model.UnixName(path.replace('experimental_', '')) | 374 path = model.UnixName(path.replace('experimental_', '')) | 
| 316 for filename in ['_permission_features.json', '_manifest_features.json']: | 375 for filename in ['_permission_features.json', '_manifest_features.json']: | 
| 317 api_perms = self._GetPermsFromFile(filename).get(path, None) | 376 api_perms = self._GetPermsFromFile(filename).get(path, None) | 
| 318 if api_perms is not None: | 377 if api_perms is not None: | 
| 319 break | 378 break | 
| 320 if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'): | 379 if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'): | 
| 321 api_perms[api_perms['channel']] = True | 380 api_perms[api_perms['channel']] = True | 
| 322 return api_perms | 381 return api_perms | 
| 323 | 382 | 
| 324 def _GenerateHandlebarContext(self, handlebar, path): | 383 def _GenerateHandlebarContext(self, handlebar, path): | 
| 325 return_dict = { | 384 return_dict = { | 
| 326 'permissions': self._GetFeature(path), | 385 'permissions': self._GetFeature(path), | 
| 327 'samples': _LazySamplesGetter(path, self._samples) | 386 'samples': _LazySamplesGetter(path, self._samples) | 
| 328 } | 387 } | 
| 329 return_dict.update(handlebar.ToDict()) | 388 return_dict.update(handlebar.ToDict(self._ref_resolver)) | 
| 330 return return_dict | 389 return return_dict | 
| 331 | 390 | 
| 391 def _GetAsSubdirectory(self, name): | |
| 392 if name.startswith('experimental_'): | |
| 393 parts = name[len('experimental_'):].split('_', 1) | |
| 394 parts[1] = 'experimental_%s' % parts[1] | |
| 395 return '/'.join(parts) | |
| 396 return name.replace('_', '/', 1) | |
| 397 | |
| 332 def __getitem__(self, key): | 398 def __getitem__(self, key): | 
| 333 return self.get(key) | 399 return self.get(key) | 
| 334 | 400 | 
| 335 def get(self, key): | 401 def get(self, key): | 
| 336 path, ext = os.path.splitext(key) | 402 if key.endswith('.html') or key.endswith('.json') or key.endswith('.idl'): | 
| 403 path, ext = os.path.splitext(key) | |
| 404 else: | |
| 405 path = key | |
| 337 unix_name = model.UnixName(path) | 406 unix_name = model.UnixName(path) | 
| 338 idl_names = self._idl_names_cache.GetFromFileListing(self._base_path) | 407 idl_names = self._idl_names_cache.GetFromFileListing(self._base_path) | 
| 408 names = self._names_cache.GetFromFileListing(self._base_path) | |
| 409 if unix_name not in names and self._GetAsSubdirectory(unix_name) in names: | |
| 410 unix_name = self._GetAsSubdirectory(unix_name) | |
| 411 | |
| 339 cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else | 412 cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else | 
| 340 (self._json_cache, '.json')) | 413 (self._json_cache, '.json')) | 
| 341 return self._GenerateHandlebarContext( | 414 return self._GenerateHandlebarContext( | 
| 342 cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)), | 415 cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)), | 
| 343 path) | 416 path) | 
| OLD | NEW |