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 |