OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import copy | 5 import copy |
6 import os.path | 6 import os.path |
7 import re | 7 import re |
8 | 8 |
9 from json_parse import OrderedDict | 9 from json_parse import OrderedDict |
10 | 10 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 - |compiler_options| the compiler_options dict, only present if | 53 - |compiler_options| the compiler_options dict, only present if |
54 |include_compiler_options| is True | 54 |include_compiler_options| is True |
55 """ | 55 """ |
56 def __init__(self, json, source_file, include_compiler_options=False): | 56 def __init__(self, json, source_file, include_compiler_options=False): |
57 self.name = json['namespace'] | 57 self.name = json['namespace'] |
58 self.unix_name = UnixName(self.name) | 58 self.unix_name = UnixName(self.name) |
59 self.source_file = source_file | 59 self.source_file = source_file |
60 self.source_file_dir, self.source_file_filename = os.path.split(source_file) | 60 self.source_file_dir, self.source_file_filename = os.path.split(source_file) |
61 self.parent = None | 61 self.parent = None |
62 self.platforms = _GetPlatforms(json) | 62 self.platforms = _GetPlatforms(json) |
63 _AddTypes(self, json, self) | 63 toplevel_origin = Origin(from_client=True, from_json=True) |
64 _AddFunctions(self, json, self) | 64 self.types = _GetTypes(self, json, self, toplevel_origin) |
65 _AddEvents(self, json, self) | 65 self.functions = _GetFunctions(self, json, self) |
66 _AddProperties(self, json, self) | 66 self.events = _GetEvents(self, json, self) |
| 67 self.properties = _GetProperties(self, json, self, toplevel_origin) |
67 if include_compiler_options: | 68 if include_compiler_options: |
68 self.compiler_options = json.get('compiler_options', {}) | 69 self.compiler_options = json.get('compiler_options', {}) |
69 | 70 |
| 71 class Origin(object): |
| 72 """Stores the possible origin of model object as a pair of bools. These are: |
| 73 |
| 74 |from_client| indicating that instances can originate from users of |
| 75 generated code (for example, function results), or |
| 76 |from_json| indicating that instances can originate from the JSON (for |
| 77 example, function parameters) |
| 78 |
| 79 It is possible for model objects to originate from both the client and json, |
| 80 for example Types defined in the top-level schema, in which case both |
| 81 |from_client| and |from_json| would be True. |
| 82 """ |
| 83 def __init__(self, from_client=False, from_json=False): |
| 84 if not from_client and not from_json: |
| 85 raise ValueError('One of from_client or from_json must be true') |
| 86 self.from_client = from_client |
| 87 self.from_json = from_json |
| 88 |
70 class Type(object): | 89 class Type(object): |
71 """A Type defined in the json. | 90 """A Type defined in the json. |
72 | 91 |
73 Properties: | 92 Properties: |
74 - |name| the type name | 93 - |name| the type name |
| 94 - |namespace| the Type's namespace |
75 - |description| the description of the type (if provided) | 95 - |description| the description of the type (if provided) |
76 - |properties| a map of property unix_names to their model.Property | 96 - |properties| a map of property unix_names to their model.Property |
77 - |functions| a map of function names to their model.Function | 97 - |functions| a map of function names to their model.Function |
78 - |events| a map of event names to their model.Event | 98 - |events| a map of event names to their model.Event |
79 - |from_client| indicates that instances of the Type can originate from the | 99 - |origin| the Origin of the type |
80 users of generated code, such as top-level types and function results | 100 - |property_type| the PropertyType of this Type |
81 - |from_json| indicates that instances of the Type can originate from the | |
82 JSON (as described by the schema), such as top-level types and function | |
83 parameters | |
84 - |type_| the PropertyType of this Type | |
85 - |item_type| if this is an array, the type of items in the array | 101 - |item_type| if this is an array, the type of items in the array |
86 - |simple_name| the name of this Type without a namespace | 102 - |simple_name| the name of this Type without a namespace |
| 103 - |additional_properties| the type of the additional properties, if any is |
| 104 specified |
87 """ | 105 """ |
88 def __init__(self, parent, name, json, namespace): | 106 def __init__(self, |
89 if json.get('type') == 'array': | 107 parent, |
90 self.type_ = PropertyType.ARRAY | 108 name, |
91 self.item_type = Property(self, | 109 json, |
92 name + "Element", | 110 namespace, |
93 json['items'], | 111 origin): |
94 namespace, | 112 self.name = name |
95 from_json=True, | 113 self.namespace = namespace |
96 from_client=True) | 114 self.simple_name = _StripNamespace(self.name, namespace) |
97 elif 'enum' in json: | 115 self.unix_name = UnixName(self.name) |
98 self.enum_values = [] | 116 self.description = json.get('description', None) |
99 for value in json['enum']: | 117 self.origin = origin |
100 self.enum_values.append(value) | 118 self.parent = parent |
101 self.type_ = PropertyType.ENUM | 119 self.instance_of = json.get('isInstanceOf', None) |
102 elif json.get('type') == 'string': | 120 |
103 self.type_ = PropertyType.STRING | 121 # TODO(kalman): Only objects need functions/events/properties, but callers |
104 else: | 122 # assume that all types have them. Fix this. |
| 123 self.functions = _GetFunctions(self, json, namespace) |
| 124 self.events = _GetEvents(self, json, namespace) |
| 125 self.properties = _GetProperties(self, json, namespace, origin) |
| 126 |
| 127 json_type = json.get('type', None) |
| 128 if json_type == 'array': |
| 129 self.property_type = PropertyType.ARRAY |
| 130 self.item_type = Type( |
| 131 self, '%sType' % name, json['items'], namespace, origin) |
| 132 elif '$ref' in json: |
| 133 self.property_type = PropertyType.REF |
| 134 self.ref_type = json['$ref'] |
| 135 elif 'enum' in json and json_type == 'string': |
| 136 self.property_type = PropertyType.ENUM |
| 137 self.enum_values = [value for value in json['enum']] |
| 138 elif json_type == 'any': |
| 139 self.property_type = PropertyType.ANY |
| 140 elif json_type == 'binary': |
| 141 self.property_type = PropertyType.BINARY |
| 142 elif json_type == 'boolean': |
| 143 self.property_type = PropertyType.BOOLEAN |
| 144 elif json_type == 'integer': |
| 145 self.property_type = PropertyType.INTEGER |
| 146 elif (json_type == 'double' or |
| 147 json_type == 'number'): |
| 148 self.property_type = PropertyType.DOUBLE |
| 149 elif json_type == 'string': |
| 150 self.property_type = PropertyType.STRING |
| 151 elif 'choices' in json: |
| 152 self.property_type = PropertyType.CHOICES |
| 153 self.choices = [Type(self, |
| 154 # The name of the choice type - there had better be |
| 155 # either a type or a $ref specified for the choice. |
| 156 json.get('type', json.get('$ref')), |
| 157 json, |
| 158 namespace, |
| 159 origin) |
| 160 for json in json['choices']] |
| 161 elif json_type == 'object': |
105 if not ( | 162 if not ( |
106 'properties' in json or | 163 'properties' in json or |
107 'additionalProperties' in json or | 164 'additionalProperties' in json or |
108 'functions' in json or | 165 'functions' in json or |
109 'events' in json): | 166 'events' in json): |
110 raise ParseException(self, name + " has no properties or functions") | 167 raise ParseException(self, name + " has no properties or functions") |
111 self.type_ = PropertyType.OBJECT | 168 self.property_type = PropertyType.OBJECT |
112 self.name = name | 169 additional_properties_json = json.get('additionalProperties', None) |
113 self.simple_name = _StripNamespace(self.name, namespace) | 170 if additional_properties_json is not None: |
114 self.unix_name = UnixName(self.name) | 171 self.additional_properties = Type(self, |
115 self.description = json.get('description') | 172 'additionalProperties', |
116 self.from_json = True | 173 additional_properties_json, |
117 self.from_client = True | 174 namespace, |
118 self.parent = parent | 175 origin) |
119 self.instance_of = json.get('isInstanceOf', None) | 176 else: |
120 _AddFunctions(self, json, namespace) | 177 self.additional_properties = None |
121 _AddEvents(self, json, namespace) | 178 elif json_type == 'function': |
122 _AddProperties(self, json, namespace, from_json=True, from_client=True) | 179 self.property_type = PropertyType.FUNCTION |
123 | 180 # Sometimes we might have an unnamed function, e.g. if it's a property |
124 additional_properties_key = 'additionalProperties' | 181 # of an object. Use the name of the property in that case. |
125 additional_properties = json.get(additional_properties_key) | 182 function_name = json.get('name', name) |
126 if additional_properties: | 183 self.function = Function(self, function_name, json, namespace, origin) |
127 self.properties[additional_properties_key] = Property( | 184 else: |
128 self, | 185 raise ParseException(self, 'Unsupported JSON type %s' % json_type) |
129 additional_properties_key, | |
130 additional_properties, | |
131 namespace, | |
132 is_additional_properties=True) | |
133 | 186 |
134 class Function(object): | 187 class Function(object): |
135 """A Function defined in the API. | 188 """A Function defined in the API. |
136 | 189 |
137 Properties: | 190 Properties: |
138 - |name| the function name | 191 - |name| the function name |
139 - |platforms| if not None, the list of platforms that the function is | 192 - |platforms| if not None, the list of platforms that the function is |
140 available to | 193 available to |
141 - |params| a list of parameters to the function (order matters). A separate | 194 - |params| a list of parameters to the function (order matters). A separate |
142 parameter is used for each choice of a 'choices' parameter | 195 parameter is used for each choice of a 'choices' parameter |
143 - |description| a description of the function (if provided) | 196 - |description| a description of the function (if provided) |
144 - |callback| the callback parameter to the function. There should be exactly | 197 - |callback| the callback parameter to the function. There should be exactly |
145 one | 198 one |
146 - |optional| whether the Function is "optional"; this only makes sense to be | 199 - |optional| whether the Function is "optional"; this only makes sense to be |
147 present when the Function is representing a callback property | 200 present when the Function is representing a callback property |
148 - |simple_name| the name of this Function without a namespace | 201 - |simple_name| the name of this Function without a namespace |
149 """ | 202 """ |
150 def __init__(self, | 203 def __init__(self, |
151 parent, | 204 parent, |
| 205 name, |
152 json, | 206 json, |
153 namespace, | 207 namespace, |
154 from_json=False, | 208 origin): |
155 from_client=False): | 209 self.name = name |
156 self.name = json['name'] | |
157 self.simple_name = _StripNamespace(self.name, namespace) | 210 self.simple_name = _StripNamespace(self.name, namespace) |
158 self.platforms = _GetPlatforms(json) | 211 self.platforms = _GetPlatforms(json) |
159 self.params = [] | 212 self.params = [] |
160 self.description = json.get('description') | 213 self.description = json.get('description') |
161 self.callback = None | 214 self.callback = None |
162 self.optional = json.get('optional', False) | 215 self.optional = json.get('optional', False) |
163 self.parent = parent | 216 self.parent = parent |
164 self.nocompile = json.get('nocompile') | 217 self.nocompile = json.get('nocompile') |
165 options = json.get('options', {}) | 218 options = json.get('options', {}) |
166 self.conditions = options.get('conditions', []) | 219 self.conditions = options.get('conditions', []) |
167 self.actions = options.get('actions', []) | 220 self.actions = options.get('actions', []) |
168 self.supports_listeners = options.get('supportsListeners', True) | 221 self.supports_listeners = options.get('supportsListeners', True) |
169 self.supports_rules = options.get('supportsRules', False) | 222 self.supports_rules = options.get('supportsRules', False) |
| 223 |
170 def GeneratePropertyFromParam(p): | 224 def GeneratePropertyFromParam(p): |
171 return Property(self, | 225 return Property.FromJSON(self, p['name'], p, namespace, origin) |
172 p['name'], p, | |
173 namespace, | |
174 from_json=from_json, | |
175 from_client=from_client) | |
176 | 226 |
177 self.filters = [GeneratePropertyFromParam(filter) | 227 self.filters = [GeneratePropertyFromParam(filter) |
178 for filter in json.get('filters', [])] | 228 for filter in json.get('filters', [])] |
179 callback_param = None | 229 callback_param = None |
180 for param in json.get('parameters', []): | 230 for param in json.get('parameters', []): |
181 | |
182 if param.get('type') == 'function': | 231 if param.get('type') == 'function': |
183 if callback_param: | 232 if callback_param: |
184 # No ParseException because the webstore has this. | 233 # No ParseException because the webstore has this. |
185 # Instead, pretend all intermediate callbacks are properties. | 234 # Instead, pretend all intermediate callbacks are properties. |
186 self.params.append(GeneratePropertyFromParam(callback_param)) | 235 self.params.append(GeneratePropertyFromParam(callback_param)) |
187 callback_param = param | 236 callback_param = param |
188 else: | 237 else: |
189 self.params.append(GeneratePropertyFromParam(param)) | 238 self.params.append(GeneratePropertyFromParam(param)) |
190 | 239 |
191 if callback_param: | 240 if callback_param: |
192 self.callback = Function(self, | 241 self.callback = Function(self, |
| 242 callback_param['name'], |
193 callback_param, | 243 callback_param, |
194 namespace, | 244 namespace, |
195 from_client=True) | 245 Origin(from_client=True)) |
196 | 246 |
197 self.returns = None | 247 self.returns = None |
198 if 'returns' in json: | 248 if 'returns' in json: |
199 self.returns = Property(self, 'return', json['returns'], namespace) | 249 self.returns = Property.FromJSON( |
| 250 self, 'return', json['returns'], namespace, origin) |
200 | 251 |
201 class Property(object): | 252 class Property(object): |
202 """A property of a type OR a parameter to a function. | 253 """A property of a type OR a parameter to a function. |
203 | |
204 Properties: | 254 Properties: |
205 - |name| name of the property as in the json. This shouldn't change since | 255 - |name| name of the property as in the json. This shouldn't change since |
206 it is the key used to access DictionaryValues | 256 it is the key used to access DictionaryValues |
207 - |unix_name| the unix_style_name of the property. Used as variable name | 257 - |unix_name| the unix_style_name of the property. Used as variable name |
208 - |optional| a boolean representing whether the property is optional | 258 - |optional| a boolean representing whether the property is optional |
209 - |description| a description of the property (if provided) | 259 - |description| a description of the property (if provided) |
210 - |type_| the model.PropertyType of this property | 260 - |type_| the model.Type of this property |
211 - |compiled_type| the model.PropertyType that this property should be | |
212 compiled to from the JSON. Defaults to |type_|. | |
213 - |ref_type| the type that the REF property is referencing. Can be used to | |
214 map to its model.Type | |
215 - |item_type| a model.Property representing the type of each element in an | |
216 ARRAY | |
217 - |properties| the properties of an OBJECT parameter | |
218 - |from_client| indicates that instances of the Type can originate from the | |
219 users of generated code, such as top-level types and function results | |
220 - |from_json| indicates that instances of the Type can originate from the | |
221 JSON (as described by the schema), such as top-level types and function | |
222 parameters | |
223 - |simple_name| the name of this Property without a namespace | 261 - |simple_name| the name of this Property without a namespace |
224 """ | 262 """ |
225 | 263 |
| 264 @staticmethod |
| 265 def FromJSON(parent, name, json, namespace, origin): |
| 266 """Creates a Property from JSON. |
| 267 """ |
| 268 opt_args = {} |
| 269 if 'description' in json: |
| 270 opt_args['description'] = json['description'] |
| 271 if 'optional' in json: |
| 272 opt_args['optional'] = json.get('optional') |
| 273 if 'isInstanceOf' in json: |
| 274 opt_args['instance_of'] = json.get('isInstanceOf') |
| 275 |
| 276 # HACK: only support very specific value types. |
| 277 is_allowed_value = ( |
| 278 '$ref' not in json and |
| 279 ('type' not in json or json['type'] == 'integer' |
| 280 or json['type'] == 'string')) |
| 281 |
| 282 if 'value' in json and is_allowed_value: |
| 283 value = json['value'] |
| 284 opt_args['value'] = value |
| 285 if 'type' not in json: |
| 286 # Sometimes the type of the value is left out, and we need to figure |
| 287 # it out for ourselves. |
| 288 if isinstance(value, int): |
| 289 json['type'] = 'integer' |
| 290 elif isinstance(value, basestring): |
| 291 json['type'] = 'string' |
| 292 else: |
| 293 # TODO(kalman): support more types as necessary. |
| 294 raise ParseException( |
| 295 parent, '"%s" is not a supported type for "value"' % type(value)) |
| 296 |
| 297 type_ = Type(parent, name, json, namespace, origin) |
| 298 return Property(parent, |
| 299 name, |
| 300 namespace, |
| 301 type_, |
| 302 origin, |
| 303 **opt_args); |
| 304 |
226 def __init__(self, | 305 def __init__(self, |
227 parent, | 306 parent, |
228 name, | 307 name, |
229 json, | |
230 namespace, | 308 namespace, |
231 is_additional_properties=False, | 309 type_, |
232 from_json=False, | 310 origin, |
233 from_client=False): | 311 description=None, |
| 312 optional=False, |
| 313 returns=None, |
| 314 instance_of=None, |
| 315 value=None): |
| 316 """Directly initializes the fields of the Property. |
| 317 """ |
234 self.name = name | 318 self.name = name |
235 self.simple_name = _StripNamespace(self.name, namespace) | 319 self.simple_name = _StripNamespace(self.name, namespace) |
236 self._unix_name = UnixName(self.name) | 320 self._unix_name = UnixName(self.name) |
237 self._unix_name_used = False | 321 self._unix_name_used = False |
238 self.optional = json.get('optional', False) | 322 self.optional = optional |
239 self.functions = OrderedDict() | 323 self.description = description |
240 self.has_value = False | |
241 self.description = json.get('description') | |
242 self.parent = parent | 324 self.parent = parent |
243 self.from_json = from_json | 325 self.origin = origin |
244 self.from_client = from_client | 326 if not isinstance(type_, Type): |
245 self.instance_of = json.get('isInstanceOf', None) | 327 raise ValueError("not Type: %s" % type_) |
246 self.params = [] | 328 self.type_ = type_ |
247 self.returns = None | 329 self.returns = returns |
248 _AddProperties(self, json, namespace) | 330 if instance_of is not None: |
249 if is_additional_properties: | 331 self.instance_of = instance_of |
250 self.type_ = PropertyType.ADDITIONAL_PROPERTIES | 332 self.value = value |
251 elif '$ref' in json: | |
252 self.ref_type = json['$ref'] | |
253 self.type_ = PropertyType.REF | |
254 elif 'enum' in json and json.get('type') == 'string': | |
255 # Non-string enums (as in the case of [legalValues=(1,2)]) should fall | |
256 # through to the next elif. | |
257 self.enum_values = [] | |
258 for value in json['enum']: | |
259 self.enum_values.append(value) | |
260 self.type_ = PropertyType.ENUM | |
261 elif 'type' in json: | |
262 self.type_ = self._JsonTypeToPropertyType(json['type']) | |
263 if self.type_ == PropertyType.ARRAY: | |
264 self.item_type = Property(self, | |
265 name + "Element", | |
266 json['items'], | |
267 namespace, | |
268 from_json=from_json, | |
269 from_client=from_client) | |
270 elif self.type_ == PropertyType.OBJECT: | |
271 # These members are read when this OBJECT Property is used as a Type | |
272 type_ = Type(self, self.name, json, namespace) | |
273 # self.properties will already have some value from |_AddProperties|. | |
274 self.properties.update(type_.properties) | |
275 self.functions = type_.functions | |
276 elif self.type_ == PropertyType.FUNCTION: | |
277 for p in json.get('parameters', []): | |
278 self.params.append(Property(self, | |
279 p['name'], | |
280 p, | |
281 namespace, | |
282 from_json=from_json, | |
283 from_client=from_client)) | |
284 if 'returns' in json: | |
285 self.returns = Property(self, 'return', json['returns'], namespace) | |
286 elif 'choices' in json: | |
287 if not json['choices'] or len(json['choices']) == 0: | |
288 raise ParseException(self, 'Choices has no choices') | |
289 self.choices = {} | |
290 self.type_ = PropertyType.CHOICES | |
291 self.compiled_type = self.type_ | |
292 for choice_json in json['choices']: | |
293 choice = Property(self, | |
294 self.name, | |
295 choice_json, | |
296 namespace, | |
297 from_json=from_json, | |
298 from_client=from_client) | |
299 choice.unix_name = UnixName(self.name + choice.type_.name) | |
300 # The existence of any single choice is optional | |
301 choice.optional = True | |
302 self.choices[choice.type_] = choice | |
303 elif 'value' in json: | |
304 self.has_value = True | |
305 self.value = json['value'] | |
306 if type(self.value) == int: | |
307 self.type_ = PropertyType.INTEGER | |
308 self.compiled_type = self.type_ | |
309 else: | |
310 # TODO(kalman): support more types as necessary. | |
311 raise ParseException( | |
312 self, '"%s" is not a supported type' % type(self.value)) | |
313 else: | |
314 raise ParseException( | |
315 self, 'Property has no type, $ref, choices, or value') | |
316 if 'compiled_type' in json: | |
317 if 'type' in json: | |
318 self.compiled_type = self._JsonTypeToPropertyType(json['compiled_type']) | |
319 else: | |
320 raise ParseException(self, 'Property has compiled_type but no type') | |
321 else: | |
322 self.compiled_type = self.type_ | |
323 | |
324 def _JsonTypeToPropertyType(self, json_type): | |
325 try: | |
326 return { | |
327 'any': PropertyType.ANY, | |
328 'array': PropertyType.ARRAY, | |
329 'binary': PropertyType.BINARY, | |
330 'boolean': PropertyType.BOOLEAN, | |
331 'integer': PropertyType.INTEGER, | |
332 'int64': PropertyType.INT64, | |
333 'function': PropertyType.FUNCTION, | |
334 'number': PropertyType.DOUBLE, | |
335 'object': PropertyType.OBJECT, | |
336 'string': PropertyType.STRING, | |
337 }[json_type] | |
338 except KeyError: | |
339 raise NotImplementedError('Type %s not recognized' % json_type) | |
340 | 333 |
341 def GetUnixName(self): | 334 def GetUnixName(self): |
342 """Gets the property's unix_name. Raises AttributeError if not set. | 335 """Gets the property's unix_name. Raises AttributeError if not set. |
343 """ | 336 """ |
344 if not self._unix_name: | 337 if not self._unix_name: |
345 raise AttributeError('No unix_name set on %s' % self.name) | 338 raise AttributeError('No unix_name set on %s' % self.name) |
346 self._unix_name_used = True | 339 self._unix_name_used = True |
347 return self._unix_name | 340 return self._unix_name |
348 | 341 |
349 def SetUnixName(self, unix_name): | 342 def SetUnixName(self, unix_name): |
350 """Set the property's unix_name. Raises AttributeError if the unix_name has | 343 """Set the property's unix_name. Raises AttributeError if the unix_name has |
351 already been used (GetUnixName has been called). | 344 already been used (GetUnixName has been called). |
352 """ | 345 """ |
353 if unix_name == self._unix_name: | 346 if unix_name == self._unix_name: |
354 return | 347 return |
355 if self._unix_name_used: | 348 if self._unix_name_used: |
356 raise AttributeError( | 349 raise AttributeError( |
357 'Cannot set the unix_name on %s; ' | 350 'Cannot set the unix_name on %s; ' |
358 'it is already used elsewhere as %s' % | 351 'it is already used elsewhere as %s' % |
359 (self.name, self._unix_name)) | 352 (self.name, self._unix_name)) |
360 self._unix_name = unix_name | 353 self._unix_name = unix_name |
361 | 354 |
362 def Copy(self): | |
363 """Makes a copy of this model.Property object and allow the unix_name to be | |
364 set again. | |
365 """ | |
366 property_copy = copy.copy(self) | |
367 property_copy._unix_name_used = False | |
368 return property_copy | |
369 | |
370 unix_name = property(GetUnixName, SetUnixName) | 355 unix_name = property(GetUnixName, SetUnixName) |
371 | 356 |
372 class _Enum(object): | 357 class _Enum(object): |
373 """Superclass for enum types with a "name" field, setting up repr/eq/ne. | 358 """Superclass for enum types with a "name" field, setting up repr/eq/ne. |
374 Enums need to do this so that equality/non-equality work over pickling. | 359 Enums need to do this so that equality/non-equality work over pickling. |
375 """ | 360 """ |
376 | 361 |
377 @staticmethod | 362 @staticmethod |
378 def GetAll(cls): | 363 def GetAll(cls): |
379 """Yields all _Enum objects declared in |cls|. | 364 """Yields all _Enum objects declared in |cls|. |
(...skipping 16 matching lines...) Expand all Loading... |
396 return not (self == other) | 381 return not (self == other) |
397 | 382 |
398 class _PropertyTypeInfo(_Enum): | 383 class _PropertyTypeInfo(_Enum): |
399 def __init__(self, is_fundamental, name): | 384 def __init__(self, is_fundamental, name): |
400 _Enum.__init__(self, name) | 385 _Enum.__init__(self, name) |
401 self.is_fundamental = is_fundamental | 386 self.is_fundamental = is_fundamental |
402 | 387 |
403 class PropertyType(object): | 388 class PropertyType(object): |
404 """Enum of different types of properties/parameters. | 389 """Enum of different types of properties/parameters. |
405 """ | 390 """ |
406 INTEGER = _PropertyTypeInfo(True, "INTEGER") | 391 INTEGER = _PropertyTypeInfo(True, "integer") |
407 INT64 = _PropertyTypeInfo(True, "INT64") | 392 INT64 = _PropertyTypeInfo(True, "int64") |
408 DOUBLE = _PropertyTypeInfo(True, "DOUBLE") | 393 DOUBLE = _PropertyTypeInfo(True, "double") |
409 BOOLEAN = _PropertyTypeInfo(True, "BOOLEAN") | 394 BOOLEAN = _PropertyTypeInfo(True, "boolean") |
410 STRING = _PropertyTypeInfo(True, "STRING") | 395 STRING = _PropertyTypeInfo(True, "string") |
411 ENUM = _PropertyTypeInfo(False, "ENUM") | 396 ENUM = _PropertyTypeInfo(False, "enum") |
412 ARRAY = _PropertyTypeInfo(False, "ARRAY") | 397 ARRAY = _PropertyTypeInfo(False, "array") |
413 REF = _PropertyTypeInfo(False, "REF") | 398 REF = _PropertyTypeInfo(False, "ref") |
414 CHOICES = _PropertyTypeInfo(False, "CHOICES") | 399 CHOICES = _PropertyTypeInfo(False, "choices") |
415 OBJECT = _PropertyTypeInfo(False, "OBJECT") | 400 OBJECT = _PropertyTypeInfo(False, "object") |
416 FUNCTION = _PropertyTypeInfo(False, "FUNCTION") | 401 FUNCTION = _PropertyTypeInfo(False, "function") |
417 BINARY = _PropertyTypeInfo(False, "BINARY") | 402 BINARY = _PropertyTypeInfo(False, "binary") |
418 ANY = _PropertyTypeInfo(False, "ANY") | 403 ANY = _PropertyTypeInfo(False, "any") |
419 ADDITIONAL_PROPERTIES = _PropertyTypeInfo(False, "ADDITIONAL_PROPERTIES") | |
420 | 404 |
421 def UnixName(name): | 405 def UnixName(name): |
422 """Returns the unix_style name for a given lowerCamelCase string. | 406 """Returns the unix_style name for a given lowerCamelCase string. |
423 """ | 407 """ |
424 # First replace any lowerUpper patterns with lower_Upper. | 408 # First replace any lowerUpper patterns with lower_Upper. |
425 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) | 409 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) |
426 # Now replace any ACMEWidgets patterns with ACME_Widgets | 410 # Now replace any ACMEWidgets patterns with ACME_Widgets |
427 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) | 411 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) |
428 # Finally, replace any remaining periods, and make lowercase. | 412 # Finally, replace any remaining periods, and make lowercase. |
429 return s2.replace('.', '_').lower() | 413 return s2.replace('.', '_').lower() |
430 | 414 |
431 def _StripNamespace(name, namespace): | 415 def _StripNamespace(name, namespace): |
432 if name.startswith(namespace.name + '.'): | 416 if name.startswith(namespace.name + '.'): |
433 return name[len(namespace.name + '.'):] | 417 return name[len(namespace.name + '.'):] |
434 return name | 418 return name |
435 | 419 |
436 def _GetModelHierarchy(entity): | 420 def _GetModelHierarchy(entity): |
437 """Returns the hierarchy of the given model entity.""" | 421 """Returns the hierarchy of the given model entity.""" |
438 hierarchy = [] | 422 hierarchy = [] |
439 while entity: | 423 while entity is not None: |
440 try: | 424 hierarchy.append(getattr(entity, 'name', repr(entity))) |
441 hierarchy.append(entity.name) | 425 if isinstance(entity, Namespace): |
442 except AttributeError: | 426 hierarchy.insert(0, ' in %s' % entity.source_file) |
443 hierarchy.append(repr(entity)) | 427 entity = getattr(entity, 'parent', None) |
444 entity = entity.parent | |
445 hierarchy.reverse() | 428 hierarchy.reverse() |
446 return hierarchy | 429 return hierarchy |
447 | 430 |
448 def _AddTypes(model, json, namespace): | 431 def _GetTypes(parent, json, namespace, origin): |
449 """Adds Type objects to |model| contained in the 'types' field of |json|. | 432 """Creates Type objects extracted from |json|. |
450 """ | 433 """ |
451 model.types = OrderedDict() | 434 types = OrderedDict() |
452 for type_json in json.get('types', []): | 435 for type_json in json.get('types', []): |
453 type_ = Type(model, type_json['id'], type_json, namespace) | 436 type_ = Type(parent, type_json['id'], type_json, namespace, origin) |
454 model.types[type_.name] = type_ | 437 types[type_.name] = type_ |
| 438 return types |
455 | 439 |
456 def _AddFunctions(model, json, namespace): | 440 def _GetFunctions(parent, json, namespace): |
457 """Adds Function objects to |model| contained in the 'functions' field of | 441 """Creates Function objects extracted from |json|. |
458 |json|. | |
459 """ | 442 """ |
460 model.functions = OrderedDict() | 443 functions = OrderedDict() |
461 for function_json in json.get('functions', []): | 444 for function_json in json.get('functions', []): |
462 function = Function(model, function_json, namespace, from_json=True) | 445 function = Function(parent, |
463 model.functions[function.name] = function | 446 function_json['name'], |
| 447 function_json, |
| 448 namespace, |
| 449 Origin(from_json=True)) |
| 450 functions[function.name] = function |
| 451 return functions |
464 | 452 |
465 def _AddEvents(model, json, namespace): | 453 def _GetEvents(parent, json, namespace): |
466 """Adds Function objects to |model| contained in the 'events' field of |json|. | 454 """Creates Function objects generated from the events in |json|. |
467 """ | 455 """ |
468 model.events = OrderedDict() | 456 events = OrderedDict() |
469 for event_json in json.get('events', []): | 457 for event_json in json.get('events', []): |
470 event = Function(model, event_json, namespace, from_client=True) | 458 event = Function(parent, |
471 model.events[event.name] = event | 459 event_json['name'], |
| 460 event_json, |
| 461 namespace, |
| 462 Origin(from_client=True)) |
| 463 events[event.name] = event |
| 464 return events |
472 | 465 |
473 def _AddProperties(model, | 466 def _GetProperties(parent, json, namespace, origin): |
474 json, | 467 """Generates Property objects extracted from |json|. |
475 namespace, | |
476 from_json=False, | |
477 from_client=False): | |
478 """Adds model.Property objects to |model| contained in the 'properties' field | |
479 of |json|. | |
480 """ | 468 """ |
481 model.properties = OrderedDict() | 469 properties = OrderedDict() |
482 for name, property_json in json.get('properties', {}).items(): | 470 for name, property_json in json.get('properties', {}).items(): |
483 model.properties[name] = Property( | 471 properties[name] = Property.FromJSON( |
484 model, | 472 parent, name, property_json, namespace, origin) |
485 name, | 473 return properties |
486 property_json, | |
487 namespace, | |
488 from_json=from_json, | |
489 from_client=from_client) | |
490 | 474 |
491 class _PlatformInfo(_Enum): | 475 class _PlatformInfo(_Enum): |
492 def __init__(self, name): | 476 def __init__(self, name): |
493 _Enum.__init__(self, name) | 477 _Enum.__init__(self, name) |
494 | 478 |
495 class Platforms(object): | 479 class Platforms(object): |
496 """Enum of the possible platforms. | 480 """Enum of the possible platforms. |
497 """ | 481 """ |
498 CHROMEOS = _PlatformInfo("chromeos") | 482 CHROMEOS = _PlatformInfo("chromeos") |
499 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch") | 483 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch") |
500 LINUX = _PlatformInfo("linux") | 484 LINUX = _PlatformInfo("linux") |
501 MAC = _PlatformInfo("mac") | 485 MAC = _PlatformInfo("mac") |
502 WIN = _PlatformInfo("win") | 486 WIN = _PlatformInfo("win") |
503 | 487 |
504 def _GetPlatforms(json): | 488 def _GetPlatforms(json): |
505 if 'platforms' not in json: | 489 if 'platforms' not in json: |
506 return None | 490 return None |
507 platforms = [] | 491 platforms = [] |
508 for platform_name in json['platforms']: | 492 for platform_name in json['platforms']: |
509 for platform_enum in _Enum.GetAll(Platforms): | 493 for platform_enum in _Enum.GetAll(Platforms): |
510 if platform_name == platform_enum.name: | 494 if platform_name == platform_enum.name: |
511 platforms.append(platform_enum) | 495 platforms.append(platform_enum) |
512 break | 496 break |
513 return platforms | 497 return platforms |
OLD | NEW |