blob: 637942790825b1e76a9ac4033777589be57680e7 [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]242d5e7a2013-01-17 06:50:3163 toplevel_origin = Origin(from_client=True, from_json=True)
64 self.types = _GetTypes(self, json, self, toplevel_origin)
65 self.functions = _GetFunctions(self, json, self)
66 self.events = _GetEvents(self, json, self)
67 self.properties = _GetProperties(self, json, self, toplevel_origin)
[email protected]4636c832013-01-11 02:10:1168 if include_compiler_options:
69 self.compiler_options = json.get('compiler_options', {})
[email protected]15f08dd2012-01-27 07:29:4870
[email protected]242d5e7a2013-01-17 06:50:3171class 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
[email protected]15f08dd2012-01-27 07:29:4889class Type(object):
90 """A Type defined in the json.
[email protected]cfe484902012-02-15 14:52:3291
92 Properties:
93 - |name| the type name
[email protected]242d5e7a2013-01-17 06:50:3194 - |namespace| the Type's namespace
[email protected]cfe484902012-02-15 14:52:3295 - |description| the description of the type (if provided)
[email protected]feba21e2012-03-02 15:05:2796 - |properties| a map of property unix_names to their model.Property
97 - |functions| a map of function names to their model.Function
[email protected]d32b8e52012-07-23 18:40:0898 - |events| a map of event names to their model.Event
[email protected]242d5e7a2013-01-17 06:50:3199 - |origin| the Origin of the type
100 - |property_type| the PropertyType of this Type
[email protected]cf6d0b32012-04-12 04:30:22101 - |item_type| if this is an array, the type of items in the array
[email protected]0b255f002012-10-05 01:58:47102 - |simple_name| the name of this Type without a namespace
[email protected]242d5e7a2013-01-17 06:50:31103 - |additional_properties| the type of the additional properties, if any is
104 specified
[email protected]15f08dd2012-01-27 07:29:48105 """
[email protected]242d5e7a2013-01-17 06:50:31106 def __init__(self,
107 parent,
108 name,
109 json,
110 namespace,
111 origin):
112 self.name = name
113 self.namespace = namespace
114 self.simple_name = _StripNamespace(self.name, namespace)
115 self.unix_name = UnixName(self.name)
116 self.description = json.get('description', None)
117 self.origin = origin
118 self.parent = parent
119 self.instance_of = json.get('isInstanceOf', None)
120
121 # TODO(kalman): Only objects need functions/events/properties, but callers
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':
[email protected]cf6d0b32012-04-12 04:30:22162 if not (
163 'properties' in json or
164 'additionalProperties' in json or
[email protected]e975d112012-07-31 22:12:43165 'functions' in json or
166 'events' in json):
[email protected]116f0a3a2012-04-19 04:22:38167 raise ParseException(self, name + " has no properties or functions")
[email protected]242d5e7a2013-01-17 06:50:31168 self.property_type = PropertyType.OBJECT
169 additional_properties_json = json.get('additionalProperties', None)
170 if additional_properties_json is not None:
171 self.additional_properties = Type(self,
172 'additionalProperties',
173 additional_properties_json,
174 namespace,
175 origin)
176 else:
177 self.additional_properties = None
178 elif json_type == 'function':
179 self.property_type = PropertyType.FUNCTION
180 # Sometimes we might have an unnamed function, e.g. if it's a property
181 # of an object. Use the name of the property in that case.
182 function_name = json.get('name', name)
183 self.function = Function(self, function_name, json, namespace, origin)
184 else:
185 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
[email protected]15f08dd2012-01-27 07:29:48186
[email protected]15f08dd2012-01-27 07:29:48187class Function(object):
188 """A Function defined in the API.
[email protected]cfe484902012-02-15 14:52:32189
190 Properties:
191 - |name| the function name
[email protected]4636c832013-01-11 02:10:11192 - |platforms| if not None, the list of platforms that the function is
193 available to
[email protected]cfe484902012-02-15 14:52:32194 - |params| a list of parameters to the function (order matters). A separate
[email protected]4636c832013-01-11 02:10:11195 parameter is used for each choice of a 'choices' parameter
[email protected]cfe484902012-02-15 14:52:32196 - |description| a description of the function (if provided)
197 - |callback| the callback parameter to the function. There should be exactly
[email protected]4636c832013-01-11 02:10:11198 one
[email protected]4b3f7852012-07-17 06:33:30199 - |optional| whether the Function is "optional"; this only makes sense to be
[email protected]4636c832013-01-11 02:10:11200 present when the Function is representing a callback property
[email protected]0b255f002012-10-05 01:58:47201 - |simple_name| the name of this Function without a namespace
[email protected]15f08dd2012-01-27 07:29:48202 """
[email protected]0b255f002012-10-05 01:58:47203 def __init__(self,
204 parent,
[email protected]242d5e7a2013-01-17 06:50:31205 name,
[email protected]0b255f002012-10-05 01:58:47206 json,
207 namespace,
[email protected]242d5e7a2013-01-17 06:50:31208 origin):
209 self.name = name
[email protected]0b255f002012-10-05 01:58:47210 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4636c832013-01-11 02:10:11211 self.platforms = _GetPlatforms(json)
[email protected]15f08dd2012-01-27 07:29:48212 self.params = []
[email protected]feba21e2012-03-02 15:05:27213 self.description = json.get('description')
[email protected]15f08dd2012-01-27 07:29:48214 self.callback = None
[email protected]4b3f7852012-07-17 06:33:30215 self.optional = json.get('optional', False)
[email protected]feba21e2012-03-02 15:05:27216 self.parent = parent
[email protected]a9ead752012-05-24 02:08:45217 self.nocompile = json.get('nocompile')
[email protected]c0718352012-08-21 02:34:24218 options = json.get('options', {})
219 self.conditions = options.get('conditions', [])
220 self.actions = options.get('actions', [])
221 self.supports_listeners = options.get('supportsListeners', True)
222 self.supports_rules = options.get('supportsRules', False)
[email protected]242d5e7a2013-01-17 06:50:31223
[email protected]c0718352012-08-21 02:34:24224 def GeneratePropertyFromParam(p):
[email protected]242d5e7a2013-01-17 06:50:31225 return Property.FromJSON(self, p['name'], p, namespace, origin)
[email protected]db943992012-08-02 14:02:54226
[email protected]c0718352012-08-21 02:34:24227 self.filters = [GeneratePropertyFromParam(filter)
228 for filter in json.get('filters', [])]
[email protected]db943992012-08-02 14:02:54229 callback_param = None
[email protected]b741e8f2012-07-16 21:47:24230 for param in json.get('parameters', []):
[email protected]15f08dd2012-01-27 07:29:48231 if param.get('type') == 'function':
[email protected]db943992012-08-02 14:02:54232 if callback_param:
233 # No ParseException because the webstore has this.
234 # Instead, pretend all intermediate callbacks are properties.
235 self.params.append(GeneratePropertyFromParam(callback_param))
236 callback_param = param
[email protected]15f08dd2012-01-27 07:29:48237 else:
[email protected]db943992012-08-02 14:02:54238 self.params.append(GeneratePropertyFromParam(param))
239
240 if callback_param:
[email protected]0b255f002012-10-05 01:58:47241 self.callback = Function(self,
[email protected]242d5e7a2013-01-17 06:50:31242 callback_param['name'],
[email protected]0b255f002012-10-05 01:58:47243 callback_param,
244 namespace,
[email protected]242d5e7a2013-01-17 06:50:31245 Origin(from_client=True))
[email protected]db943992012-08-02 14:02:54246
[email protected]491e60d32012-07-20 01:03:13247 self.returns = None
248 if 'returns' in json:
[email protected]242d5e7a2013-01-17 06:50:31249 self.returns = Property.FromJSON(
250 self, 'return', json['returns'], namespace, origin)
[email protected]15f08dd2012-01-27 07:29:48251
[email protected]15f08dd2012-01-27 07:29:48252class Property(object):
253 """A property of a type OR a parameter to a function.
[email protected]cfe484902012-02-15 14:52:32254 Properties:
255 - |name| name of the property as in the json. This shouldn't change since
256 it is the key used to access DictionaryValues
257 - |unix_name| the unix_style_name of the property. Used as variable name
258 - |optional| a boolean representing whether the property is optional
259 - |description| a description of the property (if provided)
[email protected]242d5e7a2013-01-17 06:50:31260 - |type_| the model.Type of this property
[email protected]0b255f002012-10-05 01:58:47261 - |simple_name| the name of this Property without a namespace
[email protected]15f08dd2012-01-27 07:29:48262 """
[email protected]feba21e2012-03-02 15:05:27263
[email protected]242d5e7a2013-01-17 06:50:31264 @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
[email protected]0b255f002012-10-05 01:58:47305 def __init__(self,
306 parent,
307 name,
[email protected]0b255f002012-10-05 01:58:47308 namespace,
[email protected]242d5e7a2013-01-17 06:50:31309 type_,
310 origin,
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 """
[email protected]15f08dd2012-01-27 07:29:48318 self.name = name
[email protected]0b255f002012-10-05 01:58:47319 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4ba6bdc2012-06-18 20:40:14320 self._unix_name = UnixName(self.name)
[email protected]cfe484902012-02-15 14:52:32321 self._unix_name_used = False
[email protected]242d5e7a2013-01-17 06:50:31322 self.optional = optional
323 self.description = description
[email protected]feba21e2012-03-02 15:05:27324 self.parent = parent
[email protected]242d5e7a2013-01-17 06:50:31325 self.origin = origin
326 if not isinstance(type_, Type):
327 raise ValueError("not Type: %s" % type_)
328 self.type_ = type_
329 self.returns = returns
330 if instance_of is not None:
331 self.instance_of = instance_of
332 self.value = value
[email protected]cfe484902012-02-15 14:52:32333
334 def GetUnixName(self):
335 """Gets the property's unix_name. Raises AttributeError if not set.
336 """
[email protected]116f0a3a2012-04-19 04:22:38337 if not self._unix_name:
[email protected]cfe484902012-02-15 14:52:32338 raise AttributeError('No unix_name set on %s' % self.name)
339 self._unix_name_used = True
340 return self._unix_name
341
342 def SetUnixName(self, unix_name):
343 """Set the property's unix_name. Raises AttributeError if the unix_name has
344 already been used (GetUnixName has been called).
345 """
346 if unix_name == self._unix_name:
347 return
348 if self._unix_name_used:
349 raise AttributeError(
350 'Cannot set the unix_name on %s; '
351 'it is already used elsewhere as %s' %
352 (self.name, self._unix_name))
353 self._unix_name = unix_name
354
355 unix_name = property(GetUnixName, SetUnixName)
[email protected]15f08dd2012-01-27 07:29:48356
[email protected]4636c832013-01-11 02:10:11357class _Enum(object):
358 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
359 Enums need to do this so that equality/non-equality work over pickling.
[email protected]fe027682012-08-21 01:51:34360 """
[email protected]4636c832013-01-11 02:10:11361
362 @staticmethod
363 def GetAll(cls):
364 """Yields all _Enum objects declared in |cls|.
365 """
366 for prop_key in dir(cls):
367 prop_value = getattr(cls, prop_key)
368 if isinstance(prop_value, _Enum):
369 yield prop_value
370
371 def __init__(self, name):
[email protected]fe027682012-08-21 01:51:34372 self.name = name
373
[email protected]4636c832013-01-11 02:10:11374 def __repr(self):
[email protected]fe027682012-08-21 01:51:34375 return self.name
376
[email protected]dc5f2fecf2012-08-31 01:55:51377 def __eq__(self, other):
[email protected]4636c832013-01-11 02:10:11378 return type(other) == type(self) and other.name == self.name
[email protected]dc5f2fecf2012-08-31 01:55:51379
[email protected]e15dccb2012-10-05 06:02:25380 def __ne__(self, other):
[email protected]e15dccb2012-10-05 06:02:25381 return not (self == other)
382
[email protected]4636c832013-01-11 02:10:11383class _PropertyTypeInfo(_Enum):
384 def __init__(self, is_fundamental, name):
385 _Enum.__init__(self, name)
386 self.is_fundamental = is_fundamental
387
[email protected]15f08dd2012-01-27 07:29:48388class PropertyType(object):
389 """Enum of different types of properties/parameters.
390 """
[email protected]242d5e7a2013-01-17 06:50:31391 INTEGER = _PropertyTypeInfo(True, "integer")
392 INT64 = _PropertyTypeInfo(True, "int64")
393 DOUBLE = _PropertyTypeInfo(True, "double")
394 BOOLEAN = _PropertyTypeInfo(True, "boolean")
395 STRING = _PropertyTypeInfo(True, "string")
396 ENUM = _PropertyTypeInfo(False, "enum")
397 ARRAY = _PropertyTypeInfo(False, "array")
398 REF = _PropertyTypeInfo(False, "ref")
399 CHOICES = _PropertyTypeInfo(False, "choices")
400 OBJECT = _PropertyTypeInfo(False, "object")
401 FUNCTION = _PropertyTypeInfo(False, "function")
402 BINARY = _PropertyTypeInfo(False, "binary")
403 ANY = _PropertyTypeInfo(False, "any")
[email protected]cfe484902012-02-15 14:52:32404
[email protected]4ba6bdc2012-06-18 20:40:14405def UnixName(name):
[email protected]712eca0f2012-02-21 01:13:07406 """Returns the unix_style name for a given lowerCamelCase string.
[email protected]cfe484902012-02-15 14:52:32407 """
[email protected]df74dc42012-04-03 07:08:04408 # First replace any lowerUpper patterns with lower_Upper.
409 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
410 # Now replace any ACMEWidgets patterns with ACME_Widgets
411 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
412 # Finally, replace any remaining periods, and make lowercase.
413 return s2.replace('.', '_').lower()
[email protected]cfe484902012-02-15 14:52:32414
[email protected]0b255f002012-10-05 01:58:47415def _StripNamespace(name, namespace):
416 if name.startswith(namespace.name + '.'):
417 return name[len(namespace.name + '.'):]
418 return name
419
[email protected]116f0a3a2012-04-19 04:22:38420def _GetModelHierarchy(entity):
[email protected]feba21e2012-03-02 15:05:27421 """Returns the hierarchy of the given model entity."""
422 hierarchy = []
[email protected]242d5e7a2013-01-17 06:50:31423 while entity is not None:
424 hierarchy.append(getattr(entity, 'name', repr(entity)))
425 if isinstance(entity, Namespace):
426 hierarchy.insert(0, ' in %s' % entity.source_file)
427 entity = getattr(entity, 'parent', None)
[email protected]feba21e2012-03-02 15:05:27428 hierarchy.reverse()
429 return hierarchy
[email protected]116f0a3a2012-04-19 04:22:38430
[email protected]242d5e7a2013-01-17 06:50:31431def _GetTypes(parent, json, namespace, origin):
432 """Creates Type objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38433 """
[email protected]242d5e7a2013-01-17 06:50:31434 types = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38435 for type_json in json.get('types', []):
[email protected]242d5e7a2013-01-17 06:50:31436 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
437 types[type_.name] = type_
438 return types
[email protected]116f0a3a2012-04-19 04:22:38439
[email protected]242d5e7a2013-01-17 06:50:31440def _GetFunctions(parent, json, namespace):
441 """Creates Function objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38442 """
[email protected]242d5e7a2013-01-17 06:50:31443 functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38444 for function_json in json.get('functions', []):
[email protected]242d5e7a2013-01-17 06:50:31445 function = Function(parent,
446 function_json['name'],
447 function_json,
448 namespace,
449 Origin(from_json=True))
450 functions[function.name] = function
451 return functions
[email protected]116f0a3a2012-04-19 04:22:38452
[email protected]242d5e7a2013-01-17 06:50:31453def _GetEvents(parent, json, namespace):
454 """Creates Function objects generated from the events in |json|.
[email protected]b741e8f2012-07-16 21:47:24455 """
[email protected]242d5e7a2013-01-17 06:50:31456 events = OrderedDict()
[email protected]b741e8f2012-07-16 21:47:24457 for event_json in json.get('events', []):
[email protected]242d5e7a2013-01-17 06:50:31458 event = Function(parent,
459 event_json['name'],
460 event_json,
461 namespace,
462 Origin(from_client=True))
463 events[event.name] = event
464 return events
[email protected]b741e8f2012-07-16 21:47:24465
[email protected]242d5e7a2013-01-17 06:50:31466def _GetProperties(parent, json, namespace, origin):
467 """Generates Property objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38468 """
[email protected]242d5e7a2013-01-17 06:50:31469 properties = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38470 for name, property_json in json.get('properties', {}).items():
[email protected]242d5e7a2013-01-17 06:50:31471 properties[name] = Property.FromJSON(
472 parent, name, property_json, namespace, origin)
473 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):
489 if 'platforms' not in json:
490 return None
491 platforms = []
492 for platform_name in json['platforms']:
493 for platform_enum in _Enum.GetAll(Platforms):
494 if platform_name == platform_enum.name:
495 platforms.append(platform_enum)
496 break
497 return platforms