diff --git a/capnp/capnp.pyx b/capnp/capnp.pyx index 46b259b..e219fa6 100644 --- a/capnp/capnp.pyx +++ b/capnp/capnp.pyx @@ -87,6 +87,12 @@ cdef class _NodeReader: property nestedNodes: def __get__(self): return _List_NestedNode_Reader()._init(self.thisptr.getNestedNodes()) + property isStruct: + def __get__(self): + return self.thisptr.isStruct() + property isConst: + def __get__(self): + return self.thisptr.isConst() cdef class _NestedNodeReader: cdef C_Node.NestedNode.Reader thisptr @@ -134,13 +140,15 @@ cdef class _DynamicListBuilder: # self.thisptr._init(size) # return self + cpdef _get(self, index) except +ValueError: + return toPython(self.thisptr[index], self._parent) + def __getitem__(self, index): size = self.thisptr.size() if index >= size: raise IndexError('Out of bounds') index = index % size - temp = self.thisptr[index] - return toPython(temp, self._parent) + return self._get(index) def _setitem(self, index, valid_values value): cdef C_DynamicValue.Reader temp = C_DynamicValue.Reader(value) @@ -242,39 +250,7 @@ cdef class _DynamicValueReader: else: raise ValueError("Cannot convert type to Python. Type is unhandled by capnproto library") - -cdef int getType(C_DynamicValue.Builder & self): - return self.getType() - -cdef toPython(C_DynamicValue.Builder & self, object parent): - cdef int type = getType(self) - if type == capnp.TYPE_BOOL: - return self.asBool() - elif type == capnp.TYPE_INT: - return self.asInt() - elif type == capnp.TYPE_UINT: - return self.asUint() - elif type == capnp.TYPE_FLOAT: - return self.asDouble() - elif type == capnp.TYPE_TEXT: - return self.asText()[:] - elif type == capnp.TYPE_DATA: - temp = self.asData() - return (temp.begin())[:temp.size()] - elif type == capnp.TYPE_LIST: - return list(_DynamicListBuilder()._init(self.asList(), parent)) - elif type == capnp.TYPE_STRUCT: - return _DynamicStructBuilder()._init(self.asStruct(), parent) - elif type == capnp.TYPE_ENUM: - return fixMaybe(self.asEnum().getEnumerant()).getProto().getName().cStr() - elif type == capnp.TYPE_VOID: - return None - elif type == capnp.TYPE_UNKOWN: - raise ValueError("Cannot convert type to Python. Type is unknown by capnproto library") - else: - raise ValueError("Cannot convert type to Python. Type is unhandled by capnproto library") - -cdef toPythonByValue(C_DynamicValue.Builder self, object parent): +cdef toPython(C_DynamicValue.Builder self, object parent): cdef int type = self.getType() if type == capnp.TYPE_BOOL: return self.asBool() @@ -330,9 +306,12 @@ cdef class _DynamicStructBuilder: self._parent = parent return self - def __getattr__(self, field): + cpdef _get(self, field) except +ValueError: return toPython(self.thisptr.get(field), self._parent) + def __getattr__(self, field): + return self._get(field) + cdef _setattrInt(self, field, value): cdef C_DynamicValue.Reader temp = C_DynamicValue.Reader(value) self.thisptr.set(field, temp) @@ -373,9 +352,9 @@ cdef class _DynamicStructBuilder: cpdef init(self, field, size=None) except +ValueError: if size is None: - return toPythonByValue(self.thisptr.init(field), self._parent) + return toPython(self.thisptr.init(field), self._parent) else: - return toPythonByValue(self.thisptr.init(field, size), self._parent) + return toPython(self.thisptr.init(field, size), self._parent) # cpdef which(self): # try: @@ -391,6 +370,9 @@ cdef class Schema: self.thisptr = other return self + cpdef asConstValue(self): + return _DynamicValueReader()._init(self.thisptr.asConst(), self).toPython() + cpdef asStruct(self): return StructSchema()._init(self.thisptr.asStruct()) @@ -412,6 +394,9 @@ cdef class ParsedSchema: self.thisptr = other return self + cpdef asConstValue(self): + return _DynamicValueReader()._init(self.thisptr.asConst(), self).toPython() + cpdef asStruct(self): return StructSchema()._init(self.thisptr.asStruct()) @@ -533,10 +518,11 @@ def _load(nodeSchema, module): module.__dict__[node.name] = local_module schema = nodeSchema.getNested(node.name) - try: + proto = schema.getProto() + if proto.isStruct: local_module.Schema = schema.asStruct() - except: - pass + elif proto.isConst: + module.__dict__[node.name] = schema.asConstValue() _load(schema, local_module) diff --git a/capnp/capnp_cpp.pxd b/capnp/capnp_cpp.pxd index 6ef4d98..efa3f3a 100644 --- a/capnp/capnp_cpp.pxd +++ b/capnp/capnp_cpp.pxd @@ -29,6 +29,7 @@ cdef extern from "capnp/schema.h" namespace " ::capnp": Node.Reader getProto() except + StructSchema asStruct() except + EnumSchema asEnum() except + + ConstSchema asConst() except + Schema getDependency(uint64_t id) except + #InterfaceSchema asInterface() const; @@ -64,6 +65,9 @@ cdef extern from "capnp/schema.h" namespace " ::capnp": Enumerant getEnumerantByName(char * name) Node.Reader getProto() + cdef cppclass ConstSchema: + pass + cdef extern from "capnp/schema-loader.h" namespace " ::capnp": cdef cppclass SchemaLoader: SchemaLoader() @@ -99,7 +103,7 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": StructSchema getSchema() Maybe[StructSchema.Field] which() cppclass Builder: - DynamicValueForward.Builder get(char *) except +ValueError + DynamicValueForward.Builder get(char *) bint has(char *) except +ValueError void set(char *, DynamicValueForward.Reader&) except +ValueError DynamicValueForward.Builder init(char *, uint size) @@ -121,10 +125,10 @@ cdef extern from "capnp/dynamic.h" namespace " ::capnp": DynamicValueForward.Reader operator[](uint) except +ValueError uint size() cppclass Builder: - DynamicValueForward.Builder operator[](uint) except +ValueError + DynamicValueForward.Builder operator[](uint) uint size() - void set(uint index, DynamicValueForward.Reader& value) - DynamicValueForward.Builder init(uint index, uint size) + void set(uint index, DynamicValueForward.Reader& value) except +ValueError + DynamicValueForward.Builder init(uint index, uint size) except +ValueError cdef cppclass DynamicValue: cppclass Reader: diff --git a/capnp/schema_cpp.pxd b/capnp/schema_cpp.pxd index 41157cf..c779541 100644 --- a/capnp/schema_cpp.pxd +++ b/capnp/schema_cpp.pxd @@ -438,6 +438,12 @@ cdef extern from "capnp/schema.capnp.h" namespace " ::capnp::schema": UInt64 getScopeId() List[Node.Node.NestedNode].Reader getNestedNodes() UInt64 getId() + bint isFile() + bint isStruct() + bint isEnum() + bint isInterface() + bint isConst() + bint isAnnotation() cppclass Builder: Node.Body getBody() @@ -452,6 +458,12 @@ cdef extern from "capnp/schema.capnp.h" namespace " ::capnp::schema": List[Node.Node.NestedNode].Builder initNestedNodes(int) UInt64 getId() void setId(UInt64) + bint isFile() + bint isStruct() + bint isEnum() + bint isInterface() + bint isConst() + bint isAnnotation() cdef cppclass AnnotationNode: diff --git a/docs/quickstart.rst b/docs/quickstart.rst index cf632d8..a185de3 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -16,7 +16,9 @@ First you need to import the library:: Then you can load the Cap'n Proto schema with:: - capnp.load('addressbook.capnp') + addressbook = capnp.load('addressbook.capnp') + +Note that we assign the loaded module to a variable, named `addressbook`. We'll use this from now on to access the Cap'n Proto schema, ie. when we need to get a Struct's class or accessing const values. You can also provide an absolute path to the Cap'n Proto schema you wish to load. Otherwise, it will only look in the current working directory. @@ -25,6 +27,8 @@ For future reference, here is the Cap'n Proto schema. Also available in the gith # addressbook.capnp 0x934efea7f017fff0; + const qux :UInt32 = 123; + struct Person { id @0 :UInt32; name @1 :Text; @@ -55,6 +59,14 @@ For future reference, here is the Cap'n Proto schema. Also available in the gith people @0 :List(Person); } +Const values +~~~~~~~~~~~~~~ + +Const values show up just as you'd expect under the loaded schema. For example:: + + print addressbook.qux + # 123 + Build a message ------------------ diff --git a/examples/addressbook.capnp b/examples/addressbook.capnp index 02e626a..e1cd77c 100644 --- a/examples/addressbook.capnp +++ b/examples/addressbook.capnp @@ -1,5 +1,7 @@ @0x934efea7f017fff0; +const qux :UInt32 = 123; + struct Person { id @0 :UInt32; name @1 :Text; diff --git a/setup.py b/setup.py index 30473ac..6451e72 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ import os MAJOR = 0 MINOR = 3 -MICRO = 4 +MICRO = 5 VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)