blob: dd68e9b1056f7e84c9aab6d997a1a3730a22030b [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]0853bcf2013-11-06 05:14:3310
[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]0853bcf2013-11-06 05:14:3320
[email protected]15f08dd2012-01-27 07:29:4821class Model(object):
22 """Model of all namespaces that comprise an API.
[email protected]cfe484902012-02-15 14:52:3223
24 Properties:
25 - |namespaces| a map of a namespace name to its model.Namespace
[email protected]15f08dd2012-01-27 07:29:4826 """
27 def __init__(self):
28 self.namespaces = {}
29
[email protected]4636c832013-01-11 02:10:1130 def AddNamespace(self, json, source_file, include_compiler_options=False):
[email protected]a1f774972012-04-17 02:11:0931 """Add a namespace's json to the model and returns the namespace.
[email protected]15f08dd2012-01-27 07:29:4832 """
[email protected]4636c832013-01-11 02:10:1133 namespace = Namespace(json,
34 source_file,
35 include_compiler_options=include_compiler_options)
[email protected]15f08dd2012-01-27 07:29:4836 self.namespaces[namespace.name] = namespace
37 return namespace
38
[email protected]0853bcf2013-11-06 05:14:3339
40def CreateFeature(name, model):
41 if isinstance(model, dict):
42 return SimpleFeature(name, model)
43 return ComplexFeature(name, [SimpleFeature(name, child) for child in model])
44
45
46class ComplexFeature(object):
47 """A complex feature which may be made of several simple features.
48
49 Properties:
50 - |name| the name of the feature
51 - |unix_name| the unix_name of the feature
52 - |feature_list| a list of simple features which make up the feature
53 """
54 def __init__(self, feature_name, features):
55 self.name = feature_name
56 self.unix_name = UnixName(self.name)
57 self.feature_list = features
58
59class SimpleFeature(object):
60 """A simple feature, which can make up a complex feature, as specified in
61 files such as chrome/common/extensions/api/_permission_features.json.
62
63 Properties:
64 - |name| the name of the feature
65 - |unix_name| the unix_name of the feature
66 - |channel| the channel where the feature is released
67 - |extension_types| the types which can use the feature
68 - |whitelist| a list of extensions allowed to use the feature
69 """
70 def __init__(self, feature_name, feature_def):
71 self.name = feature_name
72 self.unix_name = UnixName(self.name)
73 self.channel = feature_def['channel']
74 self.extension_types = feature_def['extension_types']
75 self.whitelist = feature_def.get('whitelist')
76
77
[email protected]15f08dd2012-01-27 07:29:4878class Namespace(object):
79 """An API namespace.
[email protected]cfe484902012-02-15 14:52:3280
81 Properties:
82 - |name| the name of the namespace
[email protected]8426f8d72013-06-23 04:24:5583 - |description| the description of the namespace
[email protected]712eca0f2012-02-21 01:13:0784 - |unix_name| the unix_name of the namespace
85 - |source_file| the file that contained the namespace definition
86 - |source_file_dir| the directory component of |source_file|
87 - |source_file_filename| the filename component of |source_file|
[email protected]4636c832013-01-11 02:10:1188 - |platforms| if not None, the list of platforms that the namespace is
89 available to
[email protected]cfe484902012-02-15 14:52:3290 - |types| a map of type names to their model.Type
91 - |functions| a map of function names to their model.Function
[email protected]b741e8f2012-07-16 21:47:2492 - |events| a map of event names to their model.Function
[email protected]116f0a3a2012-04-19 04:22:3893 - |properties| a map of property names to their model.Property
[email protected]bee7a7932013-08-12 23:45:3894 - |compiler_options| the compiler_options dict, only not empty if
[email protected]4636c832013-01-11 02:10:1195 |include_compiler_options| is True
[email protected]15f08dd2012-01-27 07:29:4896 """
[email protected]4636c832013-01-11 02:10:1197 def __init__(self, json, source_file, include_compiler_options=False):
[email protected]15f08dd2012-01-27 07:29:4898 self.name = json['namespace']
[email protected]8426f8d72013-06-23 04:24:5599 if 'description' not in json:
[email protected]a081aeb2013-07-09 20:52:47100 # TODO(kalman): Go back to throwing an error here.
101 print('%s must have a "description" field. This will appear '
[email protected]8426f8d72013-06-23 04:24:55102 'on the API summary page.' % self.name)
[email protected]a081aeb2013-07-09 20:52:47103 json['description'] = ''
104 self.description = json['description']
[email protected]4ba6bdc2012-06-18 20:40:14105 self.unix_name = UnixName(self.name)
[email protected]15f08dd2012-01-27 07:29:48106 self.source_file = source_file
107 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
[email protected]feba21e2012-03-02 15:05:27108 self.parent = None
[email protected]4636c832013-01-11 02:10:11109 self.platforms = _GetPlatforms(json)
[email protected]242d5e7a2013-01-17 06:50:31110 toplevel_origin = Origin(from_client=True, from_json=True)
111 self.types = _GetTypes(self, json, self, toplevel_origin)
112 self.functions = _GetFunctions(self, json, self)
113 self.events = _GetEvents(self, json, self)
114 self.properties = _GetProperties(self, json, self, toplevel_origin)
[email protected]03e5ffe2013-11-07 01:54:53115 if include_compiler_options:
116 self.compiler_options = json.get('compiler_options', {})
117 else:
118 self.compiler_options = {}
[email protected]0b022482013-10-03 19:38:05119 self.documentation_options = json.get('documentation_options', {})
[email protected]15f08dd2012-01-27 07:29:48120
[email protected]0853bcf2013-11-06 05:14:33121
[email protected]242d5e7a2013-01-17 06:50:31122class Origin(object):
123 """Stores the possible origin of model object as a pair of bools. These are:
124
125 |from_client| indicating that instances can originate from users of
126 generated code (for example, function results), or
127 |from_json| indicating that instances can originate from the JSON (for
128 example, function parameters)
129
130 It is possible for model objects to originate from both the client and json,
131 for example Types defined in the top-level schema, in which case both
132 |from_client| and |from_json| would be True.
133 """
134 def __init__(self, from_client=False, from_json=False):
135 if not from_client and not from_json:
136 raise ValueError('One of from_client or from_json must be true')
137 self.from_client = from_client
138 self.from_json = from_json
139
[email protected]0853bcf2013-11-06 05:14:33140
[email protected]15f08dd2012-01-27 07:29:48141class Type(object):
142 """A Type defined in the json.
[email protected]cfe484902012-02-15 14:52:32143
144 Properties:
145 - |name| the type name
[email protected]242d5e7a2013-01-17 06:50:31146 - |namespace| the Type's namespace
[email protected]cfe484902012-02-15 14:52:32147 - |description| the description of the type (if provided)
[email protected]feba21e2012-03-02 15:05:27148 - |properties| a map of property unix_names to their model.Property
149 - |functions| a map of function names to their model.Function
[email protected]d32b8e52012-07-23 18:40:08150 - |events| a map of event names to their model.Event
[email protected]242d5e7a2013-01-17 06:50:31151 - |origin| the Origin of the type
152 - |property_type| the PropertyType of this Type
[email protected]cf6d0b32012-04-12 04:30:22153 - |item_type| if this is an array, the type of items in the array
[email protected]0b255f002012-10-05 01:58:47154 - |simple_name| the name of this Type without a namespace
[email protected]242d5e7a2013-01-17 06:50:31155 - |additional_properties| the type of the additional properties, if any is
156 specified
[email protected]15f08dd2012-01-27 07:29:48157 """
[email protected]242d5e7a2013-01-17 06:50:31158 def __init__(self,
159 parent,
160 name,
161 json,
162 namespace,
163 origin):
164 self.name = name
165 self.namespace = namespace
166 self.simple_name = _StripNamespace(self.name, namespace)
167 self.unix_name = UnixName(self.name)
168 self.description = json.get('description', None)
169 self.origin = origin
170 self.parent = parent
171 self.instance_of = json.get('isInstanceOf', None)
172
173 # TODO(kalman): Only objects need functions/events/properties, but callers
174 # assume that all types have them. Fix this.
175 self.functions = _GetFunctions(self, json, namespace)
176 self.events = _GetEvents(self, json, namespace)
177 self.properties = _GetProperties(self, json, namespace, origin)
178
179 json_type = json.get('type', None)
180 if json_type == 'array':
181 self.property_type = PropertyType.ARRAY
182 self.item_type = Type(
183 self, '%sType' % name, json['items'], namespace, origin)
184 elif '$ref' in json:
185 self.property_type = PropertyType.REF
186 self.ref_type = json['$ref']
187 elif 'enum' in json and json_type == 'string':
188 self.property_type = PropertyType.ENUM
[email protected]7f138d42013-11-01 05:27:27189 self.enum_values = [EnumValue(value) for value in json['enum']]
[email protected]242d5e7a2013-01-17 06:50:31190 elif json_type == 'any':
191 self.property_type = PropertyType.ANY
192 elif json_type == 'binary':
193 self.property_type = PropertyType.BINARY
194 elif json_type == 'boolean':
195 self.property_type = PropertyType.BOOLEAN
196 elif json_type == 'integer':
197 self.property_type = PropertyType.INTEGER
198 elif (json_type == 'double' or
199 json_type == 'number'):
200 self.property_type = PropertyType.DOUBLE
201 elif json_type == 'string':
202 self.property_type = PropertyType.STRING
203 elif 'choices' in json:
204 self.property_type = PropertyType.CHOICES
[email protected]e11b9aa2013-07-13 00:05:42205 def generate_type_name(type_json):
206 if 'items' in type_json:
207 return '%ss' % generate_type_name(type_json['items'])
208 if '$ref' in type_json:
209 return type_json['$ref']
210 if 'type' in type_json:
211 return type_json['type']
212 return None
213 self.choices = [
214 Type(self,
215 generate_type_name(choice) or 'choice%s' % i,
216 choice,
217 namespace,
218 origin)
219 for i, choice in enumerate(json['choices'])]
[email protected]242d5e7a2013-01-17 06:50:31220 elif json_type == 'object':
[email protected]cf6d0b32012-04-12 04:30:22221 if not (
[email protected]117afcf2013-08-30 02:38:09222 'isInstanceOf' in json or
[email protected]cf6d0b32012-04-12 04:30:22223 'properties' in json or
224 'additionalProperties' in json or
[email protected]e975d112012-07-31 22:12:43225 'functions' in json or
226 'events' in json):
[email protected]116f0a3a2012-04-19 04:22:38227 raise ParseException(self, name + " has no properties or functions")
[email protected]242d5e7a2013-01-17 06:50:31228 self.property_type = PropertyType.OBJECT
229 additional_properties_json = json.get('additionalProperties', None)
230 if additional_properties_json is not None:
231 self.additional_properties = Type(self,
232 'additionalProperties',
233 additional_properties_json,
234 namespace,
235 origin)
236 else:
237 self.additional_properties = None
238 elif json_type == 'function':
239 self.property_type = PropertyType.FUNCTION
240 # Sometimes we might have an unnamed function, e.g. if it's a property
241 # of an object. Use the name of the property in that case.
242 function_name = json.get('name', name)
243 self.function = Function(self, function_name, json, namespace, origin)
244 else:
245 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
[email protected]15f08dd2012-01-27 07:29:48246
[email protected]0853bcf2013-11-06 05:14:33247
[email protected]15f08dd2012-01-27 07:29:48248class Function(object):
249 """A Function defined in the API.
[email protected]cfe484902012-02-15 14:52:32250
251 Properties:
252 - |name| the function name
[email protected]4636c832013-01-11 02:10:11253 - |platforms| if not None, the list of platforms that the function is
254 available to
[email protected]cfe484902012-02-15 14:52:32255 - |params| a list of parameters to the function (order matters). A separate
[email protected]4636c832013-01-11 02:10:11256 parameter is used for each choice of a 'choices' parameter
[email protected]9c7830ba2013-10-17 19:28:46257 - |deprecated| a reason and possible alternative for a deprecated function
[email protected]cfe484902012-02-15 14:52:32258 - |description| a description of the function (if provided)
259 - |callback| the callback parameter to the function. There should be exactly
[email protected]4636c832013-01-11 02:10:11260 one
[email protected]4b3f7852012-07-17 06:33:30261 - |optional| whether the Function is "optional"; this only makes sense to be
[email protected]4636c832013-01-11 02:10:11262 present when the Function is representing a callback property
[email protected]0b255f002012-10-05 01:58:47263 - |simple_name| the name of this Function without a namespace
[email protected]32096af2013-02-06 01:29:31264 - |returns| the return type of the function; None if the function does not
265 return a value
[email protected]15f08dd2012-01-27 07:29:48266 """
[email protected]0b255f002012-10-05 01:58:47267 def __init__(self,
268 parent,
[email protected]242d5e7a2013-01-17 06:50:31269 name,
[email protected]0b255f002012-10-05 01:58:47270 json,
271 namespace,
[email protected]242d5e7a2013-01-17 06:50:31272 origin):
273 self.name = name
[email protected]0b255f002012-10-05 01:58:47274 self.simple_name = _StripNamespace(self.name, namespace)
[email protected]4636c832013-01-11 02:10:11275 self.platforms = _GetPlatforms(json)
[email protected]15f08dd2012-01-27 07:29:48276 self.params = []
[email protected]feba21e2012-03-02 15:05:27277 self.description = json.get('description')
[email protected]9c7830ba2013-10-17 19:28:46278 self.deprecated = json.get('deprecated')
[email protected]15f08dd2012-01-27 07:29:48279 self.callback = None
[email protected]4b3f7852012-07-17 06:33:30280 self.optional = json.get('optional', False)
[email protected]feba21e2012-03-02 15:05:27281 self.parent = parent
[email protected]a9ead752012-05-24 02:08:45282 self.nocompile = json.get('nocompile')
[email protected]c0718352012-08-21 02:34:24283 options = json.get('options', {})
284 self.conditions = options.get('conditions', [])
285 self.actions = options.get('actions', [])
286 self.supports_listeners = options.get('supportsListeners', True)
287 self.supports_rules = options.get('supportsRules', False)
[email protected]c18d6712013-10-03 18:39:30288 self.supports_dom = options.get('supportsDom', False)
[email protected]242d5e7a2013-01-17 06:50:31289
[email protected]c0718352012-08-21 02:34:24290 def GeneratePropertyFromParam(p):
[email protected]627b54d2013-02-04 23:53:59291 return Property(self, p['name'], p, namespace, origin)
[email protected]db943992012-08-02 14:02:54292
[email protected]c0718352012-08-21 02:34:24293 self.filters = [GeneratePropertyFromParam(filter)
294 for filter in json.get('filters', [])]
[email protected]db943992012-08-02 14:02:54295 callback_param = None
[email protected]b741e8f2012-07-16 21:47:24296 for param in json.get('parameters', []):
[email protected]15f08dd2012-01-27 07:29:48297 if param.get('type') == 'function':
[email protected]db943992012-08-02 14:02:54298 if callback_param:
299 # No ParseException because the webstore has this.
300 # Instead, pretend all intermediate callbacks are properties.
301 self.params.append(GeneratePropertyFromParam(callback_param))
302 callback_param = param
[email protected]15f08dd2012-01-27 07:29:48303 else:
[email protected]db943992012-08-02 14:02:54304 self.params.append(GeneratePropertyFromParam(param))
305
306 if callback_param:
[email protected]0b255f002012-10-05 01:58:47307 self.callback = Function(self,
[email protected]242d5e7a2013-01-17 06:50:31308 callback_param['name'],
[email protected]0b255f002012-10-05 01:58:47309 callback_param,
310 namespace,
[email protected]242d5e7a2013-01-17 06:50:31311 Origin(from_client=True))
[email protected]db943992012-08-02 14:02:54312
[email protected]491e60d32012-07-20 01:03:13313 self.returns = None
314 if 'returns' in json:
[email protected]627b54d2013-02-04 23:53:59315 self.returns = Type(self,
316 '%sReturnType' % name,
317 json['returns'],
318 namespace,
319 origin)
[email protected]15f08dd2012-01-27 07:29:48320
[email protected]0853bcf2013-11-06 05:14:33321
[email protected]15f08dd2012-01-27 07:29:48322class Property(object):
323 """A property of a type OR a parameter to a function.
[email protected]cfe484902012-02-15 14:52:32324 Properties:
325 - |name| name of the property as in the json. This shouldn't change since
326 it is the key used to access DictionaryValues
327 - |unix_name| the unix_style_name of the property. Used as variable name
328 - |optional| a boolean representing whether the property is optional
329 - |description| a description of the property (if provided)
[email protected]242d5e7a2013-01-17 06:50:31330 - |type_| the model.Type of this property
[email protected]0b255f002012-10-05 01:58:47331 - |simple_name| the name of this Property without a namespace
[email protected]04afd692013-11-14 19:35:04332 - |deprecated| a reason and possible alternative for a deprecated property
[email protected]15f08dd2012-01-27 07:29:48333 """
[email protected]627b54d2013-02-04 23:53:59334 def __init__(self, parent, name, json, namespace, origin):
[email protected]242d5e7a2013-01-17 06:50:31335 """Creates a Property from JSON.
336 """
[email protected]627b54d2013-02-04 23:53:59337 self.parent = parent
338 self.name = name
339 self._unix_name = UnixName(self.name)
340 self._unix_name_used = False
341 self.origin = origin
342 self.simple_name = _StripNamespace(self.name, namespace)
343 self.description = json.get('description', None)
344 self.optional = json.get('optional', None)
345 self.instance_of = json.get('isInstanceOf', None)
[email protected]04afd692013-11-14 19:35:04346 self.deprecated = json.get('deprecated')
[email protected]242d5e7a2013-01-17 06:50:31347
348 # HACK: only support very specific value types.
349 is_allowed_value = (
350 '$ref' not in json and
351 ('type' not in json or json['type'] == 'integer'
352 or json['type'] == 'string'))
353
[email protected]627b54d2013-02-04 23:53:59354 self.value = None
[email protected]242d5e7a2013-01-17 06:50:31355 if 'value' in json and is_allowed_value:
[email protected]627b54d2013-02-04 23:53:59356 self.value = json['value']
[email protected]242d5e7a2013-01-17 06:50:31357 if 'type' not in json:
358 # Sometimes the type of the value is left out, and we need to figure
359 # it out for ourselves.
[email protected]627b54d2013-02-04 23:53:59360 if isinstance(self.value, int):
[email protected]242d5e7a2013-01-17 06:50:31361 json['type'] = 'integer'
[email protected]627b54d2013-02-04 23:53:59362 elif isinstance(self.value, basestring):
[email protected]242d5e7a2013-01-17 06:50:31363 json['type'] = 'string'
364 else:
365 # TODO(kalman): support more types as necessary.
366 raise ParseException(
[email protected]627b54d2013-02-04 23:53:59367 parent,
368 '"%s" is not a supported type for "value"' % type(self.value))
[email protected]242d5e7a2013-01-17 06:50:31369
[email protected]627b54d2013-02-04 23:53:59370 self.type_ = Type(parent, name, json, namespace, origin)
[email protected]cfe484902012-02-15 14:52:32371
372 def GetUnixName(self):
373 """Gets the property's unix_name. Raises AttributeError if not set.
374 """
[email protected]116f0a3a2012-04-19 04:22:38375 if not self._unix_name:
[email protected]cfe484902012-02-15 14:52:32376 raise AttributeError('No unix_name set on %s' % self.name)
377 self._unix_name_used = True
378 return self._unix_name
379
380 def SetUnixName(self, unix_name):
381 """Set the property's unix_name. Raises AttributeError if the unix_name has
382 already been used (GetUnixName has been called).
383 """
384 if unix_name == self._unix_name:
385 return
386 if self._unix_name_used:
387 raise AttributeError(
388 'Cannot set the unix_name on %s; '
389 'it is already used elsewhere as %s' %
390 (self.name, self._unix_name))
391 self._unix_name = unix_name
392
393 unix_name = property(GetUnixName, SetUnixName)
[email protected]15f08dd2012-01-27 07:29:48394
[email protected]7f138d42013-11-01 05:27:27395class EnumValue(object):
396 """A single value from an enum.
397 Properties:
398 - |name| name of the property as in the json.
399 - |description| a description of the property (if provided)
400 """
401 def __init__(self, json):
402 if isinstance(json, dict):
403 self.name = json['name']
404 self.description = json.get('description')
405 else:
406 self.name = json
407 self.description = None
408
[email protected]4636c832013-01-11 02:10:11409class _Enum(object):
410 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
411 Enums need to do this so that equality/non-equality work over pickling.
[email protected]fe027682012-08-21 01:51:34412 """
[email protected]4636c832013-01-11 02:10:11413 @staticmethod
414 def GetAll(cls):
415 """Yields all _Enum objects declared in |cls|.
416 """
417 for prop_key in dir(cls):
418 prop_value = getattr(cls, prop_key)
419 if isinstance(prop_value, _Enum):
420 yield prop_value
421
422 def __init__(self, name):
[email protected]fe027682012-08-21 01:51:34423 self.name = name
424
[email protected]dc5f2fecf2012-08-31 01:55:51425 def __eq__(self, other):
[email protected]4636c832013-01-11 02:10:11426 return type(other) == type(self) and other.name == self.name
[email protected]e15dccb2012-10-05 06:02:25427 def __ne__(self, other):
[email protected]e15dccb2012-10-05 06:02:25428 return not (self == other)
429
[email protected]e11b9aa2013-07-13 00:05:42430 def __repr__(self):
431 return self.name
432
433 def __str__(self):
434 return repr(self)
435
[email protected]0853bcf2013-11-06 05:14:33436
[email protected]4636c832013-01-11 02:10:11437class _PropertyTypeInfo(_Enum):
438 def __init__(self, is_fundamental, name):
439 _Enum.__init__(self, name)
440 self.is_fundamental = is_fundamental
441
[email protected]0853bcf2013-11-06 05:14:33442
[email protected]15f08dd2012-01-27 07:29:48443class PropertyType(object):
444 """Enum of different types of properties/parameters.
445 """
[email protected]242d5e7a2013-01-17 06:50:31446 ANY = _PropertyTypeInfo(False, "any")
[email protected]e11b9aa2013-07-13 00:05:42447 ARRAY = _PropertyTypeInfo(False, "array")
448 BINARY = _PropertyTypeInfo(False, "binary")
449 BOOLEAN = _PropertyTypeInfo(True, "boolean")
450 CHOICES = _PropertyTypeInfo(False, "choices")
451 DOUBLE = _PropertyTypeInfo(True, "double")
452 ENUM = _PropertyTypeInfo(False, "enum")
453 FUNCTION = _PropertyTypeInfo(False, "function")
454 INT64 = _PropertyTypeInfo(True, "int64")
455 INTEGER = _PropertyTypeInfo(True, "integer")
456 OBJECT = _PropertyTypeInfo(False, "object")
457 REF = _PropertyTypeInfo(False, "ref")
458 STRING = _PropertyTypeInfo(True, "string")
[email protected]cfe484902012-02-15 14:52:32459
[email protected]0853bcf2013-11-06 05:14:33460
[email protected]cb5670c2013-04-10 06:31:08461@memoize
[email protected]4ba6bdc2012-06-18 20:40:14462def UnixName(name):
[email protected]cb5670c2013-04-10 06:31:08463 '''Returns the unix_style name for a given lowerCamelCase string.
464 '''
465 unix_name = []
466 for i, c in enumerate(name):
[email protected]e11b9aa2013-07-13 00:05:42467 if c.isupper() and i > 0 and name[i - 1] != '_':
[email protected]cb5670c2013-04-10 06:31:08468 # Replace lowerUpper with lower_Upper.
469 if name[i - 1].islower():
470 unix_name.append('_')
471 # Replace ACMEWidgets with ACME_Widgets
472 elif i + 1 < len(name) and name[i + 1].islower():
473 unix_name.append('_')
474 if c == '.':
475 # Replace hello.world with hello_world.
476 unix_name.append('_')
477 else:
478 # Everything is lowercase.
479 unix_name.append(c.lower())
480 return ''.join(unix_name)
[email protected]cfe484902012-02-15 14:52:32481
[email protected]0853bcf2013-11-06 05:14:33482
[email protected]0b255f002012-10-05 01:58:47483def _StripNamespace(name, namespace):
484 if name.startswith(namespace.name + '.'):
485 return name[len(namespace.name + '.'):]
486 return name
487
[email protected]0853bcf2013-11-06 05:14:33488
[email protected]116f0a3a2012-04-19 04:22:38489def _GetModelHierarchy(entity):
[email protected]feba21e2012-03-02 15:05:27490 """Returns the hierarchy of the given model entity."""
491 hierarchy = []
[email protected]242d5e7a2013-01-17 06:50:31492 while entity is not None:
493 hierarchy.append(getattr(entity, 'name', repr(entity)))
494 if isinstance(entity, Namespace):
495 hierarchy.insert(0, ' in %s' % entity.source_file)
496 entity = getattr(entity, 'parent', None)
[email protected]feba21e2012-03-02 15:05:27497 hierarchy.reverse()
498 return hierarchy
[email protected]116f0a3a2012-04-19 04:22:38499
[email protected]0853bcf2013-11-06 05:14:33500
[email protected]242d5e7a2013-01-17 06:50:31501def _GetTypes(parent, json, namespace, origin):
502 """Creates Type objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38503 """
[email protected]242d5e7a2013-01-17 06:50:31504 types = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38505 for type_json in json.get('types', []):
[email protected]242d5e7a2013-01-17 06:50:31506 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
507 types[type_.name] = type_
508 return types
[email protected]116f0a3a2012-04-19 04:22:38509
[email protected]0853bcf2013-11-06 05:14:33510
[email protected]242d5e7a2013-01-17 06:50:31511def _GetFunctions(parent, json, namespace):
512 """Creates Function objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38513 """
[email protected]242d5e7a2013-01-17 06:50:31514 functions = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38515 for function_json in json.get('functions', []):
[email protected]242d5e7a2013-01-17 06:50:31516 function = Function(parent,
517 function_json['name'],
518 function_json,
519 namespace,
520 Origin(from_json=True))
521 functions[function.name] = function
522 return functions
[email protected]116f0a3a2012-04-19 04:22:38523
[email protected]0853bcf2013-11-06 05:14:33524
[email protected]242d5e7a2013-01-17 06:50:31525def _GetEvents(parent, json, namespace):
526 """Creates Function objects generated from the events in |json|.
[email protected]b741e8f2012-07-16 21:47:24527 """
[email protected]242d5e7a2013-01-17 06:50:31528 events = OrderedDict()
[email protected]b741e8f2012-07-16 21:47:24529 for event_json in json.get('events', []):
[email protected]242d5e7a2013-01-17 06:50:31530 event = Function(parent,
531 event_json['name'],
532 event_json,
533 namespace,
534 Origin(from_client=True))
535 events[event.name] = event
536 return events
[email protected]b741e8f2012-07-16 21:47:24537
[email protected]0853bcf2013-11-06 05:14:33538
[email protected]242d5e7a2013-01-17 06:50:31539def _GetProperties(parent, json, namespace, origin):
540 """Generates Property objects extracted from |json|.
[email protected]116f0a3a2012-04-19 04:22:38541 """
[email protected]242d5e7a2013-01-17 06:50:31542 properties = OrderedDict()
[email protected]116f0a3a2012-04-19 04:22:38543 for name, property_json in json.get('properties', {}).items():
[email protected]627b54d2013-02-04 23:53:59544 properties[name] = Property(parent, name, property_json, namespace, origin)
[email protected]242d5e7a2013-01-17 06:50:31545 return properties
[email protected]4636c832013-01-11 02:10:11546
[email protected]0853bcf2013-11-06 05:14:33547
[email protected]4636c832013-01-11 02:10:11548class _PlatformInfo(_Enum):
549 def __init__(self, name):
550 _Enum.__init__(self, name)
551
[email protected]0853bcf2013-11-06 05:14:33552
[email protected]4636c832013-01-11 02:10:11553class Platforms(object):
554 """Enum of the possible platforms.
555 """
556 CHROMEOS = _PlatformInfo("chromeos")
557 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
558 LINUX = _PlatformInfo("linux")
559 MAC = _PlatformInfo("mac")
560 WIN = _PlatformInfo("win")
561
[email protected]0853bcf2013-11-06 05:14:33562
[email protected]4636c832013-01-11 02:10:11563def _GetPlatforms(json):
[email protected]e0eec63f2013-10-30 05:28:58564 if 'platforms' not in json or json['platforms'] == None:
[email protected]4636c832013-01-11 02:10:11565 return None
[email protected]e0eec63f2013-10-30 05:28:58566 # Sanity check: platforms should not be an empty list.
567 if not json['platforms']:
568 raise ValueError('"platforms" cannot be an empty list')
[email protected]4636c832013-01-11 02:10:11569 platforms = []
570 for platform_name in json['platforms']:
571 for platform_enum in _Enum.GetAll(Platforms):
572 if platform_name == platform_enum.name:
573 platforms.append(platform_enum)
574 break
575 return platforms