blob: 3de975caebe2fe0ad7ef694c9d618fe6fd4d2432 [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
[email protected]7f138d42013-11-01 05:27:27144 self.enum_values = [EnumValue(value) for value in json['enum']]
[email protected]242d5e7a2013-01-17 06:50:31145 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]7f138d42013-11-01 05:27:27346class EnumValue(object):
347 """A single value from an enum.
348 Properties:
349 - |name| name of the property as in the json.
350 - |description| a description of the property (if provided)
351 """
352 def __init__(self, json):
353 if isinstance(json, dict):
354 self.name = json['name']
355 self.description = json.get('description')
356 else:
357 self.name = json
358 self.description = None
359
[email protected]4636c832013-01-11 02:10:11360class _Enum(object):
361 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
362 Enums need to do this so that equality/non-equality work over pickling.
[email protected]fe027682012-08-21 01:51:34363 """
[email protected]4636c832013-01-11 02:10:11364 @staticmethod
365 def GetAll(cls):
366 """Yields all _Enum objects declared in |cls|.
367 """
368 for prop_key in dir(cls):
369 prop_value = getattr(cls, prop_key)
370 if isinstance(prop_value, _Enum):
371 yield prop_value
372
373 def __init__(self, name):
[email protected]fe027682012-08-21 01:51:34374 self.name = name
375
[email protected]dc5f2fecf2012-08-31 01:55:51376 def __eq__(self, other):
[email protected]4636c832013-01-11 02:10:11377 return type(other) == type(self) and other.name == self.name
[email protected]e15dccb2012-10-05 06:02:25378 def __ne__(self, other):
[email protected]e15dccb2012-10-05 06:02:25379 return not (self == other)
380
[email protected]e11b9aa2013-07-13 00:05:42381 def __repr__(self):
382 return self.name
383
384 def __str__(self):
385 return repr(self)
386
[email protected]4636c832013-01-11 02:10:11387class _PropertyTypeInfo(_Enum):
388 def __init__(self, is_fundamental, name):
389 _Enum.__init__(self, name)
390 self.is_fundamental = is_fundamental
391
[email protected]15f08dd2012-01-27 07:29:48392class PropertyType(object):
393 """Enum of different types of properties/parameters.
394 """
[email protected]242d5e7a2013-01-17 06:50:31395 ANY = _PropertyTypeInfo(False, "any")
[email protected]e11b9aa2013-07-13 00:05:42396 ARRAY = _PropertyTypeInfo(False, "array")
397 BINARY = _PropertyTypeInfo(False, "binary")
398 BOOLEAN = _PropertyTypeInfo(True, "boolean")
399 CHOICES = _PropertyTypeInfo(False, "choices")
400 DOUBLE = _PropertyTypeInfo(True, "double")
401 ENUM = _PropertyTypeInfo(False, "enum")
402 FUNCTION = _PropertyTypeInfo(False, "function")
403 INT64 = _PropertyTypeInfo(True, "int64")
404 INTEGER = _PropertyTypeInfo(True, "integer")
405 OBJECT = _PropertyTypeInfo(False, "object")
406 REF = _PropertyTypeInfo(False, "ref")
407 STRING = _PropertyTypeInfo(True, "string")
[email protected]cfe484902012-02-15 14:52:32408
[email protected]cb5670c2013-04-10 06:31:08409@memoize
[email protected]4ba6bdc2012-06-18 20:40:14410def UnixName(name):
[email protected]cb5670c2013-04-10 06:31:08411 '''Returns the unix_style name for a given lowerCamelCase string.
412 '''
413 unix_name = []
414 for i, c in enumerate(name):
[email protected]e11b9aa2013-07-13 00:05:42415 if c.isupper() and i > 0 and name[i - 1] != '_':
[email protected]cb5670c2013-04-10 06:31:08416 # Replace lowerUpper with lower_Upper.
417 if name[i - 1].islower():
418 unix_name.append('_')
419 # Replace ACMEWidgets with ACME_Widgets
420 elif i + 1 < len(name) and name[i + 1].islower():
421 unix_name.append('_')
422 if c == '.':
423 # Replace hello.world with hello_world.
424 unix_name.append('_')
425 else:
426 # Everything is lowercase.
427 unix_name.append(c.lower())
428 return ''.join(unix_name)
[email protected]cfe484902012-02-15 14:52:32429
[email protected]0b255f002012-10-05 01:58:47430def _StripNamespace(name, namespace):
431 if name.startswith(namespace.name + '.'):
432 return name[len(namespace.name + '.'):]
433 return name
434
[email protected]116f0a3a2012-04-19 04:22:38435def _GetModelHierarchy(entity):
[email protected]feba21e2012-03-02 15:05:27436 """Returns the hierarchy of the given model entity."""
437 hierarchy = []
[email protected]242d5e7a2013-01-17 06:50:31438 while entity is not None:
439 hierarchy.append(getattr(entity, 'name', repr(entity)))
440 if isinstance(entity, Namespace):
441 hierarchy.insert(0, ' in %s' % entity.source_file)
442 entity = getattr(entity, 'parent', None)
[email protected]feba21e2012-03-02 15:05:27443 hierarchy.reverse()
444 return hierarchy
[email protected]116f0a3a2012-04-19 04:22:38445
[email protected]242d5e7a2013-01-17 06:50:31446def _GetTypes(parent, json, namespace, origin):
447 """Creates Type objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38448 """
[email protected]242d5e7a2013-01-17 06:50:31449 types = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38450 for type_json in json.get('types', []):
[email protected]242d5e7a2013-01-17 06:50:31451 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
452 types[type_.name] = type_
453 return types
[email protected]116f0a3a2012-04-19 04:22:38454
[email protected]242d5e7a2013-01-17 06:50:31455def _GetFunctions(parent, json, namespace):
456 """Creates Function objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38457 """
[email protected]242d5e7a2013-01-17 06:50:31458 functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38459 for function_json in json.get('functions', []):
[email protected]242d5e7a2013-01-17 06:50:31460 function = Function(parent,
461 function_json['name'],
462 function_json,
463 namespace,
464 Origin(from_json=True))
465 functions[function.name] = function
466 return functions
[email protected]116f0a3a2012-04-19 04:22:38467
[email protected]242d5e7a2013-01-17 06:50:31468def _GetEvents(parent, json, namespace):
469 """Creates Function objects generated from the events in |json|.
[email protected]b741e8f2012-07-16 21:47:24470 """
[email protected]242d5e7a2013-01-17 06:50:31471 events = OrderedDict()
[email protected]b741e8f2012-07-16 21:47:24472 for event_json in json.get('events', []):
[email protected]242d5e7a2013-01-17 06:50:31473 event = Function(parent,
474 event_json['name'],
475 event_json,
476 namespace,
477 Origin(from_client=True))
478 events[event.name] = event
479 return events
[email protected]b741e8f2012-07-16 21:47:24480
[email protected]242d5e7a2013-01-17 06:50:31481def _GetProperties(parent, json, namespace, origin):
482 """Generates Property objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38483 """
[email protected]242d5e7a2013-01-17 06:50:31484 properties = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38485 for name, property_json in json.get('properties', {}).items():
[email protected]627b54d2013-02-04 23:53:59486 properties[name] = Property(parent, name, property_json, namespace, origin)
[email protected]242d5e7a2013-01-17 06:50:31487 return properties
[email protected]4636c832013-01-11 02:10:11488
489class _PlatformInfo(_Enum):
490 def __init__(self, name):
491 _Enum.__init__(self, name)
492
493class Platforms(object):
494 """Enum of the possible platforms.
495 """
496 CHROMEOS = _PlatformInfo("chromeos")
497 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
498 LINUX = _PlatformInfo("linux")
499 MAC = _PlatformInfo("mac")
500 WIN = _PlatformInfo("win")
501
502def _GetPlatforms(json):
[email protected]e0eec63f2013-10-30 05:28:58503 if 'platforms' not in json or json['platforms'] == None:
[email protected]4636c832013-01-11 02:10:11504 return None
[email protected]e0eec63f2013-10-30 05:28:58505 # Sanity check: platforms should not be an empty list.
506 if not json['platforms']:
507 raise ValueError('"platforms" cannot be an empty list')
[email protected]4636c832013-01-11 02:10:11508 platforms = []
509 for platform_name in json['platforms']:
510 for platform_enum in _Enum.GetAll(Platforms):
511 if platform_name == platform_enum.name:
512 platforms.append(platform_enum)
513 break
514 return platforms