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

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

Issue 11018003: Extensions Docs Server: Server code for showing properties of properties (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add simple_name to model.py Created 8 years, 2 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 class ParseException(Exception): 9 class ParseException(Exception):
10 """Thrown when data in the model is invalid. 10 """Thrown when data in the model is invalid.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 - |functions| a map of function names to their model.Function 44 - |functions| a map of function names to their model.Function
45 - |events| a map of event names to their model.Function 45 - |events| a map of event names to their model.Function
46 - |properties| a map of property names to their model.Property 46 - |properties| a map of property names to their model.Property
47 """ 47 """
48 def __init__(self, json, source_file): 48 def __init__(self, json, source_file):
49 self.name = json['namespace'] 49 self.name = json['namespace']
50 self.unix_name = UnixName(self.name) 50 self.unix_name = UnixName(self.name)
51 self.source_file = source_file 51 self.source_file = source_file
52 self.source_file_dir, self.source_file_filename = os.path.split(source_file) 52 self.source_file_dir, self.source_file_filename = os.path.split(source_file)
53 self.parent = None 53 self.parent = None
54 _AddTypes(self, json) 54 _AddTypes(self, json, self.name)
not at google - send to devlin 2012/10/05 01:30:16 I think passing around the namespace itself rather
cduvall 2012/10/05 01:44:57 Done.
55 _AddFunctions(self, json) 55 _AddFunctions(self, json, self.name)
56 _AddEvents(self, json) 56 _AddEvents(self, json, self.name)
57 _AddProperties(self, json) 57 _AddProperties(self, json, self.name)
58 58
59 class Type(object): 59 class Type(object):
60 """A Type defined in the json. 60 """A Type defined in the json.
61 61
62 Properties: 62 Properties:
63 - |name| the type name 63 - |name| the type name
64 - |description| the description of the type (if provided) 64 - |description| the description of the type (if provided)
65 - |properties| a map of property unix_names to their model.Property 65 - |properties| a map of property unix_names to their model.Property
66 - |functions| a map of function names to their model.Function 66 - |functions| a map of function names to their model.Function
67 - |events| a map of event names to their model.Event 67 - |events| a map of event names to their model.Event
68 - |from_client| indicates that instances of the Type can originate from the 68 - |from_client| indicates that instances of the Type can originate from the
69 users of generated code, such as top-level types and function results 69 users of generated code, such as top-level types and function results
70 - |from_json| indicates that instances of the Type can originate from the 70 - |from_json| indicates that instances of the Type can originate from the
71 JSON (as described by the schema), such as top-level types and function 71 JSON (as described by the schema), such as top-level types and function
72 parameters 72 parameters
73 - |type_| the PropertyType of this Type 73 - |type_| the PropertyType of this Type
74 - |item_type| if this is an array, the type of items in the array 74 - |item_type| if this is an array, the type of items in the array
not at google - send to devlin 2012/10/05 01:30:16 add simple_name to this list?
cduvall 2012/10/05 01:44:57 Done.
75 """ 75 """
76 def __init__(self, parent, name, json): 76 def __init__(self, parent, name, json, namespace_name):
77 if json.get('type') == 'array': 77 if json.get('type') == 'array':
78 self.type_ = PropertyType.ARRAY 78 self.type_ = PropertyType.ARRAY
79 self.item_type = Property(self, name + "Element", json['items'], 79 self.item_type = Property(self,
80 name + "Element",
81 json['items'],
82 namespace_name,
80 from_json=True, 83 from_json=True,
81 from_client=True) 84 from_client=True)
82 elif 'enum' in json: 85 elif 'enum' in json:
83 self.enum_values = [] 86 self.enum_values = []
84 for value in json['enum']: 87 for value in json['enum']:
85 self.enum_values.append(value) 88 self.enum_values.append(value)
86 self.type_ = PropertyType.ENUM 89 self.type_ = PropertyType.ENUM
87 elif json.get('type') == 'string': 90 elif json.get('type') == 'string':
88 self.type_ = PropertyType.STRING 91 self.type_ = PropertyType.STRING
89 else: 92 else:
90 if not ( 93 if not (
91 'properties' in json or 94 'properties' in json or
92 'additionalProperties' in json or 95 'additionalProperties' in json or
93 'functions' in json or 96 'functions' in json or
94 'events' in json): 97 'events' in json):
95 raise ParseException(self, name + " has no properties or functions") 98 raise ParseException(self, name + " has no properties or functions")
96 self.type_ = PropertyType.OBJECT 99 self.type_ = PropertyType.OBJECT
97 self.name = name 100 self.name = name
101 self.simple_name = _StripNamespace(self.name, namespace_name)
98 self.unix_name = UnixName(self.name) 102 self.unix_name = UnixName(self.name)
99 self.description = json.get('description') 103 self.description = json.get('description')
100 self.from_json = True 104 self.from_json = True
101 self.from_client = True 105 self.from_client = True
102 self.parent = parent 106 self.parent = parent
103 self.instance_of = json.get('isInstanceOf', None) 107 self.instance_of = json.get('isInstanceOf', None)
104 _AddFunctions(self, json) 108 _AddFunctions(self, json, namespace_name)
105 _AddEvents(self, json) 109 _AddEvents(self, json, namespace_name)
106 _AddProperties(self, json, from_json=True, from_client=True) 110 _AddProperties(self, json, namespace_name, from_json=True, from_client=True)
107 111
108 additional_properties_key = 'additionalProperties' 112 additional_properties_key = 'additionalProperties'
109 additional_properties = json.get(additional_properties_key) 113 additional_properties = json.get(additional_properties_key)
110 if additional_properties: 114 if additional_properties:
111 self.properties[additional_properties_key] = Property( 115 self.properties[additional_properties_key] = Property(
112 self, 116 self,
113 additional_properties_key, 117 additional_properties_key,
114 additional_properties, 118 additional_properties,
119 namespace_name,
115 is_additional_properties=True) 120 is_additional_properties=True)
116 121
117 class Function(object): 122 class Function(object):
118 """A Function defined in the API. 123 """A Function defined in the API.
119 124
120 Properties: 125 Properties:
121 - |name| the function name 126 - |name| the function name
122 - |params| a list of parameters to the function (order matters). A separate 127 - |params| a list of parameters to the function (order matters). A separate
123 parameter is used for each choice of a 'choices' parameter. 128 parameter is used for each choice of a 'choices' parameter.
124 - |description| a description of the function (if provided) 129 - |description| a description of the function (if provided)
125 - |callback| the callback parameter to the function. There should be exactly 130 - |callback| the callback parameter to the function. There should be exactly
126 one 131 one
127 - |optional| whether the Function is "optional"; this only makes sense to be 132 - |optional| whether the Function is "optional"; this only makes sense to be
128 present when the Function is representing a callback property. 133 present when the Function is representing a callback property.
129 """ 134 """
130 def __init__(self, parent, json, from_json=False, from_client=False): 135 def __init__(self,
136 parent,
137 json,
138 namespace_name,
139 from_json=False,
140 from_client=False):
131 self.name = json['name'] 141 self.name = json['name']
142 self.simple_name = _StripNamespace(self.name, namespace_name)
132 self.params = [] 143 self.params = []
133 self.description = json.get('description') 144 self.description = json.get('description')
134 self.callback = None 145 self.callback = None
135 self.optional = json.get('optional', False) 146 self.optional = json.get('optional', False)
136 self.parent = parent 147 self.parent = parent
137 self.nocompile = json.get('nocompile') 148 self.nocompile = json.get('nocompile')
138 options = json.get('options', {}) 149 options = json.get('options', {})
139 self.conditions = options.get('conditions', []) 150 self.conditions = options.get('conditions', [])
140 self.actions = options.get('actions', []) 151 self.actions = options.get('actions', [])
141 self.supports_listeners = options.get('supportsListeners', True) 152 self.supports_listeners = options.get('supportsListeners', True)
142 self.supports_rules = options.get('supportsRules', False) 153 self.supports_rules = options.get('supportsRules', False)
143 def GeneratePropertyFromParam(p): 154 def GeneratePropertyFromParam(p):
144 return Property(self, 155 return Property(self,
145 p['name'], p, 156 p['name'], p,
157 namespace_name,
146 from_json=from_json, 158 from_json=from_json,
147 from_client=from_client) 159 from_client=from_client)
148 160
149 self.filters = [GeneratePropertyFromParam(filter) 161 self.filters = [GeneratePropertyFromParam(filter)
150 for filter in json.get('filters', [])] 162 for filter in json.get('filters', [])]
151 callback_param = None 163 callback_param = None
152 for param in json.get('parameters', []): 164 for param in json.get('parameters', []):
153 165
154 if param.get('type') == 'function': 166 if param.get('type') == 'function':
155 if callback_param: 167 if callback_param:
156 # No ParseException because the webstore has this. 168 # No ParseException because the webstore has this.
157 # Instead, pretend all intermediate callbacks are properties. 169 # Instead, pretend all intermediate callbacks are properties.
158 self.params.append(GeneratePropertyFromParam(callback_param)) 170 self.params.append(GeneratePropertyFromParam(callback_param))
159 callback_param = param 171 callback_param = param
160 else: 172 else:
161 self.params.append(GeneratePropertyFromParam(param)) 173 self.params.append(GeneratePropertyFromParam(param))
162 174
163 if callback_param: 175 if callback_param:
164 self.callback = Function(self, callback_param, from_client=True) 176 self.callback = Function(self,
177 callback_param,
178 namespace_name,
179 from_client=True)
165 180
166 self.returns = None 181 self.returns = None
167 if 'returns' in json: 182 if 'returns' in json:
168 self.returns = Property(self, 'return', json['returns']) 183 self.returns = Property(self, 'return', json['returns'], namespace_name)
169 184
170 class Property(object): 185 class Property(object):
171 """A property of a type OR a parameter to a function. 186 """A property of a type OR a parameter to a function.
172 187
173 Properties: 188 Properties:
174 - |name| name of the property as in the json. This shouldn't change since 189 - |name| name of the property as in the json. This shouldn't change since
175 it is the key used to access DictionaryValues 190 it is the key used to access DictionaryValues
176 - |unix_name| the unix_style_name of the property. Used as variable name 191 - |unix_name| the unix_style_name of the property. Used as variable name
177 - |optional| a boolean representing whether the property is optional 192 - |optional| a boolean representing whether the property is optional
178 - |description| a description of the property (if provided) 193 - |description| a description of the property (if provided)
179 - |type_| the model.PropertyType of this property 194 - |type_| the model.PropertyType of this property
180 - |compiled_type| the model.PropertyType that this property should be 195 - |compiled_type| the model.PropertyType that this property should be
181 compiled to from the JSON. Defaults to |type_|. 196 compiled to from the JSON. Defaults to |type_|.
182 - |ref_type| the type that the REF property is referencing. Can be used to 197 - |ref_type| the type that the REF property is referencing. Can be used to
183 map to its model.Type 198 map to its model.Type
184 - |item_type| a model.Property representing the type of each element in an 199 - |item_type| a model.Property representing the type of each element in an
185 ARRAY 200 ARRAY
186 - |properties| the properties of an OBJECT parameter 201 - |properties| the properties of an OBJECT parameter
187 - |from_client| indicates that instances of the Type can originate from the 202 - |from_client| indicates that instances of the Type can originate from the
188 users of generated code, such as top-level types and function results 203 users of generated code, such as top-level types and function results
189 - |from_json| indicates that instances of the Type can originate from the 204 - |from_json| indicates that instances of the Type can originate from the
190 JSON (as described by the schema), such as top-level types and function 205 JSON (as described by the schema), such as top-level types and function
191 parameters 206 parameters
192 """ 207 """
193 208
194 def __init__(self, parent, name, json, is_additional_properties=False, 209 def __init__(self,
195 from_json=False, from_client=False): 210 parent,
211 name,
212 json,
213 namespace_name,
214 is_additional_properties=False,
215 from_json=False,
216 from_client=False):
196 self.name = name 217 self.name = name
218 self.simple_name = _StripNamespace(self.name, namespace_name)
197 self._unix_name = UnixName(self.name) 219 self._unix_name = UnixName(self.name)
198 self._unix_name_used = False 220 self._unix_name_used = False
199 self.optional = json.get('optional', False) 221 self.optional = json.get('optional', False)
200 self.functions = {} 222 self.functions = {}
201 self.has_value = False 223 self.has_value = False
202 self.description = json.get('description') 224 self.description = json.get('description')
203 self.parent = parent 225 self.parent = parent
204 self.from_json = from_json 226 self.from_json = from_json
205 self.from_client = from_client 227 self.from_client = from_client
206 self.instance_of = json.get('isInstanceOf', None) 228 self.instance_of = json.get('isInstanceOf', None)
207 _AddProperties(self, json) 229 _AddProperties(self, json, namespace_name)
208 if is_additional_properties: 230 if is_additional_properties:
209 self.type_ = PropertyType.ADDITIONAL_PROPERTIES 231 self.type_ = PropertyType.ADDITIONAL_PROPERTIES
210 elif '$ref' in json: 232 elif '$ref' in json:
211 self.ref_type = json['$ref'] 233 self.ref_type = json['$ref']
212 self.type_ = PropertyType.REF 234 self.type_ = PropertyType.REF
213 elif 'enum' in json and json.get('type') == 'string': 235 elif 'enum' in json and json.get('type') == 'string':
214 # Non-string enums (as in the case of [legalValues=(1,2)]) should fall 236 # Non-string enums (as in the case of [legalValues=(1,2)]) should fall
215 # through to the next elif. 237 # through to the next elif.
216 self.enum_values = [] 238 self.enum_values = []
217 for value in json['enum']: 239 for value in json['enum']:
218 self.enum_values.append(value) 240 self.enum_values.append(value)
219 self.type_ = PropertyType.ENUM 241 self.type_ = PropertyType.ENUM
220 elif 'type' in json: 242 elif 'type' in json:
221 self.type_ = self._JsonTypeToPropertyType(json['type']) 243 self.type_ = self._JsonTypeToPropertyType(json['type'])
222 if self.type_ == PropertyType.ARRAY: 244 if self.type_ == PropertyType.ARRAY:
223 self.item_type = Property(self, name + "Element", json['items'], 245 self.item_type = Property(self,
224 from_json=from_json, 246 name + "Element",
225 from_client=from_client) 247 json['items'],
248 namespace_name,
249 from_json=from_json,
250 from_client=from_client)
226 elif self.type_ == PropertyType.OBJECT: 251 elif self.type_ == PropertyType.OBJECT:
227 # These members are read when this OBJECT Property is used as a Type 252 # These members are read when this OBJECT Property is used as a Type
228 type_ = Type(self, self.name, json) 253 type_ = Type(self, self.name, json, namespace_name)
229 # self.properties will already have some value from |_AddProperties|. 254 # self.properties will already have some value from |_AddProperties|.
230 self.properties.update(type_.properties) 255 self.properties.update(type_.properties)
231 self.functions = type_.functions 256 self.functions = type_.functions
232 elif 'choices' in json: 257 elif 'choices' in json:
233 if not json['choices'] or len(json['choices']) == 0: 258 if not json['choices'] or len(json['choices']) == 0:
234 raise ParseException(self, 'Choices has no choices') 259 raise ParseException(self, 'Choices has no choices')
235 self.choices = {} 260 self.choices = {}
236 self.type_ = PropertyType.CHOICES 261 self.type_ = PropertyType.CHOICES
237 self.compiled_type = self.type_ 262 self.compiled_type = self.type_
238 for choice_json in json['choices']: 263 for choice_json in json['choices']:
239 choice = Property(self, self.name, choice_json, 264 choice = Property(self,
240 from_json=from_json, 265 self.name,
241 from_client=from_client) 266 choice_json,
267 namespace_name,
268 from_json=from_json,
269 from_client=from_client)
242 choice.unix_name = UnixName(self.name + choice.type_.name) 270 choice.unix_name = UnixName(self.name + choice.type_.name)
243 # The existence of any single choice is optional 271 # The existence of any single choice is optional
244 choice.optional = True 272 choice.optional = True
245 self.choices[choice.type_] = choice 273 self.choices[choice.type_] = choice
246 elif 'value' in json: 274 elif 'value' in json:
247 self.has_value = True 275 self.has_value = True
248 self.value = json['value'] 276 self.value = json['value']
249 if type(self.value) == int: 277 if type(self.value) == int:
250 self.type_ = PropertyType.INTEGER 278 self.type_ = PropertyType.INTEGER
251 self.compiled_type = self.type_ 279 self.compiled_type = self.type_
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 def UnixName(name): 374 def UnixName(name):
347 """Returns the unix_style name for a given lowerCamelCase string. 375 """Returns the unix_style name for a given lowerCamelCase string.
348 """ 376 """
349 # First replace any lowerUpper patterns with lower_Upper. 377 # First replace any lowerUpper patterns with lower_Upper.
350 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) 378 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
351 # Now replace any ACMEWidgets patterns with ACME_Widgets 379 # Now replace any ACMEWidgets patterns with ACME_Widgets
352 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) 380 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
353 # Finally, replace any remaining periods, and make lowercase. 381 # Finally, replace any remaining periods, and make lowercase.
354 return s2.replace('.', '_').lower() 382 return s2.replace('.', '_').lower()
355 383
384 def _StripNamespace(name, namespace_name):
385 if name.startswith(namespace_name + '.'):
386 return name[len(namespace_name + '.'):]
387 return name
388
356 def _GetModelHierarchy(entity): 389 def _GetModelHierarchy(entity):
357 """Returns the hierarchy of the given model entity.""" 390 """Returns the hierarchy of the given model entity."""
358 hierarchy = [] 391 hierarchy = []
359 while entity: 392 while entity:
360 try: 393 try:
361 hierarchy.append(entity.name) 394 hierarchy.append(entity.name)
362 except AttributeError: 395 except AttributeError:
363 hierarchy.append(repr(entity)) 396 hierarchy.append(repr(entity))
364 entity = entity.parent 397 entity = entity.parent
365 hierarchy.reverse() 398 hierarchy.reverse()
366 return hierarchy 399 return hierarchy
367 400
368 def _AddTypes(model, json): 401 def _AddTypes(model, json, namespace_name):
369 """Adds Type objects to |model| contained in the 'types' field of |json|. 402 """Adds Type objects to |model| contained in the 'types' field of |json|.
370 """ 403 """
371 model.types = {} 404 model.types = {}
372 for type_json in json.get('types', []): 405 for type_json in json.get('types', []):
373 type_ = Type(model, type_json['id'], type_json) 406 type_ = Type(model, type_json['id'], type_json, namespace_name)
374 model.types[type_.name] = type_ 407 model.types[type_.name] = type_
375 408
376 def _AddFunctions(model, json): 409 def _AddFunctions(model, json, namespace_name):
377 """Adds Function objects to |model| contained in the 'functions' field of 410 """Adds Function objects to |model| contained in the 'functions' field of
378 |json|. 411 |json|.
379 """ 412 """
380 model.functions = {} 413 model.functions = {}
381 for function_json in json.get('functions', []): 414 for function_json in json.get('functions', []):
382 function = Function(model, function_json, from_json=True) 415 function = Function(model, function_json, namespace_name, from_json=True)
383 model.functions[function.name] = function 416 model.functions[function.name] = function
384 417
385 def _AddEvents(model, json): 418 def _AddEvents(model, json, namespace_name):
386 """Adds Function objects to |model| contained in the 'events' field of |json|. 419 """Adds Function objects to |model| contained in the 'events' field of |json|.
387 """ 420 """
388 model.events = {} 421 model.events = {}
389 for event_json in json.get('events', []): 422 for event_json in json.get('events', []):
390 event = Function(model, event_json, from_client=True) 423 event = Function(model, event_json, namespace_name, from_client=True)
391 model.events[event.name] = event 424 model.events[event.name] = event
392 425
393 def _AddProperties(model, json, from_json=False, from_client=False): 426 def _AddProperties(model,
427 json,
428 namespace_name,
429 from_json=False,
430 from_client=False):
394 """Adds model.Property objects to |model| contained in the 'properties' field 431 """Adds model.Property objects to |model| contained in the 'properties' field
395 of |json|. 432 of |json|.
396 """ 433 """
397 model.properties = {} 434 model.properties = {}
398 for name, property_json in json.get('properties', {}).items(): 435 for name, property_json in json.get('properties', {}).items():
399 model.properties[name] = Property( 436 model.properties[name] = Property(
400 model, 437 model,
401 name, 438 name,
402 property_json, 439 property_json,
440 namespace_name,
403 from_json=from_json, 441 from_json=from_json,
404 from_client=from_client) 442 from_client=from_client)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698