api_models.py revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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
5import logging
6import os
7import posixpath
8
9from file_system import FileNotFoundError
10from future import Gettable, Future
11from schema_util import ProcessSchema
12from svn_constants import API_PATH
13from third_party.json_schema_compiler.model import Namespace, UnixName
14
15
16def _CreateAPIModel(path, data):
17  schema = ProcessSchema(path, data)
18  if os.path.splitext(path)[1] == '.json':
19    schema = schema[0]
20  return Namespace(schema, schema['namespace'])
21
22
23class APIModels(object):
24  '''Tracks APIs and their Models.
25  '''
26
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)
31
32  def GetNames(self):
33    return self._features_bundle.GetAPIFeatures().keys()
34
35  def GetModel(self, api_name):
36    # Callers sometimes specify a filename which includes .json or .idl - if
37    # so, believe them. They may even include the 'api/' prefix.
38    if os.path.splitext(api_name)[1] in ('.json', '.idl'):
39      if not api_name.startswith(API_PATH + '/'):
40        api_name = posixpath.join(API_PATH, api_name)
41      return self._model_cache.GetFromFile(api_name)
42
43    assert not api_name.startswith(API_PATH)
44
45    # API names are given as declarativeContent and app.window but file names
46    # will be declarative_content and app_window.
47    file_name = UnixName(api_name).replace('.', '_')
48    # Devtools APIs are in API_PATH/devtools/ not API_PATH/, and have their
49    # "devtools" names removed from the file names.
50    basename = posixpath.basename(file_name)
51    if basename.startswith('devtools_'):
52      file_name = posixpath.join(
53          'devtools', file_name.replace(basename, basename[len('devtools_'):]))
54
55    futures = [self._model_cache.GetFromFile('%s/%s.%s' %
56                                             (API_PATH, file_name, ext))
57               for ext in ('json', 'idl')]
58    def resolve():
59      for future in futures:
60        try:
61          return future.Get()
62        except FileNotFoundError: pass
63      # Propagate the first FileNotFoundError if neither were found.
64      futures[0].Get()
65    return Future(delegate=Gettable(resolve))
66