OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 """Generates Python source files from a mojom.Module.""" | 5 """Generates Python source files from a mojom.Module.""" |
6 | 6 |
7 import re | 7 import re |
8 from itertools import ifilter | 8 from itertools import ifilter |
9 | 9 |
10 import mojom.generate.generator as generator | 10 import mojom.generate.generator as generator |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 def CamelCase(name): | 83 def CamelCase(name): |
84 uccc = UpperCamelCase(name) | 84 uccc = UpperCamelCase(name) |
85 return uccc[0].lower() + uccc[1:] | 85 return uccc[0].lower() + uccc[1:] |
86 | 86 |
87 def ConstantStyle(name): | 87 def ConstantStyle(name): |
88 components = NameToComponent(name) | 88 components = NameToComponent(name) |
89 if components[0] == 'k': | 89 if components[0] == 'k': |
90 components = components[1:] | 90 components = components[1:] |
91 return '_'.join([x.upper() for x in components]) | 91 return '_'.join([x.upper() for x in components]) |
92 | 92 |
93 def FieldStyle(name): | |
94 components = NameToComponent(name) | |
95 return '_'.join([x.lower() for x in components]) | |
96 | |
97 def GetNameForElement(element): | 93 def GetNameForElement(element): |
98 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or | 94 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or |
99 mojom.IsStructKind(element) or isinstance(element, mojom.Method)): | 95 mojom.IsStructKind(element)): |
100 return UpperCamelCase(element.name) | 96 return UpperCamelCase(element.name) |
101 if isinstance(element, mojom.EnumValue): | 97 if isinstance(element, mojom.EnumValue): |
102 return (GetNameForElement(element.enum) + '.' + | 98 return (GetNameForElement(element.enum) + '.' + |
103 ConstantStyle(element.name)) | 99 ConstantStyle(element.name)) |
104 if isinstance(element, (mojom.NamedValue, | 100 if isinstance(element, (mojom.NamedValue, |
105 mojom.Constant)): | 101 mojom.Constant)): |
106 return ConstantStyle(element.name) | 102 return ConstantStyle(element.name) |
107 if isinstance(element, mojom.Field): | 103 raise Exception('Unexpected element: ' % element) |
108 return FieldStyle(element.name) | |
109 raise Exception('Unexpected element: %s' % element) | |
110 | 104 |
111 def ExpressionToText(token): | 105 def ExpressionToText(token): |
112 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): | 106 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): |
113 return str(token.computed_value) | 107 return str(token.computed_value) |
114 | 108 |
115 if isinstance(token, mojom.BuiltinValue): | 109 if isinstance(token, mojom.BuiltinValue): |
116 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': | 110 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': |
117 return 'float(\'inf\')'; | 111 return 'float(\'inf\')'; |
118 if (token.value == 'double.NEGATIVE_INFINITY' or | 112 if (token.value == 'double.NEGATIVE_INFINITY' or |
119 token.value == 'float.NEGATIVE_INFINITY'): | 113 token.value == 'float.NEGATIVE_INFINITY'): |
120 return 'float(\'-inf\')' | 114 return 'float(\'-inf\')' |
121 if token.value == 'double.NAN' or token.value == 'float.NAN': | 115 if token.value == 'double.NAN' or token.value == 'float.NAN': |
122 return 'float(\'nan\')'; | 116 return 'float(\'nan\')'; |
123 | 117 |
124 if token in ['true', 'false']: | 118 if token in ['true', 'false']: |
125 return str(token == 'true') | 119 return str(token == 'true') |
126 | 120 |
127 return token | 121 return token |
128 | 122 |
129 def GetFullyQualifiedName(kind): | 123 def GetStructClass(kind): |
130 name = [] | 124 name = [] |
131 if kind.imported_from: | 125 if kind.imported_from: |
132 name.append(kind.imported_from['python_module']) | 126 name.append(kind.imported_from['python_module']) |
133 name.append(GetNameForElement(kind)) | 127 name.append(GetNameForElement(kind)) |
134 return '.'.join(name) | 128 return '.'.join(name) |
135 | 129 |
136 def GetFieldType(kind, field=None): | 130 def GetFieldType(kind, field=None): |
137 if mojom.IsArrayKind(kind): | 131 if mojom.IsArrayKind(kind): |
138 arguments = [] | 132 arguments = [] |
139 if kind.kind in _kind_to_typecode_for_native_array: | 133 if kind.kind in _kind_to_typecode_for_native_array: |
(...skipping 14 matching lines...) Expand all Loading... |
154 if mojom.IsMapKind(kind): | 148 if mojom.IsMapKind(kind): |
155 arguments = [ | 149 arguments = [ |
156 GetFieldType(kind.key_kind), | 150 GetFieldType(kind.key_kind), |
157 GetFieldType(kind.value_kind), | 151 GetFieldType(kind.value_kind), |
158 ] | 152 ] |
159 if mojom.IsNullableKind(kind): | 153 if mojom.IsNullableKind(kind): |
160 arguments.append('nullable=True') | 154 arguments.append('nullable=True') |
161 return '_descriptor.MapType(%s)' % ', '.join(arguments) | 155 return '_descriptor.MapType(%s)' % ', '.join(arguments) |
162 | 156 |
163 if mojom.IsStructKind(kind): | 157 if mojom.IsStructKind(kind): |
164 arguments = [ 'lambda: %s' % GetFullyQualifiedName(kind) ] | 158 arguments = [ 'lambda: %s' % GetStructClass(kind) ] |
165 if mojom.IsNullableKind(kind): | 159 if mojom.IsNullableKind(kind): |
166 arguments.append('nullable=True') | 160 arguments.append('nullable=True') |
167 return '_descriptor.StructType(%s)' % ', '.join(arguments) | 161 return '_descriptor.StructType(%s)' % ', '.join(arguments) |
168 | 162 |
169 if mojom.IsEnumKind(kind): | 163 if mojom.IsEnumKind(kind): |
170 return GetFieldType(mojom.INT32) | 164 return GetFieldType(mojom.INT32) |
171 | 165 |
172 return _kind_to_type.get(kind, '_descriptor.TYPE_NONE') | 166 return _kind_to_type.get(kind, '_descriptor.TYPE_NONE') |
173 | 167 |
174 def GetFieldDescriptor(packed_field): | 168 def GetFieldDescriptor(packed_field): |
175 field = packed_field.field | 169 field = packed_field.field |
176 class_name = 'SingleFieldGroup' | 170 class_name = 'SingleFieldGroup' |
177 if field.kind == mojom.BOOL: | 171 if field.kind == mojom.BOOL: |
178 class_name = 'FieldDescriptor' | 172 class_name = 'FieldDescriptor' |
179 arguments = [ '%r' % GetNameForElement(field) ] | 173 arguments = [ '%r' % field.name ] |
180 arguments.append(GetFieldType(field.kind, field)) | 174 arguments.append(GetFieldType(field.kind, field)) |
181 arguments.append(str(packed_field.index)) | 175 arguments.append(str(packed_field.index)) |
182 arguments.append(str(packed_field.ordinal)) | 176 arguments.append(str(packed_field.ordinal)) |
183 if field.default: | 177 if field.default: |
184 if mojom.IsStructKind(field.kind): | 178 if mojom.IsStructKind(field.kind): |
185 arguments.append('default_value=True') | 179 arguments.append('default_value=True') |
186 else: | 180 else: |
187 arguments.append('default_value=%s' % ExpressionToText(field.default)) | 181 arguments.append('default_value=%s' % ExpressionToText(field.default)) |
188 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) | 182 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) |
189 | 183 |
190 def GetFieldGroup(byte): | 184 def GetFieldGroup(byte): |
191 if byte.packed_fields[0].field.kind == mojom.BOOL: | 185 if len(byte.packed_fields) > 1: |
192 descriptors = map(GetFieldDescriptor, byte.packed_fields) | 186 descriptors = map(GetFieldDescriptor, byte.packed_fields) |
193 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) | 187 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) |
194 assert len(byte.packed_fields) == 1 | 188 assert len(byte.packed_fields) == 1 |
195 return GetFieldDescriptor(byte.packed_fields[0]) | 189 return GetFieldDescriptor(byte.packed_fields[0]) |
196 | 190 |
197 def GetResponseStructFromMethod(method): | |
198 return generator.GetDataHeader( | |
199 False, generator.GetResponseStructFromMethod(method)) | |
200 | |
201 def GetStructFromMethod(method): | |
202 return generator.GetDataHeader( | |
203 False, generator.GetStructFromMethod(method)) | |
204 | |
205 def ComputeStaticValues(module): | 191 def ComputeStaticValues(module): |
206 in_progress = set() | 192 in_progress = set() |
207 computed = set() | 193 computed = set() |
208 | 194 |
209 def GetComputedValue(named_value): | 195 def GetComputedValue(named_value): |
210 if isinstance(named_value, mojom.EnumValue): | 196 if isinstance(named_value, mojom.EnumValue): |
211 field = next(ifilter(lambda field: field.name == named_value.name, | 197 field = next(ifilter(lambda field: field.name == named_value.name, |
212 named_value.enum.fields), None) | 198 named_value.enum.fields), None) |
213 if not field: | 199 if not field: |
214 raise RuntimeError( | 200 raise RuntimeError( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return module | 267 return module |
282 | 268 |
283 def MojomToPythonImport(mojom): | 269 def MojomToPythonImport(mojom): |
284 return mojom.replace('.mojom', '_mojom') | 270 return mojom.replace('.mojom', '_mojom') |
285 | 271 |
286 class Generator(generator.Generator): | 272 class Generator(generator.Generator): |
287 | 273 |
288 python_filters = { | 274 python_filters = { |
289 'expression_to_text': ExpressionToText, | 275 'expression_to_text': ExpressionToText, |
290 'field_group': GetFieldGroup, | 276 'field_group': GetFieldGroup, |
291 'fully_qualified_name': GetFullyQualifiedName, | |
292 'name': GetNameForElement, | 277 'name': GetNameForElement, |
293 'response_struct_from_method': GetResponseStructFromMethod, | |
294 'struct_from_method': GetStructFromMethod, | |
295 } | 278 } |
296 | 279 |
297 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) | 280 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) |
298 def GeneratePythonModule(self): | 281 def GeneratePythonModule(self): |
299 return { | 282 return { |
| 283 'imports': self.GetImports(), |
300 'enums': self.module.enums, | 284 'enums': self.module.enums, |
301 'imports': self.GetImports(), | |
302 'interfaces': self.GetQualifiedInterfaces(), | |
303 'module': ComputeStaticValues(self.module), | 285 'module': ComputeStaticValues(self.module), |
304 'structs': self.GetStructs(), | 286 'structs': self.GetStructs(), |
305 } | 287 } |
306 | 288 |
307 def GenerateFiles(self, args): | 289 def GenerateFiles(self, args): |
308 import_path = MojomToPythonImport(self.module.name) | 290 import_path = MojomToPythonImport(self.module.name) |
309 self.Write(self.GeneratePythonModule(), | 291 self.Write(self.GeneratePythonModule(), |
310 self.MatchMojomFilePath('%s.py' % import_path)) | 292 self.MatchMojomFilePath('%s.py' % import_path)) |
311 | 293 |
312 def GetImports(self): | 294 def GetImports(self): |
313 for each in self.module.imports: | 295 for each in self.module.imports: |
314 each['python_module'] = MojomToPythonImport(each['module_name']) | 296 each['python_module'] = MojomToPythonImport(each['module_name']) |
315 return self.module.imports | 297 return self.module.imports |
316 | 298 |
317 def GetQualifiedInterfaces(self): | |
318 """ | |
319 Returns the list of interfaces of the module. Each interface that has a | |
320 client will have a reference to the representation of the client interface | |
321 in the 'qualified_client' field. | |
322 """ | |
323 interfaces = self.module.interfaces | |
324 all_interfaces = [] + interfaces | |
325 for each in self.module.imports: | |
326 all_interfaces += each['module'].interfaces | |
327 interfaces_by_name = dict((x.name, x) for x in all_interfaces) | |
328 for interface in interfaces: | |
329 if interface.client: | |
330 assert interface.client in interfaces_by_name, ( | |
331 'Unable to find interface %s declared as client of %s.' % | |
332 (interface.client, interface.name)) | |
333 interface.qualified_client = interfaces_by_name[interface.client] | |
334 return sorted(interfaces, key=lambda i: (bool(i.client), i.name)) | |
335 | |
336 def GetJinjaParameters(self): | 299 def GetJinjaParameters(self): |
337 return { | 300 return { |
338 'lstrip_blocks': True, | 301 'lstrip_blocks': True, |
339 'trim_blocks': True, | 302 'trim_blocks': True, |
340 } | 303 } |
OLD | NEW |