···11+This is a uv project to get started with Capnproto
+34
py-template/bellairs.capnp
···11+@0xa59e1c95e37fb55d;
22+33+interface Directory {
44+ # Represents a directory in the filesystem
55+66+ list @0 () -> (entries :List(Entry));
77+ # Lists all entries in the directory
88+99+ struct Entry {
1010+ name @0 :Text; # Name of the entry
1111+ file @1 :File; # Reference to the file object
1212+ }
1313+1414+ create @1 (name :Text) -> (file :File);
1515+ # Creates a new file with the given name
1616+1717+ open @2 (name :Text) -> (file :File);
1818+ # Opens an existing file with the given name
1919+2020+ delete @3 (name :Text);
2121+ # Deletes a file with the given name
2222+}
2323+2424+interface File {
2525+ # Represents a file in the filesystem
2626+2727+ size @0 () -> (size :UInt64);
2828+ # Returns the size of the file in bytes
2929+3030+ read @1 (off :UInt64 = 0, len :UInt64 = 0xffffffffffffffff) -> (data :Data);
3131+ # Reads data from the file, optionally starting at offset and reading up to len bytes
3232+ # Default is to read the entire file
3333+}
3434+
+58
py-template/client-and-mock-server.py
···11+import asyncio
22+import socket
33+44+import capnp
55+66+capnp.remove_import_hook()
77+88+bellairs_capnp = capnp.load("bellairs.capnp")
99+1010+"""
1111+Mock file server so I can test this.
1212+"""
1313+1414+1515+class TestServer(bellairs_capnp.File.Server):
1616+ def __init__(self):
1717+ self.data = "Voop"
1818+1919+ async def size(self, **kwargs):
2020+ return len(self.data)
2121+2222+ async def read(self, offset, len, **kwargs):
2323+ return self.data
2424+2525+2626+async def client(sock):
2727+ # See https://capnproto.github.io/pycapnp/capnp.html?highlight=twopartyclient#capnp.TwoPartyClient
2828+ # AP: I am a bit unsure why the only thing available here
2929+ # is a two-party client, but this works as a hack.
3030+ client = capnp.TwoPartyClient(sock)
3131+ cap = client.bootstrap()
3232+ cap = cap.cast_as(bellairs_capnp.File)
3333+ result = await cap.size()
3434+ size = result.size
3535+ print("Got %d" % size)
3636+ assert size == 4
3737+3838+3939+async def main():
4040+ # Create a UNIX socket pair, because the network is
4141+ # more complex.
4242+ client_end, server_end = socket.socketpair(socket.AF_UNIX)
4343+ # Create AsyncIoStreams, which is really a wrapper around
4444+ # the C++ Capnproto connection. See https://github.com/capnproto/pycapnp/blob/59a639fa977e4a2e19c6cc60b44cbc9926418710/capnp/lib/capnp.pyx#L1314
4545+ client_end = await capnp.AsyncIoStream.create_connection(sock=client_end)
4646+ server_end = await capnp.AsyncIoStream.create_connection(sock=server_end)
4747+ # Create a TwoPartyServer. Better options
4848+ # are available (e.g., see https://github.com/capnproto/pycapnp/blob/master/examples/async_ssl_server.py#L60), but
4949+ # I did this for now. I think we will need to use
5050+ # `AsyncIoStream.create_server` and do some amount
5151+ # of indirection in there
5252+ _ = capnp.TwoPartyServer(server_end, bootstrap=TestServer())
5353+ print("Started file server")
5454+ await client(client_end)
5555+5656+5757+if __name__ == "__main__":
5858+ asyncio.run(capnp.run(main()))