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.
7 from compiled_file_system
import SingleFile
, Unicode
8 from extensions_paths
import API_PATHS
9 from file_system
import FileNotFoundError
10 from future
import Future
11 from schema_util
import ProcessSchema
12 from third_party
.json_schema_compiler
.model
import Namespace
, UnixName
17 def _CreateAPIModel(path
, data
):
18 schema
= ProcessSchema(path
, data
)[0]
19 if not schema
: return None
20 return Namespace(schema
, schema
['namespace'])
23 class APIModels(object):
24 '''Tracks APIs and their Models.
27 def __init__(self
, features_bundle
, compiled_fs_factory
, file_system
):
28 self
._features
_bundle
= features_bundle
29 self
._model
_cache
= compiled_fs_factory
.Create(
30 file_system
, _CreateAPIModel
, APIModels
)
33 # API names appear alongside some of their methods/events/etc in the
34 # features file. APIs are those which either implicitly or explicitly have
35 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are
36 # APIs; runtime.onConnectNative is not).
37 api_features
= self
._features
_bundle
.GetAPIFeatures().Get()
38 return [name
for name
, feature
in api_features
.iteritems()
39 if ('.' not in name
or
40 name
.rsplit('.', 1)[0] not in api_features
or
41 feature
.get('noparent'))]
43 def GetModel(self
, api_name
):
44 # By default |api_name| is assumed to be given without a path or extension,
45 # so combinations of known paths and extension types will be searched.
46 api_extensions
= ('.json', '.idl')
49 # Callers sometimes include a file extension and/or prefix path with the
50 # |api_name| argument. We believe them and narrow the search space
52 name
, ext
= posixpath
.splitext(api_name
)
53 if ext
in api_extensions
:
54 api_extensions
= (ext
,)
56 for api_path
in api_paths
:
57 if api_name
.startswith(api_path
):
58 api_name
= api_name
[len(api_path
):]
59 api_paths
= (api_path
,)
62 # API names are given as declarativeContent and app.window but file names
63 # will be declarative_content and app_window.
64 file_name
= UnixName(api_name
).replace('.', '_')
65 # Devtools APIs are in API/devtools/ not API/, and have their
66 # "devtools" names removed from the file names.
67 basename
= posixpath
.basename(file_name
)
68 if 'devtools_' in basename
:
69 file_name
= posixpath
.join(
70 'devtools', file_name
.replace(basename
,
71 basename
.replace('devtools_' , '')))
73 futures
= [self
._model
_cache
.GetFromFile(
74 posixpath
.join(path
, '%s%s' % (file_name
, ext
)))
75 for ext
in api_extensions
76 for path
in api_paths
]
78 for future
in futures
:
81 except FileNotFoundError
: pass
82 # Propagate the first FileNotFoundError if neither were found.
84 return Future(callback
=resolve
)
87 future_models
= [(name
, self
.GetModel(name
)) for name
in self
.GetNames()]
88 for name
, future_model
in future_models
:
90 model
= future_model
.Get()
91 except FileNotFoundError
: