Index: mojo/public/python/mojo/bindings/reflection.py |
diff --git a/mojo/public/python/mojo/bindings/reflection.py b/mojo/public/python/mojo/bindings/reflection.py |
index 5ee2c1dd0eec03afea0198265ce73692baa4c7ca..bb8dfe803327dffe1f70f30d7969553db38879b1 100644 |
--- a/mojo/public/python/mojo/bindings/reflection.py |
+++ b/mojo/public/python/mojo/bindings/reflection.py |
@@ -2,7 +2,7 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
-"""The meta classes used by the mojo python bindings.""" |
+"""The metaclasses used by the mojo python bindings.""" |
class MojoEnumType(type): |
"""Meta class for enumerations. |
@@ -16,22 +16,21 @@ class MojoEnumType(type): |
('C', 5), |
] |
- This will define a enum with 3 values, A = 0, B = 1 and C = 5. |
+ 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, |
- } |
+ dictionary['__slots__'] = () |
+ dictionary['__new__'] = None |
for value in dictionary.pop('VALUES', []): |
if not isinstance(value, tuple): |
raise ValueError('incorrect value: %r' % value) |
key, enum_value = value |
if isinstance(key, str) and isinstance(enum_value, int): |
- class_members[key] = enum_value |
+ dictionary[key] = enum_value |
else: |
raise ValueError('incorrect value: %r' % value) |
- return type.__new__(mcs, name, bases, class_members) |
+ return type.__new__(mcs, name, bases, dictionary) |
def __setattr__(mcs, key, value): |
raise AttributeError, 'can\'t set attribute' |
@@ -61,32 +60,65 @@ class MojoStructType(type): |
'V2', |
], |
}, |
+ 'fields': [ |
+ FieldDescriptor('x', _descriptor.TYPE_INT32, 0), |
+ ], |
} |
- 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. |
+ This will define an struct, with: |
+ - 2 constants 'C1' and 'C2'; |
+ - 2 enums 'ENUM1' and 'ENUM2', each of those having 2 values, 'V1' and |
+ 'V2'; |
+ - 1 int32 field named 'x'. |
""" |
def __new__(mcs, name, bases, dictionary): |
- class_members = { |
- '__slots__': [], |
- } |
+ dictionary['__slots__'] = ('_fields') |
descriptor = dictionary.pop('DESCRIPTOR', {}) |
# Add constants |
- class_members.update(descriptor.get('constants', {})) |
+ dictionary.update(descriptor.get('constants', {})) |
# Add enums |
enums = descriptor.get('enums', {}) |
for key in enums: |
- class_members[key] = MojoEnumType(key, |
- (object,), |
- { 'VALUES': enums[key] }) |
+ dictionary[key] = MojoEnumType(key, (object,), { 'VALUES': enums[key] }) |
- return type.__new__(mcs, name, bases, class_members) |
+ # Add fields |
+ for field in descriptor.get('fields', []): |
+ dictionary[field.name] = _BuildProperty(field) |
+ # Add init |
+ dictionary['__init__'] = _StructInit |
+ |
+ return type.__new__(mcs, name, bases, dictionary) |
+ |
+ # Prevent adding new attributes, or mutating constants. |
def __setattr__(mcs, key, value): |
raise AttributeError, 'can\'t set attribute' |
+ # Prevent deleting constants. |
def __delattr__(mcs, key): |
raise AttributeError, 'can\'t delete attribute' |
+ |
+ |
+def _StructInit(self, **kwargs): |
+ self._fields = {} |
+ for name in kwargs: |
+ self.__setattr__(name, kwargs[name]) |
+ |
+ |
+def _BuildProperty(field): |
+ """Build the property for the given field.""" |
+ |
+ # pylint: disable=W0212 |
+ def Get(self): |
+ if field.name not in self._fields: |
+ self._fields[field.name] = field.GetDefaultValue() |
+ return self._fields[field.name] |
+ |
+ # pylint: disable=W0212 |
+ def Set(self, value): |
+ self._fields[field.name] = field.field_type.Convert(value) |
+ |
+ return property(Get, Set) |