Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: tools/json_schema_compiler/model.py

Issue 11827026: Overhaul JSON Schema Compiler to support a number of features required to (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: yoz Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import copy 5 import copy
6 import os.path 6 import os.path
7 import re 7 import re
8 8
9 from json_parse import OrderedDict 9 from json_parse import OrderedDict
10 10
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 - |functions| a map of function names to their model.Function 46 - |functions| a map of function names to their model.Function
47 - |events| a map of event names to their model.Function 47 - |events| a map of event names to their model.Function
48 - |properties| a map of property names to their model.Property 48 - |properties| a map of property names to their model.Property
49 """ 49 """
50 def __init__(self, json, source_file): 50 def __init__(self, json, source_file):
51 self.name = json['namespace'] 51 self.name = json['namespace']
52 self.unix_name = UnixName(self.name) 52 self.unix_name = UnixName(self.name)
53 self.source_file = source_file 53 self.source_file = source_file
54 self.source_file_dir, self.source_file_filename = os.path.split(source_file) 54 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
55 self.parent = None 55 self.parent = None
56 _AddTypes(self, json, self) 56 toplevel_origin = Origin(from_client=True, from_json=True)
57 _AddFunctions(self, json, self) 57 self.types = _GetTypes(self, json, self, toplevel_origin)
58 _AddEvents(self, json, self) 58 self.functions = _GetFunctions(self, json, self)
59 _AddProperties(self, json, self) 59 self.events = _GetEvents(self, json, self)
60 self.properties = _GetProperties(self, json, self, toplevel_origin)
61
62 class Origin(object):
63 """Stores the possible origin of model object as a pair of bools. These are:
64
65 |from_client| indicating that instances can originate from users of
66 generated code (for example, function results), or
67 |from_json| indicating that instances can originate from the JSON (for
68 example, function parameters)
69
70 It is possible for model objects to originate from both the client and json,
71 for example Types defined in the top-level schema, in which case both
72 |from_client| and |from_json| would be True.
73 """
74 def __init__(self, from_client=False, from_json=False):
75 if not from_client and not from_json:
76 raise ValueError('One of from_client or from_json must be true')
77 self.from_client = from_client
78 self.from_json = from_json
60 79
61 class Type(object): 80 class Type(object):
62 """A Type defined in the json. 81 """A Type defined in the json.
63 82
64 Properties: 83 Properties:
65 - |name| the type name 84 - |name| the type name
85 - |namespace| the Type's namespace
66 - |description| the description of the type (if provided) 86 - |description| the description of the type (if provided)
67 - |properties| a map of property unix_names to their model.Property 87 - |properties| a map of property unix_names to their model.Property
68 - |functions| a map of function names to their model.Function 88 - |functions| a map of function names to their model.Function
69 - |events| a map of event names to their model.Event 89 - |events| a map of event names to their model.Event
70 - |from_client| indicates that instances of the Type can originate from the 90 - |origin| the Origin of the type
71 users of generated code, such as top-level types and function results 91 - |property_type| the PropertyType of this Type
72 - |from_json| indicates that instances of the Type can originate from the
73 JSON (as described by the schema), such as top-level types and function
74 parameters
75 - |type_| the PropertyType of this Type
76 - |item_type| if this is an array, the type of items in the array 92 - |item_type| if this is an array, the type of items in the array
77 - |simple_name| the name of this Type without a namespace 93 - |simple_name| the name of this Type without a namespace
94 - |additional_properties| the type of the additional properties, if any is
95 specified
78 """ 96 """
79 def __init__(self, parent, name, json, namespace): 97 def __init__(self,
80 if json.get('type') == 'array': 98 parent,
81 self.type_ = PropertyType.ARRAY 99 name,
82 self.item_type = Property(self, 100 json,
83 name + "Element", 101 namespace,
84 json['items'], 102 origin):
85 namespace, 103 self.name = name
86 from_json=True, 104 self.namespace = namespace
87 from_client=True) 105 self.simple_name = _StripNamespace(self.name, namespace)
88 elif 'enum' in json: 106 self.unix_name = UnixName(self.name)
89 self.enum_values = [] 107 self.description = json.get('description', None)
90 for value in json['enum']: 108 self.origin = origin
91 self.enum_values.append(value) 109 self.parent = parent
92 self.type_ = PropertyType.ENUM 110 self.instance_of = json.get('isInstanceOf', None)
93 elif json.get('type') == 'string': 111
94 self.type_ = PropertyType.STRING 112 # TODO(kalman): Only objects need functions/events/properties, but callers
95 else: 113 # assume that all types have them. Fix this.
114 self.functions = _GetFunctions(self, json, namespace)
115 self.events = _GetEvents(self, json, namespace)
116 self.properties = _GetProperties(self, json, namespace, origin)
117
118 json_type = json.get('type', None)
119 if json_type == 'array':
120 self.property_type = PropertyType.ARRAY
121 self.item_type = Type(
122 self, '%sType' % name, json['items'], namespace, origin)
123 elif '$ref' in json:
124 self.property_type = PropertyType.REF
125 self.ref_type = json['$ref']
126 elif 'enum' in json and json_type == 'string':
127 self.property_type = PropertyType.ENUM
128 self.enum_values = [value for value in json['enum']]
129 elif json_type == 'any':
130 self.property_type = PropertyType.ANY
131 elif json_type == 'binary':
132 self.property_type = PropertyType.BINARY
133 elif json_type == 'boolean':
134 self.property_type = PropertyType.BOOLEAN
135 elif json_type == 'integer':
136 self.property_type = PropertyType.INTEGER
137 elif (json_type == 'double' or
138 json_type == 'number'):
139 self.property_type = PropertyType.DOUBLE
140 elif json_type == 'string':
141 self.property_type = PropertyType.STRING
142 elif 'choices' in json:
143 self.property_type = PropertyType.CHOICES
144 self.choices = [Type(self,
145 # The name of the choice type - there had better be
146 # either a type or a $ref specified for the choice.
147 json.get('type', json.get('$ref')),
148 json,
149 namespace,
150 origin)
151 for json in json['choices']]
152 elif json_type == 'object':
96 if not ( 153 if not (
97 'properties' in json or 154 'properties' in json or
98 'additionalProperties' in json or 155 'additionalProperties' in json or
99 'functions' in json or 156 'functions' in json or
100 'events' in json): 157 'events' in json):
101 raise ParseException(self, name + " has no properties or functions") 158 raise ParseException(self, name + " has no properties or functions")
102 self.type_ = PropertyType.OBJECT 159 self.property_type = PropertyType.OBJECT
103 self.name = name 160 additional_properties_json = json.get('additionalProperties', None)
104 self.simple_name = _StripNamespace(self.name, namespace) 161 if additional_properties_json is not None:
105 self.unix_name = UnixName(self.name) 162 self.additional_properties = Type(self,
106 self.description = json.get('description') 163 'additionalProperties',
107 self.from_json = True 164 additional_properties_json,
108 self.from_client = True 165 namespace,
109 self.parent = parent 166 origin)
110 self.instance_of = json.get('isInstanceOf', None) 167 else:
111 _AddFunctions(self, json, namespace) 168 self.additional_properties = None
112 _AddEvents(self, json, namespace) 169 elif json_type == 'function':
113 _AddProperties(self, json, namespace, from_json=True, from_client=True) 170 self.property_type = PropertyType.FUNCTION
114 171 # Sometimes we might have an unnamed function, e.g. if it's a property
115 additional_properties_key = 'additionalProperties' 172 # of an object. Use the name of the property in that case.
116 additional_properties = json.get(additional_properties_key) 173 function_name = json.get('name', name)
117 if additional_properties: 174 self.function = Function(self, function_name, json, namespace, origin)
118 self.properties[additional_properties_key] = Property( 175 else:
119 self, 176 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
120 additional_properties_key,
121 additional_properties,
122 namespace,
123 is_additional_properties=True)
124 177
125 class Function(object): 178 class Function(object):
126 """A Function defined in the API. 179 """A Function defined in the API.
127 180
128 Properties: 181 Properties:
129 - |name| the function name 182 - |name| the function name
130 - |params| a list of parameters to the function (order matters). A separate 183 - |params| a list of parameters to the function (order matters). A separate
131 parameter is used for each choice of a 'choices' parameter. 184 parameter is used for each choice of a 'choices' parameter.
132 - |description| a description of the function (if provided) 185 - |description| a description of the function (if provided)
133 - |callback| the callback parameter to the function. There should be exactly 186 - |callback| the callback parameter to the function. There should be exactly
134 one 187 one
135 - |optional| whether the Function is "optional"; this only makes sense to be 188 - |optional| whether the Function is "optional"; this only makes sense to be
136 present when the Function is representing a callback property. 189 present when the Function is representing a callback property.
137 - |simple_name| the name of this Function without a namespace 190 - |simple_name| the name of this Function without a namespace
138 """ 191 """
139 def __init__(self, 192 def __init__(self,
140 parent, 193 parent,
194 name,
141 json, 195 json,
142 namespace, 196 namespace,
143 from_json=False, 197 origin):
144 from_client=False): 198 self.name = name
145 self.name = json['name']
146 self.simple_name = _StripNamespace(self.name, namespace) 199 self.simple_name = _StripNamespace(self.name, namespace)
147 self.params = [] 200 self.params = []
148 self.description = json.get('description') 201 self.description = json.get('description')
149 self.callback = None 202 self.callback = None
150 self.optional = json.get('optional', False) 203 self.optional = json.get('optional', False)
151 self.parent = parent 204 self.parent = parent
152 self.nocompile = json.get('nocompile') 205 self.nocompile = json.get('nocompile')
153 options = json.get('options', {}) 206 options = json.get('options', {})
154 self.conditions = options.get('conditions', []) 207 self.conditions = options.get('conditions', [])
155 self.actions = options.get('actions', []) 208 self.actions = options.get('actions', [])
156 self.supports_listeners = options.get('supportsListeners', True) 209 self.supports_listeners = options.get('supportsListeners', True)
157 self.supports_rules = options.get('supportsRules', False) 210 self.supports_rules = options.get('supportsRules', False)
211
158 def GeneratePropertyFromParam(p): 212 def GeneratePropertyFromParam(p):
159 return Property(self, 213 return Property.FromJSON(self, p['name'], p, namespace, origin)
160 p['name'], p,
161 namespace,
162 from_json=from_json,
163 from_client=from_client)
164 214
165 self.filters = [GeneratePropertyFromParam(filter) 215 self.filters = [GeneratePropertyFromParam(filter)
166 for filter in json.get('filters', [])] 216 for filter in json.get('filters', [])]
167 callback_param = None 217 callback_param = None
168 for param in json.get('parameters', []): 218 for param in json.get('parameters', []):
169
170 if param.get('type') == 'function': 219 if param.get('type') == 'function':
171 if callback_param: 220 if callback_param:
172 # No ParseException because the webstore has this. 221 # No ParseException because the webstore has this.
173 # Instead, pretend all intermediate callbacks are properties. 222 # Instead, pretend all intermediate callbacks are properties.
174 self.params.append(GeneratePropertyFromParam(callback_param)) 223 self.params.append(GeneratePropertyFromParam(callback_param))
175 callback_param = param 224 callback_param = param
176 else: 225 else:
177 self.params.append(GeneratePropertyFromParam(param)) 226 self.params.append(GeneratePropertyFromParam(param))
178 227
179 if callback_param: 228 if callback_param:
180 self.callback = Function(self, 229 self.callback = Function(self,
230 callback_param['name'],
181 callback_param, 231 callback_param,
182 namespace, 232 namespace,
183 from_client=True) 233 Origin(from_client=True))
184 234
185 self.returns = None 235 self.returns = None
186 if 'returns' in json: 236 if 'returns' in json:
187 self.returns = Property(self, 'return', json['returns'], namespace) 237 self.returns = Property.FromJSON(
238 self, 'return', json['returns'], namespace, origin)
188 239
189 class Property(object): 240 class Property(object):
190 """A property of a type OR a parameter to a function. 241 """A property of a type OR a parameter to a function.
191
192 Properties: 242 Properties:
193 - |name| name of the property as in the json. This shouldn't change since 243 - |name| name of the property as in the json. This shouldn't change since
194 it is the key used to access DictionaryValues 244 it is the key used to access DictionaryValues
195 - |unix_name| the unix_style_name of the property. Used as variable name 245 - |unix_name| the unix_style_name of the property. Used as variable name
196 - |optional| a boolean representing whether the property is optional 246 - |optional| a boolean representing whether the property is optional
197 - |description| a description of the property (if provided) 247 - |description| a description of the property (if provided)
198 - |type_| the model.PropertyType of this property 248 - |type_| the model.Type of this property
199 - |compiled_type| the model.PropertyType that this property should be
200 compiled to from the JSON. Defaults to |type_|.
201 - |ref_type| the type that the REF property is referencing. Can be used to
202 map to its model.Type
203 - |item_type| a model.Property representing the type of each element in an
204 ARRAY
205 - |properties| the properties of an OBJECT parameter
206 - |from_client| indicates that instances of the Type can originate from the
207 users of generated code, such as top-level types and function results
208 - |from_json| indicates that instances of the Type can originate from the
209 JSON (as described by the schema), such as top-level types and function
210 parameters
211 - |simple_name| the name of this Property without a namespace 249 - |simple_name| the name of this Property without a namespace
212 """ 250 """
213 251
252 @staticmethod
253 def FromJSON(parent, name, json, namespace, origin):
254 """Creates a Property from JSON.
255 """
256 opt_args = {}
257 if 'description' in json:
258 opt_args['description'] = json['description']
259 if 'optional' in json:
260 opt_args['optional'] = json.get('optional')
261 if 'isInstanceOf' in json:
262 opt_args['instance_of'] = json.get('isInstanceOf')
263
264 # HACK: only support very specific value types.
265 is_allowed_value = (
266 '$ref' not in json and
267 ('type' not in json or json['type'] == 'integer'
268 or json['type'] == 'string'))
269
270 if 'value' in json and is_allowed_value:
271 value = json['value']
272 opt_args['value'] = value
273 if 'type' not in json:
274 # Sometimes the type of the value is left out, and we need to figure
275 # it out for ourselves.
276 if isinstance(value, int):
277 json['type'] = 'integer'
278 elif isinstance(value, basestring):
279 json['type'] = 'string'
280 else:
281 # TODO(kalman): support more types as necessary.
282 raise ParseException(
283 parent, '"%s" is not a supported type for "value"' % type(value))
284
285 type_ = Type(parent, name, json, namespace, origin)
286 return Property(parent,
287 name,
288 namespace,
289 type_,
290 origin,
291 **opt_args);
292
214 def __init__(self, 293 def __init__(self,
215 parent, 294 parent,
216 name, 295 name,
217 json,
218 namespace, 296 namespace,
219 is_additional_properties=False, 297 type_,
220 from_json=False, 298 origin,
221 from_client=False): 299 description=None,
300 optional=False,
301 returns=None,
302 instance_of=None,
303 value=None):
304 """Directly initializes the fields of the Property.
305 """
222 self.name = name 306 self.name = name
223 self.simple_name = _StripNamespace(self.name, namespace) 307 self.simple_name = _StripNamespace(self.name, namespace)
224 self._unix_name = UnixName(self.name) 308 self._unix_name = UnixName(self.name)
225 self._unix_name_used = False 309 self._unix_name_used = False
226 self.optional = json.get('optional', False) 310 self.optional = optional
227 self.functions = OrderedDict() 311 self.description = description
228 self.has_value = False
229 self.description = json.get('description')
230 self.parent = parent 312 self.parent = parent
231 self.from_json = from_json 313 self.origin = origin
232 self.from_client = from_client 314 if not isinstance(type_, Type):
233 self.instance_of = json.get('isInstanceOf', None) 315 raise ValueError("not Type: %s" % type_)
234 self.params = [] 316 self.type_ = type_
235 self.returns = None 317 self.returns = returns
236 _AddProperties(self, json, namespace) 318 if instance_of is not None:
237 if is_additional_properties: 319 self.instance_of = instance_of
238 self.type_ = PropertyType.ADDITIONAL_PROPERTIES 320 self.value = value
239 elif '$ref' in json:
240 self.ref_type = json['$ref']
241 self.type_ = PropertyType.REF
242 elif 'enum' in json and json.get('type') == 'string':
243 # Non-string enums (as in the case of [legalValues=(1,2)]) should fall
244 # through to the next elif.
245 self.enum_values = []
246 for value in json['enum']:
247 self.enum_values.append(value)
248 self.type_ = PropertyType.ENUM
249 elif 'type' in json:
250 self.type_ = self._JsonTypeToPropertyType(json['type'])
251 if self.type_ == PropertyType.ARRAY:
252 self.item_type = Property(self,
253 name + "Element",
254 json['items'],
255 namespace,
256 from_json=from_json,
257 from_client=from_client)
258 elif self.type_ == PropertyType.OBJECT:
259 # These members are read when this OBJECT Property is used as a Type
260 type_ = Type(self, self.name, json, namespace)
261 # self.properties will already have some value from |_AddProperties|.
262 self.properties.update(type_.properties)
263 self.functions = type_.functions
264 elif self.type_ == PropertyType.FUNCTION:
265 for p in json.get('parameters', []):
266 self.params.append(Property(self,
267 p['name'],
268 p,
269 namespace,
270 from_json=from_json,
271 from_client=from_client))
272 if 'returns' in json:
273 self.returns = Property(self, 'return', json['returns'], namespace)
274 elif 'choices' in json:
275 if not json['choices'] or len(json['choices']) == 0:
276 raise ParseException(self, 'Choices has no choices')
277 self.choices = {}
278 self.type_ = PropertyType.CHOICES
279 self.compiled_type = self.type_
280 for choice_json in json['choices']:
281 choice = Property(self,
282 self.name,
283 choice_json,
284 namespace,
285 from_json=from_json,
286 from_client=from_client)
287 choice.unix_name = UnixName(self.name + choice.type_.name)
288 # The existence of any single choice is optional
289 choice.optional = True
290 self.choices[choice.type_] = choice
291 elif 'value' in json:
292 self.has_value = True
293 self.value = json['value']
294 if type(self.value) == int:
295 self.type_ = PropertyType.INTEGER
296 self.compiled_type = self.type_
297 else:
298 # TODO(kalman): support more types as necessary.
299 raise ParseException(
300 self, '"%s" is not a supported type' % type(self.value))
301 else:
302 raise ParseException(
303 self, 'Property has no type, $ref, choices, or value')
304 if 'compiled_type' in json:
305 if 'type' in json:
306 self.compiled_type = self._JsonTypeToPropertyType(json['compiled_type'])
307 else:
308 raise ParseException(self, 'Property has compiled_type but no type')
309 else:
310 self.compiled_type = self.type_
311
312 def _JsonTypeToPropertyType(self, json_type):
313 try:
314 return {
315 'any': PropertyType.ANY,
316 'array': PropertyType.ARRAY,
317 'binary': PropertyType.BINARY,
318 'boolean': PropertyType.BOOLEAN,
319 'integer': PropertyType.INTEGER,
320 'int64': PropertyType.INT64,
321 'function': PropertyType.FUNCTION,
322 'number': PropertyType.DOUBLE,
323 'object': PropertyType.OBJECT,
324 'string': PropertyType.STRING,
325 }[json_type]
326 except KeyError:
327 raise NotImplementedError('Type %s not recognized' % json_type)
328 321
329 def GetUnixName(self): 322 def GetUnixName(self):
330 """Gets the property's unix_name. Raises AttributeError if not set. 323 """Gets the property's unix_name. Raises AttributeError if not set.
331 """ 324 """
332 if not self._unix_name: 325 if not self._unix_name:
333 raise AttributeError('No unix_name set on %s' % self.name) 326 raise AttributeError('No unix_name set on %s' % self.name)
334 self._unix_name_used = True 327 self._unix_name_used = True
335 return self._unix_name 328 return self._unix_name
336 329
337 def SetUnixName(self, unix_name): 330 def SetUnixName(self, unix_name):
338 """Set the property's unix_name. Raises AttributeError if the unix_name has 331 """Set the property's unix_name. Raises AttributeError if the unix_name has
339 already been used (GetUnixName has been called). 332 already been used (GetUnixName has been called).
340 """ 333 """
341 if unix_name == self._unix_name: 334 if unix_name == self._unix_name:
342 return 335 return
343 if self._unix_name_used: 336 if self._unix_name_used:
344 raise AttributeError( 337 raise AttributeError(
345 'Cannot set the unix_name on %s; ' 338 'Cannot set the unix_name on %s; '
346 'it is already used elsewhere as %s' % 339 'it is already used elsewhere as %s' %
347 (self.name, self._unix_name)) 340 (self.name, self._unix_name))
348 self._unix_name = unix_name 341 self._unix_name = unix_name
349 342
350 def Copy(self):
351 """Makes a copy of this model.Property object and allow the unix_name to be
352 set again.
353 """
354 property_copy = copy.copy(self)
355 property_copy._unix_name_used = False
356 return property_copy
357
358 unix_name = property(GetUnixName, SetUnixName) 343 unix_name = property(GetUnixName, SetUnixName)
359 344
360 class _PropertyTypeInfo(object): 345 class _PropertyTypeInfo(object):
361 """This class is not an inner class of |PropertyType| so it can be pickled. 346 """This class is not an inner class of |PropertyType| so it can be pickled.
362 """ 347 """
363 def __init__(self, is_fundamental, name): 348 def __init__(self, is_fundamental, name):
364 self.is_fundamental = is_fundamental 349 self.is_fundamental = is_fundamental
365 self.name = name 350 self.name = name
366 351
367 def __repr__(self): 352 def __repr__(self):
368 return self.name 353 return self.name
369 354
370 def __eq__(self, other): 355 def __eq__(self, other):
371 return isinstance(other, _PropertyTypeInfo) and self.name == other.name 356 return isinstance(other, _PropertyTypeInfo) and self.name == other.name
372 357
373 def __ne__(self, other): 358 def __ne__(self, other):
374 # Yes. You seriously do need this. 359 # Yes. You seriously do need this.
375 return not (self == other) 360 return not (self == other)
376 361
377 class PropertyType(object): 362 class PropertyType(object):
378 """Enum of different types of properties/parameters. 363 """Enum of different types of properties/parameters.
379 """ 364 """
380 INTEGER = _PropertyTypeInfo(True, "INTEGER") 365 INTEGER = _PropertyTypeInfo(True, "integer")
381 INT64 = _PropertyTypeInfo(True, "INT64") 366 INT64 = _PropertyTypeInfo(True, "int64")
382 DOUBLE = _PropertyTypeInfo(True, "DOUBLE") 367 DOUBLE = _PropertyTypeInfo(True, "double")
383 BOOLEAN = _PropertyTypeInfo(True, "BOOLEAN") 368 BOOLEAN = _PropertyTypeInfo(True, "boolean")
384 STRING = _PropertyTypeInfo(True, "STRING") 369 STRING = _PropertyTypeInfo(True, "string")
385 ENUM = _PropertyTypeInfo(False, "ENUM") 370 ENUM = _PropertyTypeInfo(False, "enum")
386 ARRAY = _PropertyTypeInfo(False, "ARRAY") 371 ARRAY = _PropertyTypeInfo(False, "array")
387 REF = _PropertyTypeInfo(False, "REF") 372 REF = _PropertyTypeInfo(False, "ref")
388 CHOICES = _PropertyTypeInfo(False, "CHOICES") 373 CHOICES = _PropertyTypeInfo(False, "choices")
389 OBJECT = _PropertyTypeInfo(False, "OBJECT") 374 OBJECT = _PropertyTypeInfo(False, "object")
390 FUNCTION = _PropertyTypeInfo(False, "FUNCTION") 375 FUNCTION = _PropertyTypeInfo(False, "function")
391 BINARY = _PropertyTypeInfo(False, "BINARY") 376 BINARY = _PropertyTypeInfo(False, "binary")
392 ANY = _PropertyTypeInfo(False, "ANY") 377 ANY = _PropertyTypeInfo(False, "any")
393 ADDITIONAL_PROPERTIES = _PropertyTypeInfo(False, "ADDITIONAL_PROPERTIES")
394 378
395 def UnixName(name): 379 def UnixName(name):
396 """Returns the unix_style name for a given lowerCamelCase string. 380 """Returns the unix_style name for a given lowerCamelCase string.
397 """ 381 """
398 # First replace any lowerUpper patterns with lower_Upper. 382 # First replace any lowerUpper patterns with lower_Upper.
399 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) 383 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
400 # Now replace any ACMEWidgets patterns with ACME_Widgets 384 # Now replace any ACMEWidgets patterns with ACME_Widgets
401 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) 385 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
402 # Finally, replace any remaining periods, and make lowercase. 386 # Finally, replace any remaining periods, and make lowercase.
403 return s2.replace('.', '_').lower() 387 return s2.replace('.', '_').lower()
404 388
405 def _StripNamespace(name, namespace): 389 def _StripNamespace(name, namespace):
406 if name.startswith(namespace.name + '.'): 390 if name.startswith(namespace.name + '.'):
407 return name[len(namespace.name + '.'):] 391 return name[len(namespace.name + '.'):]
408 return name 392 return name
409 393
410 def _GetModelHierarchy(entity): 394 def _GetModelHierarchy(entity):
411 """Returns the hierarchy of the given model entity.""" 395 """Returns the hierarchy of the given model entity."""
412 hierarchy = [] 396 hierarchy = []
413 while entity: 397 while entity is not None:
414 try: 398 hierarchy.append(getattr(entity, 'name', repr(entity)))
415 hierarchy.append(entity.name) 399 if isinstance(entity, Namespace):
416 except AttributeError: 400 hierarchy.insert(0, ' in %s' % entity.source_file)
417 hierarchy.append(repr(entity)) 401 entity = getattr(entity, 'parent', None)
418 entity = entity.parent
419 hierarchy.reverse() 402 hierarchy.reverse()
420 return hierarchy 403 return hierarchy
421 404
422 def _AddTypes(model, json, namespace): 405 def _GetTypes(parent, json, namespace, origin):
423 """Adds Type objects to |model| contained in the 'types' field of |json|. 406 """Creates Type objects extracted from |json|.
424 """ 407 """
425 model.types = OrderedDict() 408 types = OrderedDict()
426 for type_json in json.get('types', []): 409 for type_json in json.get('types', []):
427 type_ = Type(model, type_json['id'], type_json, namespace) 410 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
428 model.types[type_.name] = type_ 411 types[type_.name] = type_
412 return types
429 413
430 def _AddFunctions(model, json, namespace): 414 def _GetFunctions(parent, json, namespace):
431 """Adds Function objects to |model| contained in the 'functions' field of 415 """Creates Function objects extracted from |json|.
432 |json|.
433 """ 416 """
434 model.functions = OrderedDict() 417 functions = OrderedDict()
435 for function_json in json.get('functions', []): 418 for function_json in json.get('functions', []):
436 function = Function(model, function_json, namespace, from_json=True) 419 function = Function(parent,
437 model.functions[function.name] = function 420 function_json['name'],
421 function_json,
422 namespace,
423 Origin(from_json=True))
424 functions[function.name] = function
425 return functions
438 426
439 def _AddEvents(model, json, namespace): 427 def _GetEvents(parent, json, namespace):
440 """Adds Function objects to |model| contained in the 'events' field of |json|. 428 """Creates Function objects generated from the events in |json|.
441 """ 429 """
442 model.events = OrderedDict() 430 events = OrderedDict()
443 for event_json in json.get('events', []): 431 for event_json in json.get('events', []):
444 event = Function(model, event_json, namespace, from_client=True) 432 event = Function(parent,
445 model.events[event.name] = event 433 event_json['name'],
434 event_json,
435 namespace,
436 Origin(from_client=True))
437 events[event.name] = event
438 return events
446 439
447 def _AddProperties(model, 440 def _GetProperties(parent, json, namespace, origin):
448 json, 441 """Generates Property objects extracted from |json|.
449 namespace,
450 from_json=False,
451 from_client=False):
452 """Adds model.Property objects to |model| contained in the 'properties' field
453 of |json|.
454 """ 442 """
455 model.properties = OrderedDict() 443 properties = OrderedDict()
456 for name, property_json in json.get('properties', {}).items(): 444 for name, property_json in json.get('properties', {}).items():
457 model.properties[name] = Property( 445 properties[name] = Property.FromJSON(
458 model, 446 parent, name, property_json, namespace, origin)
459 name, 447 return properties
460 property_json,
461 namespace,
462 from_json=from_json,
463 from_client=from_client)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698