OLD | NEW |
---|---|
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 Loading... | |
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) | |
OLD | NEW |