diff --git a/capnp/capnp.pyx b/capnp/capnp.pyx index 8ef44ca..12d10b9 100644 --- a/capnp/capnp.pyx +++ b/capnp/capnp.pyx @@ -525,10 +525,46 @@ cdef class _DynamicStructBuilder: """ cdef C_DynamicStruct.Builder thisptr cdef public object _parent - cdef _init(self, C_DynamicStruct.Builder other, object parent): + cdef bint _isRoot + cdef _init(self, C_DynamicStruct.Builder other, object parent, bint isRoot = False): self.thisptr = other self._parent = parent + self._isRoot = isRoot return self + + def writeTo(self, file): + """Writes the struct's containing message to the given file object in unpacked binary format. + + This is a shortcut for calling capnp.writeMessageToFd(). This can only be called on the + message's root struct. + + :type file: file + :param file: A file or socket object (or anything with a fileno() method), open for write. + + :rtype: void + + :Raises: :exc:`exceptions.ValueError` if this isn't the message's root struct. + """ + if not self._isRoot: + raise ValueError("You can only call writeTo() on the message's root struct.") + writeMessageToFd(file.fileno(), self._parent) + + def writePackedTo(self, file): + """Writes the struct's containing message to the given file object in packed binary format. + + This is a shortcut for calling capnp.writePackedMessageToFd(). This can only be called on + the message's root struct. + + :type file: file + :param file: A file or socket object (or anything with a fileno() method), open for write. + + :rtype: void + + :Raises: :exc:`exceptions.ValueError` if this isn't the message's root struct. + """ + if not self._isRoot: + raise ValueError("You can only call writeTo() on the message's root struct.") + writePackedMessageToFd(file.fileno(), self._parent) cdef _get(self, field) except +ValueError: return toPython(self.thisptr.get(field), self._parent) @@ -892,6 +928,18 @@ cdef class SchemaParser: proto = schema.getProto() if proto.isStruct: local_module.schema = schema.asStruct() + def readFrom(file): + reader = StreamFdMessageReader(file.fileno()) + return reader.getRoot(local_module) + def readPackedFrom(file): + reader = PackedFdMessageReader(file.fileno()) + return reader.getRoot(local_module) + def newMessage(): + builder = MallocMessageBuilder() + return builder.initRoot(local_module) + local_module.readFrom = readFrom + local_module.readPackedFrom = readPackedFrom + local_module.newMessage = newMessage elif proto.isConst: module.__dict__[node.name] = schema.asConstValue() @@ -943,7 +991,7 @@ cdef class MessageBuilder: s = schema.schema else: s = schema - return _DynamicStructBuilder()._init(self.thisptr.initRootDynamicStruct(s.thisptr), self) + return _DynamicStructBuilder()._init(self.thisptr.initRootDynamicStruct(s.thisptr), self, True) cpdef getRoot(self, schema): """A method for instantiating Cap'n Proto structs, from an already pre-written buffer @@ -968,7 +1016,7 @@ cdef class MessageBuilder: s = schema.schema else: s = schema - return _DynamicStructBuilder()._init(self.thisptr.getRootDynamicStruct(s.thisptr), self) + return _DynamicStructBuilder()._init(self.thisptr.getRootDynamicStruct(s.thisptr), self, True) cpdef setRoot(self, value): """A method for instantiating Cap'n Proto structs by copying from an existing struct diff --git a/test/test_regression.py b/test/test_regression.py index f19683e..1a896ad 100644 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -266,16 +266,14 @@ def check_all_types(reader): check_list(reader.enumList, ["foo", "garply"]) def test_build(all_types): - builder = capnp.MallocMessageBuilder() - root = builder.getRoot(all_types.TestAllTypes) + root = all_types.TestAllTypes.newMessage() init_all_types(root) expectedText = open(os.path.join(this_dir, 'all-types.txt'), 'r').read() assert str(root) + '\n' == expectedText def test_binary_read(all_types): f = open(os.path.join(this_dir, 'all-types.binary'), 'r') - message = capnp.StreamFdMessageReader(f.fileno()) - root = message.getRoot(all_types.TestAllTypes) + root = all_types.TestAllTypes.readFrom(f) check_all_types(root) expectedText = open(os.path.join(this_dir, 'all-types.txt'), 'r').read() @@ -292,9 +290,22 @@ def test_binary_read(all_types): def test_packed_read(all_types): f = open(os.path.join(this_dir, 'all-types.packed'), 'r') - message = capnp.PackedFdMessageReader(f.fileno()) - root = message.getRoot(all_types.TestAllTypes) + root = all_types.TestAllTypes.readPackedFrom(f) check_all_types(root) expectedText = open(os.path.join(this_dir, 'all-types.txt'), 'r').read() assert str(root) + '\n' == expectedText + +def test_binary_write(all_types): + root = all_types.TestAllTypes.newMessage() + init_all_types(root) + root.writeTo(open('example', 'w')) + + check_all_types(all_types.TestAllTypes.readFrom(open('example', 'r'))) + +def test_packed_write(all_types): + root = all_types.TestAllTypes.newMessage() + init_all_types(root) + root.writePackedTo(open('example', 'w')) + + check_all_types(all_types.TestAllTypes.readPackedFrom(open('example', 'r')))