| 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 |