Fix bug in exception handling for which(). Also standardize exceptions
to always be ValueError. Add the beginnings of to_dict()
This commit is contained in:
115
capnp/capnp.pyx
115
capnp/capnp.pyx
@@ -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, SchemaParser as C_SchemaParser, ParsedSchema as C_ParsedSchema, VOID, ArrayPtr, StringPtr, String, StringTree, DynamicOrphan as C_DynamicOrphan
|
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
|
||||||
|
|
||||||
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
|
||||||
@@ -130,7 +130,7 @@ cdef class _DynamicListReader:
|
|||||||
This class thinly wraps the C++ Cap'n Proto DynamicList::Reader class. __getitem__ and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
|
This class thinly wraps the C++ Cap'n Proto DynamicList::Reader class. __getitem__ and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
|
||||||
|
|
||||||
...
|
...
|
||||||
person = addressbook.Person.readFrom(file)
|
person = addressbook.Person.read(file)
|
||||||
|
|
||||||
phones = person.phones # This returns a _DynamicListReader
|
phones = person.phones # This returns a _DynamicListReader
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ cdef class _DynamicResizableListBuilder:
|
|||||||
This class works much like :class:`_DynamicListBuilder`, but it allows growing the list dynamically. It is meant for lists of structs, since for primitive types like int or float, you're much better off using a normal python list and then serializing straight to a Cap'n Proto list. It has __getitem__ and __len__ defined, but not __setitem__::
|
This class works much like :class:`_DynamicListBuilder`, but it allows growing the list dynamically. It is meant for lists of structs, since for primitive types like int or float, you're much better off using a normal python list and then serializing straight to a Cap'n Proto list. It has __getitem__ and __len__ defined, but not __setitem__::
|
||||||
|
|
||||||
...
|
...
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
phones = person.init_resizable_list('phones') # This returns a _DynamicResizableListBuilder
|
phones = person.init_resizable_list('phones') # This returns a _DynamicResizableListBuilder
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ cdef class _DynamicListBuilder:
|
|||||||
This class thinly wraps the C++ Cap'n Proto DynamicList::Bulder class. __getitem__, __setitem__, and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
|
This class thinly wraps the C++ Cap'n Proto DynamicList::Bulder class. __getitem__, __setitem__, and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
|
||||||
|
|
||||||
...
|
...
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
phones = person.init('phones', 2) # This returns a _DynamicListBuilder
|
phones = person.init('phones', 2) # This returns a _DynamicListBuilder
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ cdef class _DynamicListBuilder:
|
|||||||
self._parent = parent
|
self._parent = parent
|
||||||
return self
|
return self
|
||||||
|
|
||||||
cdef _get(self, index) except +ValueError:
|
cdef _get(self, index):
|
||||||
return to_python_builder(self.thisptr[index], self._parent)
|
return to_python_builder(self.thisptr[index], self._parent)
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
@@ -420,12 +420,33 @@ cdef _setDynamicField(_DynamicSetterClasses thisptr, field, value, parent):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Non primitive type")
|
raise ValueError("Non primitive type")
|
||||||
|
|
||||||
|
cdef _to_dict(msg):
|
||||||
|
msg_type = type(msg)
|
||||||
|
if msg_type is _DynamicListBuilder:
|
||||||
|
return [_to_dict(x) for x in msg]
|
||||||
|
|
||||||
|
if msg_type is _DynamicStructBuilder:
|
||||||
|
ret = {}
|
||||||
|
try:
|
||||||
|
which = msg.which()
|
||||||
|
ret['which'] = which
|
||||||
|
ret[which] = getattr(msg, which)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for field in msg.schema.non_union_fields:
|
||||||
|
ret[field] = _to_dict(getattr(msg, field))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return msg
|
||||||
|
|
||||||
cdef class _DynamicStructReader:
|
cdef class _DynamicStructReader:
|
||||||
"""Reads Cap'n Proto structs
|
"""Reads Cap'n Proto structs
|
||||||
|
|
||||||
This class is almost a 1 for 1 wrapping of the Cap'n Proto C++ DynamicStruct::Reader. The only difference is that instead of a `get` method, __getattr__ is overloaded and the field name is passed onto the C++ equivalent `get`. This means you just use . syntax to access any field. For field names that don't follow valid python naming convention for fields, use the global function :py:func:`getattr`::
|
This class is almost a 1 for 1 wrapping of the Cap'n Proto C++ DynamicStruct::Reader. The only difference is that instead of a `get` method, __getattr__ is overloaded and the field name is passed onto the C++ equivalent `get`. This means you just use . syntax to access any field. For field names that don't follow valid python naming convention for fields, use the global function :py:func:`getattr`::
|
||||||
|
|
||||||
person = addressbook.Person.readFrom(file) # This returns a _DynamicStructReader
|
person = addressbook.Person.read(file) # This returns a _DynamicStructReader
|
||||||
print person.name # using . syntax
|
print person.name # using . syntax
|
||||||
print getattr(person, 'field-with-hyphens') # for names that are invalid for python, use getattr
|
print getattr(person, 'field-with-hyphens') # for names that are invalid for python, use getattr
|
||||||
"""
|
"""
|
||||||
@@ -443,12 +464,12 @@ cdef class _DynamicStructReader:
|
|||||||
def _has(self, field):
|
def _has(self, field):
|
||||||
return self.thisptr.has(field)
|
return self.thisptr.has(field)
|
||||||
|
|
||||||
cpdef which(self) except +ValueError:
|
cpdef which(self):
|
||||||
"""Returns the enum corresponding to the union in this struct
|
"""Returns the enum corresponding to the union in this struct
|
||||||
|
|
||||||
Enums are just strings in the python Cap'n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn't a union, or a struct with an unnamed union::
|
Enums are just strings in the python Cap'n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn't a union, or a struct with an unnamed union::
|
||||||
|
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
person.which()
|
person.which()
|
||||||
# ValueError: member was null
|
# ValueError: member was null
|
||||||
@@ -462,7 +483,11 @@ cdef class _DynamicStructReader:
|
|||||||
|
|
||||||
:Raises: :exc:`exceptions.ValueError` if this struct doesn't contain a union
|
:Raises: :exc:`exceptions.ValueError` if this struct doesn't contain a union
|
||||||
"""
|
"""
|
||||||
return fixMaybe(self.thisptr.which()).getProto().getName().cStr()
|
cdef object which = getEnumString(self.thisptr)
|
||||||
|
if len(which) == 0:
|
||||||
|
raise ValueError("Attempted to call which on a non-union type")
|
||||||
|
|
||||||
|
return which
|
||||||
|
|
||||||
property schema:
|
property schema:
|
||||||
"""A property that returns the _StructSchema object matching this reader"""
|
"""A property that returns the _StructSchema object matching this reader"""
|
||||||
@@ -478,12 +503,15 @@ cdef class _DynamicStructReader:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s reader %s>' % (self.schema.node.displayName, strStructReader(self.thisptr).cStr())
|
return '<%s reader %s>' % (self.schema.node.displayName, strStructReader(self.thisptr).cStr())
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return _to_dict(self)
|
||||||
|
|
||||||
cdef class _DynamicStructBuilder:
|
cdef class _DynamicStructBuilder:
|
||||||
"""Builds Cap'n Proto structs
|
"""Builds Cap'n Proto structs
|
||||||
|
|
||||||
This class is almost a 1 for 1 wrapping of the Cap'n Proto C++ DynamicStruct::Builder. The only difference is that instead of a `get`/`set` method, __getattr__/__setattr__ is overloaded and the field name is passed onto the C++ equivalent function. This means you just use . syntax to access or set any field. For field names that don't follow valid python naming convention for fields, use the global functions :py:func:`getattr`/:py:func:`setattr`::
|
This class is almost a 1 for 1 wrapping of the Cap'n Proto C++ DynamicStruct::Builder. The only difference is that instead of a `get`/`set` method, __getattr__/__setattr__ is overloaded and the field name is passed onto the C++ equivalent function. This means you just use . syntax to access or set any field. For field names that don't follow valid python naming convention for fields, use the global functions :py:func:`getattr`/:py:func:`setattr`::
|
||||||
|
|
||||||
person = addressbook.Person.newMessage() # This returns a _DynamicStructBuilder
|
person = addressbook.Person.new_message() # This returns a _DynamicStructBuilder
|
||||||
|
|
||||||
person.name = 'foo' # using . syntax
|
person.name = 'foo' # using . syntax
|
||||||
print person.name # using . syntax
|
print person.name # using . syntax
|
||||||
@@ -534,7 +562,7 @@ cdef class _DynamicStructBuilder:
|
|||||||
raise ValueError("You can only call write() on the message's root struct.")
|
raise ValueError("You can only call write() on the message's root struct.")
|
||||||
_write_packed_message_to_fd(file.fileno(), self._parent)
|
_write_packed_message_to_fd(file.fileno(), self._parent)
|
||||||
|
|
||||||
cdef _get(self, field) except +ValueError:
|
cdef _get(self, field):
|
||||||
return to_python_builder(self.thisptr.get(field), self._parent)
|
return to_python_builder(self.thisptr.get(field), self._parent)
|
||||||
|
|
||||||
def __getattr__(self, field):
|
def __getattr__(self, field):
|
||||||
@@ -546,7 +574,7 @@ cdef class _DynamicStructBuilder:
|
|||||||
def _has(self, field):
|
def _has(self, field):
|
||||||
return self.thisptr.has(field)
|
return self.thisptr.has(field)
|
||||||
|
|
||||||
cpdef init(self, field, size=None) except +AttributeError:
|
cpdef init(self, field, size=None):
|
||||||
"""Method for initializing fields that are of type union/struct/list
|
"""Method for initializing fields that are of type union/struct/list
|
||||||
|
|
||||||
Typically, you don't have to worry about initializing structs/unions, so this method is mainly for lists.
|
Typically, you don't have to worry about initializing structs/unions, so this method is mainly for lists.
|
||||||
@@ -559,7 +587,7 @@ cdef class _DynamicStructBuilder:
|
|||||||
|
|
||||||
:rtype: :class:`_DynamicStructBuilder` or :class:`_DynamicListBuilder`
|
:rtype: :class:`_DynamicStructBuilder` or :class:`_DynamicListBuilder`
|
||||||
|
|
||||||
:Raises: :exc:`exceptions.AttributeError` if the field isn't in this struct
|
:Raises: :exc:`exceptions.ValueError` if the field isn't in this struct
|
||||||
"""
|
"""
|
||||||
if size is None:
|
if size is None:
|
||||||
return to_python_builder(self.thisptr.init(field), self._parent)
|
return to_python_builder(self.thisptr.init(field), self._parent)
|
||||||
@@ -578,16 +606,16 @@ cdef class _DynamicStructBuilder:
|
|||||||
|
|
||||||
:rtype: :class:`_DynamicResizableListBuilder`
|
:rtype: :class:`_DynamicResizableListBuilder`
|
||||||
|
|
||||||
:Raises: :exc:`exceptions.AttributeError` if the field isn't in this struct
|
:Raises: :exc:`exceptions.ValueError` if the field isn't in this struct
|
||||||
"""
|
"""
|
||||||
return _DynamicResizableListBuilder(self, field, _StructSchema()._init((<C_DynamicValue.Builder>self.thisptr.get(field)).asList().getStructElementType()))
|
return _DynamicResizableListBuilder(self, field, _StructSchema()._init((<C_DynamicValue.Builder>self.thisptr.get(field)).asList().getStructElementType()))
|
||||||
|
|
||||||
cpdef which(self) except +ValueError:
|
cpdef which(self):
|
||||||
"""Returns the enum corresponding to the union in this struct
|
"""Returns the enum corresponding to the union in this struct
|
||||||
|
|
||||||
Enums are just strings in the python Cap'n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn't a union, or a struct with an unnamed union::
|
Enums are just strings in the python Cap'n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn't a union, or a struct with an unnamed union::
|
||||||
|
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
person.which()
|
person.which()
|
||||||
# ValueError: member was null
|
# ValueError: member was null
|
||||||
@@ -601,7 +629,11 @@ cdef class _DynamicStructBuilder:
|
|||||||
|
|
||||||
:Raises: :exc:`exceptions.ValueError` if this struct doesn't contain a union
|
:Raises: :exc:`exceptions.ValueError` if this struct doesn't contain a union
|
||||||
"""
|
"""
|
||||||
return fixMaybe(self.thisptr.which()).getProto().getName().cStr()
|
cdef object which = getEnumString(self.thisptr)
|
||||||
|
if len(which) == 0:
|
||||||
|
raise ValueError("Attempted to call which on a non-union type")
|
||||||
|
|
||||||
|
return which
|
||||||
|
|
||||||
cpdef adopt(self, field, _DynamicOrphan orphan):
|
cpdef adopt(self, field, _DynamicOrphan orphan):
|
||||||
"""A method for adopting Cap'n Proto orphans
|
"""A method for adopting Cap'n Proto orphans
|
||||||
@@ -657,6 +689,9 @@ cdef class _DynamicStructBuilder:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s builder %s>' % (self.schema.node.displayName, strStructBuilder(self.thisptr).cStr())
|
return '<%s builder %s>' % (self.schema.node.displayName, strStructBuilder(self.thisptr).cStr())
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return _to_dict(self)
|
||||||
|
|
||||||
cdef class _DynamicOrphan:
|
cdef class _DynamicOrphan:
|
||||||
cdef C_DynamicOrphan thisptr
|
cdef C_DynamicOrphan thisptr
|
||||||
cdef public object _parent
|
cdef public object _parent
|
||||||
@@ -701,10 +736,12 @@ cdef class _Schema:
|
|||||||
|
|
||||||
cdef class _StructSchema:
|
cdef class _StructSchema:
|
||||||
cdef C_StructSchema thisptr
|
cdef C_StructSchema thisptr
|
||||||
cdef object __fieldnames
|
cdef object __fieldnames, __union_fields, __non_union_fields
|
||||||
cdef _init(self, C_StructSchema other):
|
cdef _init(self, C_StructSchema other):
|
||||||
self.thisptr = other
|
self.thisptr = other
|
||||||
self.__fieldnames = None
|
self.__fieldnames = None
|
||||||
|
self.__union_fields = None
|
||||||
|
self.__non_union_fields = None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
property fieldnames:
|
property fieldnames:
|
||||||
@@ -718,6 +755,28 @@ cdef class _StructSchema:
|
|||||||
for i in xrange(nfields))
|
for i in xrange(nfields))
|
||||||
return self.__fieldnames
|
return self.__fieldnames
|
||||||
|
|
||||||
|
property union_fields:
|
||||||
|
"""A tuple of the field names in the struct."""
|
||||||
|
def __get__(self):
|
||||||
|
if self.__union_fields is not None:
|
||||||
|
return self.__union_fields
|
||||||
|
fieldlist = self.thisptr.getUnionFields()
|
||||||
|
nfields = fieldlist.size()
|
||||||
|
self.__union_fields = tuple(fieldlist[i].getProto().getName().cStr()
|
||||||
|
for i in xrange(nfields))
|
||||||
|
return self.__union_fields
|
||||||
|
|
||||||
|
property non_union_fields:
|
||||||
|
"""A tuple of the field names in the struct."""
|
||||||
|
def __get__(self):
|
||||||
|
if self.__non_union_fields is not None:
|
||||||
|
return self.__non_union_fields
|
||||||
|
fieldlist = self.thisptr.getNonUnionFields()
|
||||||
|
nfields = fieldlist.size()
|
||||||
|
self.__non_union_fields = tuple(fieldlist[i].getProto().getName().cStr()
|
||||||
|
for i in xrange(nfields))
|
||||||
|
return self.__non_union_fields
|
||||||
|
|
||||||
property node:
|
property node:
|
||||||
"""The raw schema node"""
|
"""The raw schema node"""
|
||||||
def __get__(self):
|
def __get__(self):
|
||||||
@@ -786,7 +845,7 @@ cdef class SchemaParser:
|
|||||||
addressbook = parser.load('addressbook.capnp')
|
addressbook = parser.load('addressbook.capnp')
|
||||||
print addressbook.qux # qux is a top level constant
|
print addressbook.qux # qux is a top level constant
|
||||||
# 123
|
# 123
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
:type file_name: str
|
:type file_name: str
|
||||||
:param file_name: A relative or absolute path to a Cap'n Proto schema
|
:param file_name: A relative or absolute path to a Cap'n Proto schema
|
||||||
@@ -820,18 +879,24 @@ cdef class SchemaParser:
|
|||||||
proto = schema.get_proto()
|
proto = schema.get_proto()
|
||||||
if proto.isStruct:
|
if proto.isStruct:
|
||||||
local_module.schema = schema.as_struct()
|
local_module.schema = schema.as_struct()
|
||||||
def read(file):
|
def read(local_module):
|
||||||
|
def read_helper(file):
|
||||||
reader = _StreamFdMessageReader(file.fileno())
|
reader = _StreamFdMessageReader(file.fileno())
|
||||||
return reader.get_root(local_module)
|
return reader.get_root(local_module)
|
||||||
|
return read_helper
|
||||||
def read_packed(file):
|
def read_packed(file):
|
||||||
|
def read_helper(file):
|
||||||
reader = _PackedFdMessageReader(file.fileno())
|
reader = _PackedFdMessageReader(file.fileno())
|
||||||
return reader.get_root(local_module)
|
return reader.get_root(local_module)
|
||||||
def new_message():
|
return read_helper
|
||||||
|
def new_message(local_module):
|
||||||
|
def helper():
|
||||||
builder = _MallocMessageBuilder()
|
builder = _MallocMessageBuilder()
|
||||||
return builder.init_root(local_module)
|
return builder.init_root(local_module)
|
||||||
local_module.read = read
|
return helper
|
||||||
local_module.read_packed = read_packed
|
local_module.read = read(local_module)
|
||||||
local_module.new_message = new_message
|
local_module.read_packed = read_packed(local_module)
|
||||||
|
local_module.new_message = new_message(local_module)
|
||||||
elif proto.isConst:
|
elif proto.isConst:
|
||||||
module.__dict__[node.name] = schema.as_const_value()
|
module.__dict__[node.name] = schema.as_const_value()
|
||||||
|
|
||||||
@@ -1110,7 +1175,7 @@ def load(file_name, display_name=None, imports=[]):
|
|||||||
addressbook = capnp.load('addressbook.capnp')
|
addressbook = capnp.load('addressbook.capnp')
|
||||||
print addressbook.qux # qux is a top level constant in the addressbook.capnp schema
|
print addressbook.qux # qux is a top level constant in the addressbook.capnp schema
|
||||||
# 123
|
# 123
|
||||||
person = addressbook.Person.newMessage()
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
:type file_name: str
|
:type file_name: str
|
||||||
:param file_name: A relative or absolute path to a Cap'n Proto schema
|
:param file_name: A relative or absolute path to a Cap'n Proto schema
|
||||||
|
|||||||
@@ -50,7 +50,14 @@ cdef extern from "capnp/schema.h" namespace " ::capnp":
|
|||||||
uint size()
|
uint size()
|
||||||
Field operator[](uint index)
|
Field operator[](uint index)
|
||||||
|
|
||||||
|
cppclass FieldSubset:
|
||||||
|
uint size()
|
||||||
|
Field operator[](uint index)
|
||||||
|
|
||||||
FieldList getFields()
|
FieldList getFields()
|
||||||
|
FieldSubset getUnionFields()
|
||||||
|
FieldSubset getNonUnionFields()
|
||||||
|
|
||||||
Field getFieldByName(char * name)
|
Field getFieldByName(char * name)
|
||||||
|
|
||||||
cdef cppclass EnumSchema:
|
cdef cppclass EnumSchema:
|
||||||
@@ -101,20 +108,21 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
Builder()
|
Builder()
|
||||||
Builder(Builder &)
|
Builder(Builder &)
|
||||||
DynamicValueForward.Builder get(char *)
|
DynamicValueForward.Builder get(char *) except +ValueError
|
||||||
bint has(char *) except +ValueError
|
bint has(char *) except +ValueError
|
||||||
void set(char *, DynamicValueForward.Reader) except +ValueError
|
void set(char *, DynamicValueForward.Reader) except +ValueError
|
||||||
DynamicValueForward.Builder init(char *, uint size)
|
DynamicValueForward.Builder init(char *, uint size) except +ValueError
|
||||||
DynamicValueForward.Builder init(char *)
|
DynamicValueForward.Builder init(char *) except +ValueError
|
||||||
StructSchema getSchema()
|
StructSchema getSchema()
|
||||||
Maybe[StructSchema.Field] which()
|
Maybe[StructSchema.Field] which()
|
||||||
void adopt(char *, DynamicOrphan)
|
void adopt(char *, DynamicOrphan) except +ValueError
|
||||||
DynamicOrphan disown(char *)
|
DynamicOrphan disown(char *)
|
||||||
DynamicStruct.Reader asReader()
|
DynamicStruct.Reader asReader()
|
||||||
|
|
||||||
cdef extern from "fixMaybe.h":
|
cdef extern from "fixMaybe.h":
|
||||||
StructSchema.Field fixMaybe(Maybe[StructSchema.Field]) except+
|
EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except +ValueError
|
||||||
EnumSchema.Enumerant fixMaybe(Maybe[EnumSchema.Enumerant]) except+
|
char * getEnumString(DynamicStruct.Reader val)
|
||||||
|
char * getEnumString(DynamicStruct.Builder val)
|
||||||
|
|
||||||
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
||||||
cdef cppclass DynamicEnum:
|
cdef cppclass DynamicEnum:
|
||||||
@@ -128,11 +136,11 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
|||||||
cppclass Builder:
|
cppclass Builder:
|
||||||
Builder()
|
Builder()
|
||||||
Builder(Builder &)
|
Builder(Builder &)
|
||||||
DynamicValueForward.Builder operator[](uint)
|
DynamicValueForward.Builder operator[](uint) except +ValueError
|
||||||
uint size()
|
uint size()
|
||||||
void set(uint index, DynamicValueForward.Reader value) except +ValueError
|
void set(uint index, DynamicValueForward.Reader value) except +ValueError
|
||||||
DynamicValueForward.Builder init(uint index, uint size) except +ValueError
|
DynamicValueForward.Builder init(uint index, uint size) except +ValueError
|
||||||
void adopt(uint, DynamicOrphan)
|
void adopt(uint, DynamicOrphan) except +ValueError
|
||||||
DynamicOrphan disown(uint)
|
DynamicOrphan disown(uint)
|
||||||
StructSchema getStructElementType'getSchema().getStructElementType'()
|
StructSchema getStructElementType'getSchema().getStructElementType'()
|
||||||
|
|
||||||
|
|||||||
@@ -11,3 +11,14 @@ T fixMaybe(::kj::Maybe<T> val) {
|
|||||||
throw std::invalid_argument("member was null");
|
throw std::invalid_argument("member was null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const char * getEnumString(T val) {
|
||||||
|
|
||||||
|
auto maybe_val = val.which();
|
||||||
|
KJ_IF_MAYBE(new_val, maybe_val) {
|
||||||
|
return new_val->getProto().getName().cStr();;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,9 @@ def test_failed_import():
|
|||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
bar.foo = foo
|
bar.foo = foo
|
||||||
|
|
||||||
|
def test_defualt_import_hook():
|
||||||
|
import addressbook_capnp
|
||||||
|
|
||||||
def test_add_import_hook():
|
def test_add_import_hook():
|
||||||
capnp.add_import_hook([this_dir])
|
capnp.add_import_hook([this_dir])
|
||||||
|
|
||||||
|
|||||||
64
test/test_struct.py
Normal file
64
test/test_struct.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import pytest
|
||||||
|
import capnp
|
||||||
|
import os
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def addressbook():
|
||||||
|
return capnp.load(os.path.join(this_dir, 'addressbook.capnp'))
|
||||||
|
|
||||||
|
def test_which_builder(addressbook):
|
||||||
|
addresses = addressbook.AddressBook.new_message()
|
||||||
|
people = addresses.init('people', 2)
|
||||||
|
|
||||||
|
alice = people[0]
|
||||||
|
alice.employment.school = "MIT"
|
||||||
|
|
||||||
|
assert alice.employment.which() == "school"
|
||||||
|
|
||||||
|
bob = people[1]
|
||||||
|
|
||||||
|
assert bob.employment.which() == "unemployed"
|
||||||
|
|
||||||
|
bob.employment.unemployed = None
|
||||||
|
|
||||||
|
assert bob.employment.which() == "unemployed"
|
||||||
|
|
||||||
|
def test_which_reader(addressbook):
|
||||||
|
def writeAddressBook(fd):
|
||||||
|
message = capnp._MallocMessageBuilder()
|
||||||
|
addressBook = message.init_root(addressbook.AddressBook)
|
||||||
|
people = addressBook.init('people', 2)
|
||||||
|
|
||||||
|
alice = people[0]
|
||||||
|
alice.employment.school = "MIT"
|
||||||
|
|
||||||
|
bob = people[1]
|
||||||
|
bob.employment.unemployed = None
|
||||||
|
|
||||||
|
capnp._write_packed_message_to_fd(fd, message)
|
||||||
|
|
||||||
|
f = open('example', 'w')
|
||||||
|
writeAddressBook(f.fileno())
|
||||||
|
f = open('example', 'r')
|
||||||
|
|
||||||
|
addresses = addressbook.AddressBook.read_packed(f)
|
||||||
|
|
||||||
|
people = addresses.people
|
||||||
|
|
||||||
|
alice = people[0]
|
||||||
|
assert alice.employment.which() == "school"
|
||||||
|
|
||||||
|
bob = people[1]
|
||||||
|
assert bob.employment.which() == "unemployed"
|
||||||
|
|
||||||
|
def test_builder_set(addressbook):
|
||||||
|
person = addressbook.Person.new_message()
|
||||||
|
|
||||||
|
person.name = 'test'
|
||||||
|
|
||||||
|
assert person.name == 'test'
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
person.foo = 'test'
|
||||||
Reference in New Issue
Block a user