2013-06-26 23:01:37 -07:00
# capnp.pyx
# distutils: language = c++
2013-10-21 00:11:42 -07:00
# distutils: extra_compile_args = --std=c++11
2013-11-12 15:32:23 -08:00
# distutils: libraries = capnpc capnp capnp-rpc
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-12-05 00:07:51 -08:00
from capnp_cpp cimport Schema as C_Schema , StructSchema as C_StructSchema , InterfaceSchema as C_InterfaceSchema , DynamicStruct as C_DynamicStruct , DynamicValue as C_DynamicValue , Type as C_Type , DynamicList as C_DynamicList , fixMaybe , getEnumString , SchemaParser as C_SchemaParser , ParsedSchema as C_ParsedSchema , VOID , ArrayPtr , StringPtr , String , StringTree , DynamicOrphan as C_DynamicOrphan , ObjectPointer as C_DynamicObject , DynamicCapability as C_DynamicCapability , new_client , new_server , server_to_client , Request , Response , RemotePromise , convert_to_pypromise , PyPromise , VoidPromise , CallContext , PyRestorer , RpcSystem , makeRpcServer , makeRpcClient , makeRpcClientWithRestorer , restoreHelper , Capability as C_Capability , TwoPartyVatNetwork as C_TwoPartyVatNetwork , Side , AsyncIoStream , Own , makeTwoPartyVatNetwork , PromiseFulfillerPair as C_PromiseFulfillerPair , copyPromiseFulfillerPair , newPromiseAndFulfiller , reraise_kj_exception
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
2013-10-15 22:36:14 -07:00
from cpython.ref cimport PyObject , Py_INCREF , Py_DECREF
2013-11-13 20:54:57 -08:00
from cpython.exc cimport PyErr_Clear
2013-06-26 23:01:37 -07:00
from libc.stdint cimport *
ctypedef unsigned int uint
2013-11-14 00:19:52 -08:00
ctypedef uint8_t byte
2013-06-26 23:01:37 -07:00
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-08-31 16:44:54 -07:00
from libcpp cimport bool as cbool
2013-06-28 01:04:01 -07:00
2013-10-17 19:15:40 -07:00
from types import ModuleType as _ModuleType
import os as _os
import sys as _sys
import imp as _imp
from functools import partial as _partial
2013-10-20 17:24:59 -07:00
import warnings as _warnings
import inspect as _inspect
2013-11-14 23:06:14 -08:00
from operator import attrgetter as _attrgetter
2013-10-17 19:15:40 -07:00
2013-10-15 22:36:14 -07:00
# By making it public, we'll be able to call it from capabilityHelper.h
cdef public object wrap_dynamic_struct_reader ( C_DynamicStruct . Reader & reader ) :
return _DynamicStructReader ( ) . _init ( reader , None )
2013-10-20 17:24:59 -07:00
cdef public void wrap_remote_call ( PyObject * func , Response & r ) except * :
2013-10-17 22:42:14 -07:00
response = _Response ( ) . _init_childptr ( new Response ( moveResponse ( r ) ) , None )
func_obj = < object > func
# TODO: decref func?
func_obj ( response )
2013-11-14 23:06:14 -08:00
cdef _find_field_order ( struct_node ) :
return [ f . name for f in sorted ( struct_node . fields , key = _attrgetter ( ' codeOrder ' ) ) ]
2013-10-20 17:24:59 -07:00
cdef public VoidPromise * call_server_method ( PyObject * _server , char * _method_name , CallContext & _context ) except * :
2013-10-15 22:36:14 -07:00
server = < object > _server
method_name = < object > _method_name
context = _CallContext ( ) . _init ( _context )
2013-11-14 23:06:14 -08:00
func = getattr ( server , method_name + ' _context ' , None )
if func is not None :
ret = func ( context )
if ret is not None :
if type ( ret ) is _VoidPromise :
return new VoidPromise ( moveVoidPromise ( deref ( ( < _VoidPromise > ret ) . thisptr ) ) )
else :
try :
warning_msg = ' Server function ( %s ) returned a value that was not a VoidPromise: return = %s ' % ( method_name , str ( ret ) )
except :
warning_msg = ' Server function ( %s ) returned a value that was not a VoidPromise ' % ( method_name )
_warnings . warn_explicit ( warning_msg , UserWarning , _inspect . getsourcefile ( func ) , _inspect . getsourcelines ( func ) [ 1 ] )
if ret is not None :
if type ( ret ) is _VoidPromise :
return new VoidPromise ( moveVoidPromise ( deref ( ( < _VoidPromise > ret ) . thisptr ) ) )
else :
try :
warning_msg = ' Server function ( %s ) returned a value that was not a VoidPromise: return = %s ' % ( method_name , str ( ret ) )
except :
warning_msg = ' Server function ( %s ) returned a value that was not a VoidPromise ' % ( method_name )
_warnings . warn_explicit ( warning_msg , UserWarning , _inspect . getsourcefile ( func ) , _inspect . getsourcelines ( func ) [ 1 ] )
else :
func = getattr ( server , method_name ) # will raise if no function found
params = context . params
params_dict = { name : getattr ( params , name ) for name in params . schema . fieldnames }
2013-12-05 00:07:51 -08:00
params_dict [ ' _context ' ] = context
2013-11-14 23:06:14 -08:00
ret = func ( * * params_dict )
if ret is not None :
if type ( ret ) is _VoidPromise :
return new VoidPromise ( moveVoidPromise ( deref ( ( < _VoidPromise > ret ) . thisptr ) ) )
if not isinstance ( ret , tuple ) :
ret = ( ret , )
names = _find_field_order ( context . results . schema . node . struct )
if len ( ret ) > len ( names ) :
raise ValueError ( ' Too many values returned from ` %s `. Expected %d and got %d ' % ( method_name , len ( names ) , len ( ret ) ) )
results = context . results
for arg_name , arg_val in zip ( names , ret ) :
setattr ( results , arg_name , arg_val )
2013-10-17 22:42:14 -07:00
return NULL
2013-11-12 15:32:23 -08:00
cdef public C_Capability .Client * call_py_restorer ( PyObject * _restorer , C_DynamicStruct . Reader & _reader ) except * :
restorer = < object > _restorer
reader = _DynamicStructReader ( ) . _init ( _reader , None )
ret = restorer . restore ( reader )
cdef _DynamicCapabilityServer server = ret
return new C_Capability . Client ( server_to_client ( server . schema . thisptr , < PyObject * > server . server ) )
2013-11-13 17:53:34 -08:00
cdef extern from " <kj/string.h> " namespace " ::kj " :
String strStructReader " ::kj::str " ( C_DynamicStruct . Reader )
String strStructBuilder " ::kj::str " ( C_DynamicStruct . Builder )
String strRequest " ::kj::str " ( Request & )
String strListReader " ::kj::str " ( C_DynamicList . Reader )
String strListBuilder " ::kj::str " ( C_DynamicList . Builder )
String strException " ::kj::str " ( capnp . Exception )
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 )
2013-11-14 20:59:21 -08:00
_Nature = _make_enum ( ' _Nature ' ,
2013-11-13 17:53:34 -08:00
PRECONDITION = 0 ,
LOCAL_BUG = 1 ,
OS_ERROR = 2 ,
NETWORK_FAILURE = 3 ,
OTHER = 4 )
2013-11-14 20:59:21 -08:00
_Durability = _make_enum ( ' _Durability ' ,
2013-11-13 17:53:34 -08:00
PERMANENT = 0 ,
TEMPORARY = 1 ,
OVERLOADED = 2 )
cdef class _KjExceptionWrapper :
cdef capnp .Exception * thisptr
cdef _init ( self , capnp . Exception & other ) :
self . thisptr = new capnp . Exception ( moveException ( other ) )
return self
def __dealloc__ ( self ) :
del self . thisptr
property file :
def __get__ ( self ) :
return < char * > self . thisptr . getFile ( )
property line :
def __get__ ( self ) :
return self . thisptr . getLine ( )
property nature :
def __get__ ( self ) :
cdef int temp = < int > self . thisptr . getNature ( )
return _Nature . reverse_mapping [ temp ]
property durability :
def __get__ ( self ) :
cdef int temp = < int > self . thisptr . getDurability ( )
return _Durability . reverse_mapping [ temp ]
property description :
def __get__ ( self ) :
return < char * > self . thisptr . getDescription ( ) . cStr ( )
def __str__ ( self ) :
return < char * > strException ( deref ( self . thisptr ) ) . cStr ( )
# Extension classes can't inherit from Exception, so we're going to proxy wrap kj::Exception, and forward all calls to it from this Python class
class KjException ( Exception ) :
2013-11-14 20:59:21 -08:00
Nature = _make_enum ( ' Nature ' , * * { x : x for x in _Nature . reverse_mapping . values ( ) } )
Durability = _make_enum ( ' Durability ' , * * { x : x for x in _Durability . reverse_mapping . values ( ) } )
2013-11-13 17:53:34 -08:00
def __init__ ( self , message = None , nature = None , durability = None , wrapper = None ) :
if wrapper is not None :
self . wrapper = wrapper
self . message = str ( wrapper )
else :
self . message = message
self . nature = nature
self . durability = durability
@property
def file ( self ) :
return self . wrapper . file
@property
def line ( self ) :
return self . wrapper . line
@property
def nature ( self ) :
if self . wrapper is not None :
return self . wrapper . nature
else :
return self . nature
@property
def durability ( self ) :
if self . wrapper is not None :
return self . wrapper . durability
else :
return self . durability
@property
def description ( self ) :
if self . wrapper is not None :
return self . wrapper . description
else :
return self . message
def __str__ ( self ) :
return self . message
2013-10-15 22:36:14 -07:00
cdef public object wrap_kj_exception ( capnp . Exception & exception ) :
2013-11-13 20:54:57 -08:00
PyErr_Clear ( )
2013-11-13 17:53:34 -08:00
wrapper = _KjExceptionWrapper ( ) . _init ( exception )
ret = KjException ( wrapper = wrapper )
return ret
cdef public object wrap_kj_exception_for_reraise ( capnp . Exception & exception ) :
wrapper = _KjExceptionWrapper ( ) . _init ( exception )
nature = wrapper . nature
if wrapper . nature == ' PRECONDITION ' :
return ValueError ( str ( wrapper ) )
# elif wrapper.nature == 'LOCAL_BUG':
# return ValueError(str(wrapper))
if wrapper . nature == ' OS_ERROR ' :
return OSError ( str ( wrapper ) )
if wrapper . nature == ' NETWORK_FAILURE ' :
return IOError ( str ( wrapper ) )
ret = KjException ( wrapper = wrapper )
return ret
2013-10-15 22:36:14 -07:00
2013-11-13 20:54:57 -08:00
cdef public object get_exception_info ( object exc_type , object exc_obj , object exc_tb ) :
try :
2013-11-13 21:14:46 -08:00
return ( exc_tb . tb_frame . f_code . co_filename . encode ( ) , exc_tb . tb_lineno , ( repr ( exc_type ) + ' : ' + str ( exc_obj ) ) . encode ( ) )
2013-11-13 20:54:57 -08:00
except :
2013-11-13 21:14:46 -08:00
return ( b ' ' , 0 , b " Couldn ' t determine python exception " )
2013-11-13 20:54:57 -08:00
2013-08-31 17:07:44 -07:00
ctypedef fused _DynamicStructReaderOrBuilder :
_DynamicStructReader
_DynamicStructBuilder
2013-08-31 20:00:57 -07:00
ctypedef fused _DynamicSetterClasses :
C_DynamicList . Builder
C_DynamicStruct . Builder
2013-10-15 22:36:14 -07:00
Request
2013-08-31 20:00:57 -07:00
2013-11-13 17:53:34 -08:00
ctypedef fused _PromiseTypes :
2013-11-14 20:59:21 -08:00
_Promise
2013-11-13 17:53:34 -08:00
_RemotePromise
_VoidPromise
PromiseFulfillerPair
2013-08-31 20:00:57 -07:00
2013-09-03 11:54:45 -07:00
cdef extern from " Python.h " :
cdef int PyObject_AsReadBuffer ( object , void * * b , Py_ssize_t * c )
2013-09-20 14:35:35 -07:00
cdef int PyObject_AsWriteBuffer ( object , void * * b , Py_ssize_t * c )
2013-09-03 11:54:45 -07:00
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 :
2013-11-13 17:53:34 -08:00
T operator [ ] ( uint ) except + reraise_kj_exception
2013-06-26 23:01:37 -07:00
uint size ( )
cppclass Builder :
2013-11-13 17:53:34 -08:00
T operator [ ] ( uint ) except + reraise_kj_exception
2013-06-26 23:01:37 -07:00
uint size ( )
2013-08-26 14:45:15 -07:00
cdef extern from " <utility> " namespace " std " :
2013-10-19 22:38:10 -07:00
C_DynamicStruct . Pipeline moveStructPipeline " std::move " ( C_DynamicStruct . Pipeline )
2013-08-26 22:00:12 -07:00
C_DynamicOrphan moveOrphan " std::move " ( C_DynamicOrphan )
2013-10-15 22:36:14 -07:00
Request moveRequest " std::move " ( Request )
2013-10-17 19:15:40 -07:00
Response moveResponse " std::move " ( Response )
2013-10-15 22:36:14 -07:00
PyPromise movePromise " std::move " ( PyPromise )
2013-10-17 22:42:14 -07:00
VoidPromise moveVoidPromise " std::move " ( VoidPromise )
2013-10-15 22:36:14 -07:00
RemotePromise moveRemotePromise " std::move " ( RemotePromise )
CallContext moveCallContext " std::move " ( CallContext )
2013-11-12 19:38:34 -08:00
Own [ AsyncIoStream ] moveOwnAsyncIOStream " std::move " ( Own [ AsyncIoStream ] )
2013-11-13 17:53:34 -08:00
capnp . Exception moveException " std::move " ( capnp . Exception )
2013-12-05 00:07:51 -08:00
capnp . AsyncIoContext moveAsyncContext " std::move " ( capnp . AsyncIoContext )
2013-08-26 14:45:15 -07:00
2013-08-31 15:07:13 -07:00
cdef extern from " <capnp/pretty-print.h> " namespace " ::capnp " :
StringTree printStructReader " ::capnp::prettyPrint " ( C_DynamicStruct . Reader )
StringTree printStructBuilder " ::capnp::prettyPrint " ( C_DynamicStruct . Builder )
2013-10-15 22:36:14 -07:00
StringTree printRequest " ::capnp::prettyPrint " ( Request & )
2013-08-31 15:07:13 -07:00
StringTree printListReader " ::capnp::prettyPrint " ( C_DynamicList . Reader )
StringTree printListBuilder " ::capnp::prettyPrint " ( C_DynamicList . Builder )
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 ) :
2013-10-21 00:11:42 -07:00
return < char * > self . thisptr . getDisplayName ( ) . cStr ( )
2013-08-10 13:54:25 -07:00
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-10-15 13:29:54 -07:00
property isInterface :
def __get__ ( self ) :
return self . thisptr . isInterface ( )
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 ) :
2013-10-21 00:11:42 -07:00
return < char * > self . thisptr . getName ( ) . cStr ( )
2013-08-13 22:21:38 -07:00
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::
. . .
2013-09-03 00:25:32 -07:00
person = addressbook . Person . read ( file )
2013-08-26 19:27:58 -07:00
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-09-01 20:10:57 -07:00
return to_python_reader ( self . thisptr [ index ] , self . _parent )
2013-06-28 01:04:01 -07:00
def __len__ ( self ) :
return self . thisptr . size ( )
2013-08-31 15:07:13 -07:00
def __str__ ( self ) :
2013-10-21 00:11:42 -07:00
return < char * > printListReader ( self . thisptr ) . flatten ( ) . cStr ( )
2013-08-31 15:07:13 -07:00
def __repr__ ( self ) :
# TODO: Print the list type.
2013-10-21 00:11:42 -07:00
return ' <capnp list reader %s > ' % < char * > strListReader ( self . thisptr ) . cStr ( )
2013-08-31 15:07:13 -07:00
2013-08-27 10:55:06 -07:00
cdef class _DynamicResizableListBuilder :
2013-08-29 18:46:17 -07:00
""" Class for building growable Cap ' n Proto Lists
. . warning : : You need to call : meth : `finish` on this object before serializing the Cap ' n Proto message. Failure to do so will cause your objects not to be written out as well as leaking orphan structs into your message.
2013-09-01 02:13:19 -07:00
This class works much like : class : `_DynamicListBuilder` , but it allows growing the list dynamically . It is meant for lists of structs , since for primitive types like int or float , you ' re much better off using a normal python list and then serializing straight to a Cap ' n Proto list . It has __getitem__ and __len__ defined , but not __setitem__ : :
2013-08-29 18:46:17 -07:00
. . .
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
2013-08-29 18:46:17 -07:00
2013-09-01 20:10:57 -07:00
phones = person . init_resizable_list ( ' phones ' ) # This returns a _DynamicResizableListBuilder
2013-08-29 18:46:17 -07:00
phone = phones . add ( )
phone . number = ' foo '
phone = phones . add ( )
phone . number = ' bar '
people . finish ( )
2013-09-01 02:13:19 -07:00
f = open ( ' example ' , ' w ' )
2013-09-01 20:10:57 -07:00
person . write ( f )
2013-08-29 18:46:17 -07:00
"""
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 ) :
2013-08-29 18:46:17 -07:00
""" A method for adding a new struct to the list
This will return a struct , in which you can set fields that will be reflected in the serialized Cap ' n Proto message.
: rtype : : class : `_DynamicStructBuilder`
"""
2013-09-01 20:10:57 -07:00
orphan = self . _message . new_orphan ( self . _schema )
2013-08-26 22:00:12 -07:00
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-29 18:46:17 -07:00
""" A method for closing this list and serializing all its members to the message
If you don ' t call this method, the items you previously added from this object will leak into the message, ie. inaccessible but still taking up space.
"""
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::
. . .
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
2013-08-26 19:27:58 -07:00
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-31 17:22:11 -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-31 17:22:11 -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-09-03 00:25:32 -07:00
cdef _get ( self , index ) :
2013-09-01 20:10:57 -07:00
return to_python_builder ( 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 , value ) :
size = self . thisptr . size ( )
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
2013-08-31 20:00:57 -07:00
_setDynamicField ( self . thisptr , index , value , self . _parent )
2013-06-28 01:04:01 -07:00
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
2013-12-04 11:42:57 -08:00
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unknown sized list .
2013-08-26 22:00:12 -07:00
: 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-31 15:07:13 -07:00
def __str__ ( self ) :
2013-10-21 00:11:42 -07:00
return < char * > printListBuilder ( self . thisptr ) . flatten ( ) . cStr ( )
2013-08-31 15:07:13 -07:00
def __repr__ ( self ) :
# TODO: Print the list type.
2013-10-21 00:11:42 -07:00
return ' <capnp list builder %s > ' % < char * > strListBuilder ( self . thisptr ) . cStr ( )
2013-08-31 15:07:13 -07:00
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-10-19 22:38:10 -07:00
# cdef to_python_pipeline(C_DynamicValue.Pipeline self, object parent):
# cdef int type = self.getType()
# if type == capnp.TYPE_CAPABILITY:
# return _DynamicCapabilityClient()._init(self.asCapability(), parent)
# # elif type == capnp.TYPE_STRUCT:
# # return _DynamicStructReader()._init(self.asStruct(), parent)
# elif type == capnp.TYPE_UNKNOWN:
# 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-09-01 20:10:57 -07:00
cdef to_python_reader ( C_DynamicValue . Reader self , object parent ) :
2013-08-26 14:57:48 -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 :
2013-10-21 00:11:42 -07:00
return ( < char * > self . asText ( ) . cStr ( ) ) [ : ]
2013-08-26 14:57:48 -07:00
elif type == capnp . TYPE_DATA :
temp = self . asData ( )
return ( < char * > temp . begin ( ) ) [ : temp . size ( ) ]
elif type == capnp . TYPE_LIST :
2013-09-01 00:09:46 -07:00
return _DynamicListReader ( ) . _init ( self . asList ( ) , parent )
2013-08-26 14:57:48 -07:00
elif type == capnp . TYPE_STRUCT :
return _DynamicStructReader ( ) . _init ( self . asStruct ( ) , parent )
elif type == capnp . TYPE_ENUM :
2013-10-21 00:11:42 -07:00
return < char * > fixMaybe ( self . asEnum ( ) . getEnumerant ( ) ) . getProto ( ) . getName ( ) . cStr ( )
2013-08-26 14:57:48 -07:00
elif type == capnp . TYPE_VOID :
return None
2013-09-05 16:43:54 -07:00
elif type == capnp . TYPE_OBJECT :
2013-09-18 17:19:57 -07:00
return _DynamicObjectReader ( ) . _init ( self . asObject ( ) , parent )
2013-10-17 22:42:14 -07:00
elif type == capnp . TYPE_CAPABILITY :
return _DynamicCapabilityClient ( ) . _init ( self . asCapability ( ) , parent )
2013-09-05 16:43:54 -07:00
elif type == capnp . TYPE_UNKNOWN :
2013-08-26 14:57:48 -07:00
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-09-01 20:10:57 -07:00
cdef to_python_builder ( 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 :
2013-10-21 00:11:42 -07:00
return ( < char * > self . asText ( ) . cStr ( ) ) [ : ]
2013-07-06 23:10:51 -07:00
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 :
2013-10-21 00:11:42 -07:00
return < char * > fixMaybe ( self . asEnum ( ) . getEnumerant ( ) ) . getProto ( ) . getName ( ) . cStr ( )
2013-06-28 01:04:01 -07:00
elif type == capnp . TYPE_VOID :
return None
2013-09-05 16:43:54 -07:00
elif type == capnp . TYPE_OBJECT :
2013-09-24 11:49:38 -07:00
return _DynamicObjectBuilder ( ) . _init ( self . asObject ( ) , parent )
2013-10-17 22:42:14 -07:00
elif type == capnp . TYPE_CAPABILITY :
return _DynamicCapabilityClient ( ) . _init ( self . asCapability ( ) , parent )
2013-09-05 16:43:54 -07:00
elif type == capnp . TYPE_UNKNOWN :
2013-06-28 01:04:01 -07:00
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
2013-09-01 20:10:57 -07:00
cdef C_DynamicValue .Reader _extract_dynamic_struct_builder ( _DynamicStructBuilder value ) :
2013-08-31 20:00:57 -07:00
return C_DynamicValue . Reader ( value . thisptr . asReader ( ) )
2013-09-01 20:10:57 -07:00
cdef C_DynamicValue .Reader _extract_dynamic_struct_reader ( _DynamicStructReader value ) :
2013-08-31 20:00:57 -07:00
return C_DynamicValue . Reader ( value . thisptr )
2013-10-17 22:42:14 -07:00
cdef C_DynamicValue .Reader _extract_dynamic_client ( _DynamicCapabilityClient value ) :
return C_DynamicValue . Reader ( value . thisptr )
2013-10-19 22:38:10 -07:00
cdef C_DynamicValue .Reader _extract_dynamic_server ( _DynamicCapabilityServer value ) :
return new_server ( value . schema . thisptr , < PyObject * > value . server )
2013-08-31 20:00:57 -07:00
cdef _setDynamicField ( _DynamicSetterClasses thisptr , field , value , parent ) :
cdef C_DynamicValue .Reader temp
value_type = type ( value )
if value_type is int or value_type is long :
if value < 0 :
temp = C_DynamicValue . Reader ( < long long > value )
else :
temp = C_DynamicValue . Reader ( < unsigned long long > value )
thisptr . set ( field , temp )
elif value_type is float :
temp = C_DynamicValue . Reader ( < double > value )
thisptr . set ( field , temp )
elif value_type is bool :
temp = C_DynamicValue . Reader ( < cbool > value )
thisptr . set ( field , temp )
2013-10-09 22:36:55 -07:00
elif isinstance ( value , basestring ) :
2013-08-31 20:00:57 -07:00
temp = C_DynamicValue . Reader ( < char * > value )
thisptr . set ( field , temp )
elif value_type is list :
2013-09-01 20:10:57 -07:00
builder = to_python_builder ( thisptr . init ( field , len ( value ) ) , parent )
2013-08-31 20:00:57 -07:00
for ( i , v ) in enumerate ( value ) :
builder [ i ] = v
elif value is None :
temp = C_DynamicValue . Reader ( VOID )
thisptr . set ( field , temp )
elif value_type is _DynamicStructBuilder :
2013-09-01 20:10:57 -07:00
thisptr . set ( field , _extract_dynamic_struct_builder ( value ) )
2013-08-31 20:00:57 -07:00
elif value_type is _DynamicStructReader :
2013-09-01 20:10:57 -07:00
thisptr . set ( field , _extract_dynamic_struct_reader ( value ) )
2013-10-17 22:42:14 -07:00
elif value_type is _DynamicCapabilityClient :
thisptr . set ( field , _extract_dynamic_client ( value ) )
2013-10-19 22:38:10 -07:00
elif value_type is _DynamicCapabilityServer :
thisptr . set ( field , _extract_dynamic_server ( value ) )
2013-08-31 20:00:57 -07:00
else :
raise ValueError ( " Non primitive type " )
2013-10-15 22:36:14 -07:00
cdef _setDynamicFieldPtr ( _DynamicSetterClasses * thisptr , field , value , parent ) :
cdef C_DynamicValue .Reader temp
value_type = type ( value )
if value_type is int or value_type is long :
if value < 0 :
temp = C_DynamicValue . Reader ( < long long > value )
else :
temp = C_DynamicValue . Reader ( < unsigned long long > value )
thisptr . set ( field , temp )
elif value_type is float :
temp = C_DynamicValue . Reader ( < double > value )
thisptr . set ( field , temp )
elif value_type is bool :
temp = C_DynamicValue . Reader ( < cbool > value )
thisptr . set ( field , temp )
elif isinstance ( value , basestring ) :
temp = C_DynamicValue . Reader ( < char * > value )
thisptr . set ( field , temp )
elif value_type is list :
builder = to_python_builder ( thisptr . init ( field , len ( value ) ) , parent )
for ( i , v ) in enumerate ( value ) :
builder [ i ] = v
elif value is None :
temp = C_DynamicValue . Reader ( VOID )
thisptr . set ( field , temp )
elif value_type is _DynamicStructBuilder :
thisptr . set ( field , _extract_dynamic_struct_builder ( value ) )
elif value_type is _DynamicStructReader :
thisptr . set ( field , _extract_dynamic_struct_reader ( value ) )
2013-10-17 22:42:14 -07:00
elif value_type is _DynamicCapabilityClient :
thisptr . set ( field , _extract_dynamic_client ( value ) )
2013-10-15 22:36:14 -07:00
else :
raise ValueError ( " Non primitive type " )
2013-10-22 13:32:35 -07:00
cdef _to_dict ( msg , bint verbose ) :
2013-09-03 00:25:32 -07:00
msg_type = type ( msg )
2013-09-03 01:00:52 -07:00
if msg_type is _DynamicListBuilder or msg_type is _DynamicListReader or msg_type is _DynamicResizableListBuilder :
2013-10-22 13:32:35 -07:00
return [ _to_dict ( x , verbose ) for x in msg ]
2013-09-03 00:25:32 -07:00
2013-09-03 01:00:52 -07:00
if msg_type is _DynamicStructBuilder or msg_type is _DynamicStructReader :
2013-09-03 00:25:32 -07:00
ret = { }
try :
which = msg . which ( )
2013-10-22 13:32:35 -07:00
ret [ which ] = _to_dict ( getattr ( msg , which ) , verbose )
2013-09-03 00:25:32 -07:00
except ValueError :
pass
for field in msg . schema . non_union_fields :
2013-10-22 13:32:35 -07:00
if verbose or msg . _has ( field ) :
ret [ field ] = _to_dict ( getattr ( msg , field ) , verbose )
2013-09-03 00:25:32 -07:00
return ret
return msg
2013-09-03 01:00:52 -07:00
cdef _from_dict_helper ( msg , field , d ) :
2013-09-04 21:53:13 -07:00
d_type = type ( d )
if d_type is dict :
2013-10-22 13:22:08 -07:00
try :
sub_msg = getattr ( msg , field )
except Exception as e :
str_error = str ( e )
if ' expected isSetInUnion(field) ' in str_error :
msg . init ( field )
sub_msg = getattr ( msg , field )
else :
raise
2013-09-03 01:00:52 -07:00
for key , val in d . iteritems ( ) :
2013-10-22 13:32:35 -07:00
_from_dict_helper ( sub_msg , key , val )
2013-09-04 22:00:42 -07:00
elif d_type is list and len ( d ) > 0 :
2013-09-03 01:00:52 -07:00
l = msg . init ( field , len ( d ) )
for i in range ( len ( d ) ) :
2013-09-04 22:00:42 -07:00
if isinstance ( d [ i ] , ( dict , list ) ) :
2013-09-03 01:00:52 -07:00
for key , val in d [ i ] . iteritems ( ) :
2013-10-22 13:32:35 -07:00
_from_dict_helper ( l [ i ] , key , val )
2013-09-03 01:00:52 -07:00
else :
l [ i ] = d [ i ]
else :
setattr ( msg , field , d )
2013-10-22 13:22:08 -07:00
2013-09-03 01:00:52 -07:00
cdef _from_dict ( msg , d ) :
for key , val in d . iteritems ( ) :
if key != ' which ' :
_from_dict_helper ( msg , key , val )
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` : :
2013-09-03 00:25:32 -07:00
person = addressbook . Person . read ( file ) # This returns a _DynamicStructReader
2013-08-26 19:27:58 -07:00
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-11-13 10:58:16 -08:00
cdef public bint is_root
2013-08-28 14:34:37 -07:00
cdef object _obj_to_pin
2013-11-13 10:58:16 -08:00
cdef _init ( self , C_DynamicStruct . Reader other , object parent , bint isRoot = False ) :
2013-06-26 23:01:37 -07:00
self . thisptr = other
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-11-13 10:58:16 -08:00
self . is_root = isRoot
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-09-01 20:10:57 -07:00
return to_python_reader ( self . thisptr . get ( field ) , self . _parent )
2013-06-28 01:04:01 -07:00
def _has ( self , field ) :
return self . thisptr . has ( field )
2013-09-03 00:25:32 -07:00
cpdef which ( self ) :
2013-08-26 19:27:58 -07:00
""" 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 : :
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
2013-08-26 19:27:58 -07:00
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-10-21 00:11:42 -07:00
cdef object which = < char * > getEnumString ( self . thisptr )
2013-09-03 00:25:32 -07:00
if len ( which ) == 0 :
raise ValueError ( " Attempted to call which on a non-union type " )
return which
2013-08-15 15:44:54 -07:00
2013-08-28 14:34:37 -07:00
property schema :
2013-08-29 18:46:17 -07:00
"""A property that returns the _StructSchema object matching this reader"""
2013-08-28 14:34:37 -07:00
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
2013-08-31 15:07:13 -07:00
def __str__ ( self ) :
2013-10-21 00:11:42 -07:00
return < char * > printStructReader ( self . thisptr ) . flatten ( ) . cStr ( )
2013-08-31 15:07:13 -07:00
def __repr__ ( self ) :
2013-10-21 00:11:42 -07:00
return ' < %s reader %s > ' % ( self . schema . node . displayName , < char * > strStructReader ( self . thisptr ) . cStr ( ) )
2013-08-31 15:07:13 -07:00
2013-10-22 13:32:35 -07:00
def to_dict ( self , verbose = False ) :
return _to_dict ( self , verbose )
2013-09-03 00:25:32 -07:00
2013-10-20 22:55:41 -07:00
cpdef as_builder ( self ) :
""" A method for casting this Builder to a Reader
2013-11-14 20:59:21 -08:00
This is a copying operation with respect to the message ' s buffer. Changes in the new builder will not reflect in the original reader.
2013-08-31 15:07:13 -07:00
2013-11-14 20:59:21 -08:00
: rtype : : class : `_DynamicStructBuilder`
2013-10-20 22:55:41 -07:00
"""
builder = _MallocMessageBuilder ( )
return builder . set_root ( self )
2013-09-03 00:25:32 -07:00
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` : :
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( ) # This returns a _DynamicStructBuilder
2013-08-26 19:27:58 -07:00
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-31 17:22:11 -07:00
cdef C_DynamicStruct .Builder thisptr
2013-07-07 18:48:55 -07:00
cdef public object _parent
2013-11-13 10:58:16 -08:00
cdef public bint is_root
cdef bint _is_written
2013-08-31 18:19:02 -07:00
cdef _init ( self , C_DynamicStruct . Builder other , object parent , bint isRoot = False ) :
2013-08-31 17:22:11 -07:00
self . thisptr = other
2013-07-07 18:48:55 -07:00
self . _parent = parent
2013-11-13 10:58:16 -08:00
self . is_root = isRoot
2013-10-20 22:44:15 -07:00
self . _is_written = False
2013-06-28 01:04:01 -07:00
return self
2013-10-20 22:44:15 -07:00
cdef _check_write ( self ) :
2013-11-13 10:58:16 -08:00
if not self . is_root :
2013-10-20 22:44:15 -07:00
raise ValueError ( " You can only call write() on the message ' s root struct. " )
if self . _is_written :
_warnings . warn ( " This message has already been written once. Be very careful that you ' re not setting Text/Struct/List fields more than once, since that will cause memory leaks (both in memory and in the serialized data). You can disable this warning by setting the `_is_written` field of this object to False after every write. " )
2013-09-01 20:10:57 -07:00
def write ( self , file ) :
2013-08-31 18:19:02 -07:00
""" Writes the struct ' s containing message to the given file object in unpacked binary format.
2013-09-01 20:10:57 -07:00
This is a shortcut for calling capnp . _write_message_to_fd ( ) . This can only be called on the
2013-08-31 18:19:02 -07:00
message ' s root struct.
: type file : file
: param file : A file or socket object ( or anything with a fileno ( ) method ) , open for write .
: rtype : void
: Raises : : exc : `exceptions.ValueError` if this isn ' t the message ' s root struct .
"""
2013-10-20 22:44:15 -07:00
self . _check_write ( )
2013-09-01 20:10:57 -07:00
_write_message_to_fd ( file . fileno ( ) , self . _parent )
2013-10-20 22:44:15 -07:00
self . _is_written = True
2013-08-31 18:19:02 -07:00
2013-09-01 20:10:57 -07:00
def write_packed ( self , file ) :
2013-08-31 18:19:02 -07:00
""" Writes the struct ' s containing message to the given file object in packed binary format.
2013-09-01 20:10:57 -07:00
This is a shortcut for calling capnp . _write_packed_message_to_fd ( ) . This can only be called on
2013-08-31 18:19:02 -07:00
the message ' s root struct.
: type file : file
: param file : A file or socket object ( or anything with a fileno ( ) method ) , open for write .
: rtype : void
: Raises : : exc : `exceptions.ValueError` if this isn ' t the message ' s root struct .
"""
2013-10-20 22:44:15 -07:00
self . _check_write ( )
2013-09-01 20:10:57 -07:00
_write_packed_message_to_fd ( file . fileno ( ) , self . _parent )
2013-10-20 22:44:15 -07:00
self . _is_written = True
2013-06-28 01:04:01 -07:00
2013-11-13 22:14:29 -08:00
cpdef to_bytes ( _DynamicStructBuilder self ) except + reraise_kj_exception :
2013-09-03 11:54:45 -07:00
""" Returns the struct ' s containing message as a Python bytes object in the unpacked binary format.
This is inefficient ; it makes several copies .
: rtype : bytes
: Raises : : exc : `exceptions.ValueError` if this isn ' t the message ' s root struct .
"""
2013-10-20 22:44:15 -07:00
self . _check_write ( )
2013-09-03 11:54:45 -07:00
cdef _MessageBuilder builder = self . _parent
array = schema_cpp . messageToFlatArray ( deref ( builder . thisptr ) )
cdef const char * ptr = < const char * > array . begin ( )
2013-09-03 22:25:12 -07:00
cdef bytes ret = ptr [ : 8 * array . size ( ) ]
2013-10-20 22:44:15 -07:00
self . _is_written = True
2013-09-03 22:25:12 -07:00
return ret
2013-09-03 11:54:45 -07:00
2013-11-14 00:19:52 -08:00
cpdef to_bytes_packed ( _DynamicStructBuilder self ) except + reraise_kj_exception :
self . _check_write ( )
cdef _MessageBuilder builder = self . _parent
return _message_to_packed_bytes ( builder )
2013-09-03 00:25:32 -07:00
cdef _get ( self , field ) :
2013-09-18 17:19:57 -07:00
cdef C_DynamicValue .Builder value = self . thisptr . get ( field )
2013-09-24 11:49:38 -07:00
return to_python_builder ( value , self . _parent )
2013-08-25 16:41:37 -07:00
def __getattr__ ( self , field ) :
return self . _get ( field )
2013-06-28 01:04:01 -07:00
def __setattr__ ( self , field , value ) :
2013-08-31 20:00:57 -07:00
_setDynamicField ( self . thisptr , field , value , self . _parent )
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-09-03 00:25:32 -07:00
cpdef init ( self , field , size = None ) :
2013-08-26 19:27:58 -07:00
""" 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`
2013-09-03 00:25:32 -07:00
: Raises : : exc : `exceptions.ValueError` if the field isn ' t in this struct
2013-08-26 19:27:58 -07:00
"""
2013-07-06 23:10:51 -07:00
if size is None :
2013-09-01 20:10:57 -07:00
return to_python_builder ( self . thisptr . init ( field ) , self . _parent )
2013-07-06 23:10:51 -07:00
else :
2013-09-01 20:10:57 -07:00
return to_python_builder ( self . thisptr . init ( field , size ) , self . _parent )
2013-07-06 23:10:51 -07:00
2013-09-01 20:10:57 -07:00
cpdef init_resizable_list ( self , field ) :
2013-08-29 18:46:17 -07:00
""" Method for initializing fields that are of type list (of structs)
2013-08-29 21:03:00 -07:00
This version of init returns a : class : `_DynamicResizableListBuilder` that allows you to add members one at a time ( ie . if you don ' t know the size for sure). This is only meant for lists of Cap ' n Proto objects , since for primitive types you can just define a normal python list and fill it yourself .
2013-08-29 18:46:17 -07:00
. . warning : : You need to call : meth : `_DynamicResizableListBuilder.finish` on the list object before serializing the Cap ' n Proto message. Failure to do so will cause your objects not to be written out as well as leaking orphan structs into your message.
: type field : str
: param field : The field name to initialize
: rtype : : class : `_DynamicResizableListBuilder`
2013-09-03 00:25:32 -07:00
: Raises : : exc : `exceptions.ValueError` if the field isn ' t in this struct
2013-08-29 18:46:17 -07:00
"""
2013-08-27 10:55:06 -07:00
return _DynamicResizableListBuilder ( self , field , _StructSchema ( ) . _init ( ( < C_DynamicValue . Builder > self . thisptr . get ( field ) ) . asList ( ) . getStructElementType ( ) ) )
2013-09-03 00:25:32 -07:00
cpdef which ( self ) :
2013-08-26 19:27:58 -07:00
""" 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 : :
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
2013-08-26 19:27:58 -07:00
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-10-21 00:11:42 -07:00
cdef object which = < char * > getEnumString ( self . thisptr )
2013-09-03 00:25:32 -07:00
if len ( which ) == 0 :
raise ValueError ( " Attempted to call which on a non-union type " )
return which
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
2013-12-04 11:42:57 -08:00
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unknown sized list .
2013-08-26 22:00:12 -07:00
: 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-09-01 20:10:57 -07:00
cpdef as_reader ( self ) :
2013-08-29 18:46:17 -07:00
""" A method for casting this Builder to a Reader
2013-11-14 20:59:21 -08:00
This is a non - copying operation with respect to the message ' s buffer. This means changes to the fields in the original struct will carry over to the new reader.
2013-08-29 18:46:17 -07:00
: rtype : : class : `_DynamicStructReader`
"""
cdef _DynamicStructReader reader
reader = _DynamicStructReader ( ) . _init ( self . thisptr . asReader ( ) ,
2013-11-13 10:58:16 -08:00
self . _parent , self . is_root )
2013-08-29 18:46:17 -07:00
reader . _obj_to_pin = self
return reader
2013-08-28 14:34:37 -07:00
2013-11-14 20:59:21 -08:00
cpdef copy ( self ) :
""" A method for copying this Builder
This is a copying operation with respect to the message ' s buffer. Changes in the new builder will not reflect in the original reader.
: rtype : : class : `_DynamicStructBuilder`
"""
builder = _MallocMessageBuilder ( )
return builder . set_root ( self )
2013-08-28 14:34:37 -07:00
property schema :
2013-08-29 18:46:17 -07:00
"""A property that returns the _StructSchema object matching this writer"""
2013-08-28 14:34:37 -07:00
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
2013-08-31 15:07:13 -07:00
def __str__ ( self ) :
2013-10-21 00:11:42 -07:00
return < char * > printStructBuilder ( self . thisptr ) . flatten ( ) . cStr ( )
2013-08-31 15:07:13 -07:00
def __repr__ ( self ) :
2013-10-21 00:11:42 -07:00
return ' < %s builder %s > ' % ( self . schema . node . displayName , < char * > strStructBuilder ( self . thisptr ) . cStr ( ) )
2013-08-31 15:07:13 -07:00
2013-10-22 13:32:35 -07:00
def to_dict ( self , verbose = False ) :
return _to_dict ( self , verbose )
2013-09-03 00:25:32 -07:00
2013-10-19 22:38:10 -07:00
cdef class _DynamicStructPipeline :
""" Reads Cap ' n Proto structs
This class is almost a 1 for 1 wrapping of the Cap ' n Proto C++ DynamicStruct::Pipeline. 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` : :
"""
cdef C_DynamicStruct .Pipeline * thisptr
cdef public object _parent
2013-08-31 15:07:13 -07:00
2013-10-19 22:38:10 -07:00
cdef _init ( self , C_DynamicStruct . Pipeline * other , object parent ) :
self . thisptr = other
self . _parent = parent
return self
def __dealloc__ ( self ) :
del self . thisptr
2013-11-13 17:53:34 -08:00
cpdef _get ( self , field ) except + reraise_kj_exception :
2013-10-19 22:38:10 -07:00
cdef int type = ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . getType ( )
if type == capnp . TYPE_CAPABILITY :
return _DynamicCapabilityClient ( ) . _init ( ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . asCapability ( ) , self . _parent )
elif type == capnp . TYPE_STRUCT :
return _DynamicStructPipeline ( ) . _init ( new C_DynamicStruct . Pipeline ( moveStructPipeline ( ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . asStruct ( ) ) ) , self . _parent )
elif type == capnp . TYPE_UNKNOWN :
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 " )
def __getattr__ ( self , field ) :
return self . _get ( field )
property schema :
"""A property that returns the _StructSchema object matching this reader"""
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
# def __str__(self):
# return printStructReader(self.thisptr).flatten().cStr()
# def __repr__(self):
# return '<%s reader %s>' % (self.schema.node.displayName, strStructReader(self.thisptr).cStr())
2013-10-22 13:32:35 -07:00
def to_dict ( self , verbose = False ) :
return _to_dict ( self , verbose )
2013-09-03 00:25:32 -07:00
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
"""
2013-09-01 20:10:57 -07:00
return to_python_builder ( self . thisptr . get ( ) , self . _parent )
2013-08-26 22:00:12 -07:00
2013-08-31 15:07:13 -07:00
def __str__ ( self ) :
return str ( self . get ( ) )
def __repr__ ( self ) :
return repr ( self . get ( ) )
2013-09-18 17:19:57 -07:00
cdef class _DynamicObjectReader :
cdef C_DynamicObject .Reader thisptr
cdef public object _parent
2013-11-13 22:30:31 -08:00
2013-09-18 17:19:57 -07:00
cdef _init ( self , C_DynamicObject . Reader other , object parent ) :
self . thisptr = other
self . _parent = parent
return self
cpdef as_struct ( self , schema ) :
cdef _StructSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
2013-09-24 11:49:38 -07:00
return _DynamicStructReader ( ) . _init ( self . thisptr . getAs ( s . thisptr ) , self . _parent )
2013-09-18 17:19:57 -07:00
cdef class _DynamicObjectBuilder :
2013-09-24 11:49:38 -07:00
cdef C_DynamicObject .Builder * thisptr
cdef public object _parent
2013-09-24 13:11:46 -07:00
2013-09-24 11:49:38 -07:00
cdef _init ( self , C_DynamicObject . Builder other , object parent ) :
self . thisptr = new C_DynamicObject . Builder ( other )
self . _parent = parent
return self
2013-09-18 17:19:57 -07:00
2013-09-24 13:11:46 -07:00
def __dealloc__ ( self ) :
del self . thisptr
2013-09-18 17:19:57 -07:00
cpdef as_struct ( self , schema ) :
2013-09-24 11:49:38 -07:00
cdef _StructSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicStructBuilder ( ) . _init ( self . thisptr . getAs ( s . thisptr ) , self . _parent )
2013-09-18 17:19:57 -07:00
2013-12-02 17:38:32 -08:00
cdef class _EventLoop :
2013-12-05 00:07:51 -08:00
cdef capnp .AsyncIoContext * thisptr
2013-12-02 17:38:32 -08:00
def __init__ ( self ) :
self . _init ( )
cdef _init ( self ) except + reraise_kj_exception :
2013-12-05 00:07:51 -08:00
self . thisptr = new capnp . AsyncIoContext ( moveAsyncContext ( capnp . setupAsyncIo ( ) ) )
2013-12-02 17:38:32 -08:00
2013-12-04 11:42:57 -08:00
cdef Own [AsyncIoStream ] wrapSocketFd ( self , int fd ) :
2013-12-05 00:07:51 -08:00
return deref ( self . thisptr . lowLevelProvider ) . wrapSocketFd ( fd )
2013-12-02 17:38:32 -08:00
2013-12-04 11:42:57 -08:00
# def __dealloc__(self):
# self.remove()
# cpdef remove(self) except +reraise_kj_exception:
# self.thisptr = NULL
2013-12-02 17:38:32 -08:00
# cpdef evalLater(self, func):
# Py_INCREF(func)
# return _Promise()._init(capnp.evalLater(self.thisptr, <PyObject *>func))
# cpdef wait(self, _PromiseTypes promise) except +reraise_kj_exception:
# if promise.is_consumed:
# raise ValueError('Promise was already used in a consuming operation. You can no longer use this Promise object')
# ret = None
# if _PromiseTypes is _RemotePromise:
# ret = _Response()._init_child(self.thisptr.wait_remote(moveRemotePromise(deref(promise.thisptr))), promise._parent)
# elif _PromiseTypes is _VoidPromise:
# self.thisptr.wait_void(moveVoidPromise(deref(promise.thisptr)))
# elif _PromiseTypes is PromiseFulfillerPair:
# self.thisptr.wait_void(moveVoidPromise(deref(promise.thisptr).promise))
# elif _PromiseTypes is _Promise:
# ret = self.thisptr.wait(movePromise(deref(promise.thisptr)))
# else:
# raise ValueError("Not a valid promise type")
# promise.is_consumed = True
# return ret
# cpdef there(self, Promise promise, object func, object error_func=None):
# if promise.is_consumed:
# raise RuntimeError('Promise was already used in a consuming operation. You can no longer use this Promise object')
# Py_INCREF(func)
# Py_INCREF(error_func)
# return Promise()._init(capnp.there(self.thisptr, deref(promise.thisptr), <PyObject *>func, <PyObject *>error_func))
2013-12-04 11:42:57 -08:00
cdef _EventLoop C_DEFAULT_EVENT_LOOP = _EventLoop ( )
2013-12-02 17:38:32 -08:00
2013-10-15 22:36:14 -07:00
cdef class _CallContext :
cdef CallContext * thisptr
cdef _init ( self , CallContext other ) :
self . thisptr = new CallContext ( moveCallContext ( other ) )
return self
def __dealloc__ ( self ) :
del self . thisptr
property params :
def __get__ ( self ) :
return _DynamicStructReader ( ) . _init ( self . thisptr . getParams ( ) , self )
cpdef _get_results ( self , uint firstSegmentWordSize = 0 ) :
return _DynamicStructBuilder ( ) . _init ( self . thisptr . getResults ( firstSegmentWordSize ) , self )
property results :
def __get__ ( self ) :
return self . _get_results ( )
2013-12-05 00:07:51 -08:00
cpdef release_params ( self ) :
self . thisptr . releaseParams ( )
cpdef allow_async_cancellation ( self ) :
self . thisptr . allowAsyncCancellation ( )
cpdef is_canceled ( self ) :
return self . thisptr . isCanceled ( )
cpdef tail_call ( self , _Request tailRequest ) :
return _VoidPromise ( ) . _init ( self . thisptr . tailCall ( moveRequest ( deref ( tailRequest . thisptr_child ) ) ) )
2013-11-14 20:59:21 -08:00
cdef class _Promise :
2013-10-15 22:36:14 -07:00
cdef PyPromise * thisptr
2013-10-17 22:42:14 -07:00
cdef public bint is_consumed
2013-10-15 22:36:14 -07:00
def __init__ ( self ) :
self . is_consumed = True
cdef _init ( self , PyPromise other ) :
self . is_consumed = False
self . thisptr = new PyPromise ( movePromise ( other ) )
return self
def __dealloc__ ( self ) :
del self . thisptr
2013-11-13 17:53:34 -08:00
cpdef wait ( self ) except + reraise_kj_exception :
2013-10-15 22:36:14 -07:00
if self . is_consumed :
2013-11-13 17:53:34 -08:00
raise ValueError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2013-12-05 00:07:51 -08:00
ret = < object > self . thisptr . wait ( C_DEFAULT_EVENT_LOOP . thisptr . waitScope ) # TODO: make sure refcount is fine here...
2013-10-15 22:36:14 -07:00
self . is_consumed = True
return ret
2013-11-13 17:53:34 -08:00
cpdef then ( self , func , error_func = None ) except + reraise_kj_exception :
2013-10-15 22:36:14 -07:00
if self . is_consumed :
2013-11-13 17:53:34 -08:00
raise ValueError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
Py_INCREF ( func )
Py_INCREF ( error_func )
2013-11-14 20:59:21 -08:00
return _Promise ( ) . _init ( capnp . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) )
2013-10-15 22:36:14 -07:00
2013-10-17 22:42:14 -07:00
cdef class _VoidPromise :
cdef VoidPromise * thisptr
cdef public bint is_consumed
def __init__ ( self ) :
self . is_consumed = True
cdef _init ( self , VoidPromise other ) :
self . is_consumed = False
self . thisptr = new VoidPromise ( moveVoidPromise ( other ) )
return self
def __dealloc__ ( self ) :
del self . thisptr
2013-11-13 17:53:34 -08:00
cpdef wait ( self ) except + reraise_kj_exception :
2013-10-17 22:42:14 -07:00
if self . is_consumed :
2013-11-13 17:53:34 -08:00
raise ValueError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-17 22:42:14 -07:00
2013-12-05 00:07:51 -08:00
self . thisptr . wait ( C_DEFAULT_EVENT_LOOP . thisptr . waitScope )
2013-10-17 22:42:14 -07:00
self . is_consumed = True
2013-12-04 15:59:22 -08:00
cpdef then ( self , func , error_func = None ) except + reraise_kj_exception :
if self . is_consumed :
raise RuntimeError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-17 22:42:14 -07:00
2013-12-04 15:59:22 -08:00
Py_INCREF ( func )
Py_INCREF ( error_func )
2013-10-17 22:42:14 -07:00
2013-12-04 15:59:22 -08:00
return _Promise ( ) . _init ( capnp . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) )
2013-10-17 22:42:14 -07:00
2013-10-15 22:36:14 -07:00
cdef class _RemotePromise :
cdef RemotePromise * thisptr
cdef public bint is_consumed
cdef public object _parent
def __init__ ( self ) :
self . is_consumed = True
cdef _init ( self , RemotePromise other , parent ) :
self . is_consumed = False
self . thisptr = new RemotePromise ( moveRemotePromise ( other ) )
self . _parent = parent
return self
def __dealloc__ ( self ) :
del self . thisptr
2013-11-13 17:53:34 -08:00
cpdef wait ( self ) except + reraise_kj_exception :
2013-10-15 22:36:14 -07:00
if self . is_consumed :
2013-11-13 17:53:34 -08:00
raise ValueError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2013-12-05 00:07:51 -08:00
ret = _Response ( ) . _init_child ( self . thisptr . wait ( C_DEFAULT_EVENT_LOOP . thisptr . waitScope ) , self . _parent )
2013-10-15 22:36:14 -07:00
self . is_consumed = True
return ret
2013-11-13 17:53:34 -08:00
cpdef as_pypromise ( self ) except + reraise_kj_exception :
2013-11-14 20:59:21 -08:00
_Promise ( ) . _init ( convert_to_pypromise ( deref ( self . thisptr ) ) )
2013-10-15 22:36:14 -07:00
2013-11-13 17:53:34 -08:00
cpdef then ( self , func , error_func = None ) except + reraise_kj_exception :
2013-10-17 22:42:14 -07:00
if self . is_consumed :
2013-12-04 15:59:22 -08:00
raise RuntimeError ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2013-10-17 22:42:14 -07:00
Py_INCREF ( func )
Py_INCREF ( error_func )
return _VoidPromise ( ) . _init ( capnp . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) )
2013-10-15 22:36:14 -07:00
2013-11-13 17:53:34 -08:00
cpdef _get ( self , field ) except + reraise_kj_exception :
2013-10-19 22:38:10 -07:00
cdef int type = ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . getType ( )
if type == capnp . TYPE_CAPABILITY :
return _DynamicCapabilityClient ( ) . _init ( ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . asCapability ( ) , self . _parent )
elif type == capnp . TYPE_STRUCT :
return _DynamicStructPipeline ( ) . _init ( new C_DynamicStruct . Pipeline ( moveStructPipeline ( ( < C_DynamicValue . Pipeline > self . thisptr . get ( field ) ) . asStruct ( ) ) ) , self . _parent )
elif type == capnp . TYPE_UNKNOWN :
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-10-17 22:42:14 -07:00
def __getattr__ ( self , field ) :
return self . _get ( field )
property schema :
"""A property that returns the _StructSchema object matching this reader"""
def __get__ ( self ) :
return _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
def __dir__ ( self ) :
return list ( self . schema . fieldnames )
2013-10-15 22:36:14 -07:00
2013-10-22 13:32:35 -07:00
def to_dict ( self , verbose = False ) :
return _to_dict ( self , verbose )
2013-10-19 22:38:10 -07:00
2013-10-17 19:15:40 -07:00
cdef class _Request ( _DynamicStructBuilder ) :
cdef Request * thisptr_child
2013-10-15 22:36:14 -07:00
2013-10-17 19:15:40 -07:00
cdef _init_child ( self , Request other , parent ) :
self . thisptr_child = new Request ( moveRequest ( other ) )
self . _init ( < C_DynamicStruct . Builder > deref ( self . thisptr_child ) , parent )
2013-10-15 22:36:14 -07:00
return self
cpdef send ( self ) :
2013-10-17 19:15:40 -07:00
return _RemotePromise ( ) . _init ( self . thisptr_child . send ( ) , self . _parent )
2013-10-15 22:36:14 -07:00
2013-10-17 19:15:40 -07:00
cdef class _Response ( _DynamicStructReader ) :
cdef Response * thisptr_child
2013-10-15 22:36:14 -07:00
2013-10-17 19:15:40 -07:00
cdef _init_child ( self , Response other , parent ) :
self . thisptr_child = new Response ( moveResponse ( other ) )
self . _init ( < C_DynamicStruct . Reader > deref ( self . thisptr_child ) , parent )
return self
2013-10-15 22:36:14 -07:00
2013-10-17 22:42:14 -07:00
cdef _init_childptr ( self , Response * other , parent ) :
self . thisptr_child = other
self . _init ( < C_DynamicStruct . Reader > deref ( self . thisptr_child ) , parent )
return self
2013-10-19 22:38:10 -07:00
cdef class _DynamicCapabilityServer :
cdef public _InterfaceSchema schema
cdef public object server
def __init__ ( self , schema , server ) :
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
self . schema = s
self . server = server
2013-10-15 22:36:14 -07:00
cdef class _DynamicCapabilityClient :
cdef C_DynamicCapability .Client thisptr
2013-12-02 17:38:32 -08:00
cdef public object _server , _parent
2013-10-17 22:42:14 -07:00
cdef _init ( self , C_DynamicCapability . Client other , object parent ) :
self . thisptr = other
self . _parent = parent
return self
2013-10-15 22:36:14 -07:00
2013-12-02 17:38:32 -08:00
cdef _init_vals ( self , schema , server ) :
2013-10-15 22:36:14 -07:00
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
2013-12-02 17:38:32 -08:00
self . thisptr = new_client ( s . thisptr , < PyObject * > server )
2013-10-15 22:36:14 -07:00
self . _server = server
2013-10-17 22:42:14 -07:00
return self
2013-10-15 22:36:14 -07:00
2013-11-14 20:59:21 -08:00
cpdef _find_method_args ( self , method_name ) :
s = self . schema
meth = None
for meth in s . node . interface . methods :
if meth . name == method_name :
break
params = s . get_dependency ( meth . paramStructType ) . node
if params . scopeId != 0 :
2013-11-14 23:06:14 -08:00
raise ValueError ( " Cannot call method ` %s ` with positional args, since its param struct is not implicitly defined and thus does not have a set order of arguments " % method_name )
2013-11-14 20:59:21 -08:00
2013-11-14 23:06:14 -08:00
return _find_field_order ( params . struct )
2013-11-14 20:59:21 -08:00
2013-12-05 00:07:51 -08:00
cdef _set_fields ( self , Request * request , name , args , kwargs ) :
2013-11-14 20:59:21 -08:00
if args is not None :
2013-11-14 23:06:14 -08:00
arg_names = self . _find_method_args ( name )
if len ( args ) > len ( arg_names ) :
raise ValueError ( ' Too many arguments passed to ` %s `. Expected %d and got %d ' % ( name , len ( arg_names ) , len ( args ) ) )
for arg_name , arg_val in zip ( arg_names , args ) :
2013-11-14 20:59:21 -08:00
_setDynamicFieldPtr ( request , arg_name , arg_val , self )
2013-12-05 00:07:51 -08:00
if kwargs is not None :
for key , val in kwargs . items ( ) :
_setDynamicFieldPtr ( request , key , val , self )
cpdef _send_helper ( self , name , firstSegmentWordSize , args , kwargs ) except + reraise_kj_exception :
cdef Request * request = new Request ( self . thisptr . newRequest ( name , firstSegmentWordSize ) )
self . _set_fields ( request , name , args , kwargs )
2013-10-15 22:36:14 -07:00
return _RemotePromise ( ) . _init ( request . send ( ) , self )
2013-12-05 00:07:51 -08:00
cpdef _request_helper ( self , name , firstSegmentWordSize , args , kwargs ) except + reraise_kj_exception :
cdef _Request req = _Request ( ) . _init_child ( self . thisptr . newRequest ( name , firstSegmentWordSize ) , self )
self . _set_fields ( req . thisptr_child , name , args , kwargs )
return req
2013-10-17 19:15:40 -07:00
2013-12-05 00:07:51 -08:00
def _request ( self , name , * args , firstSegmentWordSize = 0 , * * kwargs ) :
return self . _request_helper ( name , firstSegmentWordSize , args , kwargs )
2013-10-15 22:36:14 -07:00
2013-10-17 19:15:40 -07:00
def _send ( self , name , * args , firstSegmentWordSize = 0 , * * kwargs ) :
2013-11-14 20:59:21 -08:00
return self . _send_helper ( name , firstSegmentWordSize , args , kwargs )
2013-10-17 19:15:40 -07:00
def __getattr__ ( self , name ) :
if name . endswith ( ' _request ' ) :
short_name = name [ : - 8 ]
return _partial ( self . _request , short_name )
return _partial ( self . _send , name )
2013-10-15 22:36:14 -07:00
2013-11-13 17:53:34 -08:00
cpdef upcast ( self , schema ) except + reraise_kj_exception :
2013-11-12 20:28:23 -08:00
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicCapabilityClient ( ) . _init ( self . thisptr . upcast ( s . thisptr ) , self . _parent )
2013-11-13 17:53:34 -08:00
cpdef cast_as ( self , schema ) except + reraise_kj_exception :
2013-11-12 20:28:23 -08:00
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicCapabilityClient ( ) . _init ( self . thisptr . castAs ( s . thisptr ) , self . _parent )
property schema :
"""A property that returns the _InterfaceSchema object matching this client"""
def __get__ ( self ) :
return _InterfaceSchema ( ) . _init ( self . thisptr . getSchema ( ) )
2013-11-13 10:58:16 -08:00
def __dir__ ( self ) :
return list ( self . schema . method_names )
2013-11-12 15:32:23 -08:00
cdef class _CapabilityClient :
cdef C_Capability .Client * thisptr
cdef public object _parent
cdef _init ( self , C_Capability . Client other , object parent ) :
self . thisptr = new C_Capability . Client ( other )
self . _parent = parent
return self
def __dealloc__ ( self ) :
del self . thisptr
cpdef cast_as ( self , schema ) :
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicCapabilityClient ( ) . _init ( self . thisptr . castAs ( s . thisptr ) , self . _parent )
cdef class Restorer :
cdef PyRestorer * thisptr
cdef C_StructSchema schema
cdef public object restore
def __init__ ( self , schema , restore_func ) :
cdef _StructSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
self . schema = s . thisptr
self . restore = restore_func
self . thisptr = new PyRestorer ( < PyObject * > self , self . schema )
def __dealloc__ ( self ) :
del self . thisptr
cdef class _TwoPartyVatNetwork :
2013-11-13 12:21:48 -08:00
cdef Own [C_TwoPartyVatNetwork ] thisptr
2013-11-12 15:32:23 -08:00
2013-12-02 17:38:32 -08:00
cdef _init ( self , AsyncIoStream & stream , Side side ) :
self . thisptr = makeTwoPartyVatNetwork ( stream , side )
2013-11-12 15:32:23 -08:00
return self
cdef class RpcClient :
cdef RpcSystem * thisptr
cdef public _TwoPartyVatNetwork network
2013-12-02 17:38:32 -08:00
cdef public object restorer , _stream
cdef public _FdAsyncIoStream stream
2013-11-12 15:32:23 -08:00
2013-12-02 17:38:32 -08:00
def __init__ ( self , stream , Restorer restorer = None ) :
self . _stream = stream
self . stream = _FdAsyncIoStream ( stream . fileno ( ) )
self . network = _TwoPartyVatNetwork ( ) . _init ( deref ( self . stream . thisptr ) , capnp . CLIENT )
2013-11-13 10:58:16 -08:00
if restorer is None :
2013-12-02 17:38:32 -08:00
self . thisptr = new RpcSystem ( makeRpcClient ( deref ( self . network . thisptr ) ) )
2013-11-13 10:58:16 -08:00
else :
self . restorer = restorer
2013-12-02 17:38:32 -08:00
self . thisptr = new RpcSystem ( makeRpcClientWithRestorer ( deref ( self . network . thisptr ) , deref ( restorer . thisptr ) ) )
2013-11-12 15:32:23 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2013-11-13 17:53:34 -08:00
cpdef restore ( self , objectId ) except + reraise_kj_exception :
2013-11-12 19:38:34 -08:00
cdef _MessageBuilder builder
cdef _MessageReader reader
2013-11-13 10:58:16 -08:00
if not hasattr ( objectId , ' is_root ' ) :
raise ValueError ( " objectId was not a valid Cap ' n Proto struct " )
if not objectId . is_root :
raise ValueError ( " objectId must be the root of a Cap ' n Proto message, ie. addressbook_capnp.Person.new_message() " )
2013-11-12 19:38:34 -08:00
try :
builder = objectId . _parent
except :
reader = objectId . _parent
2013-11-13 10:58:16 -08:00
if builder is not None :
return _CapabilityClient ( ) . _init ( restoreHelper ( deref ( self . thisptr ) , deref ( builder . thisptr ) ) , self )
elif reader is not None :
2013-11-12 19:38:34 -08:00
return _CapabilityClient ( ) . _init ( restoreHelper ( deref ( self . thisptr ) , deref ( reader . thisptr ) ) , self )
2013-11-13 10:58:16 -08:00
else :
raise ValueError ( " objectId unexpectedly was not convertible to the proper type " )
2013-11-12 15:32:23 -08:00
cdef class RpcServer :
cdef RpcSystem * thisptr
cdef public _TwoPartyVatNetwork network
2013-12-02 17:38:32 -08:00
cdef public object restorer , _stream
cdef public _FdAsyncIoStream stream
2013-11-12 15:32:23 -08:00
2013-12-02 17:38:32 -08:00
def __init__ ( self , stream , Restorer restorer ) :
self . _stream = stream
self . stream = _FdAsyncIoStream ( stream . fileno ( ) )
2013-11-12 15:32:23 -08:00
self . restorer = restorer
2013-12-02 17:38:32 -08:00
self . network = _TwoPartyVatNetwork ( ) . _init ( deref ( self . stream . thisptr ) , capnp . SERVER )
self . thisptr = new RpcSystem ( makeRpcServer ( deref ( self . network . thisptr ) , deref ( restorer . thisptr ) ) )
2013-11-12 15:32:23 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2013-11-15 01:17:35 -08:00
def run_forever ( self ) :
2013-12-04 12:17:22 -08:00
_VoidPromise ( ) . _init ( deref ( self . network . thisptr ) . onDisconnect ( ) ) . wait ( )
2013-11-15 01:17:35 -08:00
2013-11-13 17:53:34 -08:00
# TODO: add restore functionality here?
2013-12-02 17:38:32 -08:00
cdef class _FdAsyncIoStream :
2013-11-12 19:38:34 -08:00
cdef Own [AsyncIoStream ] thisptr
2013-11-12 15:32:23 -08:00
2013-11-12 19:38:34 -08:00
def __init__ ( self , int fd ) :
2013-12-04 11:42:57 -08:00
self . _init ( fd )
cdef _init ( self , int fd ) except + reraise_kj_exception :
self . thisptr = C_DEFAULT_EVENT_LOOP . wrapSocketFd ( fd )
2013-11-12 15:32:23 -08:00
2013-11-13 17:53:34 -08:00
cdef class PromiseFulfillerPair :
cdef Own [C_PromiseFulfillerPair ] thisptr
cdef public bint is_consumed
2013-12-02 17:38:32 -08:00
def __init__ ( self ) :
self . thisptr = copyPromiseFulfillerPair ( newPromiseAndFulfiller ( ) )
2013-11-13 17:53:34 -08:00
self . is_consumed = False
2013-09-18 17:19:57 -07:00
2013-11-14 20:59:21 -08:00
cpdef fulfill ( self ) :
pass #TODO
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-09-01 20:10:57 -07:00
cpdef as_const_value ( self ) :
return to_python_reader ( < C_DynamicValue . Reader > self . thisptr . asConst ( ) , self )
2013-08-25 17:07:08 -07:00
2013-09-01 20:10:57 -07:00
cpdef as_struct ( self ) :
2013-08-26 15:07:13 -07:00
return _StructSchema ( ) . _init ( self . thisptr . asStruct ( ) )
2013-06-26 23:01:37 -07:00
2013-10-15 13:29:54 -07:00
cpdef as_interface ( self ) :
return _InterfaceSchema ( ) . _init ( self . thisptr . asInterface ( ) )
2013-09-01 20:10:57 -07:00
cpdef get_dependency ( 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
2013-09-01 20:10:57 -07:00
cpdef get_proto ( self ) :
2013-07-06 16:53:00 -07:00
return _NodeReader ( ) . init ( self . thisptr . getProto ( ) )
2013-11-14 20:59:21 -08:00
property node :
"""The raw schema node"""
def __get__ ( self ) :
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , self )
2013-08-26 15:07:13 -07:00
cdef class _StructSchema :
2013-06-26 23:01:37 -07:00
cdef C_StructSchema thisptr
2013-09-03 00:25:32 -07:00
cdef object __fieldnames , __union_fields , __non_union_fields
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-09-03 00:25:32 -07:00
self . __union_fields = None
self . __non_union_fields = 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 ( )
2013-10-21 00:11:42 -07:00
self . __fieldnames = tuple ( < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
2013-08-28 14:34:37 -07:00
for i in xrange ( nfields ) )
return self . __fieldnames
2013-09-03 00:25:32 -07:00
property union_fields :
"""A tuple of the field names in the struct."""
def __get__ ( self ) :
if self . __union_fields is not None :
return self . __union_fields
fieldlist = self . thisptr . getUnionFields ( )
nfields = fieldlist . size ( )
2013-10-21 00:11:42 -07:00
self . __union_fields = tuple ( < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
2013-09-03 00:25:32 -07:00
for i in xrange ( nfields ) )
return self . __union_fields
property non_union_fields :
"""A tuple of the field names in the struct."""
def __get__ ( self ) :
if self . __non_union_fields is not None :
return self . __non_union_fields
fieldlist = self . thisptr . getNonUnionFields ( )
nfields = fieldlist . size ( )
2013-10-21 00:11:42 -07:00
self . __non_union_fields = tuple ( < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
2013-09-03 00:25:32 -07:00
for i in xrange ( nfields ) )
return self . __non_union_fields
2013-08-28 14:46:53 -07:00
property node :
"""The raw schema node"""
def __get__ ( self ) :
2013-11-14 20:59:21 -08:00
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , self )
2013-08-28 14:46:53 -07:00
2013-11-13 12:02:43 -08:00
cpdef get_dependency ( self , id ) :
return _Schema ( ) . _init ( self . thisptr . getDependency ( id ) )
2013-09-03 11:01:12 -07:00
def __richcmp__ ( _StructSchema self , _StructSchema other , mode ) :
if mode == 2 :
2013-09-03 11:54:58 -07:00
return self . thisptr == other . thisptr
2013-09-03 11:01:12 -07:00
elif mode == 3 :
return not ( self . thisptr == other . thisptr )
else :
raise NotImplementedError ( )
2013-08-31 15:07:13 -07:00
def __repr__ ( self ) :
return ' <schema for %s > ' % self . node . displayName
2013-10-15 13:29:54 -07:00
cdef class _InterfaceSchema :
cdef C_InterfaceSchema thisptr
2013-11-13 10:58:16 -08:00
cdef object __method_names
2013-10-15 13:29:54 -07:00
cdef _init ( self , C_InterfaceSchema other ) :
2013-08-13 22:21:38 -07:00
self . thisptr = other
return self
2013-11-13 10:58:16 -08:00
property method_names :
"""A tuple of the function names in the interface."""
def __get__ ( self ) :
if self . __method_names is not None :
return self . __method_names
fieldlist = self . thisptr . getMethods ( )
nfields = fieldlist . size ( )
self . __method_names = tuple ( < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
for i in xrange ( nfields ) )
return self . __method_names
2013-08-25 17:07:08 -07:00
2013-11-13 10:58:16 -08:00
property node :
"""The raw schema node"""
def __get__ ( self ) :
2013-11-14 20:59:21 -08:00
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , self )
2013-08-13 22:21:38 -07:00
2013-09-01 20:10:57 -07:00
cpdef get_dependency ( 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
2013-11-13 10:58:16 -08:00
def __repr__ ( self ) :
return ' <schema for %s > ' % self . node . displayName
2013-08-13 22:21:38 -07:00
2013-10-15 13:29:54 -07:00
cdef class _ParsedSchema ( _Schema ) :
cdef C_ParsedSchema thisptr_child
cdef _init_child ( self , C_ParsedSchema other ) :
self . thisptr_child = other
self . _init ( other )
return self
2013-08-13 22:21:38 -07:00
2013-10-15 13:29:54 -07:00
cpdef get_nested ( self , name ) :
return _ParsedSchema ( ) . _init_child ( self . thisptr_child . getNested ( name ) )
2013-08-13 22:21:38 -07:00
2013-09-03 11:01:12 -07:00
class _StructABCMeta ( type ) :
"""A metaclass for the Type.Reader and Type.Builder ABCs."""
def __instancecheck__ ( cls , obj ) :
return isinstance ( obj , cls . __base__ ) and obj . schema == cls . _schema
2013-11-14 23:06:14 -08:00
cdef _new_message ( self , kwargs ) :
builder = _MallocMessageBuilder ( )
msg = builder . init_root ( self . schema )
if kwargs is not None :
_from_dict ( msg , kwargs )
return msg
2013-11-14 20:59:21 -08:00
class _StructModule ( object ) :
2013-11-14 11:30:57 -08:00
def __init__ ( self , schema ) :
self . schema = schema
def read ( self , file , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-14 23:06:14 -08:00
""" Returns a Reader for the unpacked object read from file.
: type file : file
: param file : A python file - like object . It must be a " real " file , with a `fileno()` method .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: rtype : : class : `_DynamicStructReader` """
2013-11-14 11:30:57 -08:00
reader = _StreamFdMessageReader ( file . fileno ( ) , traversal_limit_in_words , nesting_limit )
return reader . get_root ( self . schema )
def read_multiple ( self , file , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-14 23:06:14 -08:00
""" Returns an iterable, that when traversed will return Readers for messages.
: type file : file
: param file : A python file - like object . It must be a " real " file , with a `fileno()` method .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: rtype : Iterable with elements of : class : `_DynamicStructReader` """
2013-11-14 11:30:57 -08:00
reader = _MultipleMessageReader ( file . fileno ( ) , self . schema , traversal_limit_in_words , nesting_limit )
return reader
def read_packed ( self , file , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-14 23:06:14 -08:00
""" Returns a Reader for the packed object read from file.
: type file : file
: param file : A python file - like object . It must be a " real " file , with a `fileno()` method .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: rtype : : class : `_DynamicStructReader` """
2013-11-14 11:30:57 -08:00
reader = _PackedFdMessageReader ( file . fileno ( ) , traversal_limit_in_words , nesting_limit )
return reader . get_root ( self . schema )
def read_multiple_packed ( self , file , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-14 23:06:14 -08:00
""" Returns an iterable, that when traversed will return Readers for messages.
: type file : file
: param file : A python file - like object . It must be a " real " file , with a `fileno()` method .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: rtype : Iterable with elements of : class : `_DynamicStructReader` """
2013-11-14 11:30:57 -08:00
reader = _MultiplePackedMessageReader ( file . fileno ( ) , self . schema , traversal_limit_in_words , nesting_limit )
return reader
def from_bytes ( self , buf , traversal_limit_in_words = None , nesting_limit = None , builder = False ) :
""" Returns a Reader for the unpacked object in buf.
: type buf : buffer
2013-11-14 23:06:14 -08:00
: param buf : Any Python object that supports the buffer interface .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: type builder : bool
: param builder : If true , return a builder object . This will allow you to change the contents of `buf` , so do this with care .
: rtype : : class : `_DynamicStructReader` or : class : `_DynamicStructBuilder`
"""
2013-11-14 11:30:57 -08:00
if builder :
message = _FlatMessageBuilder ( buf )
else :
message = _FlatArrayMessageReader ( buf , traversal_limit_in_words , nesting_limit )
return message . get_root ( self . schema )
def from_bytes_packed ( self , buf , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-14 23:06:14 -08:00
""" Returns a Reader for the packed object in buf.
: type buf : buffer
: param buf : Any Python object that supports the readable buffer interface .
: type traversal_limit_in_words : int
: param traversal_limit_in_words : Limits how many total words of data are allowed to be traversed . Is actually a uint64_t , and values can be up to 2 ^ 64 - 1. Default is 8 * 1024 * 1024.
: type nesting_limit : int
: param nesting_limit : Limits how many total words of data are allowed to be traversed . Default is 64.
: rtype : : class : `_DynamicStructReader`
"""
2013-11-14 11:30:57 -08:00
return _PackedMessageReaderBytes ( buf , traversal_limit_in_words , nesting_limit ) . get_root ( self . schema )
2013-11-14 23:06:14 -08:00
def new_message ( self , * * kwargs ) :
""" Returns a newly allocated builder message.
: type kwargs : dict
: param kwargs : A list of fields and their values to initialize in the struct
: rtype : : class : `_DynamicStructBuilder`
"""
return _new_message ( self , kwargs )
def from_dict ( self , kwargs ) :
' .. warning:: This method is deprecated and will be removed in the 0.5 release. Use the :meth:`new_message` function instead with **kwargs '
_warnings . warn ( ' This method is deprecated and will be removed in the 0.5 release. Use the :meth:`new_message` function instead with **kwargs ' , UserWarning )
return _new_message ( self , kwargs )
2013-11-14 11:30:57 -08:00
def from_object ( self , obj ) :
2013-11-14 23:06:14 -08:00
' .. warning:: This method is deprecated and will be removed in the 0.5 release. Use the :meth:`_DynamicStructReader.as_builder` or :meth:`_DynamicStructBuilder.copy` functions instead '
_warnings . warn ( ' This method is deprecated and will be removed in the 0.5 release. Use the :meth:`_DynamicStructReader.as_builder` or :meth:`_DynamicStructBuilder.copy` functions instead ' , UserWarning )
2013-11-14 11:30:57 -08:00
builder = _MallocMessageBuilder ( )
return builder . set_root ( obj )
2013-11-14 20:59:21 -08:00
class _InterfaceModule ( object ) :
def __init__ ( self , schema ) :
self . schema = schema
2013-12-02 17:38:32 -08:00
def _new_client ( self , server ) :
return _DynamicCapabilityClient ( ) . _init_vals ( self . schema , server )
2013-11-14 20:59:21 -08:00
def new_server ( self , server ) :
return _DynamicCapabilityServer ( self . schema , server )
2013-08-29 21:03:00 -07:00
cdef class SchemaParser :
""" A class for loading Cap ' n Proto schema files.
Do not use this class unless you ' re sure you know what you ' re doing . Use the convenience method : func : `load` instead .
"""
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-09-01 20:10:57 -07:00
def _parse_disk_file ( self , displayName , diskPath , imports ) :
2013-08-13 23:00:43 -07:00
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-10-15 13:29:54 -07:00
ret . _init_child ( self . thisptr . parseDiskFile ( displayName , diskPath , importsPtr ) )
2013-08-13 23:00:43 -07:00
free ( importArray )
2013-08-13 22:21:38 -07:00
return ret
2013-08-29 21:03:00 -07:00
def load ( self , 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 : :
parser = capnp . SchemaParser ( )
addressbook = parser . load ( ' addressbook.capnp ' )
print addressbook . qux # qux is a top level constant
# 123
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
2013-08-29 21:03:00 -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
2013-09-01 21:31:39 -07:00
: Raises :
- : exc : `exceptions.IOError` if `file_name` doesn ' t exist
- : exc : `exceptions.RuntimeError` if the Cap ' n Proto C++ library has any problems loading the schema
2013-08-29 21:03:00 -07:00
"""
def _load ( nodeSchema , module ) :
module . _nodeSchema = nodeSchema
2013-09-01 20:10:57 -07:00
nodeProto = nodeSchema . get_proto ( )
2013-08-29 21:03:00 -07:00
module . _nodeProto = nodeProto
for node in nodeProto . nestedNodes :
local_module = _ModuleType ( node . name )
2013-10-15 13:29:54 -07:00
schema = nodeSchema . get_nested ( node . name )
2013-09-01 20:10:57 -07:00
proto = schema . get_proto ( )
2013-08-29 21:03:00 -07:00
if proto . isStruct :
2013-11-14 20:59:21 -08:00
local_module = _StructModule ( schema . as_struct ( ) )
2013-09-03 11:01:12 -07:00
class Reader ( _DynamicStructReader ) :
"""An abstract base class. Readers are 'instances' of this class."""
__metaclass__ = _StructABCMeta
__slots__ = [ ]
_schema = local_module . schema
def __new__ ( self ) :
raise TypeError ( ' This is an abstract base class ' )
class Builder ( _DynamicStructBuilder ) :
"""An abstract base class. Builders are 'instances' of this class."""
__metaclass__ = _StructABCMeta
__slots__ = [ ]
_schema = local_module . schema
def __new__ ( self ) :
raise TypeError ( ' This is an abstract base class ' )
2013-09-03 01:00:52 -07:00
2013-09-03 11:01:12 -07:00
local_module . Reader = Reader
local_module . Builder = Builder
2013-11-14 20:59:21 -08:00
2013-11-14 11:30:57 -08:00
module . __dict__ [ node . name ] = local_module
2013-08-29 21:03:00 -07:00
elif proto . isConst :
2013-09-01 20:10:57 -07:00
module . __dict__ [ node . name ] = schema . as_const_value ( )
2013-10-15 13:29:54 -07:00
elif proto . isInterface :
2013-11-14 20:59:21 -08:00
local_module = _InterfaceModule ( schema . as_interface ( ) )
2013-08-29 21:03:00 -07:00
2013-11-14 11:30:57 -08:00
module . __dict__ [ node . name ] = local_module
2013-08-29 21:03:00 -07:00
_load ( schema , local_module )
2013-09-01 21:31:39 -07:00
if not _os . path . isfile ( file_name ) :
raise IOError ( " File not found: " + file_name )
2013-08-29 21:03:00 -07:00
if display_name is None :
display_name = _os . path . basename ( file_name )
module = _ModuleType ( display_name )
parser = self
module . _parser = parser
2013-09-01 20:10:57 -07:00
fileSchema = parser . _parse_disk_file ( display_name , file_name , imports )
2013-08-29 21:03:00 -07:00
_load ( fileSchema , module )
2013-09-01 22:24:46 -07:00
abs_path = _os . path . abspath ( file_name )
module . __path__ = _os . path . dirname ( abs_path )
module . __file__ = abs_path
2013-08-29 21:03:00 -07:00
return module
2013-09-01 20:10:57 -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-09-01 20:10:57 -07:00
cpdef init_root ( 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 ' )
. . .
2013-09-01 20:10:57 -07:00
person = message . init_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
: 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-08-31 18:19:02 -07:00
return _DynamicStructBuilder ( ) . _init ( self . thisptr . initRootDynamicStruct ( s . thisptr ) , self , True )
2013-08-26 14:57:48 -07:00
2013-11-14 00:19:52 -08:00
cpdef get_root ( self , schema ) except + reraise_kj_exception :
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
2013-09-01 20:10:57 -07:00
want to use init_root instead : :
2013-08-26 16:16:58 -07:00
addressbook = capnp . load ( ' addressbook.capnp ' )
. . .
2013-09-01 20:10:57 -07:00
person = message . init_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
. . .
2013-09-01 20:10:57 -07:00
person = message . get_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
: 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-08-31 18:19:02 -07:00
return _DynamicStructBuilder ( ) . _init ( self . thisptr . getRootDynamicStruct ( s . thisptr ) , self , True )
2013-08-31 17:07:44 -07:00
2013-11-14 00:19:52 -08:00
cpdef set_root ( self , value ) except + reraise_kj_exception :
2013-08-31 17:07:44 -07:00
""" A method for instantiating Cap ' n Proto structs by copying from an existing struct
: type value : : class : `_DynamicStructReader`
: param value : A Cap ' n Proto struct value to copy
: rtype : void
"""
if type ( value ) is _DynamicStructBuilder :
2013-09-01 20:10:57 -07:00
value = value . as_reader ( ) ;
2013-08-31 17:07:44 -07:00
self . thisptr . setRootDynamicStruct ( ( < _DynamicStructReader > value ) . thisptr )
2013-10-15 13:29:54 -07:00
return self . get_root ( value . schema )
2013-06-26 23:01:37 -07:00
2013-11-14 00:19:52 -08:00
cpdef new_orphan ( self , schema ) except + reraise_kj_exception :
2013-08-26 22:00:12 -07:00
""" A method for instantiating Cap ' n Proto orphans
2013-12-04 11:42:57 -08:00
Don ' t use this method unless you know what you ' re doing . Orphans are useful for dynamically allocating objects for an unknown sized list , ie : :
2013-08-26 22:00:12 -07:00
addressbook = capnp . load ( ' addressbook.capnp ' )
2013-09-01 20:10:57 -07:00
m = capnp . _MallocMessageBuilder ( )
alice = m . new_orphan ( addressbook . Person )
2013-08-26 22:00:12 -07:00
: 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-09-01 20:10:57 -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 ' )
2013-09-01 20:10:57 -07:00
message = capnp . _MallocMessageBuilder ( )
person = message . init_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
person . name = ' alice '
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
2013-09-01 20:10:57 -07:00
_write_message_to_fd ( 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-09-01 20:10:57 -07:00
cpdef _get_root_node ( self ) :
2013-06-26 23:01:37 -07:00
return _NodeReader ( ) . init ( self . thisptr . getRootNode ( ) )
2013-08-26 14:57:48 -07:00
2013-11-14 00:19:52 -08:00
cpdef get_root ( self , schema ) except + reraise_kj_exception :
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 ' )
. . .
2013-09-01 20:10:57 -07:00
person = message . get_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
: 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-09-01 20:10:57 -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-09-01 20:10:57 -07:00
You use this class to for reading message ( s ) from a file . It ' s analagous to the inverse of :func:`_write_message_to_fd` 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 ' )
2013-09-01 20:10:57 -07:00
message = _StreamFdMessageReader ( f . fileno ( ) )
person = message . get_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
2013-11-05 15:58:56 -08:00
def __init__ ( self , int fd , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-05 15:51:55 -08:00
cdef schema_cpp .ReaderOptions opts
2013-11-05 15:58:56 -08:00
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
2013-11-05 15:51:55 -08:00
self . thisptr = new schema_cpp . StreamFdMessageReader ( fd , opts )
2013-06-26 23:01:37 -07:00
2013-11-14 00:19:52 -08:00
cdef class _PackedMessageReader ( _MessageReader ) :
""" 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 :func:`_write_packed_message_to_fd` and :class:`_MessageBuilder`, but in one class.::
f = open ( ' out.txt ' )
message = _PackedFdMessageReader ( f . fileno ( ) )
person = message . get_root ( addressbook . Person )
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
cdef public object _parent
def __init__ ( self ) :
pass
cdef _init ( self , schema_cpp . BufferedInputStream & stream , traversal_limit_in_words = None , nesting_limit = None , parent = None ) :
cdef schema_cpp .ReaderOptions opts
self . _parent = parent
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
self . thisptr = new schema_cpp . PackedMessageReader ( stream , opts )
return self
cdef class _PackedMessageReaderBytes ( _MessageReader ) :
cdef public object _parent
cdef schema_cpp .ArrayInputStream * stream
def __init__ ( self , buf , traversal_limit_in_words = None , nesting_limit = None ) :
cdef schema_cpp .ReaderOptions opts
self . _parent = buf
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
cdef const void *ptr
cdef Py_ssize_t sz
PyObject_AsReadBuffer ( buf , & ptr , & sz )
self . stream = new schema_cpp . ArrayInputStream ( schema_cpp . ByteArrayPtr ( < byte * > ptr , sz ) )
self . thisptr = new schema_cpp . PackedMessageReader ( deref ( self . stream ) , opts )
def __dealloc__ ( self ) :
del self . stream
cdef class _InputMessageReader ( _MessageReader ) :
""" 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 :func:`_write_packed_message_to_fd` and :class:`_MessageBuilder`, but in one class.::
f = open ( ' out.txt ' )
message = _PackedFdMessageReader ( f . fileno ( ) )
person = message . get_root ( addressbook . Person )
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
cdef public object _parent
def __init__ ( self ) :
pass
cdef _init ( self , schema_cpp . BufferedInputStream & stream , traversal_limit_in_words = None , nesting_limit = None , parent = None ) :
cdef schema_cpp .ReaderOptions opts
self . _parent = parent
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
self . thisptr = new schema_cpp . InputStreamMessageReader ( stream , opts )
return self
2013-09-01 20:10:57 -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
2013-09-01 20:10:57 -07:00
You use this class to for reading message ( s ) from a file . It ' s analagous to the inverse of :func:`_write_packed_message_to_fd` 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 ' )
2013-09-01 20:10:57 -07:00
message = _PackedFdMessageReader ( f . fileno ( ) )
person = message . get_root ( addressbook . Person )
2013-08-26 16:16:58 -07:00
print person . name
: Parameters : - fd ( `int` ) - A file descriptor
"""
2013-11-05 15:58:56 -08:00
def __init__ ( self , int fd , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-05 15:51:55 -08:00
cdef schema_cpp .ReaderOptions opts
2013-11-05 15:58:56 -08:00
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
2013-11-05 15:51:55 -08:00
self . thisptr = new schema_cpp . PackedFdMessageReader ( fd , opts )
2013-06-26 23:01:37 -07:00
2013-11-14 00:19:52 -08:00
cdef class _MultipleMessageReader :
cdef schema_cpp .FdInputStream * stream
cdef schema_cpp .BufferedInputStream * buffered_stream
cdef public object traversal_limit_in_words , nesting_limit , schema
def __init__ ( self , int fd , schema , traversal_limit_in_words = None , nesting_limit = None ) :
self . schema = schema
self . traversal_limit_in_words = traversal_limit_in_words
self . nesting_limit = nesting_limit
self . stream = new schema_cpp . FdInputStream ( fd )
self . buffered_stream = new schema_cpp . BufferedInputStreamWrapper ( deref ( self . stream ) )
def __dealloc__ ( self ) :
del self . stream
del self . buffered_stream
def __next__ ( self ) :
try :
reader = _InputMessageReader ( ) . _init ( deref ( self . buffered_stream ) , self . traversal_limit_in_words , self . nesting_limit , self )
return reader . get_root ( self . schema )
except ValueError as e :
if ' EOF ' in str ( e ) :
raise StopIteration
else :
raise
def __iter__ ( self ) :
return self
cdef class _MultiplePackedMessageReader :
cdef schema_cpp .FdInputStream * stream
cdef schema_cpp .BufferedInputStream * buffered_stream
cdef public object traversal_limit_in_words , nesting_limit , schema
def __init__ ( self , int fd , schema , traversal_limit_in_words = None , nesting_limit = None ) :
self . schema = schema
self . traversal_limit_in_words = traversal_limit_in_words
self . nesting_limit = nesting_limit
self . stream = new schema_cpp . FdInputStream ( fd )
self . buffered_stream = new schema_cpp . BufferedInputStreamWrapper ( deref ( self . stream ) )
def __dealloc__ ( self ) :
del self . stream
del self . buffered_stream
def __next__ ( self ) :
try :
reader = _PackedMessageReader ( ) . _init ( deref ( self . buffered_stream ) , self . traversal_limit_in_words , self . nesting_limit , self )
return reader . get_root ( self . schema )
except ValueError as e :
if ' EOF ' in str ( e ) :
raise StopIteration
else :
raise
def __iter__ ( self ) :
return self
2013-09-03 11:54:45 -07:00
@cython . internal
cdef class _FlatArrayMessageReader ( _MessageReader ) :
cdef object _object_to_pin
2013-11-05 15:58:56 -08:00
def __init__ ( self , buf , traversal_limit_in_words = None , nesting_limit = None ) :
2013-11-05 15:51:55 -08:00
cdef schema_cpp .ReaderOptions opts
2013-11-05 15:58:56 -08:00
if traversal_limit_in_words is not None :
opts . traversalLimitInWords = traversal_limit_in_words
if nesting_limit is not None :
opts . nestingLimit = nesting_limit
2013-11-05 15:51:55 -08:00
2013-09-03 11:54:45 -07:00
cdef const void *ptr
cdef Py_ssize_t sz
PyObject_AsReadBuffer ( buf , & ptr , & sz )
if sz % 8 != 0 :
raise ValueError ( " input length must be a multiple of eight bytes " )
self . _object_to_pin = buf
2013-11-13 22:30:31 -08:00
2013-11-07 14:47:13 -08:00
self . thisptr = new schema_cpp . FlatArrayMessageReader ( schema_cpp . WordArrayPtr ( < schema_cpp . word * > ptr , sz / / 8 ) )
2013-09-03 11:54:45 -07:00
2013-09-20 14:35:35 -07:00
@cython . internal
cdef class _FlatMessageBuilder ( _MessageBuilder ) :
cdef object _object_to_pin
def __init__ ( self , buf ) :
cdef void *ptr
cdef Py_ssize_t sz
PyObject_AsWriteBuffer ( buf , & ptr , & sz )
if sz % 8 != 0 :
raise ValueError ( " input length must be a multiple of eight bytes " )
self . _object_to_pin = buf
2013-11-13 22:30:31 -08:00
self . thisptr = new schema_cpp . FlatMessageBuilder ( schema_cpp . WordArrayPtr ( < schema_cpp . word * > ptr , sz / / 8 ) )
2013-09-20 14:35:35 -07:00
2013-11-14 00:19:52 -08:00
def _message_to_packed_bytes ( _MessageBuilder message ) :
r , w = _os . pipe ( )
writer = new schema_cpp . FdOutputStream ( w )
schema_cpp . writePackedMessage ( deref ( writer ) , deref ( message . thisptr ) )
_os . close ( w )
2013-11-14 09:41:51 -08:00
reader = _os . fdopen ( r , ' rb ' )
2013-11-14 00:19:52 -08:00
ret = reader . read ( )
del writer
reader . close ( )
return ret
2013-09-01 20:10:57 -07:00
def _write_message_to_fd ( int fd , _MessageBuilder message ) :
2013-08-26 16:16:58 -07:00
""" 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
2013-09-01 20:10:57 -07:00
you use the proper reader to match this ( ie . don ' t use _PackedFdMessageReader)::
2013-08-26 16:16:58 -07:00
2013-09-01 20:10:57 -07:00
message = capnp . _MallocMessageBuilder ( )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
2013-09-01 20:10:57 -07:00
_write_message_to_fd ( f . fileno ( ) , message )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
2013-09-01 20:10:57 -07:00
_StreamFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
: type fd : int
: param fd : A file descriptor
2013-09-01 20:10:57 -07:00
: type message : : class : `_MessageBuilder`
2013-08-26 16:16:58 -07:00
: param message : The Cap ' n Proto message to serialize
: rtype : void
"""
schema_cpp . writeMessageToFd ( fd , deref ( message . thisptr ) )
2013-09-01 20:10:57 -07:00
def _write_packed_message_to_fd ( int fd , _MessageBuilder message ) :
2013-08-26 16:16:58 -07:00
""" 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
2013-09-01 20:10:57 -07:00
the difference in names with _write_message_to_fd . This method uses a different
2013-08-26 16:16:58 -07:00
serialization specification , and your reader will need to match . : :
2013-09-01 20:10:57 -07:00
message = capnp . _MallocMessageBuilder ( )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' , ' w ' )
2013-09-01 20:10:57 -07:00
_write_packed_message_to_fd ( f . fileno ( ) , message )
2013-08-26 16:16:58 -07:00
. . .
2013-08-26 19:27:58 -07:00
f = open ( ' out.txt ' )
2013-09-01 20:10:57 -07:00
_PackedFdMessageReader ( f . fileno ( ) )
2013-08-26 16:16:58 -07:00
: type fd : int
: param fd : A file descriptor
2013-09-01 20:10:57 -07:00
: type message : : class : `_MessageBuilder`
2013-08-26 16:16:58 -07:00
: 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-29 21:03:00 -07:00
_global_schema_parser = None
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
2013-08-29 21:03:00 -07:00
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 ' )
2013-08-30 23:13:20 -07:00
print addressbook . qux # qux is a top level constant in the addressbook.capnp schema
2013-08-26 10:07:54 -07:00
# 123
2013-09-03 00:25:32 -07:00
person = addressbook . Person . new_message ( )
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
"""
2013-08-29 21:03:00 -07:00
global _global_schema_parser
if _global_schema_parser is None :
_global_schema_parser = SchemaParser ( )
2013-07-06 16:53:00 -07:00
2013-08-29 21:03:00 -07:00
return _global_schema_parser . load ( file_name , display_name , imports )
2013-09-01 21:31:39 -07:00
class _Loader :
def __init__ ( self , fullname , path , additional_paths ) :
self . fullname = fullname
self . path = path
2013-09-03 00:21:15 -07:00
# Add current directory of the capnp schema to search path
dir_name = _os . path . dirname ( path )
if path is not ' ' :
additional_paths = [ dir_name ] + additional_paths
2013-09-01 21:31:39 -07:00
self . additional_paths = additional_paths
def load_module ( self , fullname ) :
assert self . fullname == fullname , (
" invalid module, expected %s , got %s " % (
self . fullname , fullname ) )
2013-09-03 01:03:29 -07:00
imports = self . additional_paths + _sys . path
imports = [ path if path != ' ' else ' . ' for path in imports ] # convert empty path '' to '.'
2013-09-01 22:24:46 -07:00
module = load ( self . path , fullname , imports = imports )
_sys . modules [ fullname ] = module
return module
2013-09-01 21:31:39 -07:00
class _Importer :
def __init__ ( self , additional_paths ) :
self . extension = ' .capnp '
self . additional_paths = additional_paths
def find_module ( self , fullname , package_path = None ) :
if fullname in _sys . modules : # Don't allow re-imports
return None
if ' . ' in fullname : # only when package_path anyway?
mod_parts = fullname . split ( ' . ' )
module_name = mod_parts [ - 1 ]
else :
module_name = fullname
2013-09-01 23:55:29 -07:00
if not module_name . endswith ( ' _capnp ' ) :
return None
2013-09-03 00:21:15 -07:00
module_name = module_name [ : - len ( ' _capnp ' ) ]
2013-09-01 21:31:39 -07:00
capnp_module_name = module_name + self . extension
if package_path :
paths = package_path
else :
paths = _sys . path
join_path = _os . path . join
is_file = _os . path . isfile
is_abs = _os . path . isabs
abspath = _os . path . abspath
#is_dir = os.path.isdir
sep = _os . path . sep
paths = self . additional_paths + paths
for path in paths :
if not path :
path = _os . getcwd ( )
elif not is_abs ( path ) :
path = abspath ( path )
if is_file ( path + sep + capnp_module_name ) :
return _Loader ( fullname , join_path ( path , capnp_module_name ) , self . additional_paths )
_importer = None
def add_import_hook ( additional_paths = [ ] ) :
""" Add a hook to the python import system, so that Cap ' n Proto modules are directly importable
After calling this function , you can use the python import syntax to directly import capnproto schemas : :
import capnp
capnp . add_import_hook ( )
2013-11-05 15:37:51 -08:00
import addressbook_capnp
2013-09-01 21:31:39 -07:00
# equivalent to capnp.load('addressbook.capnp', 'addressbook', sys.path), except it will search for 'addressbook.capnp' in all directories of sys.path
: type additional_paths : list
: param additional_paths : Additional paths , listed as strings , to be used to search for the . capnp files . It is prepended to the beginning of sys . path . It also affects imports inside of Cap ' n Proto schemas.
"""
global _importer
if _importer is not None :
2013-09-01 22:24:46 -07:00
remove_import_hook ( )
2013-09-01 21:31:39 -07:00
_importer = _Importer ( additional_paths )
_sys . meta_path . append ( _importer )
def remove_import_hook ( ) :
"""Remove the import hook, and return python's import to normal"""
global _importer
if _importer is not None :
_sys . meta_path . remove ( _importer )
_importer = None