2013-06-26 23:01:37 -07:00
# capnp.pyx
# distutils: language = c++
2013-07-07 03:10:38 -07:00
# distutils: extra_compile_args = --std=c++11 -fpermissive
2013-08-13 22:21:38 -07:00
# distutils: libraries = capnpc
2013-07-07 03:10:38 -07:00
# cython: c_string_type = str
# cython: c_string_encoding = default
2013-08-18 21:48:49 -07:00
# cython: embedsignature = True
2013-06-26 23:01:37 -07:00
2013-06-28 01:04:01 -07:00
cimport cython
2013-06-26 23:01:37 -07:00
cimport capnp_cpp as capnp
cimport schema_cpp
2013-08-26 15:07:13 -07:00
from capnp_cpp cimport Schema as C_Schema , StructSchema as C_StructSchema , DynamicStruct as C_DynamicStruct , DynamicValue as C_DynamicValue , Type as C_Type , DynamicList as C_DynamicList , fixMaybe , SchemaParser as C_SchemaParser , ParsedSchema as C_ParsedSchema , VOID , ArrayPtr , StringPtr , DynamicOrphan as C_DynamicOrphan
2013-07-06 16:53:00 -07:00
2013-08-22 09:18:29 -07:00
from schema_cpp cimport Node as C_Node , EnumNode as C_EnumNode
2013-06-26 23:01:37 -07:00
from cython.operator cimport dereference as deref
from libc.stdint cimport *
ctypedef unsigned int uint
ctypedef uint8_t UInt8
ctypedef uint16_t UInt16
ctypedef uint32_t UInt32
ctypedef uint64_t UInt64
ctypedef int8_t Int8
ctypedef int16_t Int16
ctypedef int32_t Int32
ctypedef int64_t Int64
ctypedef char * Object
ctypedef bint Bool
ctypedef float Float32
ctypedef double Float64
2013-08-13 23:00:43 -07:00
from libc.stdlib cimport malloc , free
2013-06-26 23:01:37 -07:00
2013-06-28 01:04:01 -07:00
ctypedef fused valid_values :
int
long
float
double
bint
2013-07-06 16:53:00 -07:00
cython . p_char
2013-06-28 01:04:01 -07:00
def _make_enum ( enum_name , * sequential , * * named ) :
enums = dict ( zip ( sequential , range ( len ( sequential ) ) ) , * * named )
reverse = dict ( ( value , key ) for key , value in enums . iteritems ( ) )
enums [ ' reverse_mapping ' ] = reverse
return type ( enum_name , ( ) , enums )
_Type = _make_enum ( ' DynamicValue.Type ' ,
UNKNOWN = capnp . TYPE_UNKNOWN ,
VOID = capnp . TYPE_VOID ,
BOOL = capnp . TYPE_BOOL ,
INT = capnp . TYPE_INT ,
UINT = capnp . TYPE_UINT ,
FLOAT = capnp . TYPE_FLOAT ,
TEXT = capnp . TYPE_TEXT ,
DATA = capnp . TYPE_DATA ,
LIST = capnp . TYPE_LIST ,
ENUM = capnp . TYPE_ENUM ,
STRUCT = capnp . TYPE_STRUCT ,
INTERFACE = capnp . TYPE_INTERFACE ,
OBJECT = capnp . TYPE_OBJECT )
2013-08-26 14:45:15 -07:00
# Templated classes are weird in cython. I couldn't put it in a pxd header for some reason
2013-07-06 18:51:04 -07:00
cdef extern from " capnp/list.h " namespace " ::capnp " :
2013-06-26 23:01:37 -07:00
cdef cppclass List [T ]:
cppclass Reader :
T operator [ ] ( uint ) except + ValueError
uint size ( )
cppclass Builder :
T operator [ ] ( uint ) except + ValueError
uint size ( )
2013-08-26 14:45:15 -07:00
cdef extern from " <utility> " namespace " std " :
2013-08-26 22:00:12 -07:00
C_DynamicOrphan moveOrphan " std::move " ( C_DynamicOrphan )
2013-08-26 14:45:15 -07:00
2013-08-10 13:54:25 -07:00
cdef class _NodeReader :
cdef C_Node .Reader thisptr
cdef init ( self , C_Node . Reader other ) :
self . thisptr = other
return self
property displayName :
def __get__ ( self ) :
return self . thisptr . getDisplayName ( ) . cStr ( )
property scopeId :
def __get__ ( self ) :
return self . thisptr . getScopeId ( )
property id :
def __get__ ( self ) :
return self . thisptr . getId ( )
2013-08-13 22:21:38 -07:00
property nestedNodes :
def __get__ ( self ) :
return _List_NestedNode_Reader ( ) . _init ( self . thisptr . getNestedNodes ( ) )
2013-08-25 17:07:08 -07:00
property isStruct :
def __get__ ( self ) :
return self . thisptr . isStruct ( )
property isConst :
def __get__ ( self ) :
return self . thisptr . isConst ( )
2013-08-13 22:21:38 -07:00
cdef class _NestedNodeReader :
cdef C_Node .NestedNode .Reader thisptr
cdef init ( self , C_Node . NestedNode . Reader other ) :
self . thisptr = other
return self
property name :
def __get__ ( self ) :
return self . thisptr . getName ( ) . cStr ( )
property id :
def __get__ ( self ) :
return self . thisptr . getId ( )
2013-08-10 13:54:25 -07:00
2013-06-28 01:04:01 -07:00
cdef class _DynamicListReader :
2013-08-26 19:27:58 -07:00
""" Class for reading Cap ' n Proto Lists
This class thinly wraps the C + + Cap ' n Proto DynamicList::Reader class. __getitem__ and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
. . .
person = message . getRoot ( addressbook . Person )
phones = person . phones # This returns a _DynamicListReader
phone = phones [ 0 ]
print phone . number
for phone in phones :
print phone . number
"""
2013-06-28 01:04:01 -07:00
cdef C_DynamicList .Reader thisptr
2013-07-07 18:48:55 -07:00
cdef public object _parent
cdef _init ( self , C_DynamicList . Reader other , object parent ) :
2013-06-28 01:04:01 -07:00
self . thisptr = other
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-06-28 01:04:01 -07:00
return self
2013-08-26 14:57:48 -07:00
def __getitem__ ( self , index ) :
2013-06-28 01:04:01 -07:00
size = self . thisptr . size ( )
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
2013-08-26 14:57:48 -07:00
return toPythonReader ( self . thisptr [ index ] , self . _parent )
2013-06-28 01:04:01 -07:00
def __len__ ( self ) :
return self . thisptr . size ( )
2013-08-27 10:55:06 -07:00
cdef class _DynamicResizableListBuilder :
2013-08-26 22:00:12 -07:00
cdef public object _parent , _message , _field , _schema
cdef public list _list
def __init__ ( self , parent , field , schema ) :
self . _parent = parent
self . _message = parent . _parent
self . _field = field
self . _schema = schema
self . _list = list ( )
cpdef add ( self ) :
orphan = self . _message . newOrphan ( self . _schema )
orphan_val = orphan . get ( )
self . _list . append ( ( orphan , orphan_val ) )
return orphan_val
def __getitem__ ( self , index ) :
return self . _list [ index ] [ 1 ]
# def __setitem__(self, index, val):
# self._list[index] = val
def __len__ ( self ) :
return len ( self . _list )
2013-08-27 10:55:06 -07:00
def finish ( self ) :
2013-08-26 22:00:12 -07:00
cdef int i = 0
new_list = self . _parent . init ( self . _field , len ( self ) )
for orphan , _ in self . _list :
new_list . adopt ( i , orphan )
i + = 1
2013-06-28 01:04:01 -07:00
cdef class _DynamicListBuilder :
2013-08-26 19:27:58 -07:00
""" Class for building Cap ' n Proto Lists
This class thinly wraps the C + + Cap ' n Proto DynamicList::Bulder class. __getitem__, __setitem__, and __len__ have been defined properly, so you can treat this class mostly like any other iterable class::
. . .
person = message . initRoot ( addressbook . Person )
phones = person . init ( ' phones ' , 2 ) # This returns a _DynamicListBuilder
phone = phones [ 0 ]
phone . number = ' foo '
phone = phones [ 1 ]
phone . number = ' bar '
for phone in phones :
print phone . number
"""
2013-08-28 22:55:18 -07:00
cdef C_DynamicList .Builder * thisptr
2013-07-07 18:48:55 -07:00
cdef public object _parent
cdef _init ( self , C_DynamicList . Builder other , object parent ) :
2013-08-28 22:55:18 -07:00
self . thisptr = new C_DynamicList . Builder ( other )
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-06-28 01:04:01 -07:00
return self
2013-08-28 22:55:18 -07:00
def __dealloc__ ( self ) :
del self . thisptr
2013-08-26 19:27:58 -07:00
cdef _get ( self , index ) except + ValueError :
2013-08-28 22:55:18 -07:00
return toPython ( deref ( self . thisptr ) [ index ] , self . _parent )
2013-08-25 16:41:37 -07:00
2013-06-28 01:04:01 -07:00
def __getitem__ ( self , index ) :
size = self . thisptr . size ( )
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
2013-08-25 16:41:37 -07:00
return self . _get ( index )
2013-06-28 01:04:01 -07:00
def _setitem ( self , index , valid_values value ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( value )
self . thisptr . set ( index , temp )
def __setitem__ ( self , index , value ) :
size = self . thisptr . size ( )
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
self . _setitem ( index , value )
def __len__ ( self ) :
return self . thisptr . size ( )
2013-08-26 22:00:12 -07:00
cpdef adopt ( self , index , _DynamicOrphan orphan ) :
""" A method for adopting Cap ' n Proto orphans
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unkown sized list , ie : :
message = capnp . MallocMessageBuilder ( )
alice = m . newOrphan ( addressbook . Person )
alice . get ( ) . name = ' alice '
bob = m . newOrphan ( addressbook . Person )
bob . get ( ) . name = ' bob '
addressBook = message . initRoot ( addressbook . AddressBook )
people = addressBook . init ( ' people ' , 2 )
people . adopt ( 0 , alice )
people . adopt ( 1 , bob )
: type index : int
: param index : The index of the element in the list to replace with the newly adopted object
: type orphan : : class : `_DynamicOrphan`
: param orphan : A Cap ' n proto orphan to adopt. It will be unusable after this operation.
: rtype : void
"""
self . thisptr . adopt ( index , orphan . move ( ) )
cpdef disown ( self , index ) :
""" A method for disowning Cap ' n Proto orphans
Don ' t use this method unless you know what you ' re doing .
: type index : int
: param index : The index of the element in the list to disown
: rtype : : class : `_DynamicOrphan`
"""
return _DynamicOrphan ( ) . _init ( self . thisptr . disown ( index ) , self . _parent )
2013-08-13 22:21:38 -07:00
cdef class _List_NestedNode_Reader :
cdef List [C_Node .NestedNode ].Reader thisptr
cdef _init ( self , List [ C_Node . NestedNode ] . Reader other ) :
self . thisptr = other
return self
2013-08-13 23:04:03 -07:00
2013-08-13 22:21:38 -07:00
def __getitem__ ( self , index ) :
size = self . thisptr . size ( )
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
return _NestedNodeReader ( ) . init ( < C_Node . NestedNode . Reader > self . thisptr [ index ] )
def __len__ ( self ) :
return self . thisptr . size ( )
2013-08-26 14:57:48 -07:00
cdef toPythonReader ( C_DynamicValue . Reader self , object parent ) :
cdef int type = self . getType ( )
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 ( < char * > temp . begin ( ) ) [ : temp . size ( ) ]
elif type == capnp . TYPE_LIST :
2013-08-28 22:55:18 -07:00
print ' list '
2013-08-26 14:57:48 -07:00
return list ( _DynamicListReader ( ) . _init ( self . asList ( ) , parent ) )
elif type == capnp . TYPE_STRUCT :
return _DynamicStructReader ( ) . _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 " )
2013-06-28 01:04:01 -07:00
2013-08-25 16:41:37 -07:00
cdef toPython ( C_DynamicValue . Builder self , object parent ) :
2013-07-06 23:10:51 -07:00
cdef int type = self . getType ( )
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 ( < char * > temp . begin ( ) ) [ : temp . size ( ) ]
elif type == capnp . TYPE_LIST :
2013-08-26 22:00:12 -07:00
return _DynamicListBuilder ( ) . _init ( self . asList ( ) , parent )
2013-07-06 23:10:51 -07:00
elif type == capnp . TYPE_STRUCT :
2013-07-07 18:48:55 -07:00
return _DynamicStructBuilder ( ) . _init ( self . asStruct ( ) , parent )
2013-07-06 23:10:51 -07:00
elif type == capnp . TYPE_ENUM :
return fixMaybe ( self . asEnum ( ) . getEnumerant ( ) ) . getProto ( ) . getName ( ) . cStr ( )
2013-06-28 01:04:01 -07:00
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 " )
2013-06-26 23:01:37 -07:00
cdef class _DynamicStructReader :
2013-08-26 19:27:58 -07:00
""" Reads Cap ' n Proto structs
This class is almost a 1 for 1 wrapping of the Cap ' n Proto C++ DynamicStruct::Reader. The only difference is that instead of a `get` method, __getattr__ is overloaded and the field name is passed onto the C++ equivalent `get`. This means you just use . syntax to access any field. For field names that don ' t follow valid python naming convention for fields , use the global function : py : func : `getattr` : :
person = message . getRoot ( addressbook . Person ) # This returns a _DynamicStructReader
print person . name # using . syntax
print getattr ( person , ' field-with-hyphens ' ) # for names that are invalid for python, use getattr
"""
2013-06-26 23:01:37 -07:00
cdef C_DynamicStruct .Reader thisptr
2013-07-07 18:48:55 -07:00
cdef public object _parent
2013-08-28 14:34:37 -07:00
cdef object _obj_to_pin
2013-07-07 18:48:55 -07:00
cdef _init ( self , C_DynamicStruct . Reader other , object parent ) :
2013-06-26 23:01:37 -07:00
self . thisptr = other
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-06-26 23:01:37 -07:00
return self
2013-07-07 18:48:55 -07:00
2013-06-28 01:04:01 -07:00
def __getattr__ ( self , field ) :
2013-08-26 14:57:48 -07:00
return toPythonReader ( self . thisptr . get ( field ) , self . _parent )
2013-06-28 01:04:01 -07:00
def _has ( self , field ) :
return self . thisptr . has ( field )
2013-08-26 19:27:58 -07:00
cpdef which ( self ) except + ValueError :
""" Returns the enum corresponding to the union in this struct
Enums are just strings in the python Cap ' n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn ' t a union , or a struct with an unnamed union : :
person = message . initRoot ( addressbook . Person )
person . which ( )
# ValueError: member was null
a . employment . employer = ' foo '
print employment . which ( )
# 'employer'
: rtype : str
: return : A string / enum corresponding to what field is set in the union
: Raises : : exc : `exceptions.ValueError` if this struct doesn ' t contain a union
"""
2013-08-22 09:18:29 -07:00
return fixMaybe ( self . thisptr . which ( ) ) . getProto ( ) . getName ( ) . cStr ( )
2013-08-15 15:44:54 -07:00
2013-08-28 14:34:37 -07:00
property schema :
"""A _StructSchema object matching this reader"""
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
2013-06-28 01:04:01 -07:00
cdef class _DynamicStructBuilder :
2013-08-26 19:27:58 -07:00
""" Builds Cap ' n Proto structs
This class is almost a 1 for 1 wrapping of the Cap ' n Proto C++ DynamicStruct::Builder. The only difference is that instead of a `get`/`set` method, __getattr__/__setattr__ is overloaded and the field name is passed onto the C++ equivalent function. This means you just use . syntax to access or set any field. For field names that don ' t follow valid python naming convention for fields , use the global functions : py : func : `getattr` / : py : func : `setattr` : :
person = message . initRoot ( addressbook . Person ) # This returns a _DynamicStructBuilder
person . name = ' foo ' # using . syntax
print person . name # using . syntax
setattr ( person , ' field-with-hyphens ' , ' foo ' ) # for names that are invalid for python, use setattr
print getattr ( person , ' field-with-hyphens ' ) # for names that are invalid for python, use getattr
"""
2013-08-28 22:55:18 -07:00
cdef C_DynamicStruct .Builder * thisptr
2013-07-07 18:48:55 -07:00
cdef public object _parent
cdef _init ( self , C_DynamicStruct . Builder other , object parent ) :
2013-08-28 22:55:18 -07:00
self . thisptr = new C_DynamicStruct . Builder ( other )
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-06-28 01:04:01 -07:00
return self
2013-08-28 22:55:18 -07:00
def __dealloc__ ( self ) :
del self . thisptr
2013-08-26 16:16:58 -07:00
cdef _get ( self , field ) except + ValueError :
2013-07-07 18:48:55 -07:00
return toPython ( self . thisptr . get ( field ) , self . _parent )
2013-06-28 01:04:01 -07:00
2013-08-25 16:41:37 -07:00
def __getattr__ ( self , field ) :
return self . _get ( field )
2013-07-06 16:53:00 -07:00
cdef _setattrInt ( self , field , value ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( < long long > value )
self . thisptr . set ( field , temp )
cdef _setattrDouble ( self , field , value ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( < double > value )
self . thisptr . set ( field , temp )
cdef _setattrBool ( self , field , value ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( < bint > value )
self . thisptr . set ( field , temp )
cdef _setattrString ( self , field , value ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( < char * > value )
2013-06-28 01:04:01 -07:00
self . thisptr . set ( field , temp )
2013-07-06 23:10:51 -07:00
cdef _setattrVoid ( self , field ) :
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( VOID )
self . thisptr . set ( field , temp )
2013-06-28 01:04:01 -07:00
def __setattr__ ( self , field , value ) :
2013-07-06 16:53:00 -07:00
value_type = type ( value )
if value_type is int :
self . _setattrInt ( field , value )
elif value_type is float :
self . _setattrDouble ( field , value )
elif value_type is bool :
self . _setattrBool ( field , value )
2013-07-07 03:10:38 -07:00
elif value_type is str :
2013-07-06 16:53:00 -07:00
self . _setattrString ( field , value )
2013-07-06 23:10:51 -07:00
elif value is None :
self . _setattrVoid ( field )
2013-07-06 16:53:00 -07:00
else :
raise ValueError ( " Non primitive type " )
2013-06-28 01:04:01 -07:00
def _has ( self , field ) :
2013-06-26 23:01:37 -07:00
return self . thisptr . has ( field )
2013-08-26 19:27:58 -07:00
cpdef init ( self , field , size = None ) except + AttributeError :
""" Method for initializing fields that are of type union/struct/list
Typically , you don ' t have to worry about initializing structs/unions, so this method is mainly for lists.
: type field : str
: param field : The field name to initialize
: type size : int
: param size : The size of the list to initiialize . This should be None for struct / union initialization .
: rtype : : class : `_DynamicStructBuilder` or : class : `_DynamicListBuilder`
: Raises : : exc : `exceptions.AttributeError` if the field isn ' t in this struct
"""
2013-07-06 23:10:51 -07:00
if size is None :
2013-08-25 16:41:37 -07:00
return toPython ( self . thisptr . init ( field ) , self . _parent )
2013-07-06 23:10:51 -07:00
else :
2013-08-25 16:41:37 -07:00
return toPython ( self . thisptr . init ( field , size ) , self . _parent )
2013-07-06 23:10:51 -07:00
2013-08-27 10:55:06 -07:00
cpdef initResizableList ( self , field ) :
return _DynamicResizableListBuilder ( self , field , _StructSchema ( ) . _init ( ( < C_DynamicValue . Builder > self . thisptr . get ( field ) ) . asList ( ) . getStructElementType ( ) ) )
2013-08-26 19:27:58 -07:00
cpdef which ( self ) except + ValueError :
""" Returns the enum corresponding to the union in this struct
Enums are just strings in the python Cap ' n Proto API, so this function will either return a string equal to the field name of the active field in the union, or throw a ValueError if this isn ' t a union , or a struct with an unnamed union : :
person = message . initRoot ( addressbook . Person )
person . which ( )
# ValueError: member was null
a . employment . employer = ' foo '
print employment . which ( )
# 'employer'
: rtype : str
: return : A string / enum corresponding to what field is set in the union
: Raises : : exc : `exceptions.ValueError` if this struct doesn ' t contain a union
"""
2013-08-26 14:57:48 -07:00
return fixMaybe ( self . thisptr . which ( ) ) . getProto ( ) . getName ( ) . cStr ( )
2013-06-26 23:01:37 -07:00
2013-08-26 22:00:12 -07:00
cpdef adopt ( self , field , _DynamicOrphan orphan ) :
""" A method for adopting Cap ' n Proto orphans
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unkown sized list , ie : :
message = capnp . MallocMessageBuilder ( )
alice = m . newOrphan ( addressbook . Person )
alice . get ( ) . name = ' alice '
bob = m . newOrphan ( addressbook . Person )
bob . get ( ) . name = ' bob '
addressBook = message . initRoot ( addressbook . AddressBook )
people = addressBook . init ( ' people ' , 2 )
people . adopt ( 0 , alice )
people . adopt ( 1 , bob )
: type field : str
: param field : The field name in the struct
: type orphan : : class : `_DynamicOrphan`
: param orphan : A Cap ' n proto orphan to adopt. It will be unusable after this operation.
: rtype : void
"""
self . thisptr . adopt ( field , orphan . move ( ) )
cpdef disown ( self , field ) :
""" A method for disowning Cap ' n Proto orphans
Don ' t use this method unless you know what you ' re doing .
: type field : str
: param field : The field name in the struct
: rtype : : class : `_DynamicOrphan`
"""
return _DynamicOrphan ( ) . _init ( self . thisptr . disown ( field ) , self . _parent )
2013-08-28 16:09:33 -07:00
cpdef asReader ( self ) :
2013-08-28 14:34:37 -07:00
cdef _DynamicStructReader reader
reader = _DynamicStructReader ( ) . _init ( self . thisptr . asReader ( ) ,
self . _parent )
reader . _obj_to_pin = self
return reader
property schema :
"""A _StructSchema object matching this reader"""
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
2013-08-26 14:45:15 -07:00
cdef class _DynamicOrphan :
cdef C_DynamicOrphan thisptr
cdef public object _parent
cdef _init ( self , C_DynamicOrphan other , object parent ) :
self . thisptr = moveOrphan ( other )
self . _parent = parent
return self
2013-08-26 22:00:12 -07:00
cdef C_DynamicOrphan move ( self ) :
return moveOrphan ( self . thisptr )
cpdef get ( self ) :
""" Returns a python object corresponding to the DynamicValue owned by this orphan
Use this DynamicValue to set fields inside the orphan
"""
return toPython ( self . thisptr . get ( ) , self . _parent )
2013-08-26 15:07:13 -07:00
cdef class _Schema :
2013-06-26 23:01:37 -07:00
cdef C_Schema thisptr
2013-07-06 23:10:51 -07:00
cdef _init ( self , C_Schema other ) :
2013-06-26 23:01:37 -07:00
self . thisptr = other
return self
2013-08-25 17:07:08 -07:00
cpdef asConstValue ( self ) :
2013-08-26 14:57:48 -07:00
return toPythonReader ( < C_DynamicValue . Reader > self . thisptr . asConst ( ) , self )
2013-08-25 17:07:08 -07:00
2013-06-26 23:01:37 -07:00
cpdef asStruct ( self ) :
2013-08-26 15:07:13 -07:00
return _StructSchema ( ) . _init ( self . thisptr . asStruct ( ) )
2013-06-26 23:01:37 -07:00
2013-07-06 16:53:00 -07:00
cpdef getDependency ( self , id ) :
2013-08-26 15:07:13 -07:00
return _Schema ( ) . _init ( self . thisptr . getDependency ( id ) )
2013-07-06 16:53:00 -07:00
cpdef getProto ( self ) :
return _NodeReader ( ) . init ( self . thisptr . getProto ( ) )
2013-08-26 15:07:13 -07:00
cdef class _StructSchema :
2013-06-26 23:01:37 -07:00
cdef C_StructSchema thisptr
2013-08-28 14:34:37 -07:00
cdef object __fieldnames
2013-07-06 23:10:51 -07:00
cdef _init ( self , C_StructSchema other ) :
2013-06-26 23:01:37 -07:00
self . thisptr = other
2013-08-28 14:34:37 -07:00
self . __fieldnames = None
2013-06-26 23:01:37 -07:00
return self
2013-08-28 14:34:37 -07:00
property fieldnames :
"""A tuple of the field names in the struct."""
def __get__ ( self ) :
if self . __fieldnames is not None :
return self . __fieldnames
fieldlist = self . thisptr . getFields ( )
nfields = fieldlist . size ( )
self . __fieldnames = tuple ( fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
for i in xrange ( nfields ) )
return self . __fieldnames
2013-08-28 14:46:53 -07:00
property node :
"""The raw schema node"""
def __get__ ( self ) :
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , None )
2013-08-26 15:07:13 -07:00
cdef class _ParsedSchema :
2013-08-13 22:21:38 -07:00
cdef C_ParsedSchema thisptr
cdef _init ( self , C_ParsedSchema other ) :
self . thisptr = other
return self
2013-08-25 17:07:08 -07:00
cpdef asConstValue ( self ) :
2013-08-26 14:57:48 -07:00
return toPythonReader ( < C_DynamicValue . Reader > self . thisptr . asConst ( ) , self )
2013-08-25 17:07:08 -07:00
2013-08-13 22:21:38 -07:00
cpdef asStruct ( self ) :
2013-08-26 15:07:13 -07:00
return _StructSchema ( ) . _init ( self . thisptr . asStruct ( ) )
2013-08-13 22:21:38 -07:00
cpdef getDependency ( self , id ) :
2013-08-26 15:07:13 -07:00
return _Schema ( ) . _init ( self . thisptr . getDependency ( id ) )
2013-08-13 22:21:38 -07:00
cpdef getProto ( self ) :
return _NodeReader ( ) . init ( self . thisptr . getProto ( ) )
cpdef getNested ( self , name ) :
2013-08-26 15:07:13 -07:00
return _ParsedSchema ( ) . _init ( self . thisptr . getNested ( name ) )
2013-08-13 22:21:38 -07:00
2013-08-26 15:07:13 -07:00
cdef class _SchemaParser :
2013-08-13 22:21:38 -07:00
cdef C_SchemaParser * thisptr
def __cinit__ ( self ) :
self . thisptr = new C_SchemaParser ( )
def __dealloc__ ( self ) :
del self . thisptr
2013-08-13 23:00:43 -07:00
def parseDiskFile ( self , displayName , diskPath , imports ) :
cdef StringPtr * importArray = < StringPtr * > malloc ( sizeof ( StringPtr ) * len ( imports ) )
for i in range ( len ( imports ) ) :
importArray [ i ] = StringPtr ( imports [ i ] )
cdef ArrayPtr [StringPtr ] importsPtr = ArrayPtr [ StringPtr ] ( importArray , < size_t > len ( imports ) )
2013-08-13 22:21:38 -07:00
2013-08-26 15:07:13 -07:00
ret = _ParsedSchema ( )
2013-08-13 23:00:43 -07:00
ret . _init ( self . thisptr . parseDiskFile ( displayName , diskPath , importsPtr ) )
free ( importArray )
2013-08-13 22:21:38 -07:00
return ret
2013-06-26 23:01:37 -07:00
cdef class MessageBuilder :
2013-08-26 16:16:58 -07:00
""" An abstract base class for building Cap ' n Proto messages
. . warning : : Don ' t ever instantiate this class directly. It is only used for inheritance.
"""
2013-06-26 23:01:37 -07:00
cdef schema_cpp .MessageBuilder * thisptr
def __dealloc__ ( self ) :
del self . thisptr
2013-08-26 16:16:58 -07:00
2013-07-07 18:48:55 -07:00
def __init__ ( self ) :
raise NotImplementedError ( " This is an abstract base class. You should use MallocMessageBuilder instead " )
2013-07-06 23:10:51 -07:00
cpdef initRoot ( self , schema ) :
2013-08-26 16:16:58 -07:00
""" A method for instantiating Cap ' n Proto structs
You will need to pass in a schema to specify which struct to
instantiate . Schemas are available in a loaded Cap ' n Proto module::
addressbook = capnp . load ( ' addressbook.capnp ' )
. . .
person = message . initRoot ( addressbook . Person )
: type schema : Schema
: param schema : A Cap ' n proto schema specifying which struct to instantiate
: rtype : : class : `_DynamicStructBuilder`
: return : An object where you will set all the members
"""
2013-08-26 15:07:13 -07:00
cdef _StructSchema s
2013-08-28 23:11:28 -07:00
if hasattr ( schema , ' schema ' ) :
s = schema . schema
2013-07-06 23:10:51 -07:00
else :
s = schema
2013-07-07 18:48:55 -07:00
return _DynamicStructBuilder ( ) . _init ( self . thisptr . initRootDynamicStruct ( s . thisptr ) , self )
2013-08-26 14:57:48 -07:00
2013-07-06 23:10:51 -07:00
cpdef getRoot ( self , schema ) :
2013-08-26 22:00:12 -07:00
""" A method for instantiating Cap ' n Proto structs, from an already pre-written buffer
2013-08-26 16:16:58 -07:00
Don ' t use this method unless you know what you ' re doing . You probably
want to use initRoot instead : :
addressbook = capnp . load ( ' addressbook.capnp ' )
. . .
person = message . initRoot ( addressbook . Person )
. . .
person = message . getRoot ( addressbook . Person )
: type schema : Schema
: param schema : A Cap ' n proto schema specifying which struct to instantiate
: rtype : : class : `_DynamicStructBuilder`
: return : An object where you will set all the members
"""
2013-08-26 15:07:13 -07:00
cdef _StructSchema s
2013-08-28 23:11:28 -07:00
if hasattr ( schema , ' schema ' ) :
s = schema . schema
2013-07-06 23:10:51 -07:00
else :
s = schema
2013-07-07 18:48:55 -07:00
return _DynamicStructBuilder ( ) . _init ( self . thisptr . getRootDynamicStruct ( s . thisptr ) , self )
2013-06-26 23:01:37 -07:00
2013-08-26 22:00:12 -07:00
cpdef newOrphan ( self , schema ) :
""" A method for instantiating Cap ' n Proto orphans
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unkown sized list , ie : :
addressbook = capnp . load ( ' addressbook.capnp ' )
alice = m . newOrphan ( addressbook . Person )
: type schema : Schema
: param schema : A Cap ' n proto schema specifying which struct to instantiate
: rtype : : class : `_DynamicOrphan`
: return : An orphan representing a : class : `_DynamicStructBuilder`
"""
cdef _StructSchema s
2013-08-28 23:11:28 -07:00
if hasattr ( schema , ' schema ' ) :
s = schema . schema
2013-08-26 22:00:12 -07:00
else :
s = schema
return _DynamicOrphan ( ) . _init ( self . thisptr . newOrphan ( s . thisptr ) , self )
2013-06-26 23:01:37 -07:00
cdef class MallocMessageBuilder ( MessageBuilder ) :
2013-08-26 16:16:58 -07:00
""" The main class for building Cap ' n Proto messages
You will use this class to handle arena allocation of the Cap ' n Proto
messages . You also use this object when you ' re done assigning to Cap ' n
Proto objects , and wish to serialize them : :
addressbook = capnp . load ( ' addressbook.capnp ' )
message = capnp . MallocMessageBuilder ( )
person = message . initRoot ( addressbook . Person )
person . name = ' alice '
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
writeMessageToFd ( f . fileno ( ) , message )
2013-08-26 16:16:58 -07:00
"""
2013-06-26 23:01:37 -07:00
def __cinit__ ( self ) :
self . thisptr = new schema_cpp . MallocMessageBuilder ( )
2013-08-26 16:16:58 -07:00
2013-07-07 18:48:55 -07:00
def __init__ ( self ) :
pass
2013-06-26 23:01:37 -07:00
2013-08-26 15:07:13 -07:00
cdef class _MessageReader :
2013-08-26 16:16:58 -07:00
""" An abstract base class for reading Cap ' n Proto messages
. . warning : : Don ' t ever instantiate this class. It is only used for inheritance.
"""
2013-06-26 23:01:37 -07:00
cdef schema_cpp .MessageReader * thisptr
def __dealloc__ ( self ) :
del self . thisptr
2013-07-07 18:48:55 -07:00
def __init__ ( self ) :
raise NotImplementedError ( " This is an abstract base class " )
2013-08-18 21:48:49 -07:00
cpdef _getRootNode ( self ) :
2013-06-26 23:01:37 -07:00
return _NodeReader ( ) . init ( self . thisptr . getRootNode ( ) )
2013-08-26 14:57:48 -07:00
2013-07-06 23:10:51 -07:00
cpdef getRoot ( self , schema ) :
2013-08-26 16:16:58 -07:00
""" A method for instantiating Cap ' n Proto structs
You will need to pass in a schema to specify which struct to
instantiate . Schemas are available in a loaded Cap ' n Proto module::
addressbook = capnp . load ( ' addressbook.capnp ' )
. . .
person = message . getRoot ( addressbook . Person )
: type schema : Schema
: param schema : A Cap ' n proto schema specifying which struct to instantiate
: rtype : : class : `_DynamicStructReader`
: return : An object with all the data of the read Cap ' n Proto message.
Access members with . syntax .
"""
2013-08-26 15:07:13 -07:00
cdef _StructSchema s
2013-08-28 23:11:28 -07:00
if hasattr ( schema , ' schema ' ) :
s = schema . schema
2013-07-06 23:10:51 -07:00
else :
s = schema
2013-07-07 18:48:55 -07:00
return _DynamicStructReader ( ) . _init ( self . thisptr . getRootDynamicStruct ( s . thisptr ) , self )
2013-06-26 23:01:37 -07:00
2013-08-26 15:07:13 -07:00
cdef class StreamFdMessageReader ( _MessageReader ) :
2013-08-26 16:16:58 -07:00
""" Read a Cap ' n Proto message from a file descriptor
2013-08-26 19:27:58 -07:00
You use this class to for reading message ( s ) from a file . It ' s analagous to the inverse of :func:`writeMessageToFd` and :class:`MessageBuilder`, but in one class::
2013-08-26 16:16:58 -07:00
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
message = StreamFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
person = message . getRoot ( addressbook . Person )
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
2013-07-07 18:48:55 -07:00
def __init__ ( self , int fd ) :
2013-06-26 23:01:37 -07:00
self . thisptr = new schema_cpp . StreamFdMessageReader ( fd )
2013-08-26 15:07:13 -07:00
cdef class PackedFdMessageReader ( _MessageReader ) :
2013-08-26 16:16:58 -07:00
""" Read a Cap ' n Proto message from a file descriptor in a packed manner
You use this class to for reading message ( s ) from a file . It ' s analagous to the inverse of writePackedMessageToFd and :class:`MessageBuilder`, but in one class.::
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
message = StreamFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
person = message . getRoot ( addressbook . Person )
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
2013-07-07 18:48:55 -07:00
def __init__ ( self , int fd ) :
2013-06-26 23:01:37 -07:00
self . thisptr = new schema_cpp . PackedFdMessageReader ( fd )
2013-08-26 16:16:58 -07:00
def writeMessageToFd ( int fd , MessageBuilder message ) :
""" Serialize a Cap ' n Proto message to a file descriptor
You use this method to serialize your message to a file . Please note that
you must pass a file descriptor ( ie . an int ) , not a file object . Make sure
you use the proper reader to match this ( ie . don ' t use PackedFdMessageReader)::
message = capnp . MallocMessageBuilder ( )
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
writeMessageToFd ( f . fileno ( ) , message )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
StreamFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
: type fd : int
: param fd : A file descriptor
: type message : : class : `MessageBuilder`
: param message : The Cap ' n Proto message to serialize
: rtype : void
"""
schema_cpp . writeMessageToFd ( fd , deref ( message . thisptr ) )
def writePackedMessageToFd ( int fd , MessageBuilder message ) :
""" Serialize a Cap ' n Proto message to a file descriptor in a packed manner
You use this method to serialize your message to a file . Please note that
you must pass a file descriptor ( ie . an int ) , not a file object . Also , note
the difference in names with writeMessageToFd . This method uses a different
serialization specification , and your reader will need to match . : :
message = capnp . MallocMessageBuilder ( )
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
writePackedMessageToFd ( f . fileno ( ) , message )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
PackedFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
: type fd : int
: param fd : A file descriptor
: type message : : class : `MessageBuilder`
: param message : The Cap ' n Proto message to serialize
2013-08-13 23:04:03 -07:00
2013-08-26 16:16:58 -07:00
: rtype : void
"""
schema_cpp . writePackedMessageToFd ( fd , deref ( message . thisptr ) )
2013-07-06 16:53:00 -07:00
2013-08-26 15:07:13 -07:00
from types import ModuleType as _ModuleType
import os as _os
2013-08-13 22:21:38 -07:00
2013-08-26 10:07:54 -07:00
def load ( file_name , display_name = None , imports = [ ] ) :
2013-08-26 16:16:58 -07:00
""" Load a Cap ' n Proto schema from a file
2013-08-13 22:21:38 -07:00
2013-08-26 10:07:54 -07:00
You will have to load a schema before you can begin doing anything
meaningful with this library . Loading a schema is much like Loading
2013-08-26 14:57:48 -07:00
a Python module ( and load even returns a `ModuleType` ) . Once it ' s been
2013-08-26 10:07:54 -07:00
loaded , you use it much like any other Module : :
2013-08-13 22:21:38 -07:00
2013-08-26 10:07:54 -07:00
addressbook = capnp . load ( ' addressbook.capnp ' )
print addressbook . qux # qux is a top level constant
# 123
message = capnp . MallocMessageBuilder ( )
person = message . initRoot ( addressbook . Person )
2013-08-13 22:21:38 -07:00
2013-08-26 10:07:54 -07:00
: 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 :
2013-08-26 15:07:13 -07:00
local_module = _ModuleType ( node . name )
2013-08-26 10:07:54 -07:00
module . __dict__ [ node . name ] = local_module
schema = nodeSchema . getNested ( node . name )
proto = schema . getProto ( )
if proto . isStruct :
2013-08-28 23:11:28 -07:00
local_module . schema = schema . asStruct ( )
2013-08-26 10:07:54 -07:00
elif proto . isConst :
module . __dict__ [ node . name ] = schema . asConstValue ( )
_load ( schema , local_module )
2013-08-13 22:21:38 -07:00
if display_name is None :
2013-08-26 15:07:13 -07:00
display_name = _os . path . basename ( file_name )
module = _ModuleType ( display_name )
parser = _SchemaParser ( )
2013-08-13 22:21:38 -07:00
module . _parser = parser
2013-08-13 23:00:43 -07:00
fileSchema = parser . parseDiskFile ( display_name , file_name , imports )
2013-08-13 22:21:38 -07:00
_load ( fileSchema , module )
2013-07-06 16:53:00 -07:00
2013-07-06 18:40:05 -07:00
return module