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

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: rebase 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
« no previous file with comments | « tools/json_schema_compiler/json_schema.py ('k') | tools/json_schema_compiler/model_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 - |compiler_options| the compiler_options dict, only present if 53 - |compiler_options| the compiler_options dict, only present if
54 |include_compiler_options| is True 54 |include_compiler_options| is True
55 """ 55 """
56 def __init__(self, json, source_file, include_compiler_options=False): 56 def __init__(self, json, source_file, include_compiler_options=False):
57 self.name = json['namespace'] 57 self.name = json['namespace']
58 self.unix_name = UnixName(self.name) 58 self.unix_name = UnixName(self.name)
59 self.source_file = source_file 59 self.source_file = source_file
60 self.source_file_dir, self.source_file_filename = os.path.split(source_file) 60 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
61 self.parent = None 61 self.parent = None
62 self.platforms = _GetPlatforms(json) 62 self.platforms = _GetPlatforms(json)
63 _AddTypes(self, json, self) 63 toplevel_origin = Origin(from_client=True, from_json=True)
64 _AddFunctions(self, json, self) 64 self.types = _GetTypes(self, json, self, toplevel_origin)
65 _AddEvents(self, json, self) 65 self.functions = _GetFunctions(self, json, self)
66 _AddProperties(self, json, self) 66 self.events = _GetEvents(self, json, self)
67 self.properties = _GetProperties(self, json, self, toplevel_origin)
67 if include_compiler_options: 68 if include_compiler_options:
68 self.compiler_options = json.get('compiler_options', {}) 69 self.compiler_options = json.get('compiler_options', {})
69 70
71 class 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
70 class Type(object): 89 class Type(object):
71 """A Type defined in the json. 90 """A Type defined in the json.
72 91
73 Properties: 92 Properties:
74 - |name| the type name 93 - |name| the type name
94 - |namespace| the Type's namespace
75 - |description| the description of the type (if provided) 95 - |description| the description of the type (if provided)
76 - |properties| a map of property unix_names to their model.Property 96 - |properties| a map of property unix_names to their model.Property
77 - |functions| a map of function names to their model.Function 97 - |functions| a map of function names to their model.Function
78 - |events| a map of event names to their model.Event 98 - |events| a map of event names to their model.Event
79 - |from_client| indicates that instances of the Type can originate from the 99 - |origin| the Origin of the type
80 users of generated code, such as top-level types and function results 100 - |property_type| the PropertyType of this Type
81 - |from_json| indicates that instances of the Type can originate from the
82 JSON (as described by the schema), such as top-level types and function
83 parameters
84 - |type_| the PropertyType of this Type
85 - |item_type| if this is an array, the type of items in the array 101 - |item_type| if this is an array, the type of items in the array
86 - |simple_name| the name of this Type without a namespace 102 - |simple_name| the name of this Type without a namespace
103 - |additional_properties| the type of the additional properties, if any is
104 specified
87 """ 105 """
88 def __init__(self, parent, name, json, namespace): 106 def __init__(self,
89 if json.get('type') == 'array': 107 parent,
90 self.type_ = PropertyType.ARRAY 108 name,
91 self.item_type = Property(self, 109 json,
92 name + "Element", 110 namespace,
93 json['items'], 111 origin):
94 namespace, 112 self.name = name
95 from_json=True, 113 self.namespace = namespace
96 from_client=True) 114 self.simple_name = _StripNamespace(self.name, namespace)
97 elif 'enum' in json: 115 self.unix_name = UnixName(self.name)
98 self.enum_values = [] 116 self.description = json.get('description', None)
99 for value in json['enum']: 117 self.origin = origin
100 self.enum_values.append(value) 118 self.parent = parent
101 self.type_ = PropertyType.ENUM 119 self.instance_of = json.get('isInstanceOf', None)
102 elif json.get('type') == 'string': 120
103 self.type_ = PropertyType.STRING 121 # TODO(kalman): Only objects need functions/events/properties, but callers
104 else: 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':
105 if not ( 162 if not (
106 'properties' in json or 163 'properties' in json or
107 'additionalProperties' in json or 164 'additionalProperties' in json or
108 'functions' in json or 165 'functions' in json or
109 'events' in json): 166 'events' in json):
110 raise ParseException(self, name + " has no properties or functions") 167 raise ParseException(self, name + " has no properties or functions")
111 self.type_ = PropertyType.OBJECT 168 self.property_type = PropertyType.OBJECT
112 self.name = name 169 additional_properties_json = json.get('additionalProperties', None)
113 self.simple_name = _StripNamespace(self.name, namespace) 170 if additional_properties_json is not None:
114 self.unix_name = UnixName(self.name) 171 self.additional_properties = Type(self,
115 self.description = json.get('description') 172 'additionalProperties',
116 self.from_json = True 173 additional_properties_json,
117 self.from_client = True 174 namespace,
118 self.parent = parent 175 origin)
119 self.instance_of = json.get('isInstanceOf', None) 176 else:
120 _AddFunctions(self, json, namespace) 177 self.additional_properties = None
121 _AddEvents(self, json, namespace) 178 elif json_type == 'function':
122 _AddProperties(self, json, namespace, from_json=True, from_client=True) 179 self.property_type = PropertyType.FUNCTION
123 180 # Sometimes we might have an unnamed function, e.g. if it's a property
124 additional_properties_key = 'additionalProperties' 181 # of an object. Use the name of the property in that case.
125 additional_properties = json.get(additional_properties_key) 182 function_name = json.get('name', name)
126 if additional_properties: 183 self.function = Function(self, function_name, json, namespace, origin)
127 self.properties[additional_properties_key] = Property( 184 else:
128 self, 185 raise ParseException(self, 'Unsupported JSON type %s' % json_type)
129 additional_properties_key,
130 additional_properties,
131 namespace,
132 is_additional_properties=True)
133 186
134 class Function(object): 187 class Function(object):
135 """A Function defined in the API. 188 """A Function defined in the API.
136 189
137 Properties: 190 Properties:
138 - |name| the function name 191 - |name| the function name
139 - |platforms| if not None, the list of platforms that the function is 192 - |platforms| if not None, the list of platforms that the function is
140 available to 193 available to
141 - |params| a list of parameters to the function (order matters). A separate 194 - |params| a list of parameters to the function (order matters). A separate
142 parameter is used for each choice of a 'choices' parameter 195 parameter is used for each choice of a 'choices' parameter
143 - |description| a description of the function (if provided) 196 - |description| a description of the function (if provided)
144 - |callback| the callback parameter to the function. There should be exactly 197 - |callback| the callback parameter to the function. There should be exactly
145 one 198 one
146 - |optional| whether the Function is "optional"; this only makes sense to be 199 - |optional| whether the Function is "optional"; this only makes sense to be
147 present when the Function is representing a callback property 200 present when the Function is representing a callback property
148 - |simple_name| the name of this Function without a namespace 201 - |simple_name| the name of this Function without a namespace
149 """ 202 """
150 def __init__(self, 203 def __init__(self,
151 parent, 204 parent,
205 name,
152 json, 206 json,
153 namespace, 207 namespace,
154 from_json=False, 208 origin):
155 from_client=False): 209 self.name = name
156 self.name = json['name']
157 self.simple_name = _StripNamespace(self.name, namespace) 210 self.simple_name = _StripNamespace(self.name, namespace)
158 self.platforms = _GetPlatforms(json) 211 self.platforms = _GetPlatforms(json)
159 self.params = [] 212 self.params = []
160 self.description = json.get('description') 213 self.description = json.get('description')
161 self.callback = None 214 self.callback = None
162 self.optional = json.get('optional', False) 215 self.optional = json.get('optional', False)
163 self.parent = parent 216 self.parent = parent
164 self.nocompile = json.get('nocompile') 217 self.nocompile = json.get('nocompile')
165 options = json.get('options', {}) 218 options = json.get('options', {})
166 self.conditions = options.get('conditions', []) 219 self.conditions = options.get('conditions', [])
167 self.actions = options.get('actions', []) 220 self.actions = options.get('actions', [])
168 self.supports_listeners = options.get('supportsListeners', True) 221 self.supports_listeners = options.get('supportsListeners', True)
169 self.supports_rules = options.get('supportsRules', False) 222 self.supports_rules = options.get('supportsRules', False)
223
170 def GeneratePropertyFromParam(p): 224 def GeneratePropertyFromParam(p):
171 return Property(self, 225 return Property.FromJSON(self, p['name'], p, namespace, origin)
172 p['name'], p,
173 namespace,
174 from_json=from_json,
175 from_client=from_client)
176 226
177 self.filters = [GeneratePropertyFromParam(filter) 227 self.filters = [GeneratePropertyFromParam(filter)
178 for filter in json.get('filters', [])] 228 for filter in json.get('filters', [])]
179 callback_param = None 229 callback_param = None
180 for param in json.get('parameters', []): 230 for param in json.get('parameters', []):
181
182 if param.get('type') == 'function': 231 if param.get('type') == 'function':
183 if callback_param: 232 if callback_param:
184 # No ParseException because the webstore has this. 233 # No ParseException because the webstore has this.
185 # Instead, pretend all intermediate callbacks are properties. 234 # Instead, pretend all intermediate callbacks are properties.
186 self.params.append(GeneratePropertyFromParam(callback_param)) 235 self.params.append(GeneratePropertyFromParam(callback_param))
187 callback_param = param 236 callback_param = param
188 else: 237 else:
189 self.params.append(GeneratePropertyFromParam(param)) 238 self.params.append(GeneratePropertyFromParam(param))
190 239
191 if callback_param: 240 if callback_param:
192 self.callback = Function(self, 241 self.callback = Function(self,
242 callback_param['name'],
193 callback_param, 243 callback_param,
194 namespace, 244 namespace,
195 from_client=True) 245 Origin(from_client=True))
196 246
197 self.returns = None 247 self.returns = None
198 if 'returns' in json: 248 if 'returns' in json:
199 self.returns = Property(self, 'return', json['returns'], namespace) 249 self.returns = Property.FromJSON(
250 self, 'return', json['returns'], namespace, origin)
200 251
201 class Property(object): 252 class Property(object):
202 """A property of a type OR a parameter to a function. 253 """A property of a type OR a parameter to a function.
203
204 Properties: 254 Properties:
205 - |name| name of the property as in the json. This shouldn't change since 255 - |name| name of the property as in the json. This shouldn't change since
206 it is the key used to access DictionaryValues 256 it is the key used to access DictionaryValues
207 - |unix_name| the unix_style_name of the property. Used as variable name 257 - |unix_name| the unix_style_name of the property. Used as variable name
208 - |optional| a boolean representing whether the property is optional 258 - |optional| a boolean representing whether the property is optional
209 - |description| a description of the property (if provided) 259 - |description| a description of the property (if provided)
210 - |type_| the model.PropertyType of this property 260 - |type_| the model.Type of this property
211 - |compiled_type| the model.PropertyType that this property should be
212 compiled to from the JSON. Defaults to |type_|.
213 - |ref_type| the type that the REF property is referencing. Can be used to
214 map to its model.Type
215 - |item_type| a model.Property representing the type of each element in an
216 ARRAY
217 - |properties| the properties of an OBJECT parameter
218 - |from_client| indicates that instances of the Type can originate from the
219 users of generated code, such as top-level types and function results
220 - |from_json| indicates that instances of the Type can originate from the
221 JSON (as described by the schema), such as top-level types and function
222 parameters
223 - |simple_name| the name of this Property without a namespace 261 - |simple_name| the name of this Property without a namespace
224 """ 262 """
225 263
264 @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
226 def __init__(self, 305 def __init__(self,
227 parent, 306 parent,
228 name, 307 name,
229 json,
230 namespace, 308 namespace,
231 is_additional_properties=False, 309 type_,
232 from_json=False, 310 origin,
233 from_client=False): 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 """
234 self.name = name 318 self.name = name
235 self.simple_name = _StripNamespace(self.name, namespace) 319 self.simple_name = _StripNamespace(self.name, namespace)
236 self._unix_name = UnixName(self.name) 320 self._unix_name = UnixName(self.name)
237 self._unix_name_used = False 321 self._unix_name_used = False
238 self.optional = json.get('optional', False) 322 self.optional = optional
239 self.functions = OrderedDict() 323 self.description = description
240 self.has_value = False
241 self.description = json.get('description')
242 self.parent = parent 324 self.parent = parent
243 self.from_json = from_json 325 self.origin = origin
244 self.from_client = from_client 326 if not isinstance(type_, Type):
245 self.instance_of = json.get('isInstanceOf', None) 327 raise ValueError("not Type: %s" % type_)
246 self.params = [] 328 self.type_ = type_
247 self.returns = None 329 self.returns = returns
248 _AddProperties(self, json, namespace) 330 if instance_of is not None:
249 if is_additional_properties: 331 self.instance_of = instance_of
250 self.type_ = PropertyType.ADDITIONAL_PROPERTIES 332 self.value = value
251 elif '$ref' in json:
252 self.ref_type = json['$ref']
253 self.type_ = PropertyType.REF
254 elif 'enum' in json and json.get('type') == 'string':
255 # Non-string enums (as in the case of [legalValues=(1,2)]) should fall
256 # through to the next elif.
257 self.enum_values = []
258 for value in json['enum']:
259 self.enum_values.append(value)
260 self.type_ = PropertyType.ENUM
261 elif 'type' in json:
262 self.type_ = self._JsonTypeToPropertyType(json['type'])
263 if self.type_ == PropertyType.ARRAY:
264 self.item_type = Property(self,
265 name + "Element",
266 json['items'],
267 namespace,
268 from_json=from_json,
269 from_client=from_client)
270 elif self.type_ == PropertyType.OBJECT:
271 # These members are read when this OBJECT Property is used as a Type
272 type_ = Type(self, self.name, json, namespace)
273 # self.properties will already have some value from |_AddProperties|.
274 self.properties.update(type_.properties)
275 self.functions = type_.functions
276 elif self.type_ == PropertyType.FUNCTION:
277 for p in json.get('parameters', []):
278 self.params.append(Property(self,
279 p['name'],
280 p,
281 namespace,
282 from_json=from_json,
283 from_client=from_client))
284 if 'returns' in json:
285 self.returns = Property(self, 'return', json['returns'], namespace)
286 elif 'choices' in json:
287 if not json['choices'] or len(json['choices']) == 0:
288 raise ParseException(self, 'Choices has no choices')
289 self.choices = {}
290 self.type_ = PropertyType.CHOICES
291 self.compiled_type = self.type_
292 for choice_json in json['choices']:
293 choice = Property(self,
294 self.name,
295 choice_json,
296 namespace,
297 from_json=from_json,
298 from_client=from_client)
299 choice.unix_name = UnixName(self.name + choice.type_.name)
300 # The existence of any single choice is optional
301 choice.optional = True
302 self.choices[choice.type_] = choice
303 elif 'value' in json:
304 self.has_value = True
305 self.value = json['value']
306 if type(self.value) == int:
307 self.type_ = PropertyType.INTEGER
308 self.compiled_type = self.type_
309 else:
310 # TODO(kalman): support more types as necessary.
311 raise ParseException(
312 self, '"%s" is not a supported type' % type(self.value))
313 else:
314 raise ParseException(
315 self, 'Property has no type, $ref, choices, or value')
316 if 'compiled_type' in json:
317 if 'type' in json:
318 self.compiled_type = self._JsonTypeToPropertyType(json['compiled_type'])
319 else:
320 raise ParseException(self, 'Property has compiled_type but no type')
321 else:
322 self.compiled_type = self.type_
323
324 def _JsonTypeToPropertyType(self, json_type):
325 try:
326 return {
327 'any': PropertyType.ANY,
328 'array': PropertyType.ARRAY,
329 'binary': PropertyType.BINARY,
330 'boolean': PropertyType.BOOLEAN,
331 'integer': PropertyType.INTEGER,
332 'int64': PropertyType.INT64,
333 'function': PropertyType.FUNCTION,
334 'number': PropertyType.DOUBLE,
335 'object': PropertyType.OBJECT,
336 'string': PropertyType.STRING,
337 }[json_type]
338 except KeyError:
339 raise NotImplementedError('Type %s not recognized' % json_type)
340 333
341 def GetUnixName(self): 334 def GetUnixName(self):
342 """Gets the property's unix_name. Raises AttributeError if not set. 335 """Gets the property's unix_name. Raises AttributeError if not set.
343 """ 336 """
344 if not self._unix_name: 337 if not self._unix_name:
345 raise AttributeError('No unix_name set on %s' % self.name) 338 raise AttributeError('No unix_name set on %s' % self.name)
346 self._unix_name_used = True 339 self._unix_name_used = True
347 return self._unix_name 340 return self._unix_name
348 341
349 def SetUnixName(self, unix_name): 342 def SetUnixName(self, unix_name):
350 """Set the property's unix_name. Raises AttributeError if the unix_name has 343 """Set the property's unix_name. Raises AttributeError if the unix_name has
351 already been used (GetUnixName has been called). 344 already been used (GetUnixName has been called).
352 """ 345 """
353 if unix_name == self._unix_name: 346 if unix_name == self._unix_name:
354 return 347 return
355 if self._unix_name_used: 348 if self._unix_name_used:
356 raise AttributeError( 349 raise AttributeError(
357 'Cannot set the unix_name on %s; ' 350 'Cannot set the unix_name on %s; '
358 'it is already used elsewhere as %s' % 351 'it is already used elsewhere as %s' %
359 (self.name, self._unix_name)) 352 (self.name, self._unix_name))
360 self._unix_name = unix_name 353 self._unix_name = unix_name
361 354
362 def Copy(self):
363 """Makes a copy of this model.Property object and allow the unix_name to be
364 set again.
365 """
366 property_copy = copy.copy(self)
367 property_copy._unix_name_used = False
368 return property_copy
369
370 unix_name = property(GetUnixName, SetUnixName) 355 unix_name = property(GetUnixName, SetUnixName)
371 356
372 class _Enum(object): 357 class _Enum(object):
373 """Superclass for enum types with a "name" field, setting up repr/eq/ne. 358 """Superclass for enum types with a "name" field, setting up repr/eq/ne.
374 Enums need to do this so that equality/non-equality work over pickling. 359 Enums need to do this so that equality/non-equality work over pickling.
375 """ 360 """
376 361
377 @staticmethod 362 @staticmethod
378 def GetAll(cls): 363 def GetAll(cls):
379 """Yields all _Enum objects declared in |cls|. 364 """Yields all _Enum objects declared in |cls|.
(...skipping 16 matching lines...) Expand all
396 return not (self == other) 381 return not (self == other)
397 382
398 class _PropertyTypeInfo(_Enum): 383 class _PropertyTypeInfo(_Enum):
399 def __init__(self, is_fundamental, name): 384 def __init__(self, is_fundamental, name):
400 _Enum.__init__(self, name) 385 _Enum.__init__(self, name)
401 self.is_fundamental = is_fundamental 386 self.is_fundamental = is_fundamental
402 387
403 class PropertyType(object): 388 class PropertyType(object):
404 """Enum of different types of properties/parameters. 389 """Enum of different types of properties/parameters.
405 """ 390 """
406 INTEGER = _PropertyTypeInfo(True, "INTEGER") 391 INTEGER = _PropertyTypeInfo(True, "integer")
407 INT64 = _PropertyTypeInfo(True, "INT64") 392 INT64 = _PropertyTypeInfo(True, "int64")
408 DOUBLE = _PropertyTypeInfo(True, "DOUBLE") 393 DOUBLE = _PropertyTypeInfo(True, "double")
409 BOOLEAN = _PropertyTypeInfo(True, "BOOLEAN") 394 BOOLEAN = _PropertyTypeInfo(True, "boolean")
410 STRING = _PropertyTypeInfo(True, "STRING") 395 STRING = _PropertyTypeInfo(True, "string")
411 ENUM = _PropertyTypeInfo(False, "ENUM") 396 ENUM = _PropertyTypeInfo(False, "enum")
412 ARRAY = _PropertyTypeInfo(False, "ARRAY") 397 ARRAY = _PropertyTypeInfo(False, "array")
413 REF = _PropertyTypeInfo(False, "REF") 398 REF = _PropertyTypeInfo(False, "ref")
414 CHOICES = _PropertyTypeInfo(False, "CHOICES") 399 CHOICES = _PropertyTypeInfo(False, "choices")
415 OBJECT = _PropertyTypeInfo(False, "OBJECT") 400 OBJECT = _PropertyTypeInfo(False, "object")
416 FUNCTION = _PropertyTypeInfo(False, "FUNCTION") 401 FUNCTION = _PropertyTypeInfo(False, "function")
417 BINARY = _PropertyTypeInfo(False, "BINARY") 402 BINARY = _PropertyTypeInfo(False, "binary")
418 ANY = _PropertyTypeInfo(False, "ANY") 403 ANY = _PropertyTypeInfo(False, "any")
419 ADDITIONAL_PROPERTIES = _PropertyTypeInfo(False, "ADDITIONAL_PROPERTIES")
420 404
421 def UnixName(name): 405 def UnixName(name):
422 """Returns the unix_style name for a given lowerCamelCase string. 406 """Returns the unix_style name for a given lowerCamelCase string.
423 """ 407 """
424 # First replace any lowerUpper patterns with lower_Upper. 408 # First replace any lowerUpper patterns with lower_Upper.
425 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) 409 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
426 # Now replace any ACMEWidgets patterns with ACME_Widgets 410 # Now replace any ACMEWidgets patterns with ACME_Widgets
427 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) 411 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
428 # Finally, replace any remaining periods, and make lowercase. 412 # Finally, replace any remaining periods, and make lowercase.
429 return s2.replace('.', '_').lower() 413 return s2.replace('.', '_').lower()
430 414
431 def _StripNamespace(name, namespace): 415 def _StripNamespace(name, namespace):
432 if name.startswith(namespace.name + '.'): 416 if name.startswith(namespace.name + '.'):
433 return name[len(namespace.name + '.'):] 417 return name[len(namespace.name + '.'):]
434 return name 418 return name
435 419
436 def _GetModelHierarchy(entity): 420 def _GetModelHierarchy(entity):
437 """Returns the hierarchy of the given model entity.""" 421 """Returns the hierarchy of the given model entity."""
438 hierarchy = [] 422 hierarchy = []
439 while entity: 423 while entity is not None:
440 try: 424 hierarchy.append(getattr(entity, 'name', repr(entity)))
441 hierarchy.append(entity.name) 425 if isinstance(entity, Namespace):
442 except AttributeError: 426 hierarchy.insert(0, ' in %s' % entity.source_file)
443 hierarchy.append(repr(entity)) 427 entity = getattr(entity, 'parent', None)
444 entity = entity.parent
445 hierarchy.reverse() 428 hierarchy.reverse()
446 return hierarchy 429 return hierarchy
447 430
448 def _AddTypes(model, json, namespace): 431 def _GetTypes(parent, json, namespace, origin):
449 """Adds Type objects to |model| contained in the 'types' field of |json|. 432 """Creates Type objects extracted from |json|.
450 """ 433 """
451 model.types = OrderedDict() 434 types = OrderedDict()
452 for type_json in json.get('types', []): 435 for type_json in json.get('types', []):
453 type_ = Type(model, type_json['id'], type_json, namespace) 436 type_ = Type(parent, type_json['id'], type_json, namespace, origin)
454 model.types[type_.name] = type_ 437 types[type_.name] = type_
438 return types
455 439
456 def _AddFunctions(model, json, namespace): 440 def _GetFunctions(parent, json, namespace):
457 """Adds Function objects to |model| contained in the 'functions' field of 441 """Creates Function objects extracted from |json|.
458 |json|.
459 """ 442 """
460 model.functions = OrderedDict() 443 functions = OrderedDict()
461 for function_json in json.get('functions', []): 444 for function_json in json.get('functions', []):
462 function = Function(model, function_json, namespace, from_json=True) 445 function = Function(parent,
463 model.functions[function.name] = function 446 function_json['name'],
447 function_json,
448 namespace,
449 Origin(from_json=True))
450 functions[function.name] = function
451 return functions
464 452
465 def _AddEvents(model, json, namespace): 453 def _GetEvents(parent, json, namespace):
466 """Adds Function objects to |model| contained in the 'events' field of |json|. 454 """Creates Function objects generated from the events in |json|.
467 """ 455 """
468 model.events = OrderedDict() 456 events = OrderedDict()
469 for event_json in json.get('events', []): 457 for event_json in json.get('events', []):
470 event = Function(model, event_json, namespace, from_client=True) 458 event = Function(parent,
471 model.events[event.name] = event 459 event_json['name'],
460 event_json,
461 namespace,
462 Origin(from_client=True))
463 events[event.name] = event
464 return events
472 465
473 def _AddProperties(model, 466 def _GetProperties(parent, json, namespace, origin):
474 json, 467 """Generates Property objects extracted from |json|.
475 namespace,
476 from_json=False,
477 from_client=False):
478 """Adds model.Property objects to |model| contained in the 'properties' field
479 of |json|.
480 """ 468 """
481 model.properties = OrderedDict() 469 properties = OrderedDict()
482 for name, property_json in json.get('properties', {}).items(): 470 for name, property_json in json.get('properties', {}).items():
483 model.properties[name] = Property( 471 properties[name] = Property.FromJSON(
484 model, 472 parent, name, property_json, namespace, origin)
485 name, 473 return properties
486 property_json,
487 namespace,
488 from_json=from_json,
489 from_client=from_client)
490 474
491 class _PlatformInfo(_Enum): 475 class _PlatformInfo(_Enum):
492 def __init__(self, name): 476 def __init__(self, name):
493 _Enum.__init__(self, name) 477 _Enum.__init__(self, name)
494 478
495 class Platforms(object): 479 class Platforms(object):
496 """Enum of the possible platforms. 480 """Enum of the possible platforms.
497 """ 481 """
498 CHROMEOS = _PlatformInfo("chromeos") 482 CHROMEOS = _PlatformInfo("chromeos")
499 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch") 483 CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
500 LINUX = _PlatformInfo("linux") 484 LINUX = _PlatformInfo("linux")
501 MAC = _PlatformInfo("mac") 485 MAC = _PlatformInfo("mac")
502 WIN = _PlatformInfo("win") 486 WIN = _PlatformInfo("win")
503 487
504 def _GetPlatforms(json): 488 def _GetPlatforms(json):
505 if 'platforms' not in json: 489 if 'platforms' not in json:
506 return None 490 return None
507 platforms = [] 491 platforms = []
508 for platform_name in json['platforms']: 492 for platform_name in json['platforms']:
509 for platform_enum in _Enum.GetAll(Platforms): 493 for platform_enum in _Enum.GetAll(Platforms):
510 if platform_name == platform_enum.name: 494 if platform_name == platform_enum.name:
511 platforms.append(platform_enum) 495 platforms.append(platform_enum)
512 break 496 break
513 return platforms 497 return platforms
OLDNEW
« no previous file with comments | « tools/json_schema_compiler/json_schema.py ('k') | tools/json_schema_compiler/model_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698