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
2014-12-11 22:00:44 -08:00
# distutils: libraries = capnpc capnp-rpc capnp kj-async kj
2014-09-03 23:25:39 -07:00
# distutils: include_dirs = .
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-07-06 16:53:00 -07:00
2014-09-10 10:48:23 -07:00
from capnp.helpers.helpers cimport makeRpcClientWithRestorer
2013-12-08 17:27:59 -08:00
2013-08-13 23:00:43 -07:00
from libc.stdlib cimport malloc , free
2014-12-12 16:23:24 -08:00
from libc.string cimport memcpy
2013-12-08 17:52:17 -08:00
from cython.operator cimport dereference as deref
2014-07-09 00:49:35 -07:00
from cpython.exc cimport PyErr_Clear
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
2013-12-10 22:57:21 -08:00
import traceback as _traceback
2013-10-17 19:15:40 -07:00
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-12-11 13:50:50 -08:00
import threading as _threading
2013-12-12 11:33:52 -08:00
import socket as _socket
import random as _random
2014-10-27 10:59:07 -04:00
import collections as _collections
2013-10-17 19:15:40 -07:00
2014-02-18 17:33:17 -08:00
_CAPNP_VERSION_MAJOR = capnp . CAPNP_VERSION_MAJOR
_CAPNP_VERSION_MINOR = capnp . CAPNP_VERSION_MINOR
_CAPNP_VERSION_MICRO = capnp . CAPNP_VERSION_MICRO
_CAPNP_VERSION = capnp . CAPNP_VERSION
2014-09-04 14:21:27 -07:00
cdef dict _type_registry = { }
def register_type ( id , klass ) :
_type_registry [ id ] = klass
def deregister_all_types ( ) :
_type_registry = { }
2013-10-15 22:36:14 -07:00
# By making it public, we'll be able to call it from capabilityHelper.h
2014-07-09 00:49:35 -07:00
cdef public object wrap_dynamic_struct_reader ( Response & r ) with gil :
2013-12-11 11:24:27 -08:00
return _Response ( ) . _init_childptr ( new Response ( moveResponse ( r ) ) , None )
2013-10-15 22:36:14 -07:00
2014-07-09 00:49:35 -07:00
cdef public PyObject * wrap_remote_call ( PyObject * func , Response & r ) except * with gil :
2013-10-17 22:42:14 -07:00
response = _Response ( ) . _init_childptr ( new Response ( moveResponse ( r ) ) , None )
func_obj = < object > func
2013-12-10 22:57:21 -08:00
ret = func_obj ( response )
Py_INCREF ( ret )
return < PyObject * > ret
2013-10-17 22:42:14 -07:00
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 ' ) ) ]
2014-07-09 00:49:35 -07:00
cdef public VoidPromise * call_server_method ( PyObject * _server , char * _method_name , CallContext & _context ) except * with gil :
2013-10-15 22:36:14 -07:00
server = < object > _server
method_name = < object > _method_name
2013-12-11 22:25:57 -08:00
context = _CallContext ( ) . _init ( _context ) # TODO:MEMORY: invalidate this with promise chain
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 ) ) )
2013-12-10 22:57:21 -08:00
elif type ( ret ) is Promise :
return new VoidPromise ( helpers . convert_to_voidpromise ( deref ( ( < Promise > ret ) . thisptr ) ) )
2013-11-14 23:06:14 -08:00
else :
try :
2013-12-10 22:57:21 -08:00
warning_msg = ' Server function ( %s ) returned a value that was not a Promise: return = %s ' % ( method_name , str ( ret ) )
2013-11-14 23:06:14 -08:00
except :
2013-12-10 22:57:21 -08:00
warning_msg = ' Server function ( %s ) returned a value that was not a Promise ' % ( method_name )
2013-11-14 23:06:14 -08:00
_warnings . warn_explicit ( warning_msg , UserWarning , _inspect . getsourcefile ( func ) , _inspect . getsourcelines ( func ) [ 1 ] )
if ret is not None :
2013-12-10 22:57:21 -08:00
if type ( ret ) is Promise :
return new VoidPromise ( helpers . convert_to_voidpromise ( deref ( ( < Promise > ret ) . thisptr ) ) )
elif type ( ret ) is Promise :
return new VoidPromise ( helpers . convert_to_voidpromise ( deref ( ( < Promise > ret ) . thisptr ) ) )
2013-11-14 23:06:14 -08:00
else :
try :
2013-12-10 22:57:21 -08:00
warning_msg = ' Server function ( %s ) returned a value that was not a Promise: return = %s ' % ( method_name , str ( ret ) )
2013-11-14 23:06:14 -08:00
except :
2013-12-10 22:57:21 -08:00
warning_msg = ' Server function ( %s ) returned a value that was not a Promise ' % ( method_name )
2013-11-14 23:06:14 -08:00
_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 ) ) )
2013-12-10 22:57:21 -08:00
elif type ( ret ) is Promise :
return new VoidPromise ( helpers . convert_to_voidpromise ( deref ( ( < Promise > ret ) . thisptr ) ) )
2013-11-14 23:06:14 -08:00
if not isinstance ( ret , tuple ) :
ret = ( ret , )
names = _find_field_order ( context . results . schema . node . struct )
if len ( ret ) > len ( names ) :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Too many values returned from ` %s `. Expected %d and got %d ' % ( method_name , len ( names ) , len ( ret ) ) )
2013-11-14 23:06:14 -08:00
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
2014-09-10 10:48:23 -07:00
2014-07-09 00:49:35 -07:00
cdef public C_Capability .Client * call_py_restorer ( PyObject * _restorer , C_DynamicObject . Reader & _reader ) except * with gil :
2013-11-12 15:32:23 -08:00
restorer = < object > _restorer
2013-12-10 22:57:21 -08:00
reader = _DynamicObjectReader ( ) . _init ( _reader , None )
2013-11-12 15:32:23 -08:00
2013-12-10 22:57:21 -08:00
ret = restorer . _restore ( reader )
2013-11-12 15:32:23 -08:00
cdef _DynamicCapabilityServer server = ret
2013-12-09 17:13:43 -08:00
cdef _InterfaceSchema schema = ret . schema
2013-11-12 15:32:23 -08:00
2013-12-09 17:13:43 -08:00
return new C_Capability . Client ( helpers . server_to_client ( schema . thisptr , < PyObject * > server ) )
2013-11-12 15:32:23 -08:00
2013-12-10 22:57:21 -08:00
2014-07-09 00:49:35 -07:00
cdef public convert_array_pyobject ( PyArray & arr ) with gil :
2013-12-10 22:57:21 -08:00
return [ < object > arr [ i ] for i in range ( arr . size ( ) ) ]
2014-07-09 00:49:35 -07:00
cdef public PyPromise * extract_promise ( object obj ) with gil :
2013-12-10 22:57:21 -08:00
if type ( obj ) is Promise :
promise = < Promise > obj
2013-12-11 22:25:57 -08:00
ret = new PyPromise ( promise . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > promise ) ) )
Py_DECREF ( obj )
return ret
2013-12-10 22:57:21 -08:00
return NULL
2014-07-09 00:49:35 -07:00
cdef public RemotePromise * extract_remote_promise ( object obj ) with gil :
2013-12-11 11:24:27 -08:00
if type ( obj ) is _RemotePromise :
promise = < _RemotePromise > obj
promise . is_consumed = True
2013-12-11 22:25:57 -08:00
return promise . thisptr # TODO:MEMORY: fix this leak
2013-12-11 11:24:27 -08:00
return NULL
2013-11-13 17:53:34 -08:00
cdef extern from " <kj/string.h> " namespace " ::kj " :
String strStructReader " ::kj::str " ( C_DynamicStruct . Reader )
2014-01-13 16:28:05 -08:00
String strStructBuilder " ::kj::str " ( DynamicStruct_Builder )
2013-11-13 17:53:34 -08:00
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 )
2014-11-30 14:27:10 -08:00
_Type = _make_enum ( ' _Type ' ,
FAILED = 0 ,
OVERLOADED = 1 ,
DISCONNECTED = 2 ,
UNIMPLEMENTED = 3 ,
2013-11-13 17:53:34 -08:00
OTHER = 4 )
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 ( )
2014-11-30 14:27:10 -08:00
property type :
2013-11-13 17:53:34 -08:00
def __get__ ( self ) :
2014-11-30 14:27:10 -08:00
cdef int temp = < int > self . thisptr . getType ( )
return _Type . reverse_mapping [ temp ]
2013-11-13 17:53:34 -08:00
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-12-11 22:25:57 -08:00
2014-11-30 14:27:10 -08:00
'''KjException is a wrapper of the internal C++ exception type. There is an enum named `Type` listed below, and a bunch of fields'''
2013-12-11 22:25:57 -08:00
2014-11-30 14:27:10 -08:00
Type = _make_enum ( ' Type ' , * * { x : x for x in _Type . 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
2014-09-10 10:48:23 -07:00
2013-11-13 17:53:34 -08:00
@property
def file ( self ) :
return self . wrapper . file
@property
def line ( self ) :
return self . wrapper . line
@property
2014-11-30 14:27:10 -08:00
def type ( self ) :
2013-11-13 17:53:34 -08:00
if self . wrapper is not None :
2014-11-30 14:27:10 -08:00
return self . wrapper . type
2013-11-13 17:53:34 -08:00
else :
2014-11-30 14:27:10 -08:00
return self . type
2013-11-13 17:53:34 -08:00
@property
def description ( self ) :
if self . wrapper is not None :
return self . wrapper . description
else :
return self . message
def __str__ ( self ) :
return self . message
2014-11-30 14:27:10 -08:00
def _to_python ( self ) :
message = self . message
if self . wrapper . type == ' FAILED ' :
if ' has no such ' in self . message :
return AttributeError ( message )
return self
2014-07-09 00:49:35 -07:00
cdef public object wrap_kj_exception ( capnp . Exception & exception ) with gil :
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
2014-07-09 00:49:35 -07:00
cdef public object wrap_kj_exception_for_reraise ( capnp . Exception & exception ) with gil :
2013-11-13 17:53:34 -08:00
wrapper = _KjExceptionWrapper ( ) . _init ( exception )
ret = KjException ( wrapper = wrapper )
return ret
2013-10-15 22:36:14 -07:00
2014-07-09 00:49:35 -07:00
cdef public object get_exception_info ( object exc_type , object exc_obj , object exc_tb ) with gil :
2013-11-13 20:54:57 -08:00
try :
2013-12-18 21:57:57 -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
2014-01-13 16:28:05 -08:00
DynamicStruct_Builder
2013-08-31 20:00:57 -07:00
2013-12-10 22:57:21 -08:00
ctypedef fused PromiseTypes :
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 )
2014-01-13 16:28:05 -08:00
StringTree printStructBuilder " ::capnp::prettyPrint " ( 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 ( )
2014-02-05 15:32:14 -08:00
property isEnum :
def __get__ ( self ) :
return self . thisptr . isEnum ( )
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
2014-10-19 20:06:00 -07:00
cpdef _get ( self , int64_t index ) :
return to_python_reader ( self . thisptr [ index ] , self . _parent )
def __getitem__ ( self , int64_t index ) :
cdef uint size = self . thisptr . size ( )
2013-06-28 01:04:01 -07:00
if index > = size :
raise IndexError ( ' Out of bounds ' )
index = index % size
2014-10-19 20:06:00 -07:00
return self . _get ( index )
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
2014-09-10 10:48:23 -07:00
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
2014-09-10 10:48:23 -07:00
2014-10-19 20:06:00 -07:00
cpdef _get ( self , index ) :
return self . _list [ index ] [ 1 ]
2013-08-26 22:00:12 -07:00
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
2014-09-10 10:48:23 -07:00
2013-08-26 19:27:58 -07:00
phone = phones [ 0 ]
phone . number = ' foo '
phone = phones [ 1 ]
phone . number = ' bar '
for phone in phones :
print phone . number
"""
2013-07-07 18:48:55 -07:00
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
2014-10-19 20:06:00 -07:00
cpdef _get ( self , int64_t 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
2014-10-19 20:06:00 -07:00
def __getitem__ ( self , int64_t index ) :
cdef uint size = self . thisptr . size ( )
2013-06-28 01:04:01 -07:00
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
2014-10-19 20:06:00 -07:00
cpdef _set ( self , index , value ) :
2014-01-15 22:08:27 -08:00
_setDynamicField ( self . thisptr , index , value , self . _parent )
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:
2014-11-30 14:27:10 -08:00
# raise KjException("Cannot convert type to Python. Type is unknown by capnproto library")
2013-10-19 22:38:10 -07:00
# else:
2014-11-30 14:27:10 -08:00
# raise KjException("Cannot convert type to Python. Type is unhandled by capnproto library")
2013-10-19 22:38:10 -07:00
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-12-18 12:39:56 -08:00
temp_text = self . asText ( )
return ( < char * > temp_text . begin ( ) ) [ : temp_text . size ( ) ]
2013-08-26 14:57:48 -07:00
elif type == capnp . TYPE_DATA :
2013-12-18 12:39:56 -08:00
temp_data = self . asData ( )
return < bytes > ( ( < char * > temp_data . begin ( ) ) [ : temp_data . size ( ) ] )
2013-08-26 14:57:48 -07:00
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 :
2014-02-05 12:11:29 -08:00
return _DynamicEnum ( ) . _init ( self . asEnum ( ) , parent )
2013-08-26 14:57:48 -07:00
elif type == capnp . TYPE_VOID :
return None
2013-12-06 13:19:30 -08:00
elif type == capnp . TYPE_ANY_POINTER :
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unknown by capnproto library " )
2013-08-26 14:57:48 -07:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " 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-12-18 12:39:56 -08:00
temp_text = self . asText ( )
return ( < char * > temp_text . begin ( ) ) [ : temp_text . size ( ) ]
2013-07-06 23:10:51 -07:00
elif type == capnp . TYPE_DATA :
2013-12-18 12:39:56 -08:00
temp_data = self . asData ( )
return < bytes > ( ( < char * > temp_data . begin ( ) ) [ : temp_data . size ( ) ] )
2013-07-06 23:10:51 -07:00
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 :
2014-02-05 12:11:29 -08:00
return _DynamicEnum ( ) . _init ( self . asEnum ( ) , parent )
2013-06-28 01:04:01 -07:00
elif type == capnp . TYPE_VOID :
return None
2013-12-06 13:19:30 -08:00
elif type == capnp . TYPE_ANY_POINTER :
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unknown by capnproto library " )
2013-06-28 01:04:01 -07:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " 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-12-09 17:13:43 -08:00
cdef C_DynamicValue .Reader _extract_dynamic_server ( object value ) :
cdef _InterfaceSchema schema = value . schema
return helpers . new_server ( schema . thisptr , < PyObject * > value )
2013-10-19 22:38:10 -07:00
2014-02-05 12:11:29 -08:00
cdef C_DynamicValue .Reader _extract_dynamic_enum ( _DynamicEnum value ) :
return C_DynamicValue . Reader ( value . thisptr )
2014-02-13 12:04:30 -08:00
cdef _setBytes ( _DynamicSetterClasses thisptr , field , value ) :
cdef capnp .StringPtr temp_string = capnp . StringPtr ( < char * > value , len ( value ) )
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( temp_string )
thisptr . set ( field , temp )
cdef _setBaseString ( _DynamicSetterClasses thisptr , field , value ) :
encoded_value = value . encode ( )
cdef capnp .StringPtr temp_string = capnp . StringPtr ( < char * > encoded_value , len ( encoded_value ) )
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( temp_string )
thisptr . set ( field , temp )
2014-09-04 14:21:27 -07:00
cdef _setBytesField ( DynamicStruct_Builder thisptr , _StructSchemaField field , value ) :
cdef capnp .StringPtr temp_string = capnp . StringPtr ( < char * > value , len ( value ) )
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( temp_string )
thisptr . setByField ( field . thisptr , temp )
cdef _setBaseStringField ( DynamicStruct_Builder thisptr , _StructSchemaField field , value ) :
encoded_value = value . encode ( )
cdef capnp .StringPtr temp_string = capnp . StringPtr ( < char * > encoded_value , len ( encoded_value ) )
cdef C_DynamicValue .Reader temp = C_DynamicValue . Reader ( temp_string )
thisptr . setByField ( field . thisptr , temp )
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-12-18 12:39:56 -08:00
elif value_type is bytes :
2014-02-13 12:04:30 -08:00
_setBytes ( thisptr , field , value )
2013-10-09 22:36:55 -07:00
elif isinstance ( value , basestring ) :
2014-02-13 12:04:30 -08:00
_setBaseString ( thisptr , field , value )
2013-08-31 20:00:57 -07:00
elif value_type is list :
2013-09-01 20:10:57 -07:00
builder = to_python_builder ( thisptr . init ( field , len ( value ) ) , parent )
2014-01-15 22:08:27 -08:00
_from_list ( builder , value )
2014-01-13 16:28:05 -08:00
elif value_type is dict :
2014-02-13 12:04:30 -08:00
if _DynamicSetterClasses is DynamicStruct_Builder :
2014-01-13 16:28:05 -08:00
builder = to_python_builder ( thisptr . get ( field ) , parent )
2014-10-19 20:06:00 -07:00
builder . from_dict ( value )
2014-01-13 16:28:05 -08:00
else :
builder = to_python_builder ( thisptr [ field ] , parent )
2014-10-19 20:06:00 -07:00
builder . from_dict ( value )
2013-08-31 20:00:57 -07:00
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-12-09 17:13:43 -08:00
elif value_type is _DynamicCapabilityServer or isinstance ( value , _DynamicCapabilityServer ) :
2013-10-19 22:38:10 -07:00
thisptr . set ( field , _extract_dynamic_server ( value ) )
2014-02-05 12:11:29 -08:00
elif value_type is _DynamicEnum :
thisptr . set ( field , _extract_dynamic_enum ( value ) )
2013-08-31 20:00:57 -07:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Tried to set field: ' {} ' with a value of: ' {} ' which is an unsupported type: ' {} ' " . format ( field , str ( value ) , str ( type ( value ) ) ) )
2013-08-31 20:00:57 -07:00
2014-09-04 14:21:27 -07:00
cdef _setDynamicFieldWithField ( DynamicStruct_Builder thisptr , _StructSchemaField field , value , parent ) :
cdef C_DynamicValue .Reader temp
value_type = type ( value )
2013-08-31 20:00:57 -07:00
2014-09-04 14:21:27 -07:00
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 . setByField ( field . thisptr , temp )
elif value_type is float :
temp = C_DynamicValue . Reader ( < double > value )
thisptr . setByField ( field . thisptr , temp )
elif value_type is bool :
temp = C_DynamicValue . Reader ( < cbool > value )
thisptr . setByField ( field . thisptr , temp )
elif value_type is bytes :
_setBytesField ( thisptr , field , value )
elif isinstance ( value , basestring ) :
_setBaseStringField ( thisptr , field , value )
elif value_type is list :
builder = to_python_builder ( thisptr . init ( field . proto . name , len ( value ) ) , parent )
_from_list ( builder , value )
elif value_type is dict :
builder = to_python_builder ( thisptr . getByField ( field . thisptr ) , parent )
2014-10-19 20:06:00 -07:00
builder . from_dict ( value )
2014-09-04 14:21:27 -07:00
elif value is None :
temp = C_DynamicValue . Reader ( VOID )
thisptr . setByField ( field . thisptr , temp )
elif value_type is _DynamicStructBuilder :
thisptr . setByField ( field . thisptr , _extract_dynamic_struct_builder ( value ) )
elif value_type is _DynamicStructReader :
thisptr . setByField ( field . thisptr , _extract_dynamic_struct_reader ( value ) )
elif value_type is _DynamicCapabilityClient :
thisptr . setByField ( field . thisptr , _extract_dynamic_client ( value ) )
elif value_type is _DynamicCapabilityServer or isinstance ( value , _DynamicCapabilityServer ) :
thisptr . setByField ( field . thisptr , _extract_dynamic_server ( value ) )
elif value_type is _DynamicEnum :
thisptr . setByField ( field . thisptr , _extract_dynamic_enum ( value ) )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Tried to set field: ' {} ' with a value of: ' {} ' which is an unsupported type: ' {} ' " . format ( field , str ( value ) , str ( type ( value ) ) ) )
2014-09-04 14:21:27 -07:00
2014-09-04 18:04:52 -07:00
cdef _setDynamicFieldStatic ( DynamicStruct_Builder 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 value_type is bytes :
_setBytes ( thisptr , field , value )
elif isinstance ( value , basestring ) :
_setBaseString ( thisptr , field , value )
elif value_type is list :
builder = to_python_builder ( thisptr . init ( field , len ( value ) ) , parent )
_from_list ( builder , value )
elif value_type is dict :
builder = to_python_builder ( thisptr . get ( field ) , parent )
2014-10-19 20:06:00 -07:00
builder . from_dict ( value )
2014-09-04 18:04:52 -07:00
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 ) )
elif value_type is _DynamicCapabilityClient :
thisptr . set ( field , _extract_dynamic_client ( value ) )
elif value_type is _DynamicCapabilityServer or isinstance ( value , _DynamicCapabilityServer ) :
thisptr . set ( field , _extract_dynamic_server ( value ) )
elif value_type is _DynamicEnum :
thisptr . set ( field , _extract_dynamic_enum ( value ) )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Tried to set field: ' {} ' with a value of: ' {} ' which is an unsupported type: ' {} ' " . format ( field , str ( value ) , str ( type ( value ) ) ) )
2014-09-04 18:04:52 -07:00
2014-10-19 20:06:00 -07:00
cdef _DynamicListBuilder temp_list_b
cdef _DynamicListReader temp_list_r
cdef _DynamicResizableListBuilder temp_list_rb
cdef _DynamicStructBuilder temp_msg_b
cdef _DynamicStructReader temp_msg_r
2014-10-27 10:59:07 -04:00
cdef _to_dict ( msg , bint verbose , bint ordered ) :
2013-09-03 00:25:32 -07:00
msg_type = type ( msg )
2014-10-19 20:06:00 -07:00
if msg_type is _DynamicListBuilder :
temp_list_b = msg
2014-10-27 10:59:07 -04:00
return [ _to_dict ( temp_list_b . _get ( i ) , verbose , ordered ) for i in range ( len ( msg ) ) ]
2014-10-19 20:06:00 -07:00
elif msg_type is _DynamicListReader :
temp_list_r = msg
2014-10-27 10:59:07 -04:00
return [ _to_dict ( temp_list_r . _get ( i ) , verbose , ordered ) for i in range ( len ( msg ) ) ]
2014-10-19 20:06:00 -07:00
elif msg_type is _DynamicResizableListBuilder :
temp_list_rb = msg
2014-10-27 10:59:07 -04:00
return [ _to_dict ( temp_list_rb . _get ( i ) , verbose , ordered ) for i in range ( len ( msg ) ) ]
2014-10-19 20:06:00 -07:00
if msg_type is _DynamicStructBuilder :
temp_msg_b = msg
2014-10-27 10:59:07 -04:00
if ordered :
ret = _collections . OrderedDict ( )
else :
ret = { }
2014-10-19 20:06:00 -07:00
try :
which = temp_msg_b . which ( )
2014-10-27 10:59:07 -04:00
ret [ which ] = _to_dict ( temp_msg_b . _get ( which ) , verbose , ordered )
2014-11-30 14:27:10 -08:00
except KjException :
2014-10-19 20:06:00 -07:00
pass
2013-09-03 00:25:32 -07:00
2014-10-19 20:06:00 -07:00
for field in temp_msg_b . schema . non_union_fields :
if verbose or temp_msg_b . _has ( field ) :
2014-10-27 10:59:07 -04:00
ret [ field ] = _to_dict ( temp_msg_b . _get ( field ) , verbose , ordered )
2014-10-19 20:06:00 -07:00
return ret
elif msg_type is _DynamicStructReader :
temp_msg_r = msg
2014-10-27 10:59:07 -04:00
if ordered :
ret = _collections . OrderedDict ( )
else :
ret = { }
2013-09-03 00:25:32 -07:00
try :
2014-10-19 20:06:00 -07:00
which = temp_msg_r . which ( )
2014-10-27 10:59:07 -04:00
ret [ which ] = _to_dict ( temp_msg_r . _get ( which ) , verbose , ordered )
2014-11-30 14:27:10 -08:00
except KjException :
2013-09-03 00:25:32 -07:00
pass
2014-10-19 20:06:00 -07:00
for field in temp_msg_r . schema . non_union_fields :
if verbose or temp_msg_r . _has ( field ) :
2014-10-27 10:59:07 -04:00
ret [ field ] = _to_dict ( temp_msg_r . _get ( field ) , verbose , ordered )
2013-09-03 00:25:32 -07:00
return ret
2014-09-04 14:21:27 -07:00
if isinstance ( msg , ( _DynamicStructBuilder , _DynamicStructReader ) ) :
2014-10-27 10:59:07 -04:00
return msg . to_dict ( verbose , ordered )
2014-09-04 14:21:27 -07:00
2014-06-26 00:53:16 -07:00
if msg_type is _DynamicEnum :
return str ( msg )
2013-09-03 00:25:32 -07:00
return msg
2014-01-15 22:08:27 -08:00
cdef _from_list ( _DynamicListBuilder msg , list d ) :
cdef size_t count = 0
2014-10-19 20:06:00 -07:00
for i in range ( len ( d ) ) :
msg . _set ( i , d [ i ] )
2013-09-03 01:00:52 -07:00
2014-02-05 12:11:29 -08:00
cdef class _DynamicEnum :
cdef _init ( self , capnp . DynamicEnum other , object parent ) :
self . thisptr = other
self . _parent = parent
return self
cpdef _as_str ( self ) except + reraise_kj_exception :
return < char * > helpers . fixMaybe ( self . thisptr . getEnumerant ( ) ) . getProto ( ) . getName ( ) . cStr ( )
property raw :
"""A property that returns the raw int of the enum"""
def __get__ ( self ) :
return self . thisptr . getRaw ( )
def __str__ ( self ) :
return self . _as_str ( )
def __repr__ ( self ) :
return ' < %s enum> ' % str ( self )
2014-02-13 19:24:06 -08:00
def __richcmp__ ( _DynamicEnum self , right , int op ) :
2014-02-05 12:11:29 -08:00
if isinstance ( right , basestring ) :
2014-02-13 19:24:06 -08:00
left = self . _as_str ( )
2014-02-05 12:11:29 -08:00
else :
2014-02-13 19:24:06 -08:00
left = self . thisptr . getRaw ( )
2014-02-05 12:11:29 -08:00
if op == 2 : # ==
return left == right
elif op == 3 : # !=
return left != right
elif op == 0 : # <
return left < right
elif op == 1 : # <=
return left < = right
elif op == 4 : # >
return left > right
elif op == 5 : # >=
return left > = right
2014-02-13 19:24:06 -08:00
cdef class _DynamicEnumField :
cdef _init ( self , proto ) :
self . thisptr = proto
return self
property raw :
"""A property that returns the raw int of the enum"""
def __get__ ( self ) :
return self . thisptr . discriminantValue
2014-10-19 20:06:00 -07:00
cpdef _str ( self ) :
2014-02-13 19:24:06 -08:00
return self . thisptr . name
2014-10-19 20:06:00 -07:00
def __str__ ( self ) :
return self . _str ( )
2014-02-13 19:24:06 -08:00
def __repr__ ( self ) :
return ' < %s which-enum> ' % str ( self )
def __richcmp__ ( _DynamicEnumField self , right , int op ) :
if isinstance ( right , basestring ) :
left = self . thisptr . name
else :
left = self . thisptr . discriminantValue
if op == 2 : # ==
return left == right
elif op == 3 : # !=
return left != right
elif op == 0 : # <
return left < right
elif op == 1 : # <=
return left < = right
elif op == 4 : # >
return left > right
elif op == 5 : # >=
return left > = right
def __call__ ( self ) :
return str ( self )
2014-02-05 12:11:29 -08:00
2014-02-24 14:06:28 -08:00
cdef class _MessageSize :
cdef public uint64_t word_count
cdef public uint cap_count
def __init__ ( self , uint64_t word_count , uint cap_count ) :
self . word_count = word_count
self . cap_count = cap_count
2014-04-19 17:00:19 -07:00
if getattr ( _sys , ' subversion ' , [ ' ' ] ) [ 0 ] == ' PyPy ' :
from pickle_helper import _struct_reducer
else :
def _struct_reducer ( schema_id , data ) :
return _global_schema_parser . modules_by_id [ schema_id ] . from_bytes ( data )
2014-02-27 18:16:31 -08:00
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
"""
2014-09-04 14:21:27 -07:00
cdef _init ( self , C_DynamicStruct . Reader other , object parent , bint isRoot = False , bint tryRegistry = True ) :
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
2014-09-03 16:50:10 -07:00
self . _schema = None
2014-09-04 14:21:27 -07:00
if tryRegistry and len ( _type_registry ) > 0 :
registered_type = _type_registry . get ( self . thisptr . getId ( ) , None )
if registered_type :
return registered_type [ 0 ] ( self )
2013-06-26 23:01:37 -07:00
return self
2013-07-07 18:48:55 -07:00
2014-09-03 16:50:10 -07:00
cpdef _get ( 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 __getattr__ ( self , field ) :
2014-11-30 14:27:10 -08:00
try :
return self . _get ( field )
except KjException as e :
raise e . _to_python ( )
2013-06-28 01:04:01 -07:00
2014-09-03 23:25:39 -07:00
cpdef _get_by_field ( self , _StructSchemaField field ) :
2014-09-03 15:20:26 -07:00
return to_python_reader ( self . thisptr . getByField ( field . thisptr ) , self . _parent )
2014-09-03 16:50:10 -07:00
cpdef _has ( self , field ) :
2013-06-28 01:04:01 -07:00
return self . thisptr . has ( field )
2014-09-03 23:25:39 -07:00
cpdef _has_by_field ( self , _StructSchemaField field ) :
2014-09-03 15:20:26 -07:00
return self . thisptr . hasByField ( field . thisptr )
2014-10-19 20:06:00 -07:00
cpdef _which_str ( self ) :
try :
return < char * > helpers . fixMaybe ( self . thisptr . which ( ) ) . getProto ( ) . getName ( ) . cStr ( )
except :
2014-11-30 14:27:10 -08:00
raise KjException ( " Attempted to call which on a non-union type " )
2014-10-19 20:06:00 -07:00
cpdef _DynamicEnumField _which ( self ) :
2013-08-26 19:27:58 -07:00
""" Returns the enum corresponding to the union in this struct
2014-02-13 19:24:06 -08:00
: rtype : : class : `_DynamicEnumField`
2013-08-26 19:27:58 -07:00
: return : A string / enum corresponding to what field is set in the union
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this struct doesn ' t contain a union
2013-08-26 19:27:58 -07:00
"""
2014-02-13 19:24:06 -08:00
try :
which = _DynamicEnumField ( ) . _init ( _StructSchemaField ( ) . _init ( helpers . fixMaybe ( self . thisptr . which ( ) ) , self ) . proto )
except :
2014-11-30 14:27:10 -08:00
raise KjException ( " Attempted to call which on a non-union type " )
2013-09-03 00:25:32 -07:00
return which
2013-08-15 15:44:54 -07:00
2014-02-13 19:24:06 -08:00
property which :
""" Returns the enum corresponding to the union in this struct
: rtype : : class : `_DynamicEnumField`
: return : A string / enum corresponding to what field is set in the union
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this struct doesn ' t contain a union
2014-02-13 19:24:06 -08:00
"""
def __get__ ( _DynamicStructReader self ) :
return self . _which ( )
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 ) :
2014-09-03 16:50:10 -07:00
if self . _schema is None :
self . _schema = _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
return self . _schema
2013-08-28 14:34:37 -07:00
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
2014-10-27 10:59:07 -04:00
def to_dict ( self , verbose = False , ordered = False ) :
return _to_dict ( self , verbose , ordered )
2013-09-03 00:25:32 -07:00
2014-02-28 13:36:38 -08:00
cpdef as_builder ( self , num_first_segment_words = None ) :
2014-11-21 23:59:47 +01:00
""" A method for casting this Reader to a Builder
2013-10-20 22:55:41 -07:00
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
2014-02-28 13:36:38 -08:00
: type num_first_segment_words : int
: param num_first_segment_words : Size of the first segment to allocate in the message ( in words ie . 8 byte increments )
2013-11-14 20:59:21 -08:00
: rtype : : class : `_DynamicStructBuilder`
2013-10-20 22:55:41 -07:00
"""
2014-02-28 13:36:38 -08:00
builder = _MallocMessageBuilder ( num_first_segment_words )
2013-10-20 22:55:41 -07:00
return builder . set_root ( self )
2013-09-03 00:25:32 -07:00
2014-02-24 14:06:28 -08:00
property total_size :
def __get__ ( self ) :
size = self . thisptr . totalSize ( )
return _MessageSize ( size . wordCount , size . capCount )
2014-04-19 17:00:19 -07:00
def __reduce_ex__ ( self , proto ) :
2014-02-27 18:16:31 -08:00
return _struct_reducer , ( self . schema . node . id , self . as_builder ( ) . to_bytes ( ) )
2014-09-03 16:50:10 -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
2014-09-10 10:48:23 -07:00
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
"""
2014-09-04 14:21:27 -07:00
cdef _init ( self , DynamicStruct_Builder other , object parent , bint isRoot = False , bint tryRegistry = True ) :
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
2014-09-03 16:50:10 -07:00
self . _schema = None
2014-09-04 14:21:27 -07:00
if tryRegistry and len ( _type_registry ) > 0 :
registered_type = _type_registry . get ( self . thisptr . getId ( ) , None )
if registered_type :
return registered_type [ 1 ] ( self )
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " You can only call write() on the message ' s root struct. " )
2013-10-20 22:44:15 -07:00
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.
2014-09-10 10:48:23 -07:00
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.
2014-09-10 10:48:23 -07:00
2013-08-31 18:19:02 -07:00
: type file : file
: param file : A file or socket object ( or anything with a fileno ( ) method ) , open for write .
2014-09-10 10:48:23 -07:00
2013-08-31 18:19:02 -07:00
: rtype : void
2014-09-10 10:48:23 -07:00
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this isn ' t the message ' s root struct .
2013-08-31 18:19:02 -07:00
"""
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.
2014-09-10 10:48:23 -07:00
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.
2014-09-10 10:48:23 -07:00
2013-08-31 18:19:02 -07:00
: type file : file
: param file : A file or socket object ( or anything with a fileno ( ) method ) , open for write .
2014-09-10 10:48:23 -07:00
2013-08-31 18:19:02 -07:00
: rtype : void
2014-09-10 10:48:23 -07:00
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this isn ' t the message ' s root struct .
2013-08-31 18:19:02 -07:00
"""
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
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this isn ' t the message ' s root struct .
2013-09-03 11:54:45 -07:00
"""
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
2014-02-24 14:06:28 -08:00
cpdef _to_bytes_packed_helper ( _DynamicStructBuilder self , word_count ) except + reraise_kj_exception :
2013-11-14 00:19:52 -08:00
cdef _MessageBuilder builder = self . _parent
2014-02-24 14:06:28 -08:00
array = helpers . messageToPackedBytes ( deref ( builder . thisptr ) , word_count )
2014-01-15 22:43:19 -08:00
cdef const char * ptr = < const char * > array . begin ( )
cdef bytes ret = ptr [ : array . size ( ) ]
2014-02-24 14:06:28 -08:00
return ret
cpdef to_bytes_packed ( _DynamicStructBuilder self ) except + reraise_kj_exception :
self . _check_write ( )
word_count = self . total_size . word_count + 2
try :
ret = self . _to_bytes_packed_helper ( word_count )
except Exception as e :
if ' backing array was not large enough ' in str ( e ) :
word_count * = 2
ret = self . _to_bytes_packed_helper ( word_count )
else :
raise
2014-01-15 22:43:19 -08:00
self . _is_written = True
return ret
2013-11-14 00:19:52 -08:00
2014-09-03 16:50:10 -07:00
cpdef _get ( self , field ) :
return to_python_builder ( self . thisptr . get ( field ) , self . _parent )
2013-09-18 17:19:57 -07:00
2014-09-03 23:25:39 -07:00
cpdef _get_by_field ( self , _StructSchemaField field ) :
2014-09-03 15:20:26 -07:00
return to_python_builder ( self . thisptr . getByField ( field . thisptr ) , self . _parent )
2014-09-10 10:48:23 -07:00
2013-08-25 16:41:37 -07:00
def __getattr__ ( self , field ) :
2014-11-30 14:27:10 -08:00
try :
return self . _get ( field )
except KjException as e :
raise e . _to_python ( )
2013-08-25 16:41:37 -07:00
2014-09-03 16:50:10 -07:00
cpdef _set ( 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
2014-09-03 23:25:39 -07:00
cpdef _set_by_field ( self , _StructSchemaField field , value ) :
2014-09-04 14:21:27 -07:00
_setDynamicFieldWithField ( self . thisptr , field , value , self . _parent )
2014-09-03 15:20:26 -07:00
2014-01-15 22:08:27 -08:00
def __setattr__ ( self , field , value ) :
2014-11-30 14:27:10 -08:00
try :
self . _set ( field , value )
except KjException as e :
raise e . _to_python ( )
2014-01-15 22:08:27 -08:00
2014-09-03 16:50:10 -07:00
cpdef _has ( self , field ) :
2013-06-26 23:01:37 -07:00
return self . thisptr . has ( field )
2014-09-03 16:50:10 -07:00
cpdef _has_by_field ( self , _StructSchemaField field ) :
2014-09-03 15:20:26 -07:00
return self . thisptr . hasByField ( field . thisptr )
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
2014-09-10 10:48:23 -07:00
Typically , you don ' t have to worry about initializing structs/unions, so this method is mainly for lists.
2013-08-26 19:27:58 -07:00
: 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`
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` 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
2014-09-03 23:25:39 -07:00
cpdef _init_by_field ( self , _StructSchemaField field , size = None ) :
2014-09-03 15:20:26 -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`
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if the field isn ' t in this struct
2014-09-03 15:20:26 -07:00
"""
if size is None :
return to_python_builder ( self . thisptr . initByField ( field . thisptr ) , self . _parent )
else :
return to_python_builder ( self . thisptr . initByField ( field . thisptr , size ) , self . _parent )
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)
2014-09-10 10:48:23 -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`
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` 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 ( ) ) )
2014-10-19 20:06:00 -07:00
cpdef _which_str ( self ) :
try :
return < char * > helpers . fixMaybe ( self . thisptr . which ( ) ) . getProto ( ) . getName ( ) . cStr ( )
except :
2014-11-30 14:27:10 -08:00
raise KjException ( " Attempted to call which on a non-union type " )
2014-10-19 20:06:00 -07:00
cpdef _DynamicEnumField _which ( self ) :
2013-08-26 19:27:58 -07:00
""" Returns the enum corresponding to the union in this struct
2014-02-13 19:24:06 -08:00
: rtype : : class : `_DynamicEnumField`
2013-08-26 19:27:58 -07:00
: return : A string / enum corresponding to what field is set in the union
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this struct doesn ' t contain a union
2013-08-26 19:27:58 -07:00
"""
2014-02-13 19:24:06 -08:00
try :
which = _DynamicEnumField ( ) . _init ( _StructSchemaField ( ) . _init ( helpers . fixMaybe ( self . thisptr . which ( ) ) , self ) . proto )
except :
2014-11-30 14:27:10 -08:00
raise KjException ( " Attempted to call which on a non-union type " )
2013-09-03 00:25:32 -07:00
return which
2013-06-26 23:01:37 -07:00
2014-02-13 19:24:06 -08:00
property which :
""" Returns the enum corresponding to the union in this struct
: rtype : : class : `_DynamicEnumField`
: return : A string / enum corresponding to what field is set in the union
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if this struct doesn ' t contain a union
2014-02-13 19:24:06 -08:00
"""
def __get__ ( _DynamicStructBuilder self ) :
return self . _which ( )
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
2014-02-28 13:36:38 -08:00
cpdef copy ( self , num_first_segment_words = None ) :
2013-11-14 20:59:21 -08:00
""" 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.
2014-02-28 13:36:38 -08:00
: type num_first_segment_words : int
: param num_first_segment_words : Size of the first segment to allocate in the message ( in words ie . 8 byte increments )
2013-11-14 20:59:21 -08:00
: rtype : : class : `_DynamicStructBuilder`
"""
2014-02-28 13:36:38 -08:00
builder = _MallocMessageBuilder ( num_first_segment_words )
2013-11-14 20:59:21 -08:00
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 ) :
2014-09-03 16:50:10 -07:00
if self . _schema is None :
self . _schema = _StructSchema ( ) . _init ( self . thisptr . getSchema ( ) )
return self . _schema
2013-08-28 14:34:37 -07:00
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
2014-10-27 10:59:07 -04:00
def to_dict ( self , verbose = False , ordered = False ) :
return _to_dict ( self , verbose , ordered )
2013-09-03 00:25:32 -07:00
2014-10-19 20:06:00 -07:00
def from_dict ( self , dict d ) :
for key , val in d . iteritems ( ) :
if key != ' which ' :
try :
self . _set ( key , val )
except Exception as e :
if ' expected isSetInUnion(field) ' in str ( e ) :
self . init ( key )
self . _set ( key , val )
else :
raise
2013-09-03 00:25:32 -07:00
2014-02-24 14:06:28 -08:00
property total_size :
def __get__ ( self ) :
size = self . thisptr . totalSize ( )
return _MessageSize ( size . wordCount , size . capCount )
2014-04-19 17:00:19 -07:00
def __reduce_ex__ ( self , proto ) :
2014-02-27 18:16:31 -08:00
return _struct_reducer , ( self . schema . node . id , self . to_bytes ( ) )
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unknown by capnproto library " )
2013-10-19 22:38:10 -07:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unhandled by capnproto library " )
2013-10-19 22:38:10 -07:00
def __getattr__ ( self , field ) :
2014-11-30 14:27:10 -08:00
try :
return self . _get ( field )
except KjException as e :
raise e . _to_python ( )
2013-10-19 22:38:10 -07:00
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())
2014-10-27 10:59:07 -04:00
def to_dict ( self , verbose = False , ordered = False ) :
return _to_dict ( self , verbose , ordered )
2013-09-03 00:25:32 -07:00
2013-08-26 14:45:15 -07:00
cdef class _DynamicOrphan :
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
2013-12-10 22:57:21 -08:00
cpdef as_struct ( self , schema ) except + reraise_kj_exception :
2013-09-18 17:19:57 -07:00
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
2014-11-19 07:36:40 -08:00
cpdef as_interface ( self , schema ) except + reraise_kj_exception :
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicCapabilityClient ( ) . _init ( self . thisptr . getAsCapability ( s . thisptr ) , self . _parent )
cpdef as_list ( self , schema ) except + reraise_kj_exception :
cdef ListSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicListReader ( ) . _init ( self . thisptr . getAsList ( s . thisptr ) , self . _parent )
2013-12-10 22:57:21 -08:00
cpdef as_text ( self ) except + reraise_kj_exception :
return ( < char * > self . thisptr . getAsText ( ) . cStr ( ) ) [ : ]
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
2013-12-10 22:57:21 -08:00
cpdef as_struct ( self , schema ) except + reraise_kj_exception :
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
2014-11-19 07:36:40 -08:00
cpdef as_interface ( self , schema ) except + reraise_kj_exception :
cdef _InterfaceSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicCapabilityClient ( ) . _init ( self . thisptr . getAsCapability ( s . thisptr ) , self . _parent )
cpdef as_list ( self , schema ) except + reraise_kj_exception :
cdef ListSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicListBuilder ( ) . _init ( self . thisptr . getAsList ( s . thisptr ) , self . _parent )
cpdef set ( self , other ) :
" Set value of this object with the value of another AnyPointer::Reader. Don ' t use this for structs "
cdef _DynamicObjectReader reader = other
self . thisptr . set ( reader . thisptr )
2013-12-09 19:18:54 -08:00
cpdef set_as_text ( self , text ) :
self . thisptr . setAsText ( text )
2014-11-19 07:36:40 -08:00
cpdef init_as_list ( self , schema , size ) :
cdef ListSchema s
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
return _DynamicListBuilder ( ) . _init ( self . thisptr . initAsList ( s . thisptr , size ) , self . _parent )
2013-12-10 22:57:21 -08:00
cpdef as_text ( self ) except + reraise_kj_exception :
return ( < char * > self . thisptr . getAsText ( ) . cStr ( ) ) [ : ]
2014-11-19 07:36:40 -08:00
cpdef as_reader ( self ) :
return _DynamicObjectReader ( ) . _init ( self . thisptr . asReader ( ) , self . _parent )
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
2014-01-08 16:18:10 -08:00
def __dealloc__ ( self ) :
del self . thisptr #TODO:MEMORY: fix problems with Promises still being around
2013-12-06 13:19:30 -08:00
2013-12-11 13:50:50 -08:00
cpdef _remove ( self ) except + reraise_kj_exception :
2013-12-06 13:19:30 -08:00
del self . thisptr
self . thisptr = NULL
2013-12-04 11:42:57 -08:00
cdef Own [AsyncIoStream ] wrapSocketFd ( self , int fd ) :
2014-01-08 16:18:10 -08:00
return deref ( deref ( self . thisptr ) . lowLevelProvider ) . wrapSocketFd ( fd )
2013-12-02 17:38:32 -08:00
2014-01-08 16:18:10 -08:00
cdef _EventLoop C_DEFAULT_EVENT_LOOP = _EventLoop ( )
2013-12-11 13:50:50 -08:00
_C_DEFAULT_EVENT_LOOP_LOCAL = None
2014-07-09 00:49:35 -07:00
_THREAD_LOCAL_EVENT_LOOPS = [ ]
2013-12-11 13:50:50 -08:00
cdef _EventLoop C_DEFAULT_EVENT_LOOP_GETTER ( ) :
' Optimization for not having to deal with threadlocal event loops unless we need to '
if C_DEFAULT_EVENT_LOOP is not None :
2014-01-08 16:18:10 -08:00
return C_DEFAULT_EVENT_LOOP
2013-12-11 13:50:50 -08:00
elif _C_DEFAULT_EVENT_LOOP_LOCAL is not None :
loop = getattr ( _C_DEFAULT_EVENT_LOOP_LOCAL , ' loop ' , None )
if loop is not None :
return < _EventLoop > _C_DEFAULT_EVENT_LOOP_LOCAL . loop
2014-01-08 16:18:10 -08:00
else :
_C_DEFAULT_EVENT_LOOP_LOCAL . loop = _EventLoop ( )
return _C_DEFAULT_EVENT_LOOP_LOCAL . loop
2013-12-11 13:50:50 -08:00
2014-11-30 14:27:10 -08:00
raise KjException ( " You don ' t have any EventLoops running. Please make sure to add one " )
2013-12-11 13:50:50 -08:00
2014-09-03 15:19:33 -07:00
cdef class _Timer :
2014-04-10 19:08:24 -07:00
cdef capnp .Timer * thisptr
cdef _init ( self , capnp . Timer * timer ) :
self . thisptr = timer
return self
2014-04-13 18:15:36 -07:00
cpdef after_delay ( self , time ) except + reraise_kj_exception :
2014-04-10 19:08:24 -07:00
return _VoidPromise ( ) . _init ( self . thisptr . afterDelay ( capnp . Duration ( time ) ) )
def getTimer ( ) :
2014-09-03 15:19:33 -07:00
return _Timer ( ) . _init ( helpers . getTimer ( C_DEFAULT_EVENT_LOOP_GETTER ( ) . thisptr ) )
2013-12-02 17:38:32 -08:00
2014-07-09 00:49:35 -07:00
cpdef remove_event_loop ( ignore_errors = False ) :
2014-04-17 22:52:13 -07:00
' Remove the global event loop '
global C_DEFAULT_EVENT_LOOP
2014-07-09 00:49:35 -07:00
global _THREAD_LOCAL_EVENT_LOOPS
global _C_DEFAULT_EVENT_LOOP_LOCAL
if C_DEFAULT_EVENT_LOOP :
try :
C_DEFAULT_EVENT_LOOP . _remove ( )
except :
if not ignore_errors :
raise
C_DEFAULT_EVENT_LOOP = None
if len ( _THREAD_LOCAL_EVENT_LOOPS ) > 0 :
for loop in _THREAD_LOCAL_EVENT_LOOPS :
try :
loop . _remove ( )
except :
if not ignore_errors :
raise
_THREAD_LOCAL_EVENT_LOOPS = [ ]
_C_DEFAULT_EVENT_LOOP_LOCAL = None
2014-04-17 22:52:13 -07:00
cpdef create_event_loop ( threaded = True ) :
''' Create a new global event loop. This will not remove the previous
EventLoop for you , so make sure to do that first '''
global C_DEFAULT_EVENT_LOOP
global _C_DEFAULT_EVENT_LOOP_LOCAL
if threaded :
if _C_DEFAULT_EVENT_LOOP_LOCAL is None :
_C_DEFAULT_EVENT_LOOP_LOCAL = _threading . local ( )
2014-07-09 00:49:35 -07:00
loop = _EventLoop ( )
_C_DEFAULT_EVENT_LOOP_LOCAL . loop = loop
_THREAD_LOCAL_EVENT_LOOPS . append ( loop )
2014-04-17 22:52:13 -07:00
else :
C_DEFAULT_EVENT_LOOP = _EventLoop ( )
2013-12-02 17:38:32 -08:00
2014-04-17 22:52:13 -07:00
cpdef reset_event_loop ( ) :
global C_DEFAULT_EVENT_LOOP
C_DEFAULT_EVENT_LOOP . _remove ( )
C_DEFAULT_EVENT_LOOP = _EventLoop ( )
2013-12-10 22:57:21 -08:00
2014-02-13 22:08:26 -08:00
def wait_forever ( ) :
cdef _EventLoop loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
helpers . waitNeverDone ( deref ( loop . thisptr ) . waitScope )
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 )
2013-12-06 13:19:30 -08:00
cpdef _get_results ( self , uint word_count = 0 ) :
return _DynamicStructBuilder ( ) . _init ( self . thisptr . getResults ( ) , self ) # TODO: pass firstSegmentWordSize
2013-10-15 22:36:14 -07:00
property results :
def __get__ ( self ) :
return self . _get_results ( )
2013-12-05 00:07:51 -08:00
cpdef release_params ( self ) :
self . thisptr . releaseParams ( )
2013-12-08 15:52:03 -08:00
cpdef allow_cancellation ( self ) :
2013-12-06 13:19:30 -08:00
self . thisptr . allowCancellation ( )
2013-12-05 00:07:51 -08:00
cpdef tail_call ( self , _Request tailRequest ) :
2013-12-10 22:57:21 -08:00
promise = _VoidPromise ( ) . _init ( self . thisptr . tailCall ( moveRequest ( deref ( tailRequest . thisptr_child ) ) ) )
promise . is_consumed = True
return promise
2013-12-05 00:07:51 -08:00
2013-12-10 22:57: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-12-10 22:57:21 -08:00
cdef public object _parent , _obj
2014-01-08 16:18:10 -08:00
cdef _EventLoop _event_loop
2013-10-15 22:36:14 -07:00
2013-12-10 22:57:21 -08:00
def __init__ ( self , obj = None ) :
if obj is None :
self . is_consumed = True
else :
self . is_consumed = False
self . _obj = obj
2014-04-13 18:15:36 -07:00
Py_INCREF ( obj ) # TODO: MEM: fix leak
2013-12-10 22:57:21 -08:00
self . thisptr = new PyPromise ( < PyObject * > obj )
2013-10-15 22:36:14 -07:00
2014-01-08 16:18:10 -08:00
self . _event_loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
2013-12-10 22:57:21 -08:00
cdef _init ( self , PyPromise other , parent = None ) :
2013-10-15 22:36:14 -07:00
self . is_consumed = False
self . thisptr = new PyPromise ( movePromise ( other ) )
2013-12-10 22:57:21 -08:00
self . _parent = parent
2013-10-15 22:36:14 -07:00
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2014-07-09 00:49:35 -07:00
ret = < object > helpers . waitPyPromise ( self . thisptr , deref ( self . _event_loop . thisptr ) . waitScope )
2013-12-11 22:25:57 -08:00
Py_DECREF ( ret )
2013-12-12 00:02:32 -08:00
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2014-04-13 18:26:01 -07:00
argspec = None
try :
argspec = _inspect . getargspec ( func )
except :
pass
if argspec :
args_length = len ( argspec . args ) if argspec . args else 0
defaults_length = len ( argspec . defaults ) if argspec . defaults else 0
if args_length - defaults_length != 1 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Function passed to `then` call must take exactly one argument ' )
2013-12-11 22:25:57 -08:00
2014-04-17 20:53:23 -07:00
cdef Promise new_promise = Promise ( ) . _init ( helpers . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) , self )
return Promise ( ) . _init ( new_promise . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > func ) , capnp . makePyRefCounter ( < PyObject * > error_func ) ) , new_promise )
2013-12-11 22:25:57 -08:00
def attach ( self , * args ) :
if self . is_consumed :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-12-11 22:25:57 -08:00
ret = Promise ( ) . _init ( self . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > args ) ) , self )
self . is_consumed = True
2013-10-15 22:36:14 -07:00
2013-12-11 22:25:57 -08:00
return ret
2013-10-15 22:36:14 -07:00
2014-04-17 20:53:23 -07:00
cpdef cancel ( self , numParents = 1 ) except + reraise_kj_exception :
if numParents > 0 and hasattr ( self . _parent , ' cancel ' ) :
self . _parent . cancel ( numParents - 1 )
2014-04-13 18:15:36 -07:00
self . is_consumed = True
del self . thisptr
self . thisptr = NULL
2013-10-17 22:42:14 -07:00
cdef class _VoidPromise :
cdef VoidPromise * thisptr
cdef public bint is_consumed
2013-12-11 22:25:57 -08:00
cdef public object _parent
2014-01-08 16:18:10 -08:00
cdef _EventLoop _event_loop
2013-10-17 22:42:14 -07:00
def __init__ ( self ) :
self . is_consumed = True
2014-01-08 16:18:10 -08:00
self . _event_loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
2013-10-17 22:42:14 -07:00
2013-12-11 22:25:57 -08:00
cdef _init ( self , VoidPromise other , parent = None ) :
2013-10-17 22:42:14 -07:00
self . is_consumed = False
self . thisptr = new VoidPromise ( moveVoidPromise ( other ) )
2013-12-11 22:25:57 -08:00
self . _parent = parent
2013-10-17 22:42:14 -07:00
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-17 22:42:14 -07:00
2014-07-09 00:49:35 -07:00
helpers . waitVoidPromise ( self . thisptr , deref ( self . _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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-17 22:42:14 -07:00
2014-04-13 18:35:53 -07:00
argspec = None
try :
argspec = _inspect . getargspec ( func )
except :
pass
if argspec :
args_length = len ( argspec . args ) if argspec . args else 0
defaults_length = len ( argspec . defaults ) if argspec . defaults else 0
if args_length - defaults_length != 0 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Function passed to `then` call must take no arguments ' )
2014-04-13 18:35:53 -07:00
2014-04-17 20:53:23 -07:00
cdef Promise new_promise = Promise ( ) . _init ( helpers . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) , self )
return Promise ( ) . _init ( new_promise . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > func ) , capnp . makePyRefCounter ( < PyObject * > error_func ) ) , new_promise )
2013-12-10 22:57:21 -08:00
cpdef as_pypromise ( self ) except + reraise_kj_exception :
if self . is_consumed :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-12-11 11:24:27 -08:00
return Promise ( ) . _init ( helpers . convert_to_pypromise ( deref ( self . thisptr ) ) , self )
2013-10-17 22:42:14 -07:00
2013-12-11 22:25:57 -08:00
def attach ( self , * args ) :
if self . is_consumed :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-12-11 22:25:57 -08:00
ret = _VoidPromise ( ) . _init ( self . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > args ) ) , self )
self . is_consumed = True
return ret
2014-04-17 20:53:23 -07:00
cpdef cancel ( self , numParents = 1 ) except + reraise_kj_exception :
if numParents > 0 and hasattr ( self . _parent , ' cancel ' ) :
self . _parent . cancel ( numParents - 1 )
2014-09-03 15:20:26 -07:00
2014-04-13 18:15:36 -07:00
self . is_consumed = True
del self . thisptr
self . thisptr = NULL
2013-10-15 22:36:14 -07:00
cdef class _RemotePromise :
cdef RemotePromise * thisptr
cdef public bint is_consumed
cdef public object _parent
2014-01-08 16:18:10 -08:00
cdef _EventLoop _event_loop
2013-10-15 22:36:14 -07:00
def __init__ ( self ) :
self . is_consumed = True
2014-01-08 16:18:10 -08:00
self . _event_loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
2013-10-15 22:36:14 -07:00
cdef _init ( self , RemotePromise other , parent ) :
self . is_consumed = False
self . thisptr = new RemotePromise ( moveRemotePromise ( other ) )
self . _parent = parent
return self
2013-12-11 22:25:57 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2013-10-15 22:36:14 -07:00
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2014-07-09 00:49:35 -07:00
ret = _Response ( ) . _init_childptr ( helpers . waitRemote ( self . thisptr , deref ( self . _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-12-10 22:57:21 -08:00
if self . is_consumed :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-12-11 11:24:27 -08:00
return Promise ( ) . _init ( helpers . convert_to_pypromise ( deref ( self . thisptr ) ) , self )
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Promise was already used in a consuming operation. You can no longer use this Promise object ' )
2013-10-15 22:36:14 -07:00
2014-04-13 18:35:53 -07:00
argspec = None
try :
argspec = _inspect . getargspec ( func )
except :
pass
if argspec :
args_length = len ( argspec . args ) if argspec . args else 0
defaults_length = len ( argspec . defaults ) if argspec . defaults else 0
if args_length - defaults_length != 1 :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Function passed to `then` call must take exactly one argument ' )
2013-10-15 22:36:14 -07:00
2013-10-17 22:42:14 -07:00
Py_INCREF ( func )
Py_INCREF ( error_func )
2014-04-17 20:53:23 -07:00
cdef Promise new_promise = Promise ( ) . _init ( helpers . then ( deref ( self . thisptr ) , < PyObject * > func , < PyObject * > error_func ) , self )
return Promise ( ) . _init ( new_promise . thisptr . attach ( capnp . makePyRefCounter ( < PyObject * > func ) , capnp . makePyRefCounter ( < PyObject * > error_func ) ) , new_promise )
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unknown by capnproto library " )
2013-10-19 22:38:10 -07:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Cannot convert type to Python. Type is unhandled by capnproto library " )
2013-10-17 22:42:14 -07:00
def __getattr__ ( self , field ) :
2014-11-30 14:27:10 -08:00
try :
return self . _get ( field )
except KjException as e :
raise e . _to_python ( )
2013-10-17 22:42:14 -07:00
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
2014-10-27 10:59:07 -04:00
def to_dict ( self , verbose = False , ordered = False ) :
return _to_dict ( self , verbose , ordered )
2013-10-19 22:38:10 -07:00
2014-04-17 20:53:23 -07:00
cpdef cancel ( self , numParents = 1 ) except + reraise_kj_exception :
if numParents > 0 and hasattr ( self . _parent , ' cancel ' ) :
self . _parent . cancel ( numParents - 1 )
2014-09-03 15:20:26 -07:00
2014-04-13 18:15:36 -07:00
self . is_consumed = True
del self . thisptr
self . thisptr = NULL
2013-10-19 22:38:10 -07:00
2013-12-11 22:25:57 -08:00
# def attach(self, *args):
# if self.is_consumed:
2014-11-30 14:27:10 -08:00
# raise KjException('Promise was already used in a consuming operation. You can no longer use this Promise object')
2013-12-11 22:25:57 -08:00
# ret = _RemotePromise()._init(self.thisptr.attach(capnp.makePyRefCounter(<PyObject *>args)), self)
# self.is_consumed = True
# return ret
2013-12-10 22:57:21 -08:00
cpdef join_promises ( promises ) except + reraise_kj_exception :
heap = capnp . heapArrayBuilderPyPromise ( len ( promises ) )
new_promises = [ ]
new_promises_append = new_promises . append
for promise in promises :
promise_type = type ( promise )
if promise_type is Promise :
pyPromise = < Promise > promise
elif promise_type is _RemotePromise or promise_type is _VoidPromise :
pyPromise = < Promise > promise . as_pypromise ( )
new_promises_append ( pyPromise )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( ' One of the promises passed to `join_promises` had a non promise value of: ' + str ( promise ) )
2013-12-10 22:57:21 -08:00
heap . add ( movePromise ( deref ( pyPromise . thisptr ) ) )
pyPromise . is_consumed = True
return Promise ( ) . _init ( helpers . then ( capnp . joinPromises ( heap . finish ( ) ) ) )
2013-10-17 19:15:40 -07:00
cdef class _Request ( _DynamicStructBuilder ) :
cdef Request * thisptr_child
2014-04-13 18:35:53 -07:00
cdef public bint is_consumed
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 ) )
2014-01-13 16:28:05 -08:00
self . _init ( < DynamicStruct_Builder > deref ( self . thisptr_child ) , parent )
2014-04-13 18:35:53 -07:00
self . is_consumed = False
2013-10-15 22:36:14 -07:00
return self
2013-12-11 22:25:57 -08:00
def __dealloc__ ( self ) :
del self . thisptr_child
2013-10-15 22:36:14 -07:00
cpdef send ( self ) :
2014-04-13 18:35:53 -07:00
if self . is_consumed :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Request has already been sent. You can only send a request once. ' )
2014-04-13 18:35:53 -07:00
self . is_consumed = True
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-12-11 22:25:57 -08:00
def __dealloc__ ( self ) :
del self . thisptr_child
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-12-09 17:13:43 -08:00
def __getattr__ ( self , field ) :
2014-11-30 14:27:10 -08:00
try :
return getattr ( self . server , field )
except KjException as e :
raise e . _to_python ( )
2013-12-09 17:13:43 -08:00
2013-10-15 22:36:14 -07:00
cdef class _DynamicCapabilityClient :
cdef C_DynamicCapability .Client thisptr
2014-04-18 18:18:54 -07:00
cdef public object _server , _parent , _cached_schema
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-08 18:03:31 -08:00
self . thisptr = helpers . 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
2014-10-19 22:45:08 -07:00
meth = s . methods_inherited . get ( method_name , None )
if meth is None :
raise AttributeError ( " Method named %s not found. " % method_name )
2013-11-14 20:59:21 -08:00
2014-10-19 22:45:08 -07:00
params = meth . param_type . node
2013-11-14 20:59:21 -08:00
if params . scopeId != 0 :
2014-11-30 14:27:10 -08:00
raise KjException ( " 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 ) :
2014-11-30 14:27:10 -08:00
raise KjException ( ' Too many arguments passed to ` %s `. Expected %d and got %d ' % ( name , len ( arg_names ) , len ( args ) ) )
2013-11-14 23:06:14 -08:00
for arg_name , arg_val in zip ( arg_names , args ) :
2014-02-13 11:49:29 -08:00
_setDynamicField ( < DynamicStruct_Builder > deref ( request ) , arg_name , arg_val , self )
2013-11-14 20:59:21 -08:00
2013-12-05 00:07:51 -08:00
if kwargs is not None :
for key , val in kwargs . items ( ) :
2014-02-13 11:49:29 -08:00
_setDynamicField ( < DynamicStruct_Builder > deref ( request ) , key , val , self )
2013-12-05 00:07:51 -08:00
2013-12-06 13:19:30 -08:00
cpdef _send_helper ( self , name , word_count , args , kwargs ) except + reraise_kj_exception :
# if word_count is None:
# word_count = 0
cdef Request * request = new Request ( self . thisptr . newRequest ( name ) ) # TODO: pass word_count
2013-12-05 00:07:51 -08:00
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 :
2013-12-06 13:19:30 -08:00
# if word_count is None:
# word_count = 0
cdef _Request req = _Request ( ) . _init_child ( self . thisptr . newRequest ( name ) , self )
2013-12-05 00:07:51 -08:00
self . _set_fields ( req . thisptr_child , name , args , kwargs )
return req
2013-10-17 19:15:40 -07:00
2013-12-06 13:19:30 -08:00
def _request ( self , name , * args , word_count = None , * * kwargs ) :
return self . _request_helper ( name , word_count , args , kwargs )
2013-10-15 22:36:14 -07:00
2013-12-06 13:19:30 -08:00
def _send ( self , name , * args , word_count = None , * * kwargs ) :
return self . _send_helper ( name , word_count , args , kwargs )
2013-10-17 19:15:40 -07:00
def __getattr__ ( self , name ) :
2014-11-30 14:27:10 -08:00
try :
if name . endswith ( ' _request ' ) :
short_name = name [ : - 8 ]
if short_name not in self . schema . method_names_inherited :
raise AttributeError ( ' Method named %s not found ' % short_name )
return _partial ( self . _request , short_name )
if name not in self . schema . method_names_inherited :
raise AttributeError ( ' Method named %s not found ' % name )
return _partial ( self . _send , name )
except KjException as e :
raise e . _to_python ( )
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 ) :
2014-04-18 18:18:54 -07:00
if self . _cached_schema is None :
self . _cached_schema = _InterfaceSchema ( ) . _init ( self . thisptr . getSchema ( ) )
return self . _cached_schema
2013-11-12 20:28:23 -08:00
2013-11-13 10:58:16 -08:00
def __dir__ ( self ) :
2014-06-12 16:44:41 -07:00
return list ( self . schema . method_names_inherited )
2013-11-13 10:58:16 -08:00
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 )
2013-12-10 22:57:21 -08:00
cdef class _Restorer :
2013-11-12 15:32:23 -08:00
cdef PyRestorer * thisptr
2013-12-10 23:29:21 -08:00
cdef public object restore , _parent
2013-11-12 15:32:23 -08:00
2013-12-10 23:29:21 -08:00
def __init__ ( self , restore , parent = None ) :
2013-12-10 22:57:21 -08:00
self . thisptr = new PyRestorer ( < PyObject * > self )
self . restore = restore
2013-12-10 23:29:21 -08:00
self . _parent = parent
2013-11-12 15:32:23 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2013-12-10 22:57:21 -08:00
def _restore ( self , obj ) :
return self . restore ( obj )
2013-11-12 15:32:23 -08:00
cdef class _TwoPartyVatNetwork :
2013-11-13 12:21:48 -08:00
cdef Own [C_TwoPartyVatNetwork ] thisptr
2014-02-24 14:06:28 -08:00
cdef _AsyncIoStream stream
2013-11-12 15:32:23 -08:00
2014-02-24 14:06:28 -08:00
cdef _init ( self , _AsyncIoStream stream , Side side ) :
2014-01-08 16:18:10 -08:00
self . stream = stream
self . thisptr = makeTwoPartyVatNetwork ( deref ( stream . thisptr ) , side )
2013-11-12 15:32:23 -08:00
return self
2013-12-11 22:25:57 -08:00
cpdef on_disconnect ( self ) except + reraise_kj_exception :
return _VoidPromise ( ) . _init ( deref ( self . thisptr ) . onDisconnect ( ) , self )
2013-12-10 22:57:21 -08:00
cdef _Restorer _convert_restorer ( restorer ) :
if isinstance ( restorer , _RestorerImpl ) :
2013-12-10 23:29:21 -08:00
return _Restorer ( restorer . _restore , restorer )
2013-12-10 22:57:21 -08:00
elif type ( restorer ) is _Restorer :
return restorer
elif hasattr ( restorer , ' restore ' ) :
2013-12-10 23:29:21 -08:00
return _Restorer ( restorer . restore , restorer )
2013-12-10 22:57:21 -08:00
elif callable ( restorer ) :
return _Restorer ( restorer )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Restorer object ({}) isn ' t able to be used as a restore " . format ( str ( restorer ) ) )
2013-12-10 22:57:21 -08:00
cdef class TwoPartyClient :
2013-11-12 15:32:23 -08:00
cdef RpcSystem * thisptr
2013-12-12 00:02:32 -08:00
cdef public _TwoPartyVatNetwork _network
cdef public object _orig_stream
cdef public _Restorer _restorer
2014-02-24 14:06:28 -08:00
cdef public _AsyncIoStream _stream
2013-11-12 15:32:23 -08:00
2013-12-12 11:33:52 -08:00
def __init__ ( self , socket , restorer = None ) :
if isinstance ( socket , basestring ) :
socket = self . _connect ( socket )
self . _orig_stream = socket
self . _stream = _FdAsyncIoStream ( socket . fileno ( ) )
2014-01-08 16:18:10 -08:00
self . _network = _TwoPartyVatNetwork ( ) . _init ( self . _stream , capnp . CLIENT )
2013-11-13 10:58:16 -08:00
if restorer is None :
2013-12-12 00:02:32 -08:00
self . thisptr = new RpcSystem ( makeRpcClient ( deref ( self . _network . thisptr ) ) )
self . _restorer = None
2013-11-13 10:58:16 -08:00
else :
2013-12-12 00:02:32 -08:00
self . _restorer = _convert_restorer ( restorer )
self . thisptr = new RpcSystem ( makeRpcClientWithRestorer ( deref ( self . _network . thisptr ) , deref ( self . _restorer . thisptr ) ) )
2013-12-11 22:25:57 -08:00
2014-02-13 22:25:25 -08:00
Py_INCREF ( self . _restorer )
Py_INCREF ( self . _orig_stream )
Py_INCREF ( self . _stream )
Py_INCREF ( self . _network ) # TODO:MEMORY: attach this to onDrained, also figure out what's leaking
2013-11-12 15:32:23 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2013-12-12 11:33:52 -08:00
cpdef _connect ( self , host_string ) :
host , port = host_string . split ( ' : ' )
sock = _socket . create_connection ( ( host , port ) )
# Set TCP_NODELAY on socket to disable Nagle's algorithm. This is not
# neccessary, but it speeds things up.
sock . setsockopt ( _socket . IPPROTO_TCP , _socket . TCP_NODELAY , 1 )
return sock
2013-11-13 17:53:34 -08:00
cpdef restore ( self , objectId ) except + reraise_kj_exception :
2014-09-10 10:48:23 -07:00
cdef _MessageBuilder builder
2013-11-12 19:38:34 -08:00
cdef _MessageReader reader
2013-12-09 19:18:54 -08:00
cdef _DynamicObjectBuilder object_builder
cdef _DynamicObjectReader object_reader
2014-04-09 17:06:34 -07:00
if objectId is None :
return _CapabilityClient ( ) . _init ( helpers . restoreHelper ( deref ( self . thisptr ) ) , self )
elif type ( objectId ) is _DynamicObjectBuilder :
2013-12-09 19:18:54 -08:00
object_builder = objectId
return _CapabilityClient ( ) . _init ( helpers . restoreHelper ( deref ( self . thisptr ) , deref ( object_builder . thisptr ) ) , self )
elif type ( objectId ) is _DynamicObjectReader :
object_reader = objectId
return _CapabilityClient ( ) . _init ( helpers . restoreHelper ( deref ( self . thisptr ) , object_reader . thisptr ) , self )
2013-11-13 10:58:16 -08:00
else :
2013-12-09 19:18:54 -08:00
if not hasattr ( objectId , ' is_root ' ) :
2014-11-30 14:27:10 -08:00
raise KjException ( " objectId was not a valid Cap ' n Proto struct " )
2013-12-09 19:18:54 -08:00
if not objectId . is_root :
2014-11-30 14:27:10 -08:00
raise KjException ( " objectId must be the root of a Cap ' n Proto message, ie. addressbook_capnp.Person.new_message() " )
2013-12-09 19:18:54 -08:00
try :
builder = objectId . _parent
except :
reader = objectId . _parent
if builder is not None :
return _CapabilityClient ( ) . _init ( helpers . restoreHelper ( deref ( self . thisptr ) , deref ( builder . thisptr ) ) , self )
elif reader is not None :
return _CapabilityClient ( ) . _init ( helpers . restoreHelper ( deref ( self . thisptr ) , deref ( reader . thisptr ) ) , self )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " objectId unexpectedly was not convertible to the proper type " )
2013-11-12 15:32:23 -08:00
2013-12-09 21:30:27 -08:00
cpdef ez_restore ( self , textId ) except + reraise_kj_exception :
2013-12-11 11:59:43 -08:00
# ez-rpc from the C++ API uses Text under the hood
ref = _MallocMessageBuilder ( ) . get_root_as_any ( )
2013-12-09 21:30:27 -08:00
# objectId is an AnyPointer, so we have a special method for setting it to text
2013-12-11 11:59:43 -08:00
ref . set_as_text ( textId )
2013-12-09 21:30:27 -08:00
2013-12-11 11:59:43 -08:00
return self . restore ( ref )
2013-12-09 21:30:27 -08:00
2014-02-13 22:08:26 -08:00
cpdef on_disconnect ( self ) except + reraise_kj_exception :
return _VoidPromise ( ) . _init ( deref ( self . _network . thisptr ) . onDisconnect ( ) )
2013-12-10 22:57:21 -08:00
cdef class TwoPartyServer :
2013-11-12 15:32:23 -08:00
cdef RpcSystem * thisptr
2013-12-12 00:02:32 -08:00
cdef public _TwoPartyVatNetwork _network
2014-02-13 22:08:26 -08:00
cdef public object _orig_stream , _server_socket , _disconnect_promise
2013-12-12 00:02:32 -08:00
cdef public _Restorer _restorer
2014-02-24 14:06:28 -08:00
cdef public _AsyncIoStream _stream
2014-02-13 22:08:26 -08:00
cdef object _port
cdef public object port_promise
cdef capnp .TaskSet * _task_set
cdef capnp .ErrorHandler _error_handler
2013-11-12 15:32:23 -08:00
2013-12-12 11:33:52 -08:00
def __init__ ( self , socket , restorer , server_socket = None ) :
2014-02-13 22:08:26 -08:00
self . _restorer = _convert_restorer ( restorer )
2013-12-12 11:33:52 -08:00
if isinstance ( socket , basestring ) :
self . _connect ( socket )
else :
self . _orig_stream = socket
self . _stream = _FdAsyncIoStream ( socket . fileno ( ) )
self . _server_socket = server_socket
2014-02-13 22:08:26 -08:00
self . _port = 0
self . _network = _TwoPartyVatNetwork ( ) . _init ( self . _stream , capnp . SERVER )
self . thisptr = new RpcSystem ( makeRpcServer ( deref ( self . _network . thisptr ) , deref ( self . _restorer . thisptr ) ) )
2013-12-11 22:25:57 -08:00
2014-02-13 22:08:26 -08:00
Py_INCREF ( self . _orig_stream )
Py_INCREF ( self . _stream )
Py_INCREF ( self . _restorer )
Py_INCREF ( self . _network )
self . _disconnect_promise = self . on_disconnect ( ) . then ( self . _decref )
2013-11-12 15:32:23 -08:00
2013-12-12 11:33:52 -08:00
cpdef _connect ( self , host_string ) :
2014-02-13 22:08:26 -08:00
cdef _EventLoop loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
cdef capnp .StringPtr temp_string = capnp . StringPtr ( < char * > host_string , len ( host_string ) )
self . _task_set = new capnp . TaskSet ( self . _error_handler )
self . port_promise = Promise ( ) . _init ( helpers . connectServer ( deref ( self . _task_set ) , deref ( self . _restorer . thisptr ) , loop . thisptr , temp_string ) )
2013-12-12 11:33:52 -08:00
2014-02-13 22:08:26 -08:00
def _decref ( self ) :
Py_DECREF ( self . _restorer )
Py_DECREF ( self . _orig_stream )
Py_DECREF ( self . _stream )
Py_DECREF ( self . _network )
2013-12-12 11:33:52 -08:00
2013-11-12 15:32:23 -08:00
def __dealloc__ ( self ) :
del self . thisptr
2014-02-13 22:08:26 -08:00
del self . _task_set
2013-11-12 15:32:23 -08:00
2013-12-12 11:33:52 -08:00
cpdef on_disconnect ( self ) except + reraise_kj_exception :
return _VoidPromise ( ) . _init ( deref ( self . _network . thisptr ) . onDisconnect ( ) )
cpdef run_forever ( self ) :
2014-02-13 22:08:26 -08:00
if self . port_promise is None :
2014-11-30 14:27:10 -08:00
raise KjException ( " You must pass a string as the socket parameter in __init__ to use this function " )
2013-12-12 11:33:52 -08:00
2014-02-13 22:08:26 -08:00
wait_forever ( )
property port :
def __get__ ( self ) :
if self . _port is None :
self . _port = self . port_promise . wait ( )
return self . _port
else :
return self . _port
2013-12-12 11:33:52 -08:00
2013-11-13 17:53:34 -08:00
# TODO: add restore functionality here?
2014-02-24 14:06:28 -08:00
cdef class _AsyncIoStream :
2013-11-12 19:38:34 -08:00
cdef Own [AsyncIoStream ] thisptr
2014-02-24 14:06:28 -08:00
cdef class _FdAsyncIoStream ( _AsyncIoStream ) :
2014-01-08 16:18:10 -08:00
cdef _EventLoop _event_loop
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 :
2014-01-08 16:18:10 -08:00
self . _event_loop = C_DEFAULT_EVENT_LOOP_GETTER ( )
self . thisptr = self . _event_loop . wrapSocketFd ( fd )
2013-11-12 15:32:23 -08:00
2014-02-24 14:06:28 -08:00
cdef class PyAsyncIoStream ( _AsyncIoStream ) :
def __init__ ( self , int fd ) :
pass
2013-11-13 17:53:34 -08:00
cdef class PromiseFulfillerPair :
cdef Own [C_PromiseFulfillerPair ] thisptr
cdef public bint is_consumed
2013-12-08 15:52:03 -08:00
cdef public _VoidPromise promise
2013-11-13 17:53:34 -08:00
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-12-08 15:52:03 -08:00
self . promise = _VoidPromise ( ) . _init ( moveVoidPromise ( deref ( self . thisptr ) . promise ) )
2013-09-18 17:19:57 -07:00
2013-11-14 20:59:21 -08:00
cpdef fulfill ( self ) :
2013-12-08 15:52:03 -08:00
deref ( deref ( self . thisptr ) . fulfiller ) . fulfill ( )
2013-11-14 20:59:21 -08:00
2013-08-26 15:07:13 -07:00
cdef class _Schema :
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 ( ) )
2014-02-05 15:32:14 -08:00
cpdef as_enum ( self ) :
return _EnumSchema ( ) . _init ( self . thisptr . asEnum ( ) )
2013-09-01 20:10:57 -07:00
cpdef get_dependency ( self , id ) :
2014-10-19 22:45:08 -07:00
' .. warning:: This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream '
_warnings . warn ( ' This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream ' , UserWarning )
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
2014-09-03 23:25:39 -07:00
cdef object __fieldnames , __union_fields , __non_union_fields , __fields , __getters
cdef list __fields_list
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
2014-09-03 15:20:26 -07:00
self . __fields = None
2014-09-03 23:25:39 -07:00
self . __fields_list = None
self . __getters = 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
2014-09-03 15:20:26 -07:00
property fields :
2014-09-03 23:25:39 -07:00
"""All of the _StructSchemaField in this schema as a dict"""
2014-09-03 15:20:26 -07:00
def __get__ ( self ) :
if self . __fields is not None :
return self . __fields
fieldlist = self . thisptr . getFields ( )
nfields = fieldlist . size ( )
self . __fields = { < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( ) : _StructSchemaField ( ) . _init ( fieldlist [ i ] , self )
for i in xrange ( nfields ) }
return self . __fields
2014-09-03 23:25:39 -07:00
property fields_list :
"""All of the _StructSchemaField in this schema as a list"""
def __get__ ( self ) :
if self . __fields_list is not None :
return self . __fields_list
fieldlist = self . thisptr . getFields ( )
nfields = fieldlist . size ( )
self . __fields_list = [ _StructSchemaField ( ) . _init ( fieldlist [ i ] , self )
for i in xrange ( nfields ) ]
return self . __fields_list
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 ) :
2014-10-19 22:45:08 -07:00
' .. warning:: This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream '
_warnings . warn ( ' This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream ' , UserWarning )
2013-11-13 12:02:43 -08:00
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
2014-11-19 02:04:57 -08:00
cdef typeAsSchema ( capnp . SchemaType fieldType ) :
# TODO(soon): make sure this is memory safe
if fieldType . isInterface ( ) :
return _InterfaceSchema ( ) . _init ( fieldType . asInterface ( ) )
elif fieldType . isStruct ( ) :
return _StructSchema ( ) . _init ( fieldType . asStruct ( ) )
elif fieldType . isEnum ( ) :
return _EnumSchema ( ) . _init ( fieldType . asEnum ( ) )
elif fieldType . isList ( ) :
return ListSchema ( ) . _init ( fieldType . asList ( ) )
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Schema type is unknown " )
2014-11-19 02:04:57 -08:00
2014-02-13 19:24:06 -08:00
cdef class _StructSchemaField :
cdef _init ( self , C_StructSchema . Field other , parent = None ) :
self . thisptr = other
self . _parent = parent
return self
property proto :
"""The raw schema proto"""
def __get__ ( self ) :
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , self )
2014-10-19 22:45:08 -07:00
property schema :
"""The schema of this field, or None if it's a type without a schema"""
def __get__ ( self ) :
2014-11-19 02:04:57 -08:00
return typeAsSchema ( self . thisptr . getType ( ) )
2014-10-19 22:45:08 -07:00
2014-02-13 19:24:06 -08:00
def __repr__ ( self ) :
return ' <field schema for %s > ' % self . proto . name
2014-10-19 22:45:08 -07:00
cdef class _InterfaceMethod :
cdef C_InterfaceSchema .Method thisptr
cdef _init ( self , C_InterfaceSchema . Method other ) :
self . thisptr = other
return self
2013-10-15 13:29:54 -07:00
2014-10-19 22:45:08 -07:00
property param_type :
"""The type of this method's parameter struct"""
def __get__ ( self ) :
# TODO(soon): make sure this is memory safe
return _StructSchema ( ) . _init ( self . thisptr . getParamType ( ) )
2013-10-15 13:29:54 -07:00
cdef class _InterfaceSchema :
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
2014-04-18 18:18:54 -07:00
property method_names_inherited :
"""A set of the function names in the interface, including inherited methods"""
def __get__ ( self ) :
2014-10-19 22:45:08 -07:00
if self . __method_names_inherited is not None :
return self . __method_names_inherited
2014-04-18 18:18:54 -07:00
fieldlist = self . thisptr . getMethods ( )
nfields = fieldlist . size ( )
2014-10-19 22:45:08 -07:00
self . __method_names_inherited = set ( < char * > fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( )
2014-04-18 18:18:54 -07:00
for i in xrange ( nfields ) )
2014-10-19 21:34:46 -07:00
for interface in self . superclasses :
2014-10-19 22:45:08 -07:00
self . __method_names_inherited | = interface . method_names_inherited
2014-04-18 18:18:54 -07:00
2014-10-19 22:45:08 -07:00
return self . __method_names_inherited
property methods :
"""A mapping of method names to their respective _InterfaceMethod"""
def __get__ ( self ) :
if self . __methods is not None :
return self . __methods
fieldlist = self . thisptr . getMethods ( )
nfields = fieldlist . size ( )
# TODO(soon): make sure this is memory safe
self . __methods = { fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( ) : _InterfaceMethod ( ) . _init ( fieldlist [ i ] )
for i in xrange ( nfields ) }
return self . __methods
property methods_inherited :
"""A mapping of method names to their respective _InterfaceMethod, including inherited methods"""
def __get__ ( self ) :
if self . __methods_inherited is not None :
return self . __methods_inherited
fieldlist = self . thisptr . getMethods ( )
nfields = fieldlist . size ( )
# TODO(soon): make sure this is memory safe
self . __methods_inherited = { fieldlist [ i ] . getProto ( ) . getName ( ) . cStr ( ) : _InterfaceMethod ( ) . _init ( fieldlist [ i ] )
for i in xrange ( nfields ) }
for interface in self . superclasses :
self . __methods_inherited . update ( interface . methods_inherited )
return self . __methods_inherited
2014-04-18 18:18:54 -07:00
2014-10-19 21:34:46 -07:00
property superclasses :
"""A list of superclasses for this interface"""
2014-04-18 18:18:54 -07:00
def __get__ ( self ) :
2014-10-19 22:45:08 -07:00
cdef C_InterfaceSchema .SuperclassList classes = self . thisptr . getSuperclasses ( )
2014-10-19 21:34:46 -07:00
return [ _InterfaceSchema ( ) . _init ( classes [ i ] ) for i in range ( classes . size ( ) ) ]
2014-04-18 18:18:54 -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 ) :
2014-10-19 22:45:08 -07:00
' .. warning:: This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream '
_warnings . warn ( ' This method is deprecated and will be removed in the 0.6 release. You can access the fields directly from the schema now, so this method is superfluous and deprecated upstream ' , UserWarning )
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
2014-02-05 15:32:14 -08:00
cdef class _EnumSchema :
cdef C_EnumSchema thisptr
cdef _init ( self , C_EnumSchema other ) :
self . thisptr = other
return self
property enumerants :
"""The list of enumerants as a dictionary"""
def __get__ ( self ) :
ret = { }
enumerants = self . thisptr . getEnumerants ( )
for i in range ( enumerants . size ( ) ) :
enumerant = enumerants [ i ]
ret [ < char * > enumerant . getProto ( ) . getName ( ) . cStr ( ) ] = enumerant . getOrdinal ( )
return ret
property node :
"""The raw schema node"""
def __get__ ( self ) :
return _DynamicStructReader ( ) . _init ( self . thisptr . getProto ( ) , self )
2014-11-20 10:24:10 -08:00
cdef class _SchemaType :
cdef capnp .SchemaType thisptr
types = _ModuleType ( ' capnp.types ' )
cdef _SchemaType _void = _SchemaType ( )
_void . thisptr = capnp . SchemaType ( capnp . TypeWhichVOID )
types . Void = _void
cdef _SchemaType _bool = _SchemaType ( )
_bool . thisptr = capnp . SchemaType ( capnp . TypeWhichBOOL )
types . Bool = _bool
cdef _SchemaType _int8 = _SchemaType ( )
_int8 . thisptr = capnp . SchemaType ( capnp . TypeWhichINT8 )
types . Int8 = _int8
cdef _SchemaType _int16 = _SchemaType ( )
_int16 . thisptr = capnp . SchemaType ( capnp . TypeWhichINT16 )
types . Int16 = _int16
cdef _SchemaType _int32 = _SchemaType ( )
_int32 . thisptr = capnp . SchemaType ( capnp . TypeWhichINT32 )
types . Int32 = _int32
cdef _SchemaType _int64 = _SchemaType ( )
_int64 . thisptr = capnp . SchemaType ( capnp . TypeWhichINT64 )
types . Int64 = _int64
cdef _SchemaType _uint8 = _SchemaType ( )
_uint8 . thisptr = capnp . SchemaType ( capnp . TypeWhichUINT8 )
types . UInt8 = _uint8
cdef _SchemaType _uint16 = _SchemaType ( )
_uint16 . thisptr = capnp . SchemaType ( capnp . TypeWhichUINT16 )
types . UInt16 = _uint16
cdef _SchemaType _uint32 = _SchemaType ( )
_uint32 . thisptr = capnp . SchemaType ( capnp . TypeWhichUINT32 )
types . UInt32 = _uint32
cdef _SchemaType _uint64 = _SchemaType ( )
_uint64 . thisptr = capnp . SchemaType ( capnp . TypeWhichUINT64 )
types . UInt64 = _uint64
cdef _SchemaType _float32 = _SchemaType ( )
_float32 . thisptr = capnp . SchemaType ( capnp . TypeWhichFLOAT32 )
types . Float32 = _float32
cdef _SchemaType _float64 = _SchemaType ( )
_float64 . thisptr = capnp . SchemaType ( capnp . TypeWhichFLOAT64 )
types . Float64 = _float64
cdef _SchemaType _text = _SchemaType ( )
_text . thisptr = capnp . SchemaType ( capnp . TypeWhichTEXT )
types . Text = _text
cdef _SchemaType _data = _SchemaType ( )
_data . thisptr = capnp . SchemaType ( capnp . TypeWhichDATA )
types . Data = _data
# cdef _SchemaType _list = _SchemaType()
# _list.thisptr = capnp.SchemaType(capnp.TypeWhichLIST)
# types.list = _list
cdef _SchemaType _enum = _SchemaType ( )
_enum . thisptr = capnp . SchemaType ( capnp . TypeWhichENUM )
types . Enum = _enum
# cdef _SchemaType _struct = _SchemaType()
# _struct.thisptr = capnp.SchemaType(capnp.TypeWhichSTRUCT)
# types.struct = _struct
# cdef _SchemaType _interface = _SchemaType()
# _interface.thisptr = capnp.SchemaType(capnp.TypeWhichINTERFACE)
# types.interface = _interface
cdef _SchemaType _any_pointer = _SchemaType ( )
_any_pointer . thisptr = capnp . SchemaType ( capnp . TypeWhichANY_POINTER )
types . AnyPointer = _any_pointer
2014-11-19 02:04:57 -08:00
cdef class ListSchema :
cdef C_ListSchema thisptr
2014-11-19 02:19:21 -08:00
def __init__ ( self , schema = None ) :
cdef _StructSchema ss
cdef _EnumSchema es
cdef _InterfaceSchema iis
cdef ListSchema ls
2014-11-20 10:24:10 -08:00
cdef _SchemaType st
2014-11-19 02:19:21 -08:00
if schema is not None :
if hasattr ( schema , ' schema ' ) :
s = schema . schema
else :
s = schema
typeSchema = type ( s )
if typeSchema is _StructSchema :
ss = s
self . thisptr = capnp . listSchemaOfStruct ( ss . thisptr )
elif typeSchema is _EnumSchema :
es = s
self . thisptr = capnp . listSchemaOfEnum ( es . thisptr )
elif typeSchema is _InterfaceSchema :
iis = s
self . thisptr = capnp . listSchemaOfInterface ( iis . thisptr )
elif typeSchema is ListSchema :
ls = s
self . thisptr = capnp . listSchemaOfList ( ls . thisptr )
2014-11-20 10:24:10 -08:00
elif typeSchema is _SchemaType :
st = s
self . thisptr = capnp . listSchemaOfType ( st . thisptr )
2014-11-19 02:19:21 -08:00
else :
2014-11-30 14:27:10 -08:00
raise KjException ( " Unknown schema type " )
2014-11-19 02:19:21 -08:00
2014-11-19 02:04:57 -08:00
cdef _init ( self , C_ListSchema other ) :
self . thisptr = other
return self
property elementType :
"""The schema of the element type of this list"""
def __get__ ( self ) :
return typeAsSchema ( self . thisptr . getElementType ( ) )
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
2014-02-28 13:36:38 -08:00
cdef _new_message ( self , kwargs , num_first_segment_words ) :
builder = _MallocMessageBuilder ( num_first_segment_words )
2013-11-14 23:06:14 -08:00
msg = builder . init_root ( self . schema )
if kwargs is not None :
2014-10-19 20:06:00 -07:00
msg . from_dict ( kwargs )
2013-11-14 23:06:14 -08:00
return msg
2013-12-10 22:57:21 -08:00
class _RestorerImpl ( object ) :
pass
2014-02-13 19:24:06 -08:00
class _StructModuleWhich ( object ) :
pass
2013-11-14 20:59:21 -08:00
class _StructModule ( object ) :
2013-12-10 22:57:21 -08:00
def __init__ ( self , schema , name ) :
def _restore ( self , obj ) :
return self . restore ( obj . as_struct ( self . schema ) )
2013-11-14 11:30:57 -08:00
self . schema = schema
2014-02-13 19:24:06 -08:00
2013-12-10 22:57:21 -08:00
self . Restorer = type ( name + ' .Restorer ' , ( _RestorerImpl , ) , { ' schema ' : schema , ' _restore ' : _restore } )
2013-11-14 11:30:57 -08:00
2014-02-13 19:24:06 -08:00
# Add enums for union fields
2014-10-19 22:45:08 -07:00
for field , raw_field in zip ( schema . node . struct . fields , schema . fields_list ) :
2014-02-13 19:24:06 -08:00
if field . which ( ) == ' group ' :
2014-10-19 20:06:00 -07:00
name = field . name [ 0 ] . upper ( ) + field . name [ 1 : ]
2014-10-19 22:45:08 -07:00
raw_schema = raw_field . schema
2014-10-19 20:06:00 -07:00
field_schema = raw_schema . node . struct
if field_schema . discriminantCount == 0 :
sub_module = _StructModule ( raw_schema , name )
else :
sub_module = _StructModuleWhich ( )
2014-10-19 22:45:08 -07:00
setattr ( sub_module , ' schema ' , raw_schema )
2014-10-19 20:06:00 -07:00
for union_field in field_schema . fields :
setattr ( sub_module , union_field . name , union_field . discriminantValue )
setattr ( self , name , sub_module )
2014-02-13 19:24:06 -08:00
2013-11-14 11:30:57 -08:00
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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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
2015-01-28 16:08:47 -08:00
def read_multiple_bytes ( self , buf , traversal_limit_in_words = None , nesting_limit = None ) :
""" Returns an iterable, that when traversed will return Readers for messages.
: type buf : buffer
: 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.
: rtype : Iterable with elements of : class : `_DynamicStructReader` """
reader = _MultipleBytesMessageReader ( buf , self . schema , traversal_limit_in_words , nesting_limit )
return reader
def read_multiple_bytes_packed ( self , buf , traversal_limit_in_words = None , nesting_limit = None ) :
""" Returns an iterable, that when traversed will return Readers for messages.
: type buf : buffer
: 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.
: rtype : Iterable with elements of : class : `_DynamicStructReader` """
reader = _MultipleBytesPackedMessageReader ( buf , self . schema , traversal_limit_in_words , nesting_limit )
return reader
2013-11-14 11:30:57 -08:00
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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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 :
2014-02-27 18:16:56 -08:00
# message = _FlatMessageBuilder(buf)
message = _FlatArrayMessageReader ( buf , traversal_limit_in_words , nesting_limit )
return message . get_root ( self . schema ) . as_builder ( )
2013-11-14 11:30:57 -08:00
else :
message = _FlatArrayMessageReader ( buf , traversal_limit_in_words , nesting_limit )
2014-02-27 18:16:56 -08:00
return message . get_root ( self . schema )
2013-11-14 11:30:57 -08:00
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 .
2014-09-10 10:48:23 -07:00
2013-11-14 23:06:14 -08:00
: 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 )
2014-02-28 13:36:38 -08:00
def new_message ( self , num_first_segment_words = None , * * kwargs ) :
2013-11-14 23:06:14 -08:00
""" Returns a newly allocated builder message.
2014-02-28 13:36:38 -08:00
: type num_first_segment_words : int
: param num_first_segment_words : Size of the first segment to allocate in the message ( in words ie . 8 byte increments )
2013-11-14 23:06:14 -08:00
: type kwargs : dict
2014-02-28 13:36:38 -08:00
: param kwargs : A list of fields and their values to initialize in the struct . Note , this is not an actual argument , but refers to Python ' s ability to pass keyword arguments. ie. new_message(my_field=100)
2013-11-14 23:06:14 -08:00
: rtype : : class : `_DynamicStructBuilder`
"""
2014-02-28 13:36:38 -08:00
return _new_message ( self , kwargs , num_first_segment_words )
2013-11-14 23:06:14 -08:00
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 )
2014-02-28 13:36:38 -08:00
return _new_message ( self , kwargs , None )
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 ) :
2013-12-09 17:13:43 -08:00
def __init__ ( self , schema , name ) :
def server_init ( server_self ) :
pass
2013-11-14 20:59:21 -08:00
self . schema = schema
2013-12-10 22:57:21 -08:00
self . Server = type ( name + ' .Server ' , ( _DynamicCapabilityServer , ) , { ' __init__ ' : server_init , ' schema ' : schema } )
2013-11-14 20:59:21 -08:00
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
2013-12-09 17:13:43 -08:00
def _new_server ( self , server ) :
2013-11-14 20:59:21 -08:00
return _DynamicCapabilityServer ( self . schema , server )
2014-02-05 15:32:14 -08:00
class _EnumModule ( object ) :
def __init__ ( self , schema , name ) :
self . schema = schema
for name , val in schema . enumerants . items ( ) :
setattr ( self , name , val )
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
2014-02-27 18:16:31 -08:00
cdef public dict modules_by_id
2013-08-13 22:21:38 -07:00
def __cinit__ ( self ) :
self . thisptr = new C_SchemaParser ( )
2014-02-27 18:16:31 -08:00
self . modules_by_id = { }
2013-08-13 22:21:38 -07:00
def __dealloc__ ( self ) :
del self . thisptr
2013-12-06 13:19:30 -08:00
cpdef _parse_disk_file ( self , displayName , diskPath , imports ) except + reraise_kj_exception :
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 = [ ] ) :
2014-09-10 10:48:23 -07:00
""" Load a Cap ' n Proto schema from a file
2013-08-29 21:03:00 -07:00
You will have to load a schema before you can begin doing anything
meaningful with this library . Loading a schema is much like loading
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
2014-11-30 14:27:10 -08:00
- : exc : `KjException` 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
2014-02-27 18:16:31 -08:00
self . modules_by_id [ nodeProto . id ] = module
2013-08-29 21:03:00 -07:00
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-12-10 22:57:21 -08:00
local_module = _StructModule ( schema . as_struct ( ) , node . name )
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-12-09 17:13:43 -08:00
local_module = _InterfaceModule ( schema . as_interface ( ) , node . name )
2013-08-29 21:03:00 -07:00
2014-02-05 15:32:14 -08:00
module . __dict__ [ node . name ] = local_module
elif proto . isEnum :
local_module = _EnumModule ( schema . as_enum ( ) , node . name )
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
2014-11-19 08:10:31 -08:00
module . schema = fileSchema
2013-09-01 22:24:46 -07:00
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-12-11 11:59:43 -08:00
cpdef get_root_as_any ( self ) except + reraise_kj_exception :
""" A method for getting a Cap ' n Proto AnyPointer, from an already pre-written buffer
Don ' t use this method unless you know what you ' re doing .
: rtype : : class : `_DynamicObjectBuilder`
: return : An AnyPointer that you can set fields in
"""
return _DynamicObjectBuilder ( ) . _init ( self . thisptr . getRootAnyPointer ( ) , self )
2014-09-10 10:48:23 -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
"""
2013-12-09 19:18:54 -08:00
value_type = type ( value )
if value_type is _DynamicStructBuilder :
self . thisptr . setRootDynamicStruct ( ( < _DynamicStructReader > value . as_reader ( ) ) . thisptr )
return self . get_root ( value . schema )
elif value_type is _DynamicStructReader :
self . thisptr . setRootDynamicStruct ( ( < _DynamicStructReader > value ) . thisptr )
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
"""
2014-02-28 13:36:38 -08:00
def __init__ ( self , size = None ) :
if size is None :
self . thisptr = new schema_cpp . MallocMessageBuilder ( )
else :
self . thisptr = new schema_cpp . MallocMessageBuilder ( size )
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.
"""
2015-01-30 13:39:58 -08:00
cdef public object _parent
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-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-12-11 13:51:13 -08:00
cpdef get_root_as_any ( self ) except + reraise_kj_exception :
""" A method for getting a Cap ' n Proto AnyPointer, from an already pre-written buffer
Don ' t use this method unless you know what you ' re doing .
: rtype : : class : `_DynamicObjectReader`
: return : An AnyPointer that you can read from
"""
return _DynamicObjectReader ( ) . _init ( self . thisptr . getRootAnyPointer ( ) , self )
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
"""
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
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
self . thisptr = new schema_cpp . PackedMessageReader ( stream , opts )
return self
cdef class _PackedMessageReaderBytes ( _MessageReader ) :
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
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
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 ) )
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
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
"""
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
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
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
2014-09-10 10:48:23 -07:00
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
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
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 )
2014-11-30 14:27:10 -08:00
except KjException as e :
2013-11-14 00:19:52 -08:00
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
2014-09-10 10:48:23 -07:00
2013-11-14 00:19:52 -08:00
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 )
2014-11-30 14:27:10 -08:00
except KjException as e :
2013-11-14 00:19:52 -08:00
if ' EOF ' in str ( e ) :
raise StopIteration
else :
raise
def __iter__ ( self ) :
return self
2015-01-28 16:08:47 -08:00
cdef class _MultipleBytesMessageReader :
cdef schema_cpp .ArrayInputStream * stream
cdef schema_cpp .BufferedInputStream * buffered_stream
cdef public object traversal_limit_in_words , nesting_limit , schema , buf
def __init__ ( self , buf , 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
cdef const void *ptr
cdef Py_ssize_t sz
PyObject_AsReadBuffer ( buf , & ptr , & sz )
self . buf = buf
self . stream = new schema_cpp . ArrayInputStream ( schema_cpp . ByteArrayPtr ( < byte * > ptr , sz ) )
self . buffered_stream = new schema_cpp . BufferedInputStreamWrapper ( deref ( self . stream ) )
def __dealloc__ ( self ) :
del self . buffered_stream
2015-01-30 13:39:58 -08:00
del self . stream
2015-01-28 16:08:47 -08:00
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 KjException as e :
if ' EOF ' in str ( e ) :
raise StopIteration
else :
raise
def __iter__ ( self ) :
return self
cdef class _MultipleBytesPackedMessageReader :
cdef schema_cpp .ArrayInputStream * stream
cdef schema_cpp .BufferedInputStream * buffered_stream
cdef public object traversal_limit_in_words , nesting_limit , schema , buf
def __init__ ( self , buf , 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
cdef const void *ptr
cdef Py_ssize_t sz
PyObject_AsReadBuffer ( buf , & ptr , & sz )
self . buf = buf
self . stream = new schema_cpp . ArrayInputStream ( schema_cpp . ByteArrayPtr ( < byte * > ptr , sz ) )
self . buffered_stream = new schema_cpp . BufferedInputStreamWrapper ( deref ( self . stream ) )
def __dealloc__ ( self ) :
del self . buffered_stream
2015-01-30 13:39:58 -08:00
del self . stream
2015-01-28 16:08:47 -08:00
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 KjException as e :
if ' EOF ' in str ( e ) :
raise StopIteration
else :
raise
def __iter__ ( self ) :
return self
2014-12-12 14:43:18 -08:00
@cython . internal
cdef class _AlignedBuffer :
cdef char * buf
cdef bint allocated
# other should also have a length that's a multiple of 8
def __init__ ( self , other ) :
2014-12-12 16:23:24 -08:00
cdef const void *ptr
cdef Py_ssize_t sz
PyObject_AsReadBuffer ( other , & ptr , & sz )
2014-12-12 14:43:18 -08:00
other_len = len ( other )
# malloc is defined as being word aligned
# we don't care about adding NULL terminating character
self . buf = < char * > malloc ( other_len )
2014-12-12 16:23:24 -08:00
memcpy ( self . buf , ptr , other_len )
2014-12-12 14:43:18 -08:00
self . allocated = True
def __dealloc__ ( self ) :
if self . allocated :
free ( self . buf )
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
2014-12-12 14:43:18 -08:00
cdef _AlignedBuffer aligned
2013-11-05 15:51:55 -08:00
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
2014-09-10 10:48:23 -07:00
2014-12-12 14:43:18 -08:00
sz = len ( buf )
2013-09-03 11:54:45 -07:00
if sz % 8 != 0 :
raise ValueError ( " input length must be a multiple of eight bytes " )
2014-12-12 14:43:18 -08:00
cdef char * ptr = buf
if ( < uintptr_t > ptr ) % 8 != 0 :
aligned = _AlignedBuffer ( buf )
ptr = aligned . buf
2014-12-12 16:23:24 -08:00
self . _object_to_pin = aligned
else :
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 :
2014-11-30 14:27:10 -08:00
raise KjException ( " input length must be a multiple of eight bytes " )
2013-09-20 14:35:35 -07:00
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 = [ ] ) :
2014-09-10 10:48:23 -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
2014-11-30 14:27:10 -08:00
: Raises : : exc : `KjException` if `file_name` doesn ' t exist
2013-08-26 10:07:54 -07:00
"""
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
2014-06-12 16:37:06 -07:00
has_underscores = False
if ' _ ' in capnp_module_name :
capnp_module_name_dashes = capnp_module_name . replace ( ' _ ' , ' - ' )
capnp_module_name_spaces = capnp_module_name . replace ( ' _ ' , ' ' )
has_underscores = True
2013-09-01 21:31:39 -07:00
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 )
2014-06-12 16:37:06 -07:00
2013-09-01 21:31:39 -07:00
if is_file ( path + sep + capnp_module_name ) :
return _Loader ( fullname , join_path ( path , capnp_module_name ) , self . additional_paths )
2014-06-12 16:37:06 -07:00
if has_underscores :
if is_file ( path + sep + capnp_module_name_dashes ) :
return _Loader ( fullname , join_path ( path , capnp_module_name_dashes ) , self . additional_paths )
if is_file ( path + sep + capnp_module_name_spaces ) :
return _Loader ( fullname , join_path ( path , capnp_module_name_spaces ) , self . additional_paths )
2013-09-01 21:31:39 -07:00
_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
2013-12-11 22:25:57 -08:00
After calling this function , you can use the python import syntax to directly import capnproto schemas . This function is automatically called upon first import of `capnp` , so you will typically never need to use this function . : :
2013-09-01 21:31:39 -07:00
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