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 |
93 def GetNameForElement(element): | 97 def GetNameForElement(element): |
94 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or | 98 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or |
95 mojom.IsStructKind(element)): | 99 mojom.IsStructKind(element) or isinstance(element, mojom.Method)): |
96 return UpperCamelCase(element.name) | 100 return UpperCamelCase(element.name) |
97 if isinstance(element, mojom.EnumValue): | 101 if isinstance(element, mojom.EnumValue): |
98 return (GetNameForElement(element.enum) + '.' + | 102 return (GetNameForElement(element.enum) + '.' + |
99 ConstantStyle(element.name)) | 103 ConstantStyle(element.name)) |
100 if isinstance(element, (mojom.NamedValue, | 104 if isinstance(element, (mojom.NamedValue, |
101 mojom.Constant)): | 105 mojom.Constant)): |
102 return ConstantStyle(element.name) | 106 return ConstantStyle(element.name) |
103 raise Exception('Unexpected element: ' % element) | 107 if isinstance(element, mojom.Field): |
| 108 return FieldStyle(element.name) |
| 109 raise Exception('Unexpected element: %s' % element) |
104 | 110 |
105 def ExpressionToText(token): | 111 def ExpressionToText(token): |
106 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): | 112 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): |
107 return str(token.computed_value) | 113 return str(token.computed_value) |
108 | 114 |
109 if isinstance(token, mojom.BuiltinValue): | 115 if isinstance(token, mojom.BuiltinValue): |
110 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': | 116 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': |
111 return 'float(\'inf\')'; | 117 return 'float(\'inf\')'; |
112 if (token.value == 'double.NEGATIVE_INFINITY' or | 118 if (token.value == 'double.NEGATIVE_INFINITY' or |
113 token.value == 'float.NEGATIVE_INFINITY'): | 119 token.value == 'float.NEGATIVE_INFINITY'): |
114 return 'float(\'-inf\')' | 120 return 'float(\'-inf\')' |
115 if token.value == 'double.NAN' or token.value == 'float.NAN': | 121 if token.value == 'double.NAN' or token.value == 'float.NAN': |
116 return 'float(\'nan\')'; | 122 return 'float(\'nan\')'; |
117 | 123 |
118 if token in ['true', 'false']: | 124 if token in ['true', 'false']: |
119 return str(token == 'true') | 125 return str(token == 'true') |
120 | 126 |
121 return token | 127 return token |
122 | 128 |
123 def GetStructClass(kind): | 129 def GetFullyQualifiedName(kind): |
124 name = [] | 130 name = [] |
125 if kind.imported_from: | 131 if kind.imported_from: |
126 name.append(kind.imported_from['python_module']) | 132 name.append(kind.imported_from['python_module']) |
127 name.append(GetNameForElement(kind)) | 133 name.append(GetNameForElement(kind)) |
128 return '.'.join(name) | 134 return '.'.join(name) |
129 | 135 |
130 def GetFieldType(kind, field=None): | 136 def GetFieldType(kind, field=None): |
131 if mojom.IsArrayKind(kind): | 137 if mojom.IsArrayKind(kind): |
132 arguments = [] | 138 arguments = [] |
133 if kind.kind in _kind_to_typecode_for_native_array: | 139 if kind.kind in _kind_to_typecode_for_native_array: |
(...skipping 14 matching lines...) Expand all Loading... |
148 if mojom.IsMapKind(kind): | 154 if mojom.IsMapKind(kind): |
149 arguments = [ | 155 arguments = [ |
150 GetFieldType(kind.key_kind), | 156 GetFieldType(kind.key_kind), |
151 GetFieldType(kind.value_kind), | 157 GetFieldType(kind.value_kind), |
152 ] | 158 ] |
153 if mojom.IsNullableKind(kind): | 159 if mojom.IsNullableKind(kind): |
154 arguments.append('nullable=True') | 160 arguments.append('nullable=True') |
155 return '_descriptor.MapType(%s)' % ', '.join(arguments) | 161 return '_descriptor.MapType(%s)' % ', '.join(arguments) |
156 | 162 |
157 if mojom.IsStructKind(kind): | 163 if mojom.IsStructKind(kind): |
158 arguments = [ 'lambda: %s' % GetStructClass(kind) ] | 164 arguments = [ 'lambda: %s' % GetFullyQualifiedName(kind) ] |
159 if mojom.IsNullableKind(kind): | 165 if mojom.IsNullableKind(kind): |
160 arguments.append('nullable=True') | 166 arguments.append('nullable=True') |
161 return '_descriptor.StructType(%s)' % ', '.join(arguments) | 167 return '_descriptor.StructType(%s)' % ', '.join(arguments) |
162 | 168 |
163 if mojom.IsEnumKind(kind): | 169 if mojom.IsEnumKind(kind): |
164 return GetFieldType(mojom.INT32) | 170 return GetFieldType(mojom.INT32) |
165 | 171 |
166 return _kind_to_type.get(kind, '_descriptor.TYPE_NONE') | 172 return _kind_to_type.get(kind, '_descriptor.TYPE_NONE') |
167 | 173 |
168 def GetFieldDescriptor(packed_field): | 174 def GetFieldDescriptor(packed_field): |
169 field = packed_field.field | 175 field = packed_field.field |
170 class_name = 'SingleFieldGroup' | 176 class_name = 'SingleFieldGroup' |
171 if field.kind == mojom.BOOL: | 177 if field.kind == mojom.BOOL: |
172 class_name = 'FieldDescriptor' | 178 class_name = 'FieldDescriptor' |
173 arguments = [ '%r' % field.name ] | 179 arguments = [ '%r' % GetNameForElement(field) ] |
174 arguments.append(GetFieldType(field.kind, field)) | 180 arguments.append(GetFieldType(field.kind, field)) |
175 arguments.append(str(packed_field.index)) | 181 arguments.append(str(packed_field.index)) |
176 arguments.append(str(packed_field.ordinal)) | 182 arguments.append(str(packed_field.ordinal)) |
177 if field.default: | 183 if field.default: |
178 if mojom.IsStructKind(field.kind): | 184 if mojom.IsStructKind(field.kind): |
179 arguments.append('default_value=True') | 185 arguments.append('default_value=True') |
180 else: | 186 else: |
181 arguments.append('default_value=%s' % ExpressionToText(field.default)) | 187 arguments.append('default_value=%s' % ExpressionToText(field.default)) |
182 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) | 188 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) |
183 | 189 |
184 def GetFieldGroup(byte): | 190 def GetFieldGroup(byte): |
185 if len(byte.packed_fields) > 1: | 191 if byte.packed_fields[0].field.kind == mojom.BOOL: |
186 descriptors = map(GetFieldDescriptor, byte.packed_fields) | 192 descriptors = map(GetFieldDescriptor, byte.packed_fields) |
187 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) | 193 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) |
188 assert len(byte.packed_fields) == 1 | 194 assert len(byte.packed_fields) == 1 |
189 return GetFieldDescriptor(byte.packed_fields[0]) | 195 return GetFieldDescriptor(byte.packed_fields[0]) |
190 | 196 |
| 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 |
191 def ComputeStaticValues(module): | 205 def ComputeStaticValues(module): |
192 in_progress = set() | 206 in_progress = set() |
193 computed = set() | 207 computed = set() |
194 | 208 |
195 def GetComputedValue(named_value): | 209 def GetComputedValue(named_value): |
196 if isinstance(named_value, mojom.EnumValue): | 210 if isinstance(named_value, mojom.EnumValue): |
197 field = next(ifilter(lambda field: field.name == named_value.name, | 211 field = next(ifilter(lambda field: field.name == named_value.name, |
198 named_value.enum.fields), None) | 212 named_value.enum.fields), None) |
199 if not field: | 213 if not field: |
200 raise RuntimeError( | 214 raise RuntimeError( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 return module | 281 return module |
268 | 282 |
269 def MojomToPythonImport(mojom): | 283 def MojomToPythonImport(mojom): |
270 return mojom.replace('.mojom', '_mojom') | 284 return mojom.replace('.mojom', '_mojom') |
271 | 285 |
272 class Generator(generator.Generator): | 286 class Generator(generator.Generator): |
273 | 287 |
274 python_filters = { | 288 python_filters = { |
275 'expression_to_text': ExpressionToText, | 289 'expression_to_text': ExpressionToText, |
276 'field_group': GetFieldGroup, | 290 'field_group': GetFieldGroup, |
| 291 'fully_qualified_name': GetFullyQualifiedName, |
277 'name': GetNameForElement, | 292 'name': GetNameForElement, |
| 293 'response_struct_from_method': GetResponseStructFromMethod, |
| 294 'struct_from_method': GetStructFromMethod, |
278 } | 295 } |
279 | 296 |
280 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) | 297 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) |
281 def GeneratePythonModule(self): | 298 def GeneratePythonModule(self): |
282 return { | 299 return { |
| 300 'enums': self.module.enums, |
283 'imports': self.GetImports(), | 301 'imports': self.GetImports(), |
284 'enums': self.module.enums, | 302 'interfaces': self.GetQualifiedInterfaces(), |
285 'module': ComputeStaticValues(self.module), | 303 'module': ComputeStaticValues(self.module), |
286 'structs': self.GetStructs(), | 304 'structs': self.GetStructs(), |
287 } | 305 } |
288 | 306 |
289 def GenerateFiles(self, args): | 307 def GenerateFiles(self, args): |
290 import_path = MojomToPythonImport(self.module.name) | 308 import_path = MojomToPythonImport(self.module.name) |
291 self.Write(self.GeneratePythonModule(), | 309 self.Write(self.GeneratePythonModule(), |
292 self.MatchMojomFilePath('%s.py' % import_path)) | 310 self.MatchMojomFilePath('%s.py' % import_path)) |
293 | 311 |
294 def GetImports(self): | 312 def GetImports(self): |
295 for each in self.module.imports: | 313 for each in self.module.imports: |
296 each['python_module'] = MojomToPythonImport(each['module_name']) | 314 each['python_module'] = MojomToPythonImport(each['module_name']) |
297 return self.module.imports | 315 return self.module.imports |
298 | 316 |
| 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 |
299 def GetJinjaParameters(self): | 336 def GetJinjaParameters(self): |
300 return { | 337 return { |
301 'lstrip_blocks': True, | 338 'lstrip_blocks': True, |
302 'trim_blocks': True, | 339 'trim_blocks': True, |
303 } | 340 } |
OLD | NEW |