More thorough docs are available at http://jparyani.github.io/pycapnp/.
pycapnp's distribution has no requirements beyond a C++11 compatible compiler. GCC 4.8+ or Clang 3.3+ should work fine.
pycapnp has additional development dependencies, including cython and py.test. See requirements.txt for them all.
Install with pip install pycapnp
. You can set the CC environment variable to control which compiler is used, ie CC=gcc-4.8 pip install pycapnp
.
Or you can clone the repo like so:
git clone https://github.com/jparyani/pycapnp.git
pip install --install-option '--force-cython' ./pycapnp
Note: for OSX, if using clang from Xcode 5, you may need to set CFLAGS
like so:
CFLAGS='-stdlib=libc++' pip install pycapnp
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" .
Python 2.6/2.7 are supported as well as Python 3.2+. PyPy 2.1+ is also supported.
One oddity to note is that Text
type fields will be treated as byte strings under Python 2, and unicode strings under Python 3. Data
fields will always be treated as byte strings.
This project uses git-flow. Essentially, just make sure you do your changes in the develop
branch. You can run the tests by installing pytest with pip install pytest
, and then run py.test
from the test
directory.
In order to build binary packages from this source code, you must specify the --disable-cython
option:
Building a dumb binary distribution:
python setup.py bdist_dumb --disable-cython
Building a Python wheel distributiion:
python setup.py bdist_wheel --disable-cython
If it fails with an error like clang: error: no such file or directory: 'capnp/lib/capnp.cpp'
, then you need to cythonize fist. This can be done with:
python setup.py build --force-cython
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 = '[email protected]'
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 = '[email protected]'
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)
If you get an error on installation like:
...
gcc-4.8: error: capnp/capnp.c: No such file or directory
gcc-4.8: fatal error: no input files
Then you have too old a version of setuptools. Run pip install -U setuptools
then try again.