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

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