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