blob: 36be5a3745f0a4b4532dffc2bac6024d273f9a0e [file] [log] [blame]
[email protected]15f08dd2012-01-27 07:29:481# 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
[email protected]df74dc42012-04-03 07:08:045import copy
[email protected]15f08dd2012-01-27 07:29:486import os.path
[email protected]cfe484902012-02-15 14:52:327import re
[email protected]15f08dd2012-01-27 07:29:488
[email protected]b2fad3f2012-11-20 02:13:249from json_parse import OrderedDict
10
[email protected]116f0a3a2012-04-19 04:22:3811class ParseException(Exception):
12 """Thrown when data in the model is invalid.
13 """
14 def __init__(self, parent, message):
15 hierarchy = _GetModelHierarchy(parent)
16 hierarchy.append(message)
17 Exception.__init__(
18 self, 'Model parse exception at:\n' + '\n'.join(hierarchy))
19
[email protected]15f08dd2012-01-27 07:29:4820class Model(object):
21 """Model of all namespaces that comprise an API.
[email protected]cfe484902012-02-15 14:52:3222
23 Properties:
24 - |namespaces| a map of a namespace name to its model.Namespace
[email protected]15f08dd2012-01-27 07:29:4825 """
26 def __init__(self):
27 self.namespaces = {}
28
[email protected]4636c832013-01-11 02:10:1129 def AddNamespace(self, json, source_file, include_compiler_options=False):
[email protected]a1f774972012-04-17 02:11:0930 """Add a namespace's json to the model and returns the namespace.
[email protected]15f08dd2012-01-27 07:29:4831 """
[email protected]4636c832013-01-11 02:10:1132 namespace = Namespace(json,
33 source_file,
34 include_compiler_options=include_compiler_options)
[email protected]15f08dd2012-01-27 07:29:4835 self.namespaces[namespace.name] = namespace
36 return namespace
37
38class Namespace(object):
39 """An API namespace.
[email protected]cfe484902012-02-15 14:52:3240
41 Properties:
42 - |name| the name of the namespace
[email protected]712eca0f2012-02-21 01:13:0743 - |unix_name| the unix_name of the namespace
44 - |source_file| the file that contained the namespace definition
45 - |source_file_dir| the directory component of |source_file|
46 - |source_file_filename| the filename component of |source_file|
[email protected]4636c832013-01-11 02:10:1147 - |platforms| if not None, the list of platforms that the namespace is
48 available to
[email protected]cfe484902012-02-15 14:52:3249 - |types| a map of type names to their model.Type
50 - |functions| a map of function names to their model.Function
[email protected]b741e8f2012-07-16 21:47:2451 - |events| a map of event names to their model.Function
[email protected]116f0a3a2012-04-19 04:22:3852 - |properties| a map of property names to their model.Property
[email protected]4636c832013-01-11 02:10:1153 - |compiler_options| the compiler_options dict, only present if
54 |include_compiler_options| is True
[email protected]15f08dd2012-01-27 07:29:4855 """
[email protected]4636c832013-01-11 02:10:1156 def __init__(self, json, source_file, include_compiler_options=False):
[email protected]15f08dd2012-01-27 07:29:4857 self.name = json['namespace']
[email protected]4ba6bdc2012-06-18 20:40:1458 self.unix_name = UnixName(self.name)
[email protected]15f08dd2012-01-27 07:29:4859 self.source_file = source_file
60 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
[email protected]feba21e2012-03-02 15:05:2761 self.parent = None
[email protected]4636c832013-01-11 02:10:1162 self.platforms = _GetPlatforms(json)
[email protected]0b255f002012-10-05 01:58:4763 _AddTypes(self, json, self)
64 _AddFunctions(self, json, self)
65 _AddEvents(self, json, self)
66 _AddProperties(self, json, self)
[email protected]4636c832013-01-11 02:10:1167 if include_compiler_options:
68 self.compiler_options = json.get('compiler_options', {})
[email protected]15f08dd2012-01-27 07:29:4869
70class Type(object):
71 """A Type defined in the json.
[email protected]cfe484902012-02-15 14:52:3272
73 Properties:
74 - |name| the type name
75 - |description| the description of the type (if provided)
[email protected]feba21e2012-03-02 15:05:2776 - |properties| a map of property unix_names to their model.Property
77 - |functions| a map of function names to their model.Function
[email protected]d32b8e52012-07-23 18:40:0878 - |events| a map of event names to their model.Event
[email protected]25cbf6012012-02-28 05:51:4479 - |from_client| indicates that instances of the Type can originate from the
80 users of generated code, such as top-level types and function results
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
[email protected]cf6d0b32012-04-12 04:30:2284 - |type_| the PropertyType of this Type
85 - |item_type| if this is an array, the type of items in the array
[email protected]0b255f002012-10-05 01:58:4786 - |simple_name| the name of this Type without a namespace
[email protected]15f08dd2012-01-27 07:29:4887 """
[email protected]0b255f002012-10-05 01:58:4788 def __init__(self, parent, name, json, namespace):
[email protected]cf6d0b32012-04-12 04:30:2289 if json.get('type') == 'array':
90 self.type_ = PropertyType.ARRAY
[email protected]0b255f002012-10-05 01:58:4791 self.item_type = Property(self,
92 name + "Element",
93 json['items'],
94 namespace,
[email protected]cf6d0b32012-04-12 04:30:2295 from_json=True,
96 from_client=True)
[email protected]e7ae70172012-08-29 04:07:1397 elif 'enum' in json:
98 self.enum_values = []
99 for value in json['enum']:
100 self.enum_values.append(value)
101 self.type_ = PropertyType.ENUM
[email protected]0ba7b4f2012-09-25 01:00:41102 elif json.get('type') == 'string':
103 self.type_ = PropertyType.STRING
[email protected]cf6d0b32012-04-12 04:30:22104 else:
105 if not (
106 'properties' in json or
107 'additionalProperties' in json or
[email protected]e975d112012-07-31 22:12:43108 'functions' in json or
109 'events' in json):
[email protected]116f0a3a2012-04-19 04:22:38110 raise ParseException(self, name + " has no properties or functions")
[email protected]cf6d0b32012-04-12 04:30:22111 self.type_ = PropertyType.OBJECT
[email protected]feba21e2012-03-02 15:05:27112 self.name = name
[email protected]0b255f002012-10-05 01:58:47113 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]0ba7b4f2012-09-25 01:00:41114 self.unix_name = UnixName(self.name)
[email protected]15f08dd2012-01-27 07:29:48115 self.description = json.get('description')
[email protected]25cbf6012012-02-28 05:51:44116 self.from_json = True
117 self.from_client = True
[email protected]feba21e2012-03-02 15:05:27118 self.parent = parent
[email protected]491e60d32012-07-20 01:03:13119 self.instance_of = json.get('isInstanceOf', None)
[email protected]0b255f002012-10-05 01:58:47120 _AddFunctions(self, json, namespace)
121 _AddEvents(self, json, namespace)
122 _AddProperties(self, json, namespace, from_json=True, from_client=True)
[email protected]feba21e2012-03-02 15:05:27123
[email protected]116f0a3a2012-04-19 04:22:38124 additional_properties_key = 'additionalProperties'
125 additional_properties = json.get(additional_properties_key)
[email protected]feba21e2012-03-02 15:05:27126 if additional_properties:
[email protected]116f0a3a2012-04-19 04:22:38127 self.properties[additional_properties_key] = Property(
128 self,
129 additional_properties_key,
130 additional_properties,
[email protected]0b255f002012-10-05 01:58:47131 namespace,
[email protected]116f0a3a2012-04-19 04:22:38132 is_additional_properties=True)
[email protected]15f08dd2012-01-27 07:29:48133
[email protected]15f08dd2012-01-27 07:29:48134class Function(object):
135 """A Function defined in the API.
[email protected]cfe484902012-02-15 14:52:32136
137 Properties:
138 - |name| the function name
[email protected]4636c832013-01-11 02:10:11139 - |platforms| if not None, the list of platforms that the function is
140 available to
[email protected]cfe484902012-02-15 14:52:32141 - |params| a list of parameters to the function (order matters). A separate
[email protected]4636c832013-01-11 02:10:11142 parameter is used for each choice of a 'choices' parameter
[email protected]cfe484902012-02-15 14:52:32143 - |description| a description of the function (if provided)
144 - |callback| the callback parameter to the function. There should be exactly
[email protected]4636c832013-01-11 02:10:11145 one
[email protected]4b3f7852012-07-17 06:33:30146 - |optional| whether the Function is "optional"; this only makes sense to be
[email protected]4636c832013-01-11 02:10:11147 present when the Function is representing a callback property
[email protected]0b255f002012-10-05 01:58:47148 - |simple_name| the name of this Function without a namespace
[email protected]15f08dd2012-01-27 07:29:48149 """
[email protected]0b255f002012-10-05 01:58:47150 def __init__(self,
151 parent,
152 json,
153 namespace,
154 from_json=False,
155 from_client=False):
[email protected]15f08dd2012-01-27 07:29:48156 self.name = json['name']
[email protected]0b255f002012-10-05 01:58:47157 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4636c832013-01-11 02:10:11158 self.platforms = _GetPlatforms(json)
[email protected]15f08dd2012-01-27 07:29:48159 self.params = []
[email protected]feba21e2012-03-02 15:05:27160 self.description = json.get('description')
[email protected]15f08dd2012-01-27 07:29:48161 self.callback = None
[email protected]4b3f7852012-07-17 06:33:30162 self.optional = json.get('optional', False)
[email protected]feba21e2012-03-02 15:05:27163 self.parent = parent
[email protected]a9ead752012-05-24 02:08:45164 self.nocompile = json.get('nocompile')
[email protected]c0718352012-08-21 02:34:24165 options = json.get('options', {})
166 self.conditions = options.get('conditions', [])
167 self.actions = options.get('actions', [])
168 self.supports_listeners = options.get('supportsListeners', True)
169 self.supports_rules = options.get('supportsRules', False)
170 def GeneratePropertyFromParam(p):
171 return Property(self,
172 p['name'], p,
[email protected]0b255f002012-10-05 01:58:47173 namespace,
[email protected]c0718352012-08-21 02:34:24174 from_json=from_json,
175 from_client=from_client)
[email protected]db943992012-08-02 14:02:54176
[email protected]c0718352012-08-21 02:34:24177 self.filters = [GeneratePropertyFromParam(filter)
178 for filter in json.get('filters', [])]
[email protected]db943992012-08-02 14:02:54179 callback_param = None
[email protected]b741e8f2012-07-16 21:47:24180 for param in json.get('parameters', []):
[email protected]db943992012-08-02 14:02:54181
[email protected]15f08dd2012-01-27 07:29:48182 if param.get('type') == 'function':
[email protected]db943992012-08-02 14:02:54183 if callback_param:
184 # No ParseException because the webstore has this.
185 # Instead, pretend all intermediate callbacks are properties.
186 self.params.append(GeneratePropertyFromParam(callback_param))
187 callback_param = param
[email protected]15f08dd2012-01-27 07:29:48188 else:
[email protected]db943992012-08-02 14:02:54189 self.params.append(GeneratePropertyFromParam(param))
190
191 if callback_param:
[email protected]0b255f002012-10-05 01:58:47192 self.callback = Function(self,
193 callback_param,
194 namespace,
195 from_client=True)
[email protected]db943992012-08-02 14:02:54196
[email protected]491e60d32012-07-20 01:03:13197 self.returns = None
198 if 'returns' in json:
[email protected]0b255f002012-10-05 01:58:47199 self.returns = Property(self, 'return', json['returns'], namespace)
[email protected]15f08dd2012-01-27 07:29:48200
[email protected]15f08dd2012-01-27 07:29:48201class Property(object):
202 """A property of a type OR a parameter to a function.
203
[email protected]cfe484902012-02-15 14:52:32204 Properties:
205 - |name| name of the property as in the json. This shouldn't change since
206 it is the key used to access DictionaryValues
207 - |unix_name| the unix_style_name of the property. Used as variable name
208 - |optional| a boolean representing whether the property is optional
209 - |description| a description of the property (if provided)
210 - |type_| the model.PropertyType of this property
[email protected]1d0f57e2012-07-31 22:47:50211 - |compiled_type| the model.PropertyType that this property should be
212 compiled to from the JSON. Defaults to |type_|.
[email protected]cfe484902012-02-15 14:52:32213 - |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
[email protected]b741e8f2012-07-16 21:47:24218 - |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
[email protected]0b255f002012-10-05 01:58:47223 - |simple_name| the name of this Property without a namespace
[email protected]15f08dd2012-01-27 07:29:48224 """
[email protected]feba21e2012-03-02 15:05:27225
[email protected]0b255f002012-10-05 01:58:47226 def __init__(self,
227 parent,
228 name,
229 json,
230 namespace,
231 is_additional_properties=False,
232 from_json=False,
233 from_client=False):
[email protected]15f08dd2012-01-27 07:29:48234 self.name = name
[email protected]0b255f002012-10-05 01:58:47235 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4ba6bdc2012-06-18 20:40:14236 self._unix_name = UnixName(self.name)
[email protected]cfe484902012-02-15 14:52:32237 self._unix_name_used = False
[email protected]15f08dd2012-01-27 07:29:48238 self.optional = json.get('optional', False)
[email protected]b2fad3f2012-11-20 02:13:24239 self.functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38240 self.has_value = False
[email protected]15f08dd2012-01-27 07:29:48241 self.description = json.get('description')
[email protected]feba21e2012-03-02 15:05:27242 self.parent = parent
[email protected]b741e8f2012-07-16 21:47:24243 self.from_json = from_json
244 self.from_client = from_client
[email protected]491e60d32012-07-20 01:03:13245 self.instance_of = json.get('isInstanceOf', None)
[email protected]c5b2a48c32012-10-26 00:29:24246 self.params = []
247 self.returns = None
[email protected]0b255f002012-10-05 01:58:47248 _AddProperties(self, json, namespace)
[email protected]feba21e2012-03-02 15:05:27249 if is_additional_properties:
250 self.type_ = PropertyType.ADDITIONAL_PROPERTIES
251 elif '$ref' in json:
[email protected]15f08dd2012-01-27 07:29:48252 self.ref_type = json['$ref']
253 self.type_ = PropertyType.REF
[email protected]9d273182012-07-11 21:03:26254 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.
[email protected]2111fff9b2012-02-22 12:06:51257 self.enum_values = []
258 for value in json['enum']:
259 self.enum_values.append(value)
260 self.type_ = PropertyType.ENUM
[email protected]15f08dd2012-01-27 07:29:48261 elif 'type' in json:
[email protected]1d0f57e2012-07-31 22:47:50262 self.type_ = self._JsonTypeToPropertyType(json['type'])
263 if self.type_ == PropertyType.ARRAY:
[email protected]0b255f002012-10-05 01:58:47264 self.item_type = Property(self,
265 name + "Element",
266 json['items'],
267 namespace,
268 from_json=from_json,
269 from_client=from_client)
[email protected]1d0f57e2012-07-31 22:47:50270 elif self.type_ == PropertyType.OBJECT:
[email protected]25cbf6012012-02-28 05:51:44271 # These members are read when this OBJECT Property is used as a Type
[email protected]0b255f002012-10-05 01:58:47272 type_ = Type(self, self.name, json, namespace)
[email protected]116f0a3a2012-04-19 04:22:38273 # self.properties will already have some value from |_AddProperties|.
274 self.properties.update(type_.properties)
[email protected]feba21e2012-03-02 15:05:27275 self.functions = type_.functions
[email protected]c5b2a48c32012-10-26 00:29:24276 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)
[email protected]15f08dd2012-01-27 07:29:48286 elif 'choices' in json:
[email protected]b741e8f2012-07-16 21:47:24287 if not json['choices'] or len(json['choices']) == 0:
[email protected]116f0a3a2012-04-19 04:22:38288 raise ParseException(self, 'Choices has no choices')
[email protected]15f08dd2012-01-27 07:29:48289 self.choices = {}
[email protected]cfe484902012-02-15 14:52:32290 self.type_ = PropertyType.CHOICES
[email protected]1d0f57e2012-07-31 22:47:50291 self.compiled_type = self.type_
[email protected]cfe484902012-02-15 14:52:32292 for choice_json in json['choices']:
[email protected]0b255f002012-10-05 01:58:47293 choice = Property(self,
294 self.name,
295 choice_json,
296 namespace,
297 from_json=from_json,
298 from_client=from_client)
[email protected]b741e8f2012-07-16 21:47:24299 choice.unix_name = UnixName(self.name + choice.type_.name)
[email protected]cfe484902012-02-15 14:52:32300 # The existence of any single choice is optional
301 choice.optional = True
302 self.choices[choice.type_] = choice
[email protected]116f0a3a2012-04-19 04:22:38303 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
[email protected]1d0f57e2012-07-31 22:47:50308 self.compiled_type = self.type_
[email protected]116f0a3a2012-04-19 04:22:38309 else:
310 # TODO(kalman): support more types as necessary.
311 raise ParseException(
312 self, '"%s" is not a supported type' % type(self.value))
[email protected]cfe484902012-02-15 14:52:32313 else:
[email protected]116f0a3a2012-04-19 04:22:38314 raise ParseException(
315 self, 'Property has no type, $ref, choices, or value')
[email protected]1d0f57e2012-07-31 22:47:50316 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)
[email protected]cfe484902012-02-15 14:52:32340
341 def GetUnixName(self):
342 """Gets the property's unix_name. Raises AttributeError if not set.
343 """
[email protected]116f0a3a2012-04-19 04:22:38344 if not self._unix_name:
[email protected]cfe484902012-02-15 14:52:32345 raise AttributeError('No unix_name set on %s' % self.name)
346 self._unix_name_used = True
347 return self._unix_name
348
349 def SetUnixName(self, unix_name):
350 """Set the property's unix_name. Raises AttributeError if the unix_name has
351 already been used (GetUnixName has been called).
352 """
353 if unix_name == self._unix_name:
354 return
355 if self._unix_name_used:
356 raise AttributeError(
357 'Cannot set the unix_name on %s; '
358 'it is already used elsewhere as %s' %
359 (self.name, self._unix_name))
360 self._unix_name = unix_name
361
[email protected]712eca0f2012-02-21 01:13:07362 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
[email protected]cfe484902012-02-15 14:52:32370 unix_name = property(GetUnixName, SetUnixName)
[email protected]15f08dd2012-01-27 07:29:48371
[email protected]4636c832013-01-11 02:10:11372class _Enum(object):
373 """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.
[email protected]fe027682012-08-21 01:51:34375 """
[email protected]4636c832013-01-11 02:10:11376
377 @staticmethod
378 def GetAll(cls):
379 """Yields all _Enum objects declared in |cls|.
380 """
381 for prop_key in dir(cls):
382 prop_value = getattr(cls, prop_key)
383 if isinstance(prop_value, _Enum):
384 yield prop_value
385
386 def __init__(self, name):
[email protected]fe027682012-08-21 01:51:34387 self.name = name
388
[email protected]4636c832013-01-11 02:10:11389 def __repr(self):
[email protected]fe027682012-08-21 01:51:34390 return self.name
391
[email protected]dc5f2fecf2012-08-31 01:55:51392 def __eq__(self, other):
[email protected]4636c832013-01-11 02:10:11393 return type(other) == type(self) and other.name == self.name
[email protected]dc5f2fecf2012-08-31 01:55:51394
[email protected]e15dccb2012-10-05 06:02:25395 def __ne__(self, other):
[email protected]e15dccb2012-10-05 06:02:25396 return not (self == other)
397
[email protected]4636c832013-01-11 02:10:11398class _PropertyTypeInfo(_Enum):
399 def __init__(self, is_fundamental, name):
400 _Enum.__init__(self, name)
401 self.is_fundamental = is_fundamental
402
[email protected]15f08dd2012-01-27 07:29:48403class PropertyType(object):
404 """Enum of different types of properties/parameters.
405 """
[email protected]fe027682012-08-21 01:51:34406 INTEGER = _PropertyTypeInfo(True, "INTEGER")
407 INT64 = _PropertyTypeInfo(True, "INT64")
408 DOUBLE = _PropertyTypeInfo(True, "DOUBLE")
409 BOOLEAN = _PropertyTypeInfo(True, "BOOLEAN")
410 STRING = _PropertyTypeInfo(True, "STRING")
411 ENUM = _PropertyTypeInfo(False, "ENUM")
412 ARRAY = _PropertyTypeInfo(False, "ARRAY")
413 REF = _PropertyTypeInfo(False, "REF")
414 CHOICES = _PropertyTypeInfo(False, "CHOICES")
415 OBJECT = _PropertyTypeInfo(False, "OBJECT")
416 FUNCTION = _PropertyTypeInfo(False, "FUNCTION")
417 BINARY = _PropertyTypeInfo(False, "BINARY")
418 ANY = _PropertyTypeInfo(False, "ANY")
419 ADDITIONAL_PROPERTIES = _PropertyTypeInfo(False, "ADDITIONAL_PROPERTIES")
[email protected]cfe484902012-02-15 14:52:32420
[email protected]4ba6bdc2012-06-18 20:40:14421def UnixName(name):
[email protected]712eca0f2012-02-21 01:13:07422 """Returns the unix_style name for a given lowerCamelCase string.
[email protected]cfe484902012-02-15 14:52:32423 """
[email protected]df74dc42012-04-03 07:08:04424 # First replace any lowerUpper patterns with lower_Upper.
425 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
426 # Now replace any ACMEWidgets patterns with ACME_Widgets
427 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
428 # Finally, replace any remaining periods, and make lowercase.
429 return s2.replace('.', '_').lower()
[email protected]cfe484902012-02-15 14:52:32430
[email protected]0b255f002012-10-05 01:58:47431def _StripNamespace(name, namespace):
432 if name.startswith(namespace.name + '.'):
433 return name[len(namespace.name + '.'):]
434 return name
435
[email protected]116f0a3a2012-04-19 04:22:38436def _GetModelHierarchy(entity):
[email protected]feba21e2012-03-02 15:05:27437 """Returns the hierarchy of the given model entity."""
438 hierarchy = []
439 while entity:
440 try:
441 hierarchy.append(entity.name)
442 except AttributeError:
443 hierarchy.append(repr(entity))
444 entity = entity.parent
445 hierarchy.reverse()
446 return hierarchy
[email protected]116f0a3a2012-04-19 04:22:38447
[email protected]0b255f002012-10-05 01:58:47448def _AddTypes(model, json, namespace):
[email protected]116f0a3a2012-04-19 04:22:38449 """Adds Type objects to |model| contained in the 'types' field of |json|.
450 """
[email protected]b2fad3f2012-11-20 02:13:24451 model.types = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38452 for type_json in json.get('types', []):
[email protected]0b255f002012-10-05 01:58:47453 type_ = Type(model, type_json['id'], type_json, namespace)
[email protected]116f0a3a2012-04-19 04:22:38454 model.types[type_.name] = type_
455
[email protected]0b255f002012-10-05 01:58:47456def _AddFunctions(model, json, namespace):
[email protected]b741e8f2012-07-16 21:47:24457 """Adds Function objects to |model| contained in the 'functions' field of
458 |json|.
[email protected]116f0a3a2012-04-19 04:22:38459 """
[email protected]b2fad3f2012-11-20 02:13:24460 model.functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38461 for function_json in json.get('functions', []):
[email protected]0b255f002012-10-05 01:58:47462 function = Function(model, function_json, namespace, from_json=True)
[email protected]116f0a3a2012-04-19 04:22:38463 model.functions[function.name] = function
464
[email protected]0b255f002012-10-05 01:58:47465def _AddEvents(model, json, namespace):
[email protected]b741e8f2012-07-16 21:47:24466 """Adds Function objects to |model| contained in the 'events' field of |json|.
467 """
[email protected]b2fad3f2012-11-20 02:13:24468 model.events = OrderedDict()
[email protected]b741e8f2012-07-16 21:47:24469 for event_json in json.get('events', []):
[email protected]0b255f002012-10-05 01:58:47470 event = Function(model, event_json, namespace, from_client=True)
[email protected]b741e8f2012-07-16 21:47:24471 model.events[event.name] = event
472
[email protected]0b255f002012-10-05 01:58:47473def _AddProperties(model,
474 json,
475 namespace,
476 from_json=False,
477 from_client=False):
[email protected]116f0a3a2012-04-19 04:22:38478 """Adds model.Property objects to |model| contained in the 'properties' field
479 of |json|.
480 """
[email protected]b2fad3f2012-11-20 02:13:24481 model.properties = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38482 for name, property_json in json.get('properties', {}).items():
[email protected]116f0a3a2012-04-19 04:22:38483 model.properties[name] = Property(
484 model,
485 name,
486 property_json,
[email protected]0b255f002012-10-05 01:58:47487 namespace,
[email protected]116f0a3a2012-04-19 04:22:38488 from_json=from_json,
489 from_client=from_client)
[email protected]4636c832013-01-11 02:10:11490
491class _PlatformInfo(_Enum):
492 def __init__(self, name):
493 _Enum.__init__(self, name)
494
495class Platforms(object):
496 """Enum of the possible platforms.
497 """
498 CHROMEOS = _PlatformInfo("chromeos")
499 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
500 LINUX = _PlatformInfo("linux")
501 MAC = _PlatformInfo("mac")
502 WIN = _PlatformInfo("win")
503
504def _GetPlatforms(json):
505 if 'platforms' not in json:
506 return None
507 platforms = []
508 for platform_name in json['platforms']:
509 for platform_enum in _Enum.GetAll(Platforms):
510 if platform_name == platform_enum.name:
511 platforms.append(platform_enum)
512 break
513 return platforms