api_models.py revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 compiled_file_system import SingleFile 10from file_system import FileNotFoundError 11from future import Gettable, Future 12from schema_util import ProcessSchema 13from svn_constants import API_PATH 14from third_party.json_schema_compiler.model import Namespace, UnixName 15 16 17@SingleFile 18def _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 25class 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)) 76