Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: mojo/public/tools/bindings/generators/mojom_python_generator.py

Issue 570563002: mojo: Starting serialization for python bindings. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 22 matching lines...) Expand all
33 mojom.NULLABLE_HANDLE: "_descriptor.TYPE_NULLABLE_HANDLE", 33 mojom.NULLABLE_HANDLE: "_descriptor.TYPE_NULLABLE_HANDLE",
34 mojom.NULLABLE_DCPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", 34 mojom.NULLABLE_DCPIPE: "_descriptor.TYPE_NULLABLE_HANDLE",
35 mojom.NULLABLE_DPPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", 35 mojom.NULLABLE_DPPIPE: "_descriptor.TYPE_NULLABLE_HANDLE",
36 mojom.NULLABLE_MSGPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", 36 mojom.NULLABLE_MSGPIPE: "_descriptor.TYPE_NULLABLE_HANDLE",
37 mojom.NULLABLE_SHAREDBUFFER: "_descriptor.TYPE_NULLABLE_HANDLE", 37 mojom.NULLABLE_SHAREDBUFFER: "_descriptor.TYPE_NULLABLE_HANDLE",
38 } 38 }
39 39
40 # int64 integers are not handled by array.array. int64/uint64 array are 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 41 # supported but storage is not optimized (ie. they are plain python list, not
42 # array.array) 42 # array.array)
43 _kind_to_typecode = { 43 _kind_to_typecode_for_array = {
sdefresne 2014/09/15 08:46:54 nit: _kind_to_typecode_for_native_array
qsr 2014/09/15 11:01:53 Done.
44 mojom.INT8: "'b'", 44 mojom.INT8: "b",
45 mojom.UINT8: "'B'", 45 mojom.UINT8: "B",
46 mojom.INT16: "'h'", 46 mojom.INT16: "h",
47 mojom.UINT16: "'H'", 47 mojom.UINT16: "H",
48 mojom.INT32: "'i'", 48 mojom.INT32: "i",
49 mojom.UINT32: "'I'", 49 mojom.UINT32: "I",
50 mojom.FLOAT: "'f'", 50 mojom.FLOAT: "f",
51 mojom.DOUBLE: "'d'", 51 mojom.DOUBLE: "d",
52 } 52 }
53 53
54 _kind_to_typecode = dict(_kind_to_typecode_for_array)
55 _kind_to_typecode.update({
56 mojom.INT64: "q",
57 mojom.UINT64: "Q",
58 mojom.HANDLE: "i",
59 mojom.DCPIPE: "i",
60 mojom.DPPIPE: "i",
61 mojom.MSGPIPE: "i",
62 mojom.SHAREDBUFFER: "i",
63 mojom.NULLABLE_HANDLE: "i",
64 mojom.NULLABLE_DCPIPE: "i",
65 mojom.NULLABLE_DPPIPE: "i",
66 mojom.NULLABLE_MSGPIPE: "i",
67 mojom.NULLABLE_SHAREDBUFFER: "i",
68 })
69
54 70
55 def NameToComponent(name): 71 def NameToComponent(name):
56 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> 72 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
57 # HTTP_Entry2_FooBar) 73 # HTTP_Entry2_FooBar)
58 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) 74 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
59 # insert '_' between non upper and start of upper blocks (e.g., 75 # insert '_' between non upper and start of upper blocks (e.g.,
60 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) 76 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
61 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) 77 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
62 return [x.lower() for x in name.split('_')] 78 return [x.lower() for x in name.split('_')]
63 79
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 122
107 def GetStructClass(kind): 123 def GetStructClass(kind):
108 name = [] 124 name = []
109 if kind.imported_from: 125 if kind.imported_from:
110 name.append(kind.imported_from['python_module']) 126 name.append(kind.imported_from['python_module'])
111 name.append(GetNameForElement(kind)) 127 name.append(GetNameForElement(kind))
112 return '.'.join(name) 128 return '.'.join(name)
113 129
114 def GetFieldType(kind, field=None): 130 def GetFieldType(kind, field=None):
115 if mojom.IsAnyArrayKind(kind): 131 if mojom.IsAnyArrayKind(kind):
116 if kind.kind in _kind_to_typecode: 132 arguments = []
117 arguments = [ _kind_to_typecode[kind.kind] ] 133 if kind.kind in _kind_to_typecode_for_array:
118 else: 134 arguments.append('\'%s\'' %_kind_to_typecode_for_array[kind.kind])
sdefresne 2014/09/15 08:46:54 nit: you can use '%r' instead of '\'%s\'' to get a
qsr 2014/09/15 11:01:53 Done.
119 arguments = [ GetFieldType(kind.kind) ] 135 elif kind.kind != mojom.BOOL:
136 arguments.append(GetFieldType(kind.kind))
120 if mojom.IsNullableKind(kind): 137 if mojom.IsNullableKind(kind):
121 arguments.append("nullable=True") 138 arguments.append("nullable=True")
122 if mojom.IsFixedArrayKind(kind): 139 if mojom.IsFixedArrayKind(kind):
123 arguments.append("length=%d" % kind.length) 140 arguments.append("length=%d" % kind.length)
124 if kind.kind in _kind_to_typecode: 141 array_type = 'GenericArrayType'
125 return "_descriptor.NativeArrayType(%s)" % ", ".join(arguments) 142 if kind.kind == mojom.BOOL:
126 else: 143 array_type = 'BooleanArrayType'
127 return "_descriptor.PointerArrayType(%s)" % ", ".join(arguments) 144 elif kind.kind in _kind_to_typecode_for_array:
145 array_type = 'NativeArrayType'
146 return "_descriptor.%s(%s)" % (array_type, ", ".join(arguments))
128 147
129 if mojom.IsStructKind(kind): 148 if mojom.IsStructKind(kind):
130 arguments = [ GetStructClass(kind) ] 149 arguments = [ GetStructClass(kind) ]
131 if mojom.IsNullableKind(kind): 150 if mojom.IsNullableKind(kind):
132 arguments.append("nullable=True") 151 arguments.append("nullable=True")
133 return "_descriptor.StructType(%s)" % ", ".join(arguments) 152 return "_descriptor.StructType(%s)" % ", ".join(arguments)
134 153
135 if mojom.IsEnumKind(kind): 154 if mojom.IsEnumKind(kind):
136 return GetFieldType(mojom.INT32) 155 return GetFieldType(mojom.INT32)
137 156
138 return _kind_to_type.get(kind, "_descriptor.TYPE_NONE") 157 return _kind_to_type.get(kind, "_descriptor.TYPE_NONE")
139 158
159 def GetPackedFormatString(struct):
160 res = '='
161 for byte in struct.bytes:
162 if len(byte.packed_fields) > 1:
163 res += 'B'
164 else:
165 for packed_field in byte.packed_fields:
166 kind = packed_field.field.kind
167 if mojom.IsEnumKind(kind):
168 res += 'i'
169 else:
170 res += _kind_to_typecode.get(packed_field.field.kind, 'Q')
171 if byte.is_padding:
172 res += 'x'
173 return res
174
140 def GetFieldDescriptor(packed_field): 175 def GetFieldDescriptor(packed_field):
141 field = packed_field.field 176 field = packed_field.field
177 class_name = 'SingleFieldGroup'
178 if field.kind == mojom.BOOL:
179 class_name = 'FieldDescriptor'
142 arguments = [ '\'%s\'' % field.name ] 180 arguments = [ '\'%s\'' % field.name ]
143 arguments.append(GetFieldType(field.kind, field)) 181 arguments.append(GetFieldType(field.kind, field))
144 arguments.append(str(packed_field.offset)) 182 arguments.append(str(packed_field.field.ordinal))
145 if field.kind == mojom.BOOL:
146 arguments.append('bit_offset=%d' % packed_field.bit)
147 if field.default: 183 if field.default:
148 if mojom.IsStructKind(field.kind): 184 if mojom.IsStructKind(field.kind):
149 arguments.append('default_value=True') 185 arguments.append('default_value=True')
150 else: 186 else:
151 arguments.append('default_value=%s' % ExpressionToText(field.default)) 187 arguments.append('default_value=%s' % ExpressionToText(field.default))
152 return '_descriptor.FieldDescriptor(%s)' % ', '.join(arguments) 188 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments))
189
190 def GetFieldGroup(byte):
191 if len(byte.packed_fields) > 1:
192 descriptors = map(GetFieldDescriptor, byte.packed_fields)
193 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors)
194 for packed_field in byte.packed_fields:
195 return GetFieldDescriptor(packed_field)
sdefresne 2014/09/15 11:14:46 This return in a for loop is strange. Do you only
qsr 2014/09/15 11:42:00 Refactored by asserting the list has a single elem
196 print byte
sdefresne 2014/09/15 08:46:55 Are those two lines debug? Since the last line is
qsr 2014/09/15 11:01:53 The assert False is correct, the print was just fo
sdefresne 2014/09/15 11:14:46 Oh, you mean this line should not be reached? What
qsr 2014/09/15 11:42:00 Removed, asserting the list has a single element i
197 assert False
153 198
154 def ComputeStaticValues(module): 199 def ComputeStaticValues(module):
155 in_progress = set() 200 in_progress = set()
156 computed = set() 201 computed = set()
157 202
158 def GetComputedValue(named_value): 203 def GetComputedValue(named_value):
159 if isinstance(named_value, mojom.EnumValue): 204 if isinstance(named_value, mojom.EnumValue):
160 field = next(ifilter(lambda field: field.name == named_value.name, 205 field = next(ifilter(lambda field: field.name == named_value.name,
161 named_value.enum.fields), None) 206 named_value.enum.fields), None)
162 if not field: 207 if not field:
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 for constant in struct.constants: 267 for constant in struct.constants:
223 ResolveConstant(constant) 268 ResolveConstant(constant)
224 for enum in struct.enums: 269 for enum in struct.enums:
225 ResolveEnum(enum) 270 ResolveEnum(enum)
226 for field in struct.fields: 271 for field in struct.fields:
227 if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)): 272 if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
228 field.default.computed_value = GetComputedValue(field.default) 273 field.default.computed_value = GetComputedValue(field.default)
229 274
230 return module 275 return module
231 276
277 _HEADER_SIZE = 8
278
232 class Generator(generator.Generator): 279 class Generator(generator.Generator):
233 280
234 python_filters = { 281 python_filters = {
235 'expression_to_text': ExpressionToText, 282 'expression_to_text': ExpressionToText,
236 'field_descriptor': GetFieldDescriptor, 283 'field_group': GetFieldGroup,
237 'name': GetNameForElement, 284 'name': GetNameForElement,
285 'packed_format_string': GetPackedFormatString,
286 'struct_size': lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
238 } 287 }
239 288
240 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) 289 @UseJinja('python_templates/module.py.tmpl', filters=python_filters)
241 def GeneratePythonModule(self): 290 def GeneratePythonModule(self):
242 return { 291 return {
243 'imports': self.GetImports(), 292 'imports': self.GetImports(),
244 'enums': self.module.enums, 293 'enums': self.module.enums,
245 'module': ComputeStaticValues(self.module), 294 'module': ComputeStaticValues(self.module),
246 'structs': self.GetStructs(), 295 'structs': self.GetStructs(),
247 } 296 }
248 297
249 def GenerateFiles(self, args): 298 def GenerateFiles(self, args):
250 self.Write(self.GeneratePythonModule(), 299 self.Write(self.GeneratePythonModule(),
251 '%s.py' % self.module.name.replace('.mojom', '_mojom')) 300 '%s.py' % self.module.name.replace('.mojom', '_mojom'))
252 301
253 def GetImports(self): 302 def GetImports(self):
254 for each in self.module.imports: 303 for each in self.module.imports:
255 each['python_module'] = each['module_name'].replace('.mojom', '_mojom') 304 each['python_module'] = each['module_name'].replace('.mojom', '_mojom')
256 return self.module.imports 305 return self.module.imports
257 306
258 def GetJinjaParameters(self): 307 def GetJinjaParameters(self):
259 return { 308 return {
260 'lstrip_blocks': True, 309 'lstrip_blocks': True,
261 'trim_blocks': True, 310 'trim_blocks': True,
262 } 311 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698