Add handling of DynamicObject

This commit is contained in:
Jason Paryani
2013-09-18 17:19:57 -07:00
parent fa5fe5a92c
commit da160960af
4 changed files with 99 additions and 4 deletions

View File

@@ -9,7 +9,7 @@
cimport cython cimport cython
cimport capnp_cpp as capnp cimport capnp_cpp as capnp
cimport schema_cpp cimport schema_cpp
from capnp_cpp cimport Schema as C_Schema, StructSchema as C_StructSchema, DynamicStruct as C_DynamicStruct, DynamicValue as C_DynamicValue, Type as C_Type, DynamicList as C_DynamicList, fixMaybe, getEnumString, SchemaParser as C_SchemaParser, ParsedSchema as C_ParsedSchema, VOID, ArrayPtr, StringPtr, String, StringTree, DynamicOrphan as C_DynamicOrphan, WordArrayPtr from capnp_cpp cimport Schema as C_Schema, StructSchema as C_StructSchema, DynamicStruct as C_DynamicStruct, DynamicValue as C_DynamicValue, Type as C_Type, DynamicList as C_DynamicList, fixMaybe, getEnumString, SchemaParser as C_SchemaParser, ParsedSchema as C_ParsedSchema, VOID, ArrayPtr, StringPtr, String, StringTree, DynamicOrphan as C_DynamicOrphan, DynamicObject as C_DynamicObject, WordArrayPtr
from schema_cpp cimport Node as C_Node, EnumNode as C_EnumNode from schema_cpp cimport Node as C_Node, EnumNode as C_EnumNode
from cython.operator cimport dereference as deref from cython.operator cimport dereference as deref
@@ -352,7 +352,7 @@ cdef to_python_reader(C_DynamicValue.Reader self, object parent):
elif type == capnp.TYPE_VOID: elif type == capnp.TYPE_VOID:
return None return None
elif type == capnp.TYPE_OBJECT: elif type == capnp.TYPE_OBJECT:
raise ValueError("Cannot convert type to Python. Object type is not supported in pycapnp yet") return _DynamicObjectReader()._init(self.asObject(), parent)
elif type == capnp.TYPE_UNKNOWN: elif type == capnp.TYPE_UNKNOWN:
raise ValueError("Cannot convert type to Python. Type is unknown by capnproto library") raise ValueError("Cannot convert type to Python. Type is unknown by capnproto library")
else: else:
@@ -382,7 +382,7 @@ cdef to_python_builder(C_DynamicValue.Builder self, object parent):
elif type == capnp.TYPE_VOID: elif type == capnp.TYPE_VOID:
return None return None
elif type == capnp.TYPE_OBJECT: elif type == capnp.TYPE_OBJECT:
raise ValueError("Cannot convert type to Python. Object type is not supported in pycapnp yet") raise ValueError("Cannot convert type to Python. Type is 'Object', but is being used improperly. You can only get 'Object' types from a struct")
elif type == capnp.TYPE_UNKNOWN: elif type == capnp.TYPE_UNKNOWN:
raise ValueError("Cannot convert type to Python. Type is unknown by capnproto library") raise ValueError("Cannot convert type to Python. Type is unknown by capnproto library")
else: else:
@@ -618,7 +618,21 @@ cdef class _DynamicStructBuilder:
return ret return ret
cdef _get(self, field): cdef _get(self, field):
return to_python_builder(self.thisptr.get(field), self._parent) cdef C_DynamicValue.Builder value = self.thisptr.get(field)
if value.getType() == capnp.TYPE_OBJECT:
return _DynamicObjectBuilder(field, self)
else:
return to_python_builder(value, self._parent)
cpdef _get_object(self, field, schema):
cdef _StructSchema s
if hasattr(schema, 'schema'):
s = schema.schema
else:
s = schema
return _DynamicStructBuilder()._init(self.thisptr.getObject(field, s.thisptr), self._parent)
def __getattr__(self, field): def __getattr__(self, field):
return self._get(field) return self._get(field)
@@ -771,6 +785,32 @@ cdef class _DynamicOrphan:
def __repr__(self): def __repr__(self):
return repr(self.get()) return repr(self.get())
cdef class _DynamicObjectReader:
cdef C_DynamicObject.Reader thisptr
cdef public object _parent
cdef _init(self, C_DynamicObject.Reader other, object parent):
self.thisptr = other
self._parent = parent
return self
cpdef as_struct(self, schema):
cdef _StructSchema s
if hasattr(schema, 'schema'):
s = schema.schema
else:
s = schema
return _DynamicStructReader()._init(self.thisptr.as(s.thisptr), self._parent)
cdef class _DynamicObjectBuilder:
cdef public object _field, _parent_struct
def __init__(self, field, parent_struct):
self._field = field
self._parent_struct = parent_struct
cpdef as_struct(self, schema):
return self._parent_struct._get_object(self._field, schema)
cdef class _Schema: cdef class _Schema:
cdef C_Schema thisptr cdef C_Schema thisptr
cdef _init(self, C_Schema other): cdef _init(self, C_Schema other):

View File

@@ -138,6 +138,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
void adopt(char *, DynamicOrphan) except +ValueError void adopt(char *, DynamicOrphan) except +ValueError
DynamicOrphan disown(char *) DynamicOrphan disown(char *)
DynamicStruct.Reader asReader() DynamicStruct.Reader asReader()
DynamicStruct.Builder getObject(char *, StructSchema)
cdef extern from "fixMaybe.h": cdef extern from "fixMaybe.h":
EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +ValueError EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +ValueError
@@ -149,6 +150,13 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
uint16_t getRaw() uint16_t getRaw()
Maybe[EnumSchema.Enumerant] getEnumerant() Maybe[EnumSchema.Enumerant] getEnumerant()
cdef cppclass DynamicObject:
cppclass Reader:
DynamicStruct.Reader as(StructSchema schema)
cppclass Builder:
DynamicObject.Reader asReader()
# DynamicList::Reader as(ListSchema schema) const;
cdef cppclass DynamicList: cdef cppclass DynamicList:
cppclass Reader: cppclass Reader:
DynamicValueForward.Reader operator[](uint) except +ValueError DynamicValueForward.Reader operator[](uint) except +ValueError
@@ -193,6 +201,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
char * asText"as< ::capnp::Text>().cStr"() char * asText"as< ::capnp::Text>().cStr"()
DynamicList.Reader asList"as< ::capnp::DynamicList>"() DynamicList.Reader asList"as< ::capnp::DynamicList>"()
DynamicStruct.Reader asStruct"as< ::capnp::DynamicStruct>"() DynamicStruct.Reader asStruct"as< ::capnp::DynamicStruct>"()
DynamicObject.Reader asObject"as< ::capnp::DynamicObject>"()
DynamicEnum asEnum"as< ::capnp::DynamicEnum>"() DynamicEnum asEnum"as< ::capnp::DynamicEnum>"()
Data.Reader asData"as< ::capnp::Data>"() Data.Reader asData"as< ::capnp::Data>"()

21
test/object.capnp Normal file
View File

@@ -0,0 +1,21 @@
@0x8186ddb142b58556;
struct Person {
id @0 :UInt32;
name @1 :Text;
}
struct Place {
id @0 :UInt32;
name @1 :Text;
}
struct Thing {
id @0 :UInt64;
value @1 :UInt64;
}
struct TestObject {
object @0 :Object;
}

25
test/test_object.py Normal file
View File

@@ -0,0 +1,25 @@
import pytest
import capnp
import os
import math
this_dir = os.path.dirname(__file__)
@pytest.fixture
def object():
return capnp.load(os.path.join(this_dir, 'object.capnp'))
def test_object_basic(object):
obj = object.TestObject.new_message()
person = obj.object.as_struct(object.Person)
person.name = 'test'
person.id = 1000
same_person = obj.object.as_struct(object.Person)
assert same_person.name == 'test'
assert same_person.id == 1000
obj_r = obj.as_reader()
same_person = obj_r.object.as_struct(object.Person)
assert same_person.name == 'test'
assert same_person.id == 1000