| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 posixpath | 5 import posixpath |
| 6 | 6 |
| 7 from compiled_file_system import SingleFile, Unicode | 7 from compiled_file_system import SingleFile, Unicode |
| 8 from docs_server_utils import StringIdentity |
| 8 from extensions_paths import API_PATHS | 9 from extensions_paths import API_PATHS |
| 10 from features_bundle import HasParentFeature |
| 9 from file_system import FileNotFoundError | 11 from file_system import FileNotFoundError |
| 10 from future import Collect, Future | 12 from future import Collect, Future |
| 13 from platform_util import PlatformToExtensionType |
| 11 from schema_util import ProcessSchema | 14 from schema_util import ProcessSchema |
| 15 from third_party.json_schema_compiler.json_schema import DeleteNodes |
| 12 from third_party.json_schema_compiler.model import Namespace, UnixName | 16 from third_party.json_schema_compiler.model import Namespace, UnixName |
| 13 | 17 |
| 14 | 18 |
| 15 @SingleFile | |
| 16 @Unicode | |
| 17 def _CreateAPIModel(path, data): | |
| 18 schema = ProcessSchema(path, data)[0] | |
| 19 if not schema: | |
| 20 raise FileNotFoundError('No schema for %s' % path) | |
| 21 return Namespace(schema, schema['namespace']) | |
| 22 | |
| 23 | |
| 24 class APIModels(object): | 19 class APIModels(object): |
| 25 '''Tracks APIs and their Models. | 20 '''Tracks APIs and their Models. |
| 26 ''' | 21 ''' |
| 27 | 22 |
| 28 def __init__(self, features_bundle, compiled_fs_factory, file_system): | 23 def __init__(self, |
| 24 features_bundle, |
| 25 compiled_fs_factory, |
| 26 file_system, |
| 27 platform): |
| 29 self._features_bundle = features_bundle | 28 self._features_bundle = features_bundle |
| 30 self._identity = file_system.GetIdentity() | 29 self._platform = PlatformToExtensionType(platform) |
| 31 self._model_cache = compiled_fs_factory.Create( | 30 self._model_cache = compiled_fs_factory.Create( |
| 32 file_system, _CreateAPIModel, APIModels) | 31 file_system, self._CreateAPIModel, APIModels, category=self._platform) |
| 32 |
| 33 @SingleFile |
| 34 @Unicode |
| 35 def _CreateAPIModel(self, path, data): |
| 36 def does_not_include_platform(node): |
| 37 return ('extension_types' in node and |
| 38 node['extension_types'] != 'all' and |
| 39 self._platform not in node['extension_types']) |
| 40 |
| 41 schema = ProcessSchema(path, data)[0] |
| 42 if not schema: |
| 43 raise ValueError('No schema for %s' % path) |
| 44 return Namespace(DeleteNodes( |
| 45 schema, matcher=does_not_include_platform), schema['namespace']) |
| 33 | 46 |
| 34 def GetNames(self): | 47 def GetNames(self): |
| 35 # API names appear alongside some of their methods/events/etc in the | 48 # API names appear alongside some of their methods/events/etc in the |
| 36 # features file. APIs are those which either implicitly or explicitly have | 49 # features file. APIs are those which either implicitly or explicitly have |
| 37 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are | 50 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are |
| 38 # APIs; runtime.onConnectNative is not). | 51 # APIs; runtime.onConnectNative is not). |
| 39 api_features = self._features_bundle.GetAPIFeatures().Get() | 52 api_features = self._features_bundle.GetAPIFeatures().Get() |
| 40 return [name for name, feature in api_features.iteritems() | 53 return [name for name, feature in api_features.iteritems() |
| 41 if ('.' not in name or | 54 if not HasParentFeature(name, feature, api_features)] |
| 42 name.rsplit('.', 1)[0] not in api_features or | |
| 43 feature.get('noparent'))] | |
| 44 | 55 |
| 45 def GetModel(self, api_name): | 56 def GetModel(self, api_name): |
| 46 # By default |api_name| is assumed to be given without a path or extension, | 57 # By default |api_name| is assumed to be given without a path or extension, |
| 47 # so combinations of known paths and extension types will be searched. | 58 # so combinations of known paths and extension types will be searched. |
| 48 api_extensions = ('.json', '.idl') | 59 api_extensions = ('.json', '.idl') |
| 49 api_paths = API_PATHS | 60 api_paths = API_PATHS |
| 50 | 61 |
| 51 # Callers sometimes include a file extension and/or prefix path with the | 62 # Callers sometimes include a file extension and/or prefix path with the |
| 52 # |api_name| argument. We believe them and narrow the search space | 63 # |api_name| argument. We believe them and narrow the search space |
| 53 # accordingly. | 64 # accordingly. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 73 basename.replace('devtools_' , ''))) | 84 basename.replace('devtools_' , ''))) |
| 74 | 85 |
| 75 futures = [self._model_cache.GetFromFile( | 86 futures = [self._model_cache.GetFromFile( |
| 76 posixpath.join(path, '%s%s' % (file_name, ext))) | 87 posixpath.join(path, '%s%s' % (file_name, ext))) |
| 77 for ext in api_extensions | 88 for ext in api_extensions |
| 78 for path in api_paths] | 89 for path in api_paths] |
| 79 def resolve(): | 90 def resolve(): |
| 80 for future in futures: | 91 for future in futures: |
| 81 try: | 92 try: |
| 82 return future.Get() | 93 return future.Get() |
| 83 except FileNotFoundError: pass | 94 # Either the file wasn't found or there was no schema for the file |
| 84 # Propagate the first FileNotFoundError if neither were found. | 95 except (FileNotFoundError, ValueError): pass |
| 96 # Propagate the first error if neither were found. |
| 85 futures[0].Get() | 97 futures[0].Get() |
| 86 return Future(callback=resolve) | 98 return Future(callback=resolve) |
| 87 | 99 |
| 88 def Cron(self): | 100 def Cron(self): |
| 89 futures = [self.GetModel(name) for name in self.GetNames()] | 101 futures = [self.GetModel(name) for name in self.GetNames()] |
| 90 return Collect(futures, except_pass=FileNotFoundError) | 102 return Collect(futures, except_pass=(FileNotFoundError, ValueError)) |
| 91 | 103 |
| 92 def IterModels(self): | 104 def IterModels(self): |
| 93 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] | 105 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] |
| 94 for name, future_model in future_models: | 106 for name, future_model in future_models: |
| 95 try: | 107 try: |
| 96 model = future_model.Get() | 108 model = future_model.Get() |
| 97 except FileNotFoundError: | 109 except FileNotFoundError: |
| 98 continue | 110 continue |
| 99 if model: | 111 if model: |
| 100 yield name, model | 112 yield name, model |
| 101 | |
| 102 def GetIdentity(self): | |
| 103 return self._identity | |
| OLD | NEW |