forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodel.py
134 lines (123 loc) · 4.23 KB
/
model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os.path
class Model(object):
"""Model of all namespaces that comprise an API.
"""
def __init__(self):
self.namespaces = {}
def AddNamespace(self, json, source_file):
"""Add a namespace's json to the model if it has a "compile" property set
to true. Returns the new namespace or None if a namespace wasn't added.
"""
if not json.get('compile'):
return None
namespace = Namespace(json, source_file)
self.namespaces[namespace.name] = namespace
return namespace
class Namespace(object):
"""An API namespace.
"""
def __init__(self, json, source_file):
self.name = json['namespace']
self.source_file = source_file
self.source_file_dir, self.source_file_filename = os.path.split(source_file)
self.type_dependencies = {}
self.types = {}
self.functions = {}
for type_json in json['types']:
type_ = Type(type_json)
self.types[type_.name] = type_
for function_json in json['functions']:
if not function_json.get('nocompile'):
function = Function(function_json)
self.functions[function.name] = function
class Type(object):
"""A Type defined in the json.
"""
def __init__(self, json):
self.name = json['id']
self.description = json.get('description')
self.properties = {}
for prop_name, prop_json in json['properties'].items():
self.properties[prop_name] = Property(prop_name, prop_json)
class Callback(object):
"""A callback parameter to a Function.
"""
def __init__(self, json):
params = json['parameters']
if len(params) == 0:
self.param = None
elif len(params) == 1:
param = params[0]
self.param = Property(param['name'], param)
else:
raise AssertionError("Callbacks can have at most a single parameter")
class Function(object):
"""A Function defined in the API.
"""
def __init__(self, json):
self.name = json['name']
self.params = []
self.description = json['description']
self.callback = None
self.type_dependencies = {}
for param in json['parameters']:
if param.get('type') == 'function':
assert (not self.callback), "Function has more than one callback"
self.callback = Callback(param)
else:
self.params.append(Property(param['name'], param))
assert (self.callback), "Function does not support callback"
# TODO(calamity): handle Enum/choices
class Property(object):
"""A property of a type OR a parameter to a function.
Members will change based on PropertyType. Check self.type_ to determine which
members actually exist.
"""
def __init__(self, name, json):
self.name = name
self.optional = json.get('optional', False)
self.description = json.get('description')
# TODO(calamity) maybe check for circular refs? could that be a problem?
if '$ref' in json:
self.ref_type = json['$ref']
self.type_ = PropertyType.REF
elif 'type' in json:
json_type = json['type']
if json_type == 'string':
self.type_ = PropertyType.STRING
elif json_type == 'boolean':
self.type_ = PropertyType.BOOLEAN
elif json_type == 'integer':
self.type_ = PropertyType.INTEGER
elif json_type == 'double':
self.type_ = PropertyType.DOUBLE
elif json_type == 'array':
self.item_type = Property(name + "_inner", json['items'])
self.type_ = PropertyType.ARRAY
elif json_type == 'object':
self.properties = {}
self.type_ = PropertyType.OBJECT
for key, val in json['properties'].items():
self.properties[key] = Property(key, val)
else:
raise NotImplementedError(json_type)
elif 'choices' in json:
self.type_ = PropertyType.CHOICES
self.choices = {}
class PropertyType(object):
"""Enum of different types of properties/parameters.
"""
class _Info(object):
def __init__(self, is_fundamental):
self.is_fundamental = is_fundamental
INTEGER = _Info(True)
DOUBLE = _Info(True)
BOOLEAN = _Info(True)
STRING = _Info(True)
ARRAY = _Info(False)
REF = _Info(False)
CHOICES = _Info(False)
OBJECT = _Info(False)