- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / api_models.py
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.
4
5 import logging
6 import os
7 import posixpath
8
9 from compiled_file_system import SingleFile
10 from file_system import FileNotFoundError
11 from future import Gettable, Future
12 from schema_util import ProcessSchema
13 from svn_constants import API_PATH
14 from third_party.json_schema_compiler.model import Namespace, UnixName
15
16
17 @SingleFile
18 def _CreateAPIModel(path, data):
19   schema = ProcessSchema(path, data)
20   if os.path.splitext(path)[1] == '.json':
21     schema = schema[0]
22   return Namespace(schema, schema['namespace'])
23
24
25 class APIModels(object):
26   '''Tracks APIs and their Models.
27   '''
28
29   def __init__(self, features_bundle, compiled_fs_factory, file_system):
30     self._features_bundle = features_bundle
31     self._model_cache = compiled_fs_factory.Create(
32         file_system, _CreateAPIModel, APIModels)
33
34   def GetNames(self):
35     # API names appear alongside some of their methods/events/etc in the
36     # features file. APIs are those which either implicitly or explicitly have
37     # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are
38     # APIs; runtime.onConnectNative is not).
39     api_features = self._features_bundle.GetAPIFeatures()
40     return [name for name, feature in api_features.iteritems()
41             if ('.' not in name or
42                 name.rsplit('.', 1)[0] not in api_features or
43                 feature.get('noparent'))]
44
45   def GetModel(self, api_name):
46     # Callers sometimes specify a filename which includes .json or .idl - if
47     # so, believe them. They may even include the 'api/' prefix.
48     if os.path.splitext(api_name)[1] in ('.json', '.idl'):
49       if not api_name.startswith(API_PATH + '/'):
50         api_name = posixpath.join(API_PATH, api_name)
51       return self._model_cache.GetFromFile(api_name)
52
53     assert not api_name.startswith(API_PATH)
54
55     # API names are given as declarativeContent and app.window but file names
56     # will be declarative_content and app_window.
57     file_name = UnixName(api_name).replace('.', '_')
58     # Devtools APIs are in API_PATH/devtools/ not API_PATH/, and have their
59     # "devtools" names removed from the file names.
60     basename = posixpath.basename(file_name)
61     if basename.startswith('devtools_'):
62       file_name = posixpath.join(
63           'devtools', file_name.replace(basename, basename[len('devtools_'):]))
64
65     futures = [self._model_cache.GetFromFile('%s/%s.%s' %
66                                              (API_PATH, file_name, ext))
67                for ext in ('json', 'idl')]
68     def resolve():
69       for future in futures:
70         try:
71           return future.Get()
72         except FileNotFoundError: pass
73       # Propagate the first FileNotFoundError if neither were found.
74       futures[0].Get()
75     return Future(delegate=Gettable(resolve))