Skip to content

Commit

Permalink
mojo: Start generating structs for python bindings
Browse files Browse the repository at this point in the history
R=pkl@chromium.org,cmasone@chromium.org

Review URL: https://codereview.chromium.org/538613005

Cr-Commit-Position: refs/heads/master@{#294161}
  • Loading branch information
qsr authored and Commit bot committed Sep 10, 2014
1 parent c648480 commit c53bf4a
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 6 deletions.
53 changes: 53 additions & 0 deletions mojo/public/python/mojo/bindings/reflection.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MyEnum(object):
This will define a enum with 3 values, A = 0, B = 1 and C = 5.
"""

def __new__(mcs, name, bases, dictionary):
class_members = {
'__new__': None,
Expand All @@ -37,3 +38,55 @@ def __setattr__(mcs, key, value):

def __delattr__(mcs, key):
raise AttributeError, 'can\'t delete attribute'


class MojoStructType(type):
"""Meta class for structs.
Usage:
class MyStruct(object):
__metaclass__ = MojoStructType
DESCRIPTOR = {
'constants': {
'C1': 1,
'C2': 2,
},
'enums': {
'ENUM1': [
('V1', 1),
'V2',
],
'ENUM2': [
('V1', 1),
'V2',
],
},
}
This will define an struct, with 2 constants C1 and C2, and 2 enums ENUM1
and ENUM2, each of those having 2 values, V1 and V2.
"""

def __new__(mcs, name, bases, dictionary):
class_members = {
'__slots__': [],
}
descriptor = dictionary.pop('DESCRIPTOR', {})

# Add constants
class_members.update(descriptor.get('constants', {}))

# Add enums
enums = descriptor.get('enums', {})
for key in enums:
class_members[key] = MojoEnumType(key,
(object,),
{ 'VALUES': enums[key] })

return type.__new__(mcs, name, bases, class_members)

def __setattr__(mcs, key, value):
raise AttributeError, 'can\'t set attribute'

def __delattr__(mcs, key):
raise AttributeError, 'can\'t delete attribute'
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def ConstantStyle(name):
return '_'.join([x.upper() for x in components])

def GetNameForElement(element):
if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or
mojom.IsStructKind(element)):
return UpperCamelCase(element.name)
if isinstance(element, mojom.EnumValue):
return (GetNameForElement(element.enum) + '.' +
ConstantStyle(element.name))
Expand Down Expand Up @@ -129,6 +132,7 @@ def GeneratePythonModule(self):
'imports': self.GetImports(),
'enums': self.module.enums,
'module': ComputeConstantValues(self.module),
'structs': self.GetStructs(),
}

def GenerateFiles(self, args):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% from "module_macros.tmpl" import enum_values %}
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
Expand All @@ -18,11 +19,28 @@ import {{import.python_module}}
{% endif %}
{% for enum in module.enums %}

class {{enum.name}}(object):
class {{enum|name}}(object):
__metaclass__ = _reflection.MojoEnumType
VALUES = [
{% for field in enum.fields %}
('{{field.name}}', {{field.computed_value}}),
{% endfor %}
]
VALUES = {{enum_values(enum)|indent(2)}}
{% endfor %}
{% for struct in module.structs %}

class {{struct|name}}(object):
__metaclass__ = _reflection.MojoStructType
DESCRIPTOR = {
{% if struct.constants %}
'constants': {
{% for constant in struct.constants %}
'{{constant|name}}': {{constant.value|expression_to_text}},
{% endfor %}
},
{% endif %}
{% if struct.enums %}
'enums': {
{% for enum in struct.enums %}
'{{enum|name}}': {{enum_values(enum)|indent(6)}},
{% endfor %}
},
{% endif %}
}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

{%- macro enum_values(enum) -%}
[
{% for field in enum.fields %}
('{{field.name}}', {{field.computed_value}}),
{% endfor %}
]
{%- endmacro -%}
1 change: 1 addition & 0 deletions mojo/public/tools/bindings/mojom.gni
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ template("mojom") {
"$generator_root/generators/js_templates/interface_definition.tmpl",
"$generator_root/generators/js_templates/module.js.tmpl",
"$generator_root/generators/js_templates/struct_definition.tmpl",
"$generator_root/generators/python_templates/module_macros.tmpl",
"$generator_root/generators/python_templates/module.py.tmpl",
"$generator_root/generators/mojom_cpp_generator.py",
"$generator_root/generators/mojom_js_generator.py",
Expand Down
1 change: 1 addition & 0 deletions mojo/public/tools/bindings/mojom_bindings_generator.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
'<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl',
'<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/module.js.tmpl',
'<(DEPTH)/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl',
'<(DEPTH)/mojo/public/tools/bindings/generators/python_templates/module_macros.tmpl',
'<(DEPTH)/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl',
'<(DEPTH)/mojo/public/tools/bindings/generators/mojom_cpp_generator.py',
'<(DEPTH)/mojo/public/tools/bindings/generators/mojom_java_generator.py',
Expand Down
11 changes: 11 additions & 0 deletions mojo/python/tests/bindings_constants_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,14 @@ def testConstantGeneration(self):
self.assertEquals(sample_service_mojom.FLOAT_NEGATIVE_INFINITY,
float('-inf'))
self.assertTrue(math.isnan(sample_service_mojom.FLOAT_NA_N))

def testConstantOnStructGeneration(self):
self.assertEquals(sample_service_mojom.Foo.FOOBY, "Fooby")

def testStructImmutability(self):
with self.assertRaises(AttributeError):
sample_service_mojom.Foo.FOOBY = 0
with self.assertRaises(AttributeError):
del sample_service_mojom.Foo.FOOBY
with self.assertRaises(AttributeError):
sample_service_mojom.Foo.BAR = 1
8 changes: 8 additions & 0 deletions mojo/python/tests/bindings_enums_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# Generated files
# pylint: disable=F0401
import sample_import_mojom
import sample_service_mojom


class EnumBindingsTest(unittest.TestCase):
Expand All @@ -27,6 +28,13 @@ def testTopLevelEnumGeneration(self):
self.assertEquals(sample_import_mojom.YetAnotherShape.CIRCLE, 21)
self.assertEquals(sample_import_mojom.YetAnotherShape.TRIANGLE, 22)

# Testing that internal enum class have expected constant values.
def testInternalEnumGeneration(self):
self.assertEquals(sample_service_mojom.Bar.Type.VERTICAL, 1)
self.assertEquals(sample_service_mojom.Bar.Type.HORIZONTAL, 2)
self.assertEquals(sample_service_mojom.Bar.Type.BOTH, 3)
self.assertEquals(sample_service_mojom.Bar.Type.INVALID, 4)

# Testing an enum class cannot be instantiated.
def testNonInstantiableEnum(self):
with self.assertRaises(TypeError):
Expand Down

0 comments on commit c53bf4a

Please sign in to comment.