| OLD | NEW |
| (Empty) |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """Generates Python source files from a mojom.Module.""" | |
| 6 | |
| 7 import re | |
| 8 | |
| 9 import mojom.generate.constant_resolver as resolver | |
| 10 import mojom.generate.generator as generator | |
| 11 import mojom.generate.module as mojom | |
| 12 from mojom.generate.template_expander import UseJinja | |
| 13 | |
| 14 _kind_to_type = { | |
| 15 mojom.BOOL: '_descriptor.TYPE_BOOL', | |
| 16 mojom.INT8: '_descriptor.TYPE_INT8', | |
| 17 mojom.UINT8: '_descriptor.TYPE_UINT8', | |
| 18 mojom.INT16: '_descriptor.TYPE_INT16', | |
| 19 mojom.UINT16: '_descriptor.TYPE_UINT16', | |
| 20 mojom.INT32: '_descriptor.TYPE_INT32', | |
| 21 mojom.UINT32: '_descriptor.TYPE_UINT32', | |
| 22 mojom.INT64: '_descriptor.TYPE_INT64', | |
| 23 mojom.UINT64: '_descriptor.TYPE_UINT64', | |
| 24 mojom.FLOAT: '_descriptor.TYPE_FLOAT', | |
| 25 mojom.DOUBLE: '_descriptor.TYPE_DOUBLE', | |
| 26 mojom.STRING: '_descriptor.TYPE_STRING', | |
| 27 mojom.NULLABLE_STRING: '_descriptor.TYPE_NULLABLE_STRING', | |
| 28 mojom.HANDLE: '_descriptor.TYPE_HANDLE', | |
| 29 mojom.DCPIPE: '_descriptor.TYPE_HANDLE', | |
| 30 mojom.DPPIPE: '_descriptor.TYPE_HANDLE', | |
| 31 mojom.MSGPIPE: '_descriptor.TYPE_HANDLE', | |
| 32 mojom.SHAREDBUFFER: '_descriptor.TYPE_HANDLE', | |
| 33 mojom.NULLABLE_HANDLE: '_descriptor.TYPE_NULLABLE_HANDLE', | |
| 34 mojom.NULLABLE_DCPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | |
| 35 mojom.NULLABLE_DPPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | |
| 36 mojom.NULLABLE_MSGPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | |
| 37 mojom.NULLABLE_SHAREDBUFFER: '_descriptor.TYPE_NULLABLE_HANDLE', | |
| 38 } | |
| 39 | |
| 40 # int64 integers are not handled by array.array. int64/uint64 array are | |
| 41 # supported but storage is not optimized (ie. they are plain python list, not | |
| 42 # array.array) | |
| 43 _kind_to_typecode_for_native_array = { | |
| 44 mojom.INT8: 'b', | |
| 45 mojom.UINT8: 'B', | |
| 46 mojom.INT16: 'h', | |
| 47 mojom.UINT16: 'H', | |
| 48 mojom.INT32: 'i', | |
| 49 mojom.UINT32: 'I', | |
| 50 mojom.FLOAT: 'f', | |
| 51 mojom.DOUBLE: 'd', | |
| 52 } | |
| 53 | |
| 54 | |
| 55 def NameToComponent(name): | |
| 56 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> | |
| 57 # HTTP_Entry2_FooBar) | |
| 58 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) | |
| 59 # insert '_' between non upper and start of upper blocks (e.g., | |
| 60 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) | |
| 61 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) | |
| 62 return [x.lower() for x in name.split('_')] | |
| 63 | |
| 64 def UpperCamelCase(name): | |
| 65 return ''.join([x.capitalize() for x in NameToComponent(name)]) | |
| 66 | |
| 67 def CamelCase(name): | |
| 68 uccc = UpperCamelCase(name) | |
| 69 return uccc[0].lower() + uccc[1:] | |
| 70 | |
| 71 def ConstantStyle(name): | |
| 72 components = NameToComponent(name) | |
| 73 if components[0] == 'k': | |
| 74 components = components[1:] | |
| 75 return '_'.join([x.upper() for x in components]) | |
| 76 | |
| 77 def FieldStyle(name): | |
| 78 components = NameToComponent(name) | |
| 79 return '_'.join([x.lower() for x in components]) | |
| 80 | |
| 81 def GetNameForElement(element): | |
| 82 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or | |
| 83 mojom.IsStructKind(element) or mojom.IsUnionKind(element) or | |
| 84 isinstance(element, mojom.Method)): | |
| 85 return UpperCamelCase(element.name) | |
| 86 if isinstance(element, mojom.EnumValue): | |
| 87 return (GetNameForElement(element.enum) + '.' + | |
| 88 ConstantStyle(element.name)) | |
| 89 if isinstance(element, (mojom.NamedValue, | |
| 90 mojom.Constant)): | |
| 91 return ConstantStyle(element.name) | |
| 92 if isinstance(element, mojom.Field): | |
| 93 return FieldStyle(element.name) | |
| 94 raise Exception('Unexpected element: %s' % element) | |
| 95 | |
| 96 def ExpressionToText(token): | |
| 97 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): | |
| 98 return str(token.resolved_value) | |
| 99 | |
| 100 if isinstance(token, mojom.BuiltinValue): | |
| 101 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': | |
| 102 return 'float(\'inf\')'; | |
| 103 if (token.value == 'double.NEGATIVE_INFINITY' or | |
| 104 token.value == 'float.NEGATIVE_INFINITY'): | |
| 105 return 'float(\'-inf\')' | |
| 106 if token.value == 'double.NAN' or token.value == 'float.NAN': | |
| 107 return 'float(\'nan\')'; | |
| 108 | |
| 109 if token in ['true', 'false']: | |
| 110 return str(token == 'true') | |
| 111 | |
| 112 return token | |
| 113 | |
| 114 def GetFullyQualifiedName(kind): | |
| 115 name = [] | |
| 116 if kind.imported_from: | |
| 117 name.append(kind.imported_from['python_module']) | |
| 118 name.append(GetNameForElement(kind)) | |
| 119 return '.'.join(name) | |
| 120 | |
| 121 def GetFieldType(kind, field=None): | |
| 122 if mojom.IsArrayKind(kind): | |
| 123 arguments = [] | |
| 124 if kind.kind in _kind_to_typecode_for_native_array: | |
| 125 arguments.append('%r' % _kind_to_typecode_for_native_array[kind.kind]) | |
| 126 elif kind.kind != mojom.BOOL: | |
| 127 arguments.append(GetFieldType(kind.kind)) | |
| 128 if mojom.IsNullableKind(kind): | |
| 129 arguments.append('nullable=True') | |
| 130 if kind.length is not None: | |
| 131 arguments.append('length=%d' % kind.length) | |
| 132 array_type = 'GenericArrayType' | |
| 133 if kind.kind == mojom.BOOL: | |
| 134 array_type = 'BooleanArrayType' | |
| 135 elif kind.kind in _kind_to_typecode_for_native_array: | |
| 136 array_type = 'NativeArrayType' | |
| 137 return '_descriptor.%s(%s)' % (array_type, ', '.join(arguments)) | |
| 138 | |
| 139 if mojom.IsMapKind(kind): | |
| 140 arguments = [ | |
| 141 GetFieldType(kind.key_kind), | |
| 142 GetFieldType(kind.value_kind), | |
| 143 ] | |
| 144 if mojom.IsNullableKind(kind): | |
| 145 arguments.append('nullable=True') | |
| 146 return '_descriptor.MapType(%s)' % ', '.join(arguments) | |
| 147 | |
| 148 if mojom.IsUnionKind(kind): | |
| 149 arguments = [ 'lambda: %s' % GetFullyQualifiedName(kind) ] | |
| 150 if mojom.IsNullableKind(kind): | |
| 151 arguments.append('nullable=True') | |
| 152 return '_descriptor.UnionType(%s)' % ', '.join(arguments) | |
| 153 | |
| 154 if mojom.IsStructKind(kind): | |
| 155 arguments = [ 'lambda: %s' % GetFullyQualifiedName(kind) ] | |
| 156 if mojom.IsNullableKind(kind): | |
| 157 arguments.append('nullable=True') | |
| 158 return '_descriptor.StructType(%s)' % ', '.join(arguments) | |
| 159 | |
| 160 if mojom.IsEnumKind(kind): | |
| 161 return GetFieldType(mojom.INT32) | |
| 162 | |
| 163 if mojom.IsInterfaceKind(kind): | |
| 164 arguments = [ 'lambda: %s' % GetFullyQualifiedName(kind) ] | |
| 165 if mojom.IsNullableKind(kind): | |
| 166 arguments.append('nullable=True') | |
| 167 return '_descriptor.InterfaceType(%s)' % ', '.join(arguments) | |
| 168 | |
| 169 if mojom.IsInterfaceRequestKind(kind): | |
| 170 arguments = [] | |
| 171 if mojom.IsNullableKind(kind): | |
| 172 arguments.append('nullable=True') | |
| 173 return '_descriptor.InterfaceRequestType(%s)' % ', '.join(arguments) | |
| 174 | |
| 175 return _kind_to_type[kind] | |
| 176 | |
| 177 def GetFieldDescriptor(field, index, min_version, union_field=False): | |
| 178 class_name = 'SingleFieldGroup' | |
| 179 if field.kind == mojom.BOOL and not union_field: | |
| 180 class_name = 'FieldDescriptor' | |
| 181 arguments = [ '%r' % GetNameForElement(field) ] | |
| 182 arguments.append(GetFieldType(field.kind, field)) | |
| 183 arguments.append(str(index)) | |
| 184 arguments.append(str(min_version)) | |
| 185 if field.default: | |
| 186 if mojom.IsStructKind(field.kind): | |
| 187 arguments.append('default_value=True') | |
| 188 else: | |
| 189 arguments.append('default_value=%s' % ExpressionToText(field.default)) | |
| 190 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) | |
| 191 | |
| 192 def GetStructFieldDescriptor(packed_field): | |
| 193 return GetFieldDescriptor( | |
| 194 packed_field.field, packed_field.index, packed_field.min_version) | |
| 195 | |
| 196 def GetUnionFieldDescriptor(field): | |
| 197 return GetFieldDescriptor(field, field.ordinal, 0, union_field=True) | |
| 198 | |
| 199 def GetFieldGroup(byte): | |
| 200 if byte.packed_fields[0].field.kind == mojom.BOOL: | |
| 201 descriptors = map(GetStructFieldDescriptor, byte.packed_fields) | |
| 202 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) | |
| 203 assert len(byte.packed_fields) == 1 | |
| 204 return GetStructFieldDescriptor(byte.packed_fields[0]) | |
| 205 | |
| 206 def MojomToPythonImport(mojom): | |
| 207 return mojom.replace('.mojom', '_mojom') | |
| 208 | |
| 209 class Generator(generator.Generator): | |
| 210 | |
| 211 python_filters = { | |
| 212 'expression_to_text': ExpressionToText, | |
| 213 'field_group': GetFieldGroup, | |
| 214 'union_field_descriptor': GetUnionFieldDescriptor, | |
| 215 'fully_qualified_name': GetFullyQualifiedName, | |
| 216 'name': GetNameForElement, | |
| 217 } | |
| 218 | |
| 219 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) | |
| 220 def GeneratePythonModule(self): | |
| 221 return { | |
| 222 'enums': self.module.enums, | |
| 223 'imports': self.GetImports(), | |
| 224 'interfaces': self.GetInterfaces(), | |
| 225 'module': resolver.ResolveConstants(self.module, ExpressionToText), | |
| 226 'namespace': self.module.namespace, | |
| 227 'structs': self.GetStructs(), | |
| 228 'unions': self.GetUnions(), | |
| 229 } | |
| 230 | |
| 231 def GenerateFiles(self, args): | |
| 232 import_path = MojomToPythonImport(self.module.name) | |
| 233 self.Write(self.GeneratePythonModule(), | |
| 234 self.MatchMojomFilePath('%s.py' % import_path)) | |
| 235 | |
| 236 def GetImports(self): | |
| 237 for each in self.module.transitive_imports: | |
| 238 each['python_module'] = MojomToPythonImport(each['module_name']) | |
| 239 return self.module.imports | |
| 240 | |
| 241 def GetJinjaParameters(self): | |
| 242 return { | |
| 243 'lstrip_blocks': True, | |
| 244 'trim_blocks': True, | |
| 245 } | |
| OLD | NEW |