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

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

Issue 551053002: mojo: Adding struct's fields for python bindings (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding constructors. 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
11 import mojom.generate.module as mojom 11 import mojom.generate.module as mojom
12 from mojom.generate.template_expander import UseJinja 12 from mojom.generate.template_expander import UseJinja
13 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
14 40
15 def NameToComponent(name): 41 def NameToComponent(name):
16 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> 42 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
17 # HTTP_Entry2_FooBar) 43 # HTTP_Entry2_FooBar)
18 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) 44 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
19 # insert '_' between non upper and start of upper blocks (e.g., 45 # insert '_' between non upper and start of upper blocks (e.g.,
20 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) 46 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
21 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) 47 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
22 return [x.lower() for x in name.split('_')] 48 return [x.lower() for x in name.split('_')]
23 49
(...skipping 17 matching lines...) Expand all
41 if isinstance(element, mojom.EnumValue): 67 if isinstance(element, mojom.EnumValue):
42 return (GetNameForElement(element.enum) + '.' + 68 return (GetNameForElement(element.enum) + '.' +
43 ConstantStyle(element.name)) 69 ConstantStyle(element.name))
44 if isinstance(element, (mojom.NamedValue, 70 if isinstance(element, (mojom.NamedValue,
45 mojom.Constant)): 71 mojom.Constant)):
46 return ConstantStyle(element.name) 72 return ConstantStyle(element.name)
47 raise Exception('Unexpected element: ' % element) 73 raise Exception('Unexpected element: ' % element)
48 74
49 def ExpressionToText(token): 75 def ExpressionToText(token):
50 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)): 76 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
51 # Both variable and enum constants are constructed like: 77 return str(token.computed_value)
52 # PythonModule[.Struct][.Enum].CONSTANT_NAME
53 name = []
54 if token.imported_from:
55 name.append(token.imported_from['python_module'])
56 if token.parent_kind:
57 name.append(GetNameForElement(token.parent_kind))
58 name.append(GetNameForElement(token))
59 return '.'.join(name)
60 78
61 if isinstance(token, mojom.BuiltinValue): 79 if isinstance(token, mojom.BuiltinValue):
62 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': 80 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY':
63 return 'float(\'inf\')'; 81 return 'float(\'inf\')';
64 if (token.value == 'double.NEGATIVE_INFINITY' or 82 if (token.value == 'double.NEGATIVE_INFINITY' or
65 token.value == 'float.NEGATIVE_INFINITY'): 83 token.value == 'float.NEGATIVE_INFINITY'):
66 return 'float(\'-inf\')' 84 return 'float(\'-inf\')'
67 if token.value == 'double.NAN' or token.value == 'float.NAN': 85 if token.value == 'double.NAN' or token.value == 'float.NAN':
68 return 'float(\'nan\')'; 86 return 'float(\'nan\')';
69 87
88 if token in ["true", "false"]:
89 return str(token == "true")
90
70 return token 91 return token
71 92
93 def GetStructClass(kind):
94 name = []
95 if kind.imported_from:
96 name.append(kind.imported_from['python_module'])
97 name.append(GetNameForElement(kind))
98 return '.'.join(name)
72 99
73 def ComputeConstantValues(module): 100 def GetFieldType(kind, field=None):
101 if mojom.IsAnyArrayKind(kind):
102 arguments = [ GetFieldType(kind.kind) ]
103 if mojom.IsNullableKind(kind):
104 arguments.append("nullable=True")
105 if mojom.IsFixedArrayKind(kind):
106 arguments.append("length=%d" % kind.length)
107 return "_descriptor.ArrayType(%s)" % ", ".join(arguments)
108
109 if mojom.IsStructKind(kind):
110 arguments = [ GetStructClass(kind) ]
111 if mojom.IsNullableKind(kind):
112 arguments.append("nullable=True")
113 return "_descriptor.StructType(%s)" % ", ".join(arguments)
114
115 if mojom.IsEnumKind(kind):
116 return GetFieldType(mojom.INT32)
117
118 return _kind_to_type.get(kind, "_descriptor.TYPE_NONE")
119
120 def GetFieldDescriptor(packed_field):
121 field = packed_field.field
122 arguments = [ '\'%s\'' % field.name ]
123 arguments.append(GetFieldType(field.kind, field))
124 arguments.append(str(packed_field.offset))
125 if field.kind == mojom.BOOL:
126 arguments.append('bit_offset=%d' % packed_field.bit)
127 if field.default:
128 if mojom.IsStructKind(field.kind):
129 arguments.append('default_value=True')
130 else:
131 arguments.append('default_value=%s' % ExpressionToText(field.default))
132 return '_descriptor.FieldDescriptor(%s)' % ', '.join(arguments)
133
134 def ComputeStaticValues(module):
74 in_progress = set() 135 in_progress = set()
75 computed = set() 136 computed = set()
76 137
77 def ResolveEnum(enum): 138 def GetComputedValue(named_value):
78 def GetComputedValue(enum_value): 139 if isinstance(named_value, mojom.EnumValue):
79 field = next(ifilter(lambda field: field.name == enum_value.name, 140 field = next(ifilter(lambda field: field.name == named_value.name,
80 enum_value.enum.fields), None) 141 named_value.enum.fields), None)
81 if not field: 142 if not field:
82 raise RuntimeError( 143 raise RuntimeError(
83 'Unable to get computed value for field %s of enum %s' % 144 'Unable to get computed value for field %s of enum %s' %
84 (enum_value.name, enum_value.enum.name)) 145 (named_value.name, named_value.enum.name))
85 if field not in computed: 146 if field not in computed:
86 ResolveEnum(enum_value.enum) 147 ResolveEnum(named_value.enum)
87 return field.computed_value 148 return field.computed_value
149 elif isinstance(named_value, mojom.ConstantValue):
150 ResolveConstant(named_value.constant)
151 named_value.computed_value = named_value.constant.computed_value
152 return named_value.computed_value
153 else:
154 print named_value
88 155
156 def ResolveConstant(constant):
157 if constant in computed:
158 return
159 if constant in in_progress:
160 raise RuntimeError('Circular dependency for constant: %s' % constant.name)
161 in_progress.add(constant)
162 if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
163 computed_value = GetComputedValue(constant.value)
164 else:
165 computed_value = ExpressionToText(constant.value)
166 constant.computed_value = computed_value
167 in_progress.remove(constant)
168 computed.add(constant)
169
170 def ResolveEnum(enum):
89 def ResolveEnumField(enum, field, default_value): 171 def ResolveEnumField(enum, field, default_value):
90 if field in computed: 172 if field in computed:
91 return 173 return
92 if field in in_progress: 174 if field in in_progress:
93 raise RuntimeError('Circular dependency for enum: %s' % enum.name) 175 raise RuntimeError('Circular dependency for enum: %s' % enum.name)
94 in_progress.add(field) 176 in_progress.add(field)
95 if field.value: 177 if field.value:
96 if isinstance(field.value, mojom.EnumValue): 178 if isinstance(field.value, mojom.EnumValue):
97 computed_value = GetComputedValue(field.value) 179 computed_value = GetComputedValue(field.value)
98 elif isinstance(field.value, str): 180 elif isinstance(field.value, str):
99 computed_value = int(field.value, 0) 181 computed_value = int(field.value, 0)
100 else: 182 else:
101 raise RuntimeError('Unexpected value: %r' % field.value) 183 raise RuntimeError('Unexpected value: %s' % field.value)
102 else: 184 else:
103 computed_value = default_value 185 computed_value = default_value
104 field.computed_value = computed_value 186 field.computed_value = computed_value
105 in_progress.remove(field) 187 in_progress.remove(field)
106 computed.add(field) 188 computed.add(field)
107 189
108 current_value = 0 190 current_value = 0
109 for field in enum.fields: 191 for field in enum.fields:
110 ResolveEnumField(enum, field, current_value) 192 ResolveEnumField(enum, field, current_value)
111 current_value = field.computed_value + 1 193 current_value = field.computed_value + 1
112 194
195 for constant in module.constants:
196 ResolveConstant(constant)
197
113 for enum in module.enums: 198 for enum in module.enums:
114 ResolveEnum(enum) 199 ResolveEnum(enum)
115 200
116 for struct in module.structs: 201 for struct in module.structs:
202 for constant in struct.constants:
203 ResolveConstant(constant)
117 for enum in struct.enums: 204 for enum in struct.enums:
118 ResolveEnum(enum) 205 ResolveEnum(enum)
206 for field in struct.fields:
207 if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
208 field.default.computed_value = GetComputedValue(field.default)
119 209
120 return module 210 return module
121 211
122 class Generator(generator.Generator): 212 class Generator(generator.Generator):
123 213
124 python_filters = { 214 python_filters = {
125 'expression_to_text': ExpressionToText, 215 'expression_to_text': ExpressionToText,
216 'field_descriptor': GetFieldDescriptor,
126 'name': GetNameForElement, 217 'name': GetNameForElement,
127 } 218 }
128 219
129 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) 220 @UseJinja('python_templates/module.py.tmpl', filters=python_filters)
130 def GeneratePythonModule(self): 221 def GeneratePythonModule(self):
131 return { 222 return {
132 'imports': self.GetImports(), 223 'imports': self.GetImports(),
133 'enums': self.module.enums, 224 'enums': self.module.enums,
134 'module': ComputeConstantValues(self.module), 225 'module': ComputeStaticValues(self.module),
135 'structs': self.GetStructs(), 226 'structs': self.GetStructs(),
136 } 227 }
137 228
138 def GenerateFiles(self, args): 229 def GenerateFiles(self, args):
139 self.Write(self.GeneratePythonModule(), 230 self.Write(self.GeneratePythonModule(),
140 '%s.py' % self.module.name.replace('.mojom', '_mojom')) 231 '%s.py' % self.module.name.replace('.mojom', '_mojom'))
141 232
142 def GetImports(self): 233 def GetImports(self):
143 for each in self.module.imports: 234 for each in self.module.imports:
144 each['python_module'] = each['module_name'].replace('.mojom', '_mojom') 235 each['python_module'] = each['module_name'].replace('.mojom', '_mojom')
145 return self.module.imports 236 return self.module.imports
146 237
147 def GetJinjaParameters(self): 238 def GetJinjaParameters(self):
148 return { 239 return {
149 'lstrip_blocks': True, 240 'lstrip_blocks': True,
150 'trim_blocks': True, 241 'trim_blocks': True,
151 } 242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698