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