blob: 7507ae761ff7edc41770f9dc72c7ffead4197bca [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
5import os.path
6
[email protected]b2fad3f2012-11-20 02:13:247from json_parse import OrderedDict
[email protected]cb5670c2013-04-10 06:31:088from memoize import memoize
[email protected]b2fad3f2012-11-20 02:13:249
[email protected]116f0a3a2012-04-19 04:22:3810class ParseException(Exception):
11 """Thrown when data in the model is invalid.
12 """
13 def __init__(self, parent, message):
14 hierarchy = _GetModelHierarchy(parent)
15 hierarchy.append(message)
16 Exception.__init__(
17 self, 'Model parse exception at:\n' + '\n'.join(hierarchy))
18
[email protected]15f08dd2012-01-27 07:29:4819class Model(object):
20 """Model of all namespaces that comprise an API.
[email protected]cfe484902012-02-15 14:52:3221
22 Properties:
23 - |namespaces| a map of a namespace name to its model.Namespace
[email protected]15f08dd2012-01-27 07:29:4824 """
25 def __init__(self):
26 self.namespaces = {}
27
[email protected]4636c832013-01-11 02:10:1128 def AddNamespace(self, json, source_file, include_compiler_options=False):
[email protected]a1f774972012-04-17 02:11:0929 """Add a namespace's json to the model and returns the namespace.
[email protected]15f08dd2012-01-27 07:29:4830 """
[email protected]4636c832013-01-11 02:10:1131 namespace = Namespace(json,
32 source_file,
33 include_compiler_options=include_compiler_options)
[email protected]15f08dd2012-01-27 07:29:4834 self.namespaces[namespace.name] = namespace
35 return namespace
36
37class Namespace(object):
38 """An API namespace.
[email protected]cfe484902012-02-15 14:52:3239
40 Properties:
41 - |name| the name of the namespace
[email protected]8426f8d72013-06-23 04:24:5542 - |description| the description 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]bee7a7932013-08-12 23:45:3853 - |compiler_options| the compiler_options dict, only not empty if
[email protected]4636c832013-01-11 02:10:1154 |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]8426f8d72013-06-23 04:24:5558 if 'description' not in json:
[email protected]a081aeb2013-07-09 20:52:4759 # TODO(kalman): Go back to throwing an error here.
60 print('%s must have a "description" field. This will appear '
[email protected]8426f8d72013-06-23 04:24:5561 'on the API summary page.' % self.name)
[email protected]a081aeb2013-07-09 20:52:4762 json['description'] = ''
63 self.description = json['description']
[email protected]4ba6bdc2012-06-18 20:40:1464 self.unix_name = UnixName(self.name)
[email protected]15f08dd2012-01-27 07:29:4865 self.source_file = source_file
66 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
[email protected]feba21e2012-03-02 15:05:2767 self.parent = None
[email protected]4636c832013-01-11 02:10:1168 self.platforms = _GetPlatforms(json)
[email protected]242d5e7a2013-01-17 06:50:3169 toplevel_origin = Origin(from_client=True, from_json=True)
70 self.types = _GetTypes(self, json, self, toplevel_origin)
71 self.functions = _GetFunctions(self, json, self)
72 self.events = _GetEvents(self, json, self)
73 self.properties = _GetProperties(self, json, self, toplevel_origin)
[email protected]bee7a7932013-08-12 23:45:3874 self.compiler_options = (json.get('compiler_options', {})
75 if include_compiler_options else {})
[email protected]0b022482013-10-03 19:38:0576 self.documentation_options = json.get('documentation_options', {})
[email protected]15f08dd2012-01-27 07:29:4877
[email protected]242d5e7a2013-01-17 06:50:3178class Origin(object):
79 """Stores the possible origin of model object as a pair of bools. These are:
80
81 |from_client| indicating that instances can originate from users of
82 generated code (for example, function results), or
83 |from_json| indicating that instances can originate from the JSON (for
84 example, function parameters)
85
86 It is possible for model objects to originate from both the client and json,
87 for example Types defined in the top-level schema, in which case both
88 |from_client| and |from_json| would be True.
89 """
90 def __init__(self, from_client=False, from_json=False):
91 if not from_client and not from_json:
92 raise ValueError('One of from_client or from_json must be true')
93 self.from_client = from_client
94 self.from_json = from_json
95
[email protected]15f08dd2012-01-27 07:29:4896class Type(object):
97 """A Type defined in the json.
[email protected]cfe484902012-02-15 14:52:3298
99 Properties:
100 - |name| the type name
[email protected]242d5e7a2013-01-17 06:50:31101 - |namespace| the Type's namespace
[email protected]cfe484902012-02-15 14:52:32102 - |description| the description of the type (if provided)
[email protected]feba21e2012-03-02 15:05:27103 - |properties| a map of property unix_names to their model.Property
104 - |functions| a map of function names to their model.Function
[email protected]d32b8e52012-07-23 18:40:08105 - |events| a map of event names to their model.Event
[email protected]242d5e7a2013-01-17 06:50:31106 - |origin| the Origin of the type
107 - |property_type| the PropertyType of this Type
[email protected]cf6d0b32012-04-12 04:30:22108 - |item_type| if this is an array, the type of items in the array
[email protected]0b255f002012-10-05 01:58:47109 - |simple_name| the name of this Type without a namespace
[email protected]242d5e7a2013-01-17 06:50:31110 - |additional_properties| the type of the additional properties, if any is
111 specified
[email protected]15f08dd2012-01-27 07:29:48112 """
[email protected]242d5e7a2013-01-17 06:50:31113 def __init__(self,
114 parent,
115 name,
116 json,
117 namespace,
118 origin):
119 self.name = name
120 self.namespace = namespace
121 self.simple_name = _StripNamespace(self.name, namespace)
122 self.unix_name = UnixName(self.name)
123 self.description = json.get('description', None)
124 self.origin = origin
125 self.parent = parent
126 self.instance_of = json.get('isInstanceOf', None)
127
128 # TODO(kalman): Only objects need functions/events/properties, but callers
129 # assume that all types have them. Fix this.
130 self.functions = _GetFunctions(self, json, namespace)
131 self.events = _GetEvents(self, json, namespace)
132 self.properties = _GetProperties(self, json, namespace, origin)
133
134 json_type = json.get('type', None)
135 if json_type == 'array':
136 self.property_type = PropertyType.ARRAY
137 self.item_type = Type(
138 self, '%sType' % name, json['items'], namespace, origin)
139 elif '$ref' in json:
140 self.property_type = PropertyType.REF
141 self.ref_type = json['$ref']
142 elif 'enum' in json and json_type == 'string':
143 self.property_type = PropertyType.ENUM
144 self.enum_values = [value for value in json['enum']]
145 elif json_type == 'any':
146 self.property_type = PropertyType.ANY
147 elif json_type == 'binary':
148 self.property_type = PropertyType.BINARY
149 elif json_type == 'boolean':
150 self.property_type = PropertyType.BOOLEAN
151 elif json_type == 'integer':
152 self.property_type = PropertyType.INTEGER
153 elif (json_type == 'double' or
154 json_type == 'number'):
155 self.property_type = PropertyType.DOUBLE
156 elif json_type == 'string':
157 self.property_type = PropertyType.STRING
158 elif 'choices' in json:
159 self.property_type = PropertyType.CHOICES
[email protected]e11b9aa2013-07-13 00:05:42160 def generate_type_name(type_json):
161 if 'items' in type_json:
162 return '%ss' % generate_type_name(type_json['items'])
163 if '$ref' in type_json:
164 return type_json['$ref']
165 if 'type' in type_json:
166 return type_json['type']
167 return None
168 self.choices = [
169 Type(self,
170 generate_type_name(choice) or 'choice%s' % i,
171 choice,
172 namespace,
173 origin)
174 for i, choice in enumerate(json['choices'])]
[email protected]242d5e7a2013-01-17 06:50:31175 elif json_type == 'object':
[email protected]cf6d0b32012-04-12 04:30:22176 if not (
[email protected]117afcf2013-08-30 02:38:09177 'isInstanceOf' in json or
[email protected]cf6d0b32012-04-12 04:30:22178 'properties' in json or
179 'additionalProperties' in json or
[email protected]e975d112012-07-31 22:12:43180 'functions' in json or
181 'events' in json):
[email protected]116f0a3a2012-04-19 04:22:38182 raise ParseException(self, name + " has no properties or functions")
[email protected]242d5e7a2013-01-17 06:50:31183 self.property_type = PropertyType.OBJECT
184 additional_properties_json = json.get('additionalProperties', None)
185 if additional_properties_json is not None:
186 self.additional_properties = Type(self,
187 'additionalProperties',
188 additional_properties_json,
189 namespace,
190 origin)
191 else:
192 self.additional_properties = None
193 elif json_type == 'function':
194 self.property_type = PropertyType.FUNCTION
195 # Sometimes we might have an unnamed function, e.g. if it's a property
196 # of an object. Use the name of the property in that case.
197 function_name = json.get('name', name)
198 self.function = Function(self, function_name, json, namespace, origin)
199 else:
200 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
[email protected]15f08dd2012-01-27 07:29:48201
[email protected]15f08dd2012-01-27 07:29:48202class Function(object):
203 """A Function defined in the API.
[email protected]cfe484902012-02-15 14:52:32204
205 Properties:
206 - |name| the function name
[email protected]4636c832013-01-11 02:10:11207 - |platforms| if not None, the list of platforms that the function is
208 available to
[email protected]cfe484902012-02-15 14:52:32209 - |params| a list of parameters to the function (order matters). A separate
[email protected]4636c832013-01-11 02:10:11210 parameter is used for each choice of a 'choices' parameter
[email protected]9c7830ba2013-10-17 19:28:46211 - |deprecated| a reason and possible alternative for a deprecated function
[email protected]cfe484902012-02-15 14:52:32212 - |description| a description of the function (if provided)
213 - |callback| the callback parameter to the function. There should be exactly
[email protected]4636c832013-01-11 02:10:11214 one
[email protected]4b3f7852012-07-17 06:33:30215 - |optional| whether the Function is "optional"; this only makes sense to be
[email protected]4636c832013-01-11 02:10:11216 present when the Function is representing a callback property
[email protected]0b255f002012-10-05 01:58:47217 - |simple_name| the name of this Function without a namespace
[email protected]32096af2013-02-06 01:29:31218 - |returns| the return type of the function; None if the function does not
219 return a value
[email protected]15f08dd2012-01-27 07:29:48220 """
[email protected]0b255f002012-10-05 01:58:47221 def __init__(self,
222 parent,
[email protected]242d5e7a2013-01-17 06:50:31223 name,
[email protected]0b255f002012-10-05 01:58:47224 json,
225 namespace,
[email protected]242d5e7a2013-01-17 06:50:31226 origin):
227 self.name = name
[email protected]0b255f002012-10-05 01:58:47228 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4636c832013-01-11 02:10:11229 self.platforms = _GetPlatforms(json)
[email protected]15f08dd2012-01-27 07:29:48230 self.params = []
[email protected]feba21e2012-03-02 15:05:27231 self.description = json.get('description')
[email protected]9c7830ba2013-10-17 19:28:46232 self.deprecated = json.get('deprecated')
[email protected]15f08dd2012-01-27 07:29:48233 self.callback = None
[email protected]4b3f7852012-07-17 06:33:30234 self.optional = json.get('optional', False)
[email protected]feba21e2012-03-02 15:05:27235 self.parent = parent
[email protected]a9ead752012-05-24 02:08:45236 self.nocompile = json.get('nocompile')
[email protected]c0718352012-08-21 02:34:24237 options = json.get('options', {})
238 self.conditions = options.get('conditions', [])
239 self.actions = options.get('actions', [])
240 self.supports_listeners = options.get('supportsListeners', True)
241 self.supports_rules = options.get('supportsRules', False)
[email protected]c18d6712013-10-03 18:39:30242 self.supports_dom = options.get('supportsDom', False)
[email protected]242d5e7a2013-01-17 06:50:31243
[email protected]c0718352012-08-21 02:34:24244 def GeneratePropertyFromParam(p):
[email protected]627b54d2013-02-04 23:53:59245 return Property(self, p['name'], p, namespace, origin)
[email protected]db943992012-08-02 14:02:54246
[email protected]c0718352012-08-21 02:34:24247 self.filters = [GeneratePropertyFromParam(filter)
248 for filter in json.get('filters', [])]
[email protected]db943992012-08-02 14:02:54249 callback_param = None
[email protected]b741e8f2012-07-16 21:47:24250 for param in json.get('parameters', []):
[email protected]15f08dd2012-01-27 07:29:48251 if param.get('type') == 'function':
[email protected]db943992012-08-02 14:02:54252 if callback_param:
253 # No ParseException because the webstore has this.
254 # Instead, pretend all intermediate callbacks are properties.
255 self.params.append(GeneratePropertyFromParam(callback_param))
256 callback_param = param
[email protected]15f08dd2012-01-27 07:29:48257 else:
[email protected]db943992012-08-02 14:02:54258 self.params.append(GeneratePropertyFromParam(param))
259
260 if callback_param:
[email protected]0b255f002012-10-05 01:58:47261 self.callback = Function(self,
[email protected]242d5e7a2013-01-17 06:50:31262 callback_param['name'],
[email protected]0b255f002012-10-05 01:58:47263 callback_param,
264 namespace,
[email protected]242d5e7a2013-01-17 06:50:31265 Origin(from_client=True))
[email protected]db943992012-08-02 14:02:54266
[email protected]491e60d32012-07-20 01:03:13267 self.returns = None
268 if 'returns' in json:
[email protected]627b54d2013-02-04 23:53:59269 self.returns = Type(self,
270 '%sReturnType' % name,
271 json['returns'],
272 namespace,
273 origin)
[email protected]15f08dd2012-01-27 07:29:48274
[email protected]15f08dd2012-01-27 07:29:48275class Property(object):
276 """A property of a type OR a parameter to a function.
[email protected]cfe484902012-02-15 14:52:32277 Properties:
278 - |name| name of the property as in the json. This shouldn't change since
279 it is the key used to access DictionaryValues
280 - |unix_name| the unix_style_name of the property. Used as variable name
281 - |optional| a boolean representing whether the property is optional
282 - |description| a description of the property (if provided)
[email protected]242d5e7a2013-01-17 06:50:31283 - |type_| the model.Type of this property
[email protected]0b255f002012-10-05 01:58:47284 - |simple_name| the name of this Property without a namespace
[email protected]15f08dd2012-01-27 07:29:48285 """
[email protected]627b54d2013-02-04 23:53:59286 def __init__(self, parent, name, json, namespace, origin):
[email protected]242d5e7a2013-01-17 06:50:31287 """Creates a Property from JSON.
288 """
[email protected]627b54d2013-02-04 23:53:59289 self.parent = parent
290 self.name = name
291 self._unix_name = UnixName(self.name)
292 self._unix_name_used = False
293 self.origin = origin
294 self.simple_name = _StripNamespace(self.name, namespace)
295 self.description = json.get('description', None)
296 self.optional = json.get('optional', None)
297 self.instance_of = json.get('isInstanceOf', None)
[email protected]242d5e7a2013-01-17 06:50:31298
299 # HACK: only support very specific value types.
300 is_allowed_value = (
301 '$ref' not in json and
302 ('type' not in json or json['type'] == 'integer'
303 or json['type'] == 'string'))
304
[email protected]627b54d2013-02-04 23:53:59305 self.value = None
[email protected]242d5e7a2013-01-17 06:50:31306 if 'value' in json and is_allowed_value:
[email protected]627b54d2013-02-04 23:53:59307 self.value = json['value']
[email protected]242d5e7a2013-01-17 06:50:31308 if 'type' not in json:
309 # Sometimes the type of the value is left out, and we need to figure
310 # it out for ourselves.
[email protected]627b54d2013-02-04 23:53:59311 if isinstance(self.value, int):
[email protected]242d5e7a2013-01-17 06:50:31312 json['type'] = 'integer'
[email protected]627b54d2013-02-04 23:53:59313 elif isinstance(self.value, basestring):
[email protected]242d5e7a2013-01-17 06:50:31314 json['type'] = 'string'
315 else:
316 # TODO(kalman): support more types as necessary.
317 raise ParseException(
[email protected]627b54d2013-02-04 23:53:59318 parent,
319 '"%s" is not a supported type for "value"' % type(self.value))
[email protected]242d5e7a2013-01-17 06:50:31320
[email protected]627b54d2013-02-04 23:53:59321 self.type_ = Type(parent, name, json, namespace, origin)
[email protected]cfe484902012-02-15 14:52:32322
323 def GetUnixName(self):
324 """Gets the property's unix_name. Raises AttributeError if not set.
325 """
[email protected]116f0a3a2012-04-19 04:22:38326 if not self._unix_name:
[email protected]cfe484902012-02-15 14:52:32327 raise AttributeError('No unix_name set on %s' % self.name)
328 self._unix_name_used = True
329 return self._unix_name
330
331 def SetUnixName(self, unix_name):
332 """Set the property's unix_name. Raises AttributeError if the unix_name has
333 already been used (GetUnixName has been called).
334 """
335 if unix_name == self._unix_name:
336 return
337 if self._unix_name_used:
338 raise AttributeError(
339 'Cannot set the unix_name on %s; '
340 'it is already used elsewhere as %s' %
341 (self.name, self._unix_name))
342 self._unix_name = unix_name
343
344 unix_name = property(GetUnixName, SetUnixName)
[email protected]15f08dd2012-01-27 07:29:48345
[email protected]4636c832013-01-11 02:10:11346class _Enum(object):
347 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
348 Enums need to do this so that equality/non-equality work over pickling.
[email protected]fe027682012-08-21 01:51:34349 """
[email protected]4636c832013-01-11 02:10:11350 @staticmethod
351 def GetAll(cls):
352 """Yields all _Enum objects declared in |cls|.
353 """
354 for prop_key in dir(cls):
355 prop_value = getattr(cls, prop_key)
356 if isinstance(prop_value, _Enum):
357 yield prop_value
358
359 def __init__(self, name):
[email protected]fe027682012-08-21 01:51:34360 self.name = name
361
[email protected]dc5f2fecf2012-08-31 01:55:51362 def __eq__(self, other):
[email protected]4636c832013-01-11 02:10:11363 return type(other) == type(self) and other.name == self.name
[email protected]e15dccb2012-10-05 06:02:25364 def __ne__(self, other):
[email protected]e15dccb2012-10-05 06:02:25365 return not (self == other)
366
[email protected]e11b9aa2013-07-13 00:05:42367 def __repr__(self):
368 return self.name
369
370 def __str__(self):
371 return repr(self)
372
[email protected]4636c832013-01-11 02:10:11373class _PropertyTypeInfo(_Enum):
374 def __init__(self, is_fundamental, name):
375 _Enum.__init__(self, name)
376 self.is_fundamental = is_fundamental
377
[email protected]15f08dd2012-01-27 07:29:48378class PropertyType(object):
379 """Enum of different types of properties/parameters.
380 """
[email protected]242d5e7a2013-01-17 06:50:31381 ANY = _PropertyTypeInfo(False, "any")
[email protected]e11b9aa2013-07-13 00:05:42382 ARRAY = _PropertyTypeInfo(False, "array")
383 BINARY = _PropertyTypeInfo(False, "binary")
384 BOOLEAN = _PropertyTypeInfo(True, "boolean")
385 CHOICES = _PropertyTypeInfo(False, "choices")
386 DOUBLE = _PropertyTypeInfo(True, "double")
387 ENUM = _PropertyTypeInfo(False, "enum")
388 FUNCTION = _PropertyTypeInfo(False, "function")
389 INT64 = _PropertyTypeInfo(True, "int64")
390 INTEGER = _PropertyTypeInfo(True, "integer")
391 OBJECT = _PropertyTypeInfo(False, "object")
392 REF = _PropertyTypeInfo(False, "ref")
393 STRING = _PropertyTypeInfo(True, "string")
[email protected]cfe484902012-02-15 14:52:32394
[email protected]cb5670c2013-04-10 06:31:08395@memoize
[email protected]4ba6bdc2012-06-18 20:40:14396def UnixName(name):
[email protected]cb5670c2013-04-10 06:31:08397 '''Returns the unix_style name for a given lowerCamelCase string.
398 '''
399 unix_name = []
400 for i, c in enumerate(name):
[email protected]e11b9aa2013-07-13 00:05:42401 if c.isupper() and i > 0 and name[i - 1] != '_':
[email protected]cb5670c2013-04-10 06:31:08402 # Replace lowerUpper with lower_Upper.
403 if name[i - 1].islower():
404 unix_name.append('_')
405 # Replace ACMEWidgets with ACME_Widgets
406 elif i + 1 < len(name) and name[i + 1].islower():
407 unix_name.append('_')
408 if c == '.':
409 # Replace hello.world with hello_world.
410 unix_name.append('_')
411 else:
412 # Everything is lowercase.
413 unix_name.append(c.lower())
414 return ''.join(unix_name)
[email protected]cfe484902012-02-15 14:52:32415
[email protected]0b255f002012-10-05 01:58:47416def _StripNamespace(name, namespace):
417 if name.startswith(namespace.name + '.'):
418 return name[len(namespace.name + '.'):]
419 return name
420
[email protected]116f0a3a2012-04-19 04:22:38421def _GetModelHierarchy(entity):
[email protected]feba21e2012-03-02 15:05:27422 """Returns the hierarchy of the given model entity."""
423 hierarchy = []
[email protected]242d5e7a2013-01-17 06:50:31424 while entity is not None:
425 hierarchy.append(getattr(entity, 'name', repr(entity)))
426 if isinstance(entity, Namespace):
427 hierarchy.insert(0, ' in %s' % entity.source_file)
428 entity = getattr(entity, 'parent', None)
[email protected]feba21e2012-03-02 15:05:27429 hierarchy.reverse()
430 return hierarchy
[email protected]116f0a3a2012-04-19 04:22:38431
[email protected]242d5e7a2013-01-17 06:50:31432def _GetTypes(parent, json, namespace, origin):
433 """Creates Type objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38434 """
[email protected]242d5e7a2013-01-17 06:50:31435 types = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38436 for type_json in json.get('types', []):
[email protected]242d5e7a2013-01-17 06:50:31437 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
438 types[type_.name] = type_
439 return types
[email protected]116f0a3a2012-04-19 04:22:38440
[email protected]242d5e7a2013-01-17 06:50:31441def _GetFunctions(parent, json, namespace):
442 """Creates Function objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38443 """
[email protected]242d5e7a2013-01-17 06:50:31444 functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38445 for function_json in json.get('functions', []):
[email protected]242d5e7a2013-01-17 06:50:31446 function = Function(parent,
447 function_json['name'],
448 function_json,
449 namespace,
450 Origin(from_json=True))
451 functions[function.name] = function
452 return functions
[email protected]116f0a3a2012-04-19 04:22:38453
[email protected]242d5e7a2013-01-17 06:50:31454def _GetEvents(parent, json, namespace):
455 """Creates Function objects generated from the events in |json|.
[email protected]b741e8f2012-07-16 21:47:24456 """
[email protected]242d5e7a2013-01-17 06:50:31457 events = OrderedDict()
[email protected]b741e8f2012-07-16 21:47:24458 for event_json in json.get('events', []):
[email protected]242d5e7a2013-01-17 06:50:31459 event = Function(parent,
460 event_json['name'],
461 event_json,
462 namespace,
463 Origin(from_client=True))
464 events[event.name] = event
465 return events
[email protected]b741e8f2012-07-16 21:47:24466
[email protected]242d5e7a2013-01-17 06:50:31467def _GetProperties(parent, json, namespace, origin):
468 """Generates Property objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38469 """
[email protected]242d5e7a2013-01-17 06:50:31470 properties = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38471 for name, property_json in json.get('properties', {}).items():
[email protected]627b54d2013-02-04 23:53:59472 properties[name] = Property(parent, name, property_json, namespace, origin)
[email protected]242d5e7a2013-01-17 06:50:31473 return properties
[email protected]4636c832013-01-11 02:10:11474
475class _PlatformInfo(_Enum):
476 def __init__(self, name):
477 _Enum.__init__(self, name)
478
479class Platforms(object):
480 """Enum of the possible platforms.
481 """
482 CHROMEOS = _PlatformInfo("chromeos")
483 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
484 LINUX = _PlatformInfo("linux")
485 MAC = _PlatformInfo("mac")
486 WIN = _PlatformInfo("win")
487
488def _GetPlatforms(json):
[email protected]e0eec63f2013-10-30 05:28:58489 if 'platforms' not in json or json['platforms'] == None:
[email protected]4636c832013-01-11 02:10:11490 return None
[email protected]e0eec63f2013-10-30 05:28:58491 # Sanity check: platforms should not be an empty list.
492 if not json['platforms']:
493 raise ValueError('"platforms" cannot be an empty list')
[email protected]4636c832013-01-11 02:10:11494 platforms = []
495 for platform_name in json['platforms']:
496 for platform_enum in _Enum.GetAll(Platforms):
497 if platform_name == platform_enum.name:
498 platforms.append(platform_enum)
499 break
500 return platforms