diff --git a/MANIFEST.in b/MANIFEST.in index bb3ec5f..3d387c3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ include README.md +include requirements.txt \ No newline at end of file diff --git a/README.md b/README.md index 3ce31e9..141093b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ #capnpc-python-cpp +More thorough docs are available at [http://jparyani.github.io/capnpc-python-cpp/](http://jparyani.github.io/capnpc-python-cpp/). + ## Requirements -First you need a system-wide installation of the Capnproto C++ library >= 0.3. Unfortunately, as of now, that means you have to build from the HEAD of Cap'n Proto. Follow these instructions to do so: +First you need a system-wide installation of the Cap'n Proto C++ library >= 0.3. Unfortunately, as of now, that means you have to build from the HEAD of Cap'n Proto. Follow these instructions to do so: ```bash wget https://github.com/kentonv/capnproto/archive/master.zip diff --git a/capnp/__init__.py b/capnp/__init__.py index 6044b55..d63cf33 100644 --- a/capnp/__init__.py +++ b/capnp/__init__.py @@ -1,2 +1,37 @@ +"""A python library wrapping the Cap'n Proto C++ library + +Example Usage:: + + import capnp + + addressbook = capnp.load('addressbook.capnp') + + # Building + message = capnp.MallocMessageBuilder() + addressBook = message.initRoot(addressbook.AddressBook) + people = addressBook.init('people', 2) + + alice = people[0] + alice.id = 123 + alice.name = 'Alice' + alice.email = 'alice@example.com' + alicePhone = alice.init('phones', 1)[0] + alicePhone.type = 'mobile' + + f = open('example.bin', 'w') + capnp.writePackedMessageToFd(f.fileno(), message) + f.close() + + # Reading + f = open('example.bin') + message = capnp.PackedFdMessageReader(f.fileno()) + + addressBook = message.getRoot(addressbook.AddressBook) + + for person in addressBook.people: + print(person.name, ':', person.email) + for phone in person.phones: + print(phone.type, ':', phone.number) +""" from .version import version as __version__ from .capnp import * diff --git a/capnp/capnp.pyx b/capnp/capnp.pyx index e219fa6..870b147 100644 --- a/capnp/capnp.pyx +++ b/capnp/capnp.pyx @@ -508,25 +508,55 @@ def writePackedMessageToFd(int fd, MessageBuilder m): from types import ModuleType import os -def _load(nodeSchema, module): - module._nodeSchema = nodeSchema - nodeProto = nodeSchema.getProto() - module._nodeProto = nodeProto - - for node in nodeProto.nestedNodes: - local_module = ModuleType(node.name) - module.__dict__[node.name] = local_module - - schema = nodeSchema.getNested(node.name) - proto = schema.getProto() - if proto.isStruct: - local_module.Schema = schema.asStruct() - elif proto.isConst: - module.__dict__[node.name] = schema.asConstValue() - - _load(schema, local_module) - def load(file_name, display_name=None, imports=[]): + """load a Cap'n Proto schema from a file + + You will have to load a schema before you can begin doing anything + meaningful with this library. Loading a schema is much like Loading + a Python module (and load even returns a ModuleType). Once it's been + loaded, you use it much like any other Module:: + + addressbook = capnp.load('addressbook.capnp') + print addressbook.qux # qux is a top level constant + # 123 + message = capnp.MallocMessageBuilder() + person = message.initRoot(addressbook.Person) + + :type file_name: str + :param file_name: A relative or absolute path to a Cap'n Proto schema + + :type display_name: str + :param display_name: The name internally used by the Cap'n Proto library + for the loaded schema. By default, it's just os.path.basename(file_name) + + :type imports: list + :param imports: A list of str directories to add to the import path. + + :rtype: ModuleType + :return: A module corresponding to the loaded schema. You can access + parsed schemas and constants with . syntax + + :Raises: :exc:`exceptions.ValueError` if `file_name` doesn't exist + + """ + def _load(nodeSchema, module): + module._nodeSchema = nodeSchema + nodeProto = nodeSchema.getProto() + module._nodeProto = nodeProto + + for node in nodeProto.nestedNodes: + local_module = ModuleType(node.name) + module.__dict__[node.name] = local_module + + schema = nodeSchema.getNested(node.name) + proto = schema.getProto() + if proto.isStruct: + local_module.Schema = schema.asStruct() + elif proto.isConst: + module.__dict__[node.name] = schema.asConstValue() + + _load(schema, local_module) + if display_name is None: display_name = os.path.basename(file_name) module = ModuleType(display_name) diff --git a/capnp/fixMaybe.h b/capnp/fixMaybe.h index be56680..a1dfac6 100644 --- a/capnp/fixMaybe.h +++ b/capnp/fixMaybe.h @@ -1,6 +1,8 @@ #include "kj/common.h" #include +static_assert(CAPNP_VERSION >= 3000, "Version of Cap'n Proto C++ Library is too old. Please upgrade to a version >= 0.3 and then re-install this python library"); + template T fixMaybe(::kj::Maybe val) { KJ_IF_MAYBE(new_val, val) { diff --git a/docs/conf.py b/docs/conf.py index 764c8fd..08eed2d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ import sys, os, string # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -48,19 +48,10 @@ copyright = u'2013, Author' # built documents. # # The short X.Y version. -def extract_version(): - """extract version from version.py, so it's not multiply defined""" - with open(os.path.join('..', 'capnp', 'version.py')) as f: - line = f.readline() - while not line.startswith("version"): - line = f.readline() - print line - exec(line) - return version +import capnp -vs = extract_version() +vs = capnp.__version__ # The short X.Y version. -import string version = vs.rstrip(string.letters) # The full version, including alpha/beta/rc tags. release = vs @@ -296,3 +287,5 @@ epub_copyright = u'2013, Author' # Allow duplicate toc entries. #epub_tocdup = True + +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/setup.py b/setup.py index 6451e72..5ef3ae1 100644 --- a/setup.py +++ b/setup.py @@ -6,17 +6,21 @@ except ImportError: raise RuntimeError('No cython installed. Please run `pip install cython`') if Cython.__version__ < '0.19.1': - raise RuntimeError('Old cython installed. Please run `pip install -U cython`') + raise RuntimeError('Old cython installed (%s). Please run `pip install -U cython`' % Cython.__version__) + +import pkg_resources +setuptools_version = pkg_resources.get_distribution("setuptools").version +if setuptools_version < '0.8': + raise RuntimeError('Old setuptools installed (%s). Please run `pip install -U setuptools`. Running `pip install capnp` will not work alone, since setuptools needs to be upgraded before installing anything else.' % setuptools_version) from distutils.core import setup import os MAJOR = 0 MINOR = 3 -MICRO = 5 +MICRO = 6 VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) - def write_version_py(filename=None): cnt = """\ version = '%s'