From 5ffe7eb2f6cf7539f03be715613359efbf053afb Mon Sep 17 00:00:00 2001 From: Jason Paryani Date: Fri, 17 Jun 2016 13:50:42 -0700 Subject: [PATCH] Fix response objects not referencing parents correctly Fixes #103 --- capnp/lib/capnp.pyx | 4 ++-- test/test_response.capnp | 13 +++++++++++++ test/test_response.py | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 test/test_response.capnp create mode 100644 test/test_response.py diff --git a/capnp/lib/capnp.pyx b/capnp/lib/capnp.pyx index 6d1eb8c..a052146 100644 --- a/capnp/lib/capnp.pyx +++ b/capnp/lib/capnp.pyx @@ -1019,7 +1019,7 @@ cdef class _DynamicStructReader: return self cpdef _get(self, field): - return to_python_reader(self.thisptr.get(field), self._parent) + return to_python_reader(self.thisptr.get(field), self) def __getattr__(self, field): try: @@ -1028,7 +1028,7 @@ cdef class _DynamicStructReader: raise e._to_python(), None, _sys.exc_info()[2] cpdef _get_by_field(self, _StructSchemaField field): - return to_python_reader(self.thisptr.getByField(field.thisptr), self._parent) + return to_python_reader(self.thisptr.getByField(field.thisptr), self) cpdef _has(self, field): return self.thisptr.has(field) diff --git a/test/test_response.capnp b/test/test_response.capnp new file mode 100644 index 0000000..268bc08 --- /dev/null +++ b/test/test_response.capnp @@ -0,0 +1,13 @@ +@0x84249be5c3bff005; + +interface Foo { + foo @0 () -> (val :UInt32); +} + +struct Bar { + foo @0 :Foo; +} + +interface Baz { + grault @0 () -> (bar: Bar); +} diff --git a/test/test_response.py b/test/test_response.py new file mode 100644 index 0000000..296031c --- /dev/null +++ b/test/test_response.py @@ -0,0 +1,40 @@ +import pytest +import capnp +import os +import time + +import test_response_capnp + +class FooServer(test_response_capnp.Foo.Server): + def __init__(self, val=1): + self.val = val + + def foo(self, **kwargs): + return 1 + +class BazServer(test_response_capnp.Baz.Server): + def __init__(self, val=1): + self.val = val + + def grault(self, **kwargs): + return {"foo": FooServer()} + +def test_response_reference(): + baz = test_response_capnp.Baz._new_client(BazServer()) + + bar = baz.grault().wait().bar + + foo = bar.foo + # This used to cause an exception about invalid pointers because the response got garbage collected + foo.foo().wait() + +def test_response_reference2(): + baz = test_response_capnp.Baz._new_client(BazServer()) + + bar = baz.grault().wait().bar + + # This always worked since it saved the intermediate response object + response = baz.grault().wait() + bar = response.bar + foo = bar.foo + foo.foo().wait()