Cap'n Proto serialization/RPC system - Python bindings
Find a file
Jacob Alexander 10355a74ac
More agressive warning fixes
capnp/lib/capnp.cpp:35163:294: warning: moving a temporary object prevents copy
      elision [-Wpessimizing-move]
  ...*)__pyx_t_3), new  ::capnp::DynamicStruct::Pipeline(std::move((( ::capn...
                                                         ^
capnp/lib/capnp.cpp:35163:294: note: remove std::move call here
  ...std::move((( ::capnp::DynamicValue::Pipeline)__pyx_v_self->thisptr->get(__pyx_t_5)).releaseAs< ::capnp::DynamicStruct>())...
     ^~~~~~~~~~                                                                                                              ~
capnp/lib/capnp.cpp:39540:53: warning: moving a temporary object prevents copy
      elision [-Wpessimizing-move]
  __pyx_v_self->thisptr = new  ::kj::AsyncIoContext(std::move( ::kj::se...
                                                    ^
capnp/lib/capnp.cpp:39540:53: note: remove std::move call here
  ...= new  ::kj::AsyncIoContext(std::move( ::kj::setupAsyncIo()));
                                 ^~~~~~~~~~                     ~
capnp/lib/capnp.cpp:47838:294: warning: moving a temporary object prevents copy
      elision [-Wpessimizing-move]
  ...*)__pyx_t_3), new  ::capnp::DynamicStruct::Pipeline(std::move((( ::capn...
                                                         ^
capnp/lib/capnp.cpp:47838:294: note: remove std::move call here
  ...std::move((( ::capnp::DynamicValue::Pipeline)__pyx_v_self->thisptr->get(__pyx_t_5)).releaseAs< ::capnp::DynamicStruct>())...
     ^~~~~~~~~~                                                                                                              ~
2019-10-14 23:54:00 -07:00
.github/workflows Currently asyncio examples require Python 3.7+ 2019-09-29 23:54:49 -07:00
benchmark Fix benchamrks 2016-08-31 14:03:19 -07:00
buildutils Guess include and lib directory using capnp executable 2019-09-30 00:58:10 -07:00
capnp More agressive warning fixes 2019-10-14 23:54:00 -07:00
docs Fixing flake8 warnings and errors 2019-09-27 00:15:13 -07:00
examples Adding reconnecting async ssl example 2019-10-05 14:50:56 -07:00
scripts Fixing flake8 warnings and errors 2019-09-27 00:15:13 -07:00
test Removing deprecated Restorer and ezRestore references 2019-10-14 23:19:39 -07:00
.gitignore ignore files created during setup.py install 2019-09-16 21:34:58 -07:00
.travis.yml Removing Python 3.7 from this PR 2018-11-18 16:27:09 -05:00
CHANGELOG.md Fix minor typo in Changelog 2019-01-31 01:30:07 -08:00
DEPLOY.md Add deploy notes about tags 2019-02-01 15:11:53 -08:00
LICENSE Change all references to old project name 2013-09-01 01:15:31 -07:00
MANIFEST.in Include the changelog in the manifest 2016-03-08 11:27:01 -08:00
README.md Fork pycapnp to pycapnp-async 2019-10-14 21:34:08 -07:00
requirements.txt Unlocking python package version requirements 2019-09-26 21:54:12 -07:00
setup.py Fork pycapnp to pycapnp-async 2019-10-14 21:34:08 -07:00
tox.ini Removing Python 3.7 from this PR 2018-11-18 16:27:09 -05:00

pycapnp-async

Actions Status

Requirements

  • C++14 supported compiler

    • gcc 6.1+ (5+ may work)
    • clang 6 (3.4+ may work)
    • Visual Studio 2017+
  • cmake (needed for bundled capnproto)

    • ninja (macOS + Linux)
    • Visual Studio 2017+
  • capnproto-0.7.0

    • Not necessary if using bundled capnproto

32-bit Linux requires that capnproto be compiled with -fPIC. This is usually set correctly unless you are compiling canproto yourself. This is also called -DCMAKE_POSITION_INDEPENDENT_CODE=1 for cmake.

pycapnp has additional development dependencies, including cython and pytest. See requirements.txt for them all.

Building and installation

Install with pip install pycapnp. You can set the CC environment variable to control which compiler is used, ie CC=gcc-8.2 pip install pycapnp.

Or you can clone the repo like so:

git clone https://github.com/haata/pycapnp-async.git
cd pycapnp-async
pip install .

If you wish to install using the latest upstream C++ Cap'n Proto:

pip install \
    --install-option "--libcapnp-url" \
    --install-option "https://github.com/sandstorm-io/capnproto/archive/master.tar.gz" \
    --install-option "--force-bundled-libcapnp" .

To force bundled python:

pip install --install-option "--force-bundled-libcapnp" .

Python Versions

Python 3.7+ is supported. Earlier versions of Python have asyncio bugs that might be possible to work around, but may require significant work (3.5 and 3.6).

Development

Git flow has been abandoned, use master.

To test, use a pipenv (or install requirements.txt and run pytest manually).

pip install pipenv
pipenv install
pipenv run pytest

Binary Packages

Building a dumb binary distribution:

python setup.py bdist_dumb

Building a Python wheel distributiion:

python setup.py bdist_wheel

Pypi Upload Instructions

Only necessary if uploading release to pypi.org.

TODO

Documentation/Example

There is some basic documentation here.

The examples directory has one example that shows off pycapnp quite nicely. Here it is, reproduced:

from __future__ import print_function
import os
import capnp

import addressbook_capnp

def writeAddressBook(file):
    addresses = addressbook_capnp.AddressBook.new_message()
    people = addresses.init('people', 2)

    alice = people[0]
    alice.id = 123
    alice.name = 'Alice'
    alice.email = 'alice@example.com'
    alicePhones = alice.init('phones', 1)
    alicePhones[0].number = "555-1212"
    alicePhones[0].type = 'mobile'
    alice.employment.school = "MIT"

    bob = people[1]
    bob.id = 456
    bob.name = 'Bob'
    bob.email = 'bob@example.com'
    bobPhones = bob.init('phones', 2)
    bobPhones[0].number = "555-4567"
    bobPhones[0].type = 'home'
    bobPhones[1].number = "555-7654"
    bobPhones[1].type = 'work'
    bob.employment.unemployed = None

    addresses.write(file)


def printAddressBook(file):
    addresses = addressbook_capnp.AddressBook.read(file)

    for person in addresses.people:
        print(person.name, ':', person.email)
        for phone in person.phones:
            print(phone.type, ':', phone.number)

        which = person.employment.which()
        print(which)

        if which == 'unemployed':
            print('unemployed')
        elif which == 'employer':
            print('employer:', person.employment.employer)
        elif which == 'school':
            print('student at:', person.employment.school)
        elif which == 'selfEmployed':
            print('self employed')
        print()


if __name__ == '__main__':
    f = open('example', 'w')
    writeAddressBook(f)

    f = open('example', 'r')
    printAddressBook(f)

Also, pycapnp has gained RPC features that include pipelining and a promise style API. Refer to the calculator example in the examples directory for a much better demonstration:

import capnp
import socket

import test_capability_capnp


class Server(test_capability_capnp.TestInterface.Server):

    def __init__(self, val=1):
        self.val = val

    def foo(self, i, j, **kwargs):
        return str(i * 5 + self.val)


def server(write_end):
    server = capnp.TwoPartyServer(write_end, bootstrap=Server(100))


def client(read_end):
    client = capnp.TwoPartyClient(read_end)

    cap = client.bootstrap()
    cap = cap.cast_as(test_capability_capnp.TestInterface)

    remote = cap.foo(i=5)
    response = remote.wait()

    assert response.x == '125'


if __name__ == '__main__':
    read_end, write_end = socket.socketpair(socket.AF_UNIX)
    # This is a toy example using socketpair.
    # In real situations, you can use any socket.

    server(write_end)
    client(read_end)