A Quick Look At Rpclib Burak Arslan burak at arskom dot com dot tr March 10, 2012 1
What is Rpclib? Rpclib makes it convenient to expose your services using multiple protocols and/or transports. 2
What is Rpclib? It also forces you to have a well-defined api. 3
How? 4
Here’s a simple function: 5
Here’s a simple function: from datetime import datetime def g e t u t c t i m e ( ) : r e t u r n datetime . utcnow () 5
Now, to make this function remotely callable; 6
Now, to make this function remotely callable; 1) We wrap it in a ServiceBase subclass: 6
def g e t u t c t i m e ( ) : r e t u r n datetime . utcnow () 7
from r p c l i b . model . p r i m i t i v e import DateTime from r p c l i b . decorator import srpc from r p c l i b . s e r v i c e import ServiceBase def g e t u t c t i m e ( ) : r e t u r n datetime . utcnow () 7
from r p c l i b . model . p r i m i t i v e import DateTime from r p c l i b . decorator import srpc from r p c l i b . s e r v i c e import ServiceBase c l a s s DateTimeService ( ServiceBase ) : def g e t u t c t i m e ( ) : r e t u r n datetime . utcnow () 7
from r p c l i b . model . p r i m i t i v e import DateTime from r p c l i b . decorator import srpc from r p c l i b . s e r v i c e import ServiceBase c l a s s DateTimeService ( ServiceBase ) : @srpc ( r e t u r n s=DateTime ) def g e t u t c t i m e ( ) : r e t u r n datetime . utcnow () 7
2) Now, we have to wrap the service definition in an Application definition. 8
[ DateTimeService ] , 9
from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc httprpc = A p p l i c a t i o n ( [ DateTimeService ] , 9
from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc httprpc = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , 9
from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc httprpc = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , i n p r o t o c o l=HttpRpc () , o u t p r o t o c o l=HttpRpc () ) 9
3) Finally, we wrap the application in a transport. 10
from r p c l i b . s e r v e r . wsgi import WsgiApplication a p p l i c a t i o n = WsgiApplication ( httprpc ) This is now a regular WSGI Application that we can pass to WSGI-compliant servers like CherryPy, mod wsgi, Twisted, etc. 11
from r p c l i b . s e r v e r . wsgi import WsgiApplication a p p l i c a t i o n = WsgiApplication ( httprpc ) This is now a regular WSGI Application that we can pass to WSGI-compliant servers like CherryPy, mod wsgi, Twisted, etc. $ c u r l http :// l o c a l h o s t :9910/ g e t u t c t i m e 2012 − 03 − 09T17 :38:11.997784 11
Now, what if we wanted to expose this function using another protocol? 12
For example: SOAP from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc from r p c l i b . p r o t o c o l . soap import Soap11 soap = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , i n p r o t o c o l=HttpRpc () , o u t p r o t o c o l= Soap11 () ) 13
For example: SOAP $ c u r l http :// l o c a l h o s t :9910/ g e t u t c t i m e \ | t i d y − xml − indent < ?xml v e r s i o n= ’1.0 ’ encoding= ’utf -8’ ? > < s e n v : E n v e l o p e xmlns:wsa= "http: // schemas.xmlsoap.org/ws /2003/03/ addressing" x m l n s : t n s= "rpclib.examples. multiple_protocols " x m l n s : p l i n k= "http: // schemas.xmlsoap.org/ws /2003/05/ partner -link/" xmlns:xop= "http: // www.w3.org /2004/08/ xop/include" xmlns:senc= "http: // schemas.xmlsoap.org/soap/encoding/" xmlns:s12env= "http: // www.w3.org /2003/05/ soap -envelope/" xmlns:s12enc= "http: // www.w3.org /2003/05/ soap -encoding/" x m l n s : x s= "http: // www.w3.org /2001/ XMLSchema" xmlns:wsdl= "http: // schemas.xmlsoap.org/wsdl/" x m l n s : x s i= "http: // www.w3.org /2001/ XMLSchema -instance" xmlns:senv= "http: // schemas.xmlsoap.org/soap/envelope/" xmlns:soap= "http: // schemas.xmlsoap.org/wsdl/soap/" > < senv:Body > < t n s : g e t u t c t i m e R e s p o n s e > < t n s : g e t u t c t i m e R e s u l t > 2012 − 03 − 06T17:43:30 .894466 < / t n s : g e t u t c t i m e R e s u l t > < / t n s : g e t u t c t i m e R e s p o n s e > < / senv:Body > < / s e n v : E n v e l o p e > 14
Or, just XML: from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc from r p c l i b . p r o t o c o l . xml import XmlObject xml = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , i n p r o t o c o l=HttpRpc () , o u t p r o t o c o l= XmlObject () ) 15
Or, just XML: $ c u r l http :// l o c a l h o s t :9910/ g e t u t c t i m e \ | t i d y − xml − indent < ?xml v e r s i o n= ’1.0’ encoding= ’utf-8’ ? > < ns0:get utc timeResponse xmlns:ns0= "rpclib.examples.multiple_protocols" > < n s 0 : g e t u t c t i m e R e s u l t > 2012 − 03 − 06 T17:49:08 .922501 < / n s 0 : g e t u t c t i m e R e s u l t > < / ns0:get utc timeResponse > 16
Or, HTML: from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n from r p c l i b . p r o t o c o l . http import HttpRpc from r p c l i b . p r o t o c o l . xml import HtmlMicroFormat html = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , i n p r o t o c o l=HttpRpc () , o u t p r o t o c o l= HtmlMicroFormat () ) 17
Or, HTML: $ c u r l http :// l o c a l h o s t :9910/ g e t u t c t i m e \ | t i d y − xml − indent < div c l a s s= "get_utc_timeResponse" > < div c l a s s= "get_utc_timeResult" > 2012 − 03 − 06T17 :52:50.234246 < / div > < / div > 18
etc... 19
Rpclib also makes it easy to implement custom protocols. 20
Let’s implement an output protocol that renders the datetime value as an analog clock. (without going into much detail � ) 21
To do that, we need to implement the serialize and create out string functions in a ProtocolBase subclass. 22
from r p c l i b . p r o t o c o l import ProtocolBase c l a s s SvgClock ( ProtocolBase ) : mime type = ’image/svg+xml’ 23
from r p c l i b . p r o t o c o l import ProtocolBase c l a s s SvgClock ( ProtocolBase ) : mime type = ’image/svg+xml’ def s e r i a l i z e ( s e l f , ctx , message ) : d = ctx . o u t o b j e c t [ 0 ] # the r e t u r n value 23
from r p c l i b . p r o t o c o l import ProtocolBase c l a s s SvgClock ( ProtocolBase ) : mime type = ’image/svg+xml’ def s e r i a l i z e ( s e l f , ctx , message ) : d = ctx . o u t o b j e c t [ 0 ] # the r e t u r n value # ( some math and b o i l e r p l a t e suppressed ) 23
from r p c l i b . p r o t o c o l import ProtocolBase c l a s s SvgClock ( ProtocolBase ) : mime type = ’image/svg+xml’ def s e r i a l i z e ( s e l f , ctx , message ) : d = ctx . o u t o b j e c t [ 0 ] # the r e t u r n value # ( some math and b o i l e r p l a t e suppressed ) # clock i s a svg f i l e parsed as lxml Element ctx . out document = clock 23
from r p c l i b . p r o t o c o l import ProtocolBase c l a s s SvgClock ( ProtocolBase ) : mime type = ’image/svg+xml’ def s e r i a l i z e ( s e l f , ctx , message ) : d = ctx . o u t o b j e c t [ 0 ] # the r e t u r n value # ( some math and b o i l e r p l a t e suppressed ) # clock i s a svg f i l e parsed as lxml Element ctx . out document = clock def c r e a t e o u t s t r i n g ( s e l f , ctx , c h a r s e t=None ) : ctx . o u t s t r i n g = [ e t r e e . t o s t r i n g ( ctx . out document ) ] 23
The custom SVG protocol: from r p c l i b . a p p l i c a t i o n import A p p l i c a t i o n svg = A p p l i c a t i o n ( [ DateTimeService ] , tns= ’rpclib.examples.multiprot’ , i n p r o t o c o l=HttpRpc () , o u t p r o t o c o l= SvgClock () ) 24
The custom SVG protocol: $ c u r l http :// l o c a l h o s t :9910/ g e t u t c t i m e \ > utc time . svg 2012-03-09 25
It’s also easy to implement declarative restrictions on your input data. 26
So instead of doing this: from datetime import datetime def get name of month ( month ) : ””” Takes an i n t e g e r between 1 − 12 and r e t u r n s the name of month as s t r i n g ””” value = i n t ( month ) i f not (1 < = value < = 12): r a i s e ValueError ( value ) r e t u r n datetime (2000 , month , 1 ) . s t r f t i m e ( "%B" ) 27
Recommend
More recommend