OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (c) 2012 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 os.path | |
6 | |
7 class Model(object): | |
8 """Model of the API. | |
Yoyo Zhou
2012/01/19 02:19:40
This is a little vague. What API is it modeling? T
calamity
2012/01/20 01:10:25
Comment has been changed. Still not sure if it's d
| |
9 """ | |
10 def __init__(self): | |
11 self.namespaces = {} | |
12 self.types = {} | |
13 | |
14 def add_namespace(self, json, source_file, namespace_suffix): | |
15 """Add a namespace's json to the model if it has a "compile" property set | |
16 to true. Returns the new namespace or None if a namespac wasn't added. | |
Yoyo Zhou
2012/01/19 02:19:40
typo: namespac
calamity
2012/01/20 01:10:25
Done.
| |
17 """ | |
18 if not json.get('compile'): | |
19 return None | |
20 namespace = Namespace(json, source_file, namespace_suffix) | |
21 self.namespaces[namespace.name] = namespace | |
22 for tipe in namespace.types.values(): | |
Yoyo Zhou
2012/01/19 02:19:40
type_ is better than tipe.
calamity
2012/01/20 01:10:25
Done.
| |
23 self.types[tipe.name] = namespace | |
24 return namespace | |
25 | |
26 class Namespace(object): | |
27 """An API namespace. | |
28 """ | |
29 def __init__(self, json, source_file, namespace_suffix): | |
30 self.name = json['namespace'] | |
31 self.source_file = source_file | |
32 self.source_file_dir, self.source_file_filename = os.path.split(source_file) | |
33 self.target_namespace = self.name + namespace_suffix | |
34 self.type_dependencies = {} | |
35 self.types = {} | |
36 self.functions = {} | |
37 for type_json in json['types']: | |
38 tipe = Type(type_json) | |
39 self.types[tipe.name] = tipe | |
40 for function_json in json['functions']: | |
41 if not function_json.get('nocompile'): | |
42 function = Function(function_json) | |
43 self.functions[function.name] = function | |
44 | |
45 class Type(object): | |
46 """A Type defined in the json. | |
47 """ | |
48 def __init__(self, json): | |
49 self.name = json['id'] | |
50 self.description = json.get('description') | |
51 self.properties = {} | |
52 for prop_name, prop_json in json['properties'].items(): | |
53 self.properties[prop_name] = Property(prop_name, prop_json) | |
54 | |
55 class Callback(object): | |
56 """A callback parameter to a Function. | |
57 """ | |
58 def __init__(self, json): | |
59 params = json['parameters'] | |
60 if len(params) == 0: | |
61 self.param = None | |
62 elif len(params) == 1: | |
63 param = params[0] | |
64 self.param = Property(param['name'], param) | |
65 else: | |
66 raise AssertionError("Callbacks can have at most a single parameter") | |
Yoyo Zhou
2012/01/19 02:19:40
Where does this constraint come from?
calamity
2012/01/20 01:10:25
I believe it's just how the extensions api system
| |
67 | |
68 class Function(object): | |
69 """A Function defined in the API. | |
70 """ | |
71 def __init__(self, json): | |
72 self.name = json['name'] | |
73 self.params = [] | |
74 self.description = json['description'] | |
75 self.callback = None | |
76 self.type_dependencies = {} | |
77 for param in json['parameters']: | |
78 if param.get('type') == 'function': | |
79 assert (not self.callback), "Function has more than one callback" | |
80 self.callback = Callback(param) | |
81 else: | |
82 self.params.append(Property(param['name'], param)) | |
83 assert (self.callback), "Function does not support callback" | |
84 | |
85 # TODO(calamity): handle Enum/choices | |
86 class Property(object): | |
87 """A property of a type OR a parameter to a function. | |
88 | |
89 Members will change based on PropertyType. Check self.type to determine which | |
90 members actually exist. | |
91 """ | |
92 def __init__(self, name, json): | |
93 self.name = name | |
94 self.optional = json.get('optional', False) | |
95 self.description = json.get('description') | |
96 # TODO(calamity) maybe check for circular refs? could that be a problem? | |
97 if '$ref' in json: | |
98 self.ref_type = json['$ref'] | |
99 self.type = PropertyType.REF | |
100 elif 'type' in json: | |
101 json_type = json['type'] | |
102 if json_type == 'string': | |
103 self.type = PropertyType.STRING | |
Yoyo Zhou
2012/01/19 02:19:40
I think even though you can name an attribute the
calamity
2012/01/20 01:10:25
Done.
| |
104 elif json_type == 'boolean': | |
105 self.type = PropertyType.BOOLEAN | |
106 elif json_type == 'integer': | |
107 self.type = PropertyType.INTEGER | |
108 elif json_type == 'double': | |
109 self.type = PropertyType.DOUBLE | |
110 elif json_type == 'array': | |
111 self.item_type = Property(name + "_inner", json['items']) | |
112 self.type = PropertyType.ARRAY | |
113 elif json_type == 'object': | |
114 self.properties = {} | |
115 self.type = PropertyType.OBJECT | |
116 for key, val in json['properties'].items(): | |
117 self.properties[key] = Property(key, val) | |
118 else: | |
119 raise NotImplementedError(json_type) | |
120 elif 'choices' in json: | |
121 self.type = PropertyType.CHOICES | |
122 self.choices = {} | |
123 | |
124 class PropertyType(object): | |
125 """Enum of different types of properties/parameters. | |
126 """ | |
127 class __Info(object): | |
128 def __init__(self, is_fundamental): | |
129 self.is_fundamental = is_fundamental | |
130 | |
131 INTEGER = __Info(True) | |
132 DOUBLE = __Info(True) | |
133 BOOLEAN = __Info(True) | |
134 STRING = __Info(True) | |
135 ARRAY = __Info(False) | |
136 REF = __Info(False) | |
137 CHOICES = __Info(False) | |
138 OBJECT = __Info(False) | |
OLD | NEW |