Trees | Indices | Help |
---|
|
1 #coding: iso-8859-1; 2 ############################################################################ 3 # # 4 # This file 'formats.py' # 5 # is part of 'SPyRO: Simple Python Remote Objects' # 6 # Copyright (C) 2004-2005 by Eric Sadit Tellez Avila # 7 # Copyright (C) 2005-2006 by Eric Sadit Tellez Avila # 8 # sadit@lsc.fie.umich.mx or donsadit@gmail.com # 9 # # 10 # This program is free software; you can redistribute it and#or modify # 11 # it under the terms of the GNU General Public License as published by # 12 # the Free Software Foundation; either version 2 of the License, or # 13 # (at your option) any later version. # 14 # # 15 # This program is distributed in the hope that it will be useful, # 16 # but WITHOUT ANY WARRANTY; without even the implied warranty of # 17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # 18 # GNU General Public License for more details. # 19 # # 20 # You should have received a copy of the GNU General Public License # 21 # along with this program; if not, write to the # 22 # Free Software Foundation, Inc., # 23 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # 24 ############################################################################ 25 26 import warn 27 warn = warn.Warn("SPyRO.formats") 28 import pickle 29 import cPickle 30 import marshal 31 import re 32 import SPyRO as spyro 33 34 import types 35 from types import DictType 36 41 42 try: 43 BooleanType = types.BooleanType 44 True 45 except: 46 warn.warn("An old version of python or jython was detected") 47 _set_booleans() 4850 """ The spyro format minimum requeriments """ 51 # General methods 559757 """ Loads a msg. Its called for every load_* if the load_* 58 method is not overloaded """ 59 raise "loads must be implemented"6062 """ Dumps a msg. Its called for every dump_* if the dump_* 63 method is not overloaded """ 64 raise "dumps must be implemented"65 66 # Client side 70 74 78 8284 return self._loads(msg)85 86 ########### Server side88 return self._loads(msg)89 9399 """ This is the Interface to serialize (load and dumps) of the 100 pickle format broker. It is quite simple, and it just uses 101 the cPickle package. 102 """ 106 109125 126111 """ Load received message, returns python data structures """ 112 #warn.debug("***************** READ1:", msg) 113 load = cPickle.loads(msg) 114 #load = pickle.loads(msg) 115 #warn.debug("***************** READ2:", load) 116 return load117128 """ Calls a personalized marshaler with loads and dumps methods 129 MarshalWrapper envolves the with _loads and _dumps methods 130 """ 133 136 139142 143 144 145 # Registed formats 146 147 try: 148 import xml.marshal.generic 149 except: 150 warn.debug("Unable to use XML generic to communicate (with ", 151 "xml.marshal.generic module)") 152 try: 153 import xml.marshal.wddx 154 except: 155 warn.debug("Unable to use XML WDDX to communicate (with ", 156 "xml.marshal.wddx module)") 157 158 try: 159 import SOAPpy 160 _USE_SOAPpy = True 161 except: 162 _USE_SOAPpy = False 163 warn.debug("Unable to use SOAP to communicate (with SOAPpy module)") 164166 """ 167 More info in /usr/lib/python2.4/site-packages/SOAPpy/SOAPBuilder.py 168 """ 171190 191 try: 192 import ZSI 193 from cStringIO import StringIO 194 _USE_ZSI = True 195 except: 196 _USE_ZSI = False 197 warn.debug("Unable to use SOAP to communicate (with ZSI module)") 198173 #x = SOAPpy.buildSOAP(msg,method="SPyRO_execute") 174 x = SOAPpy.buildSOAP(msg) 175 #print x 176 return x177202216 217 try: 218 import xmlrpclib 219 except: 220 warn.debug("Unable to use XMLRPC to communicate (with xmlrpclib module)") 221204 o = StringIO() 205 w = ZSI.SoapWriter(o) 206 w.serialize(msg, self.tcany) 207 #w.serialize(msg) 208 w.close() 209 s = o.getvalue() 210 o.close() 211 return s212223 """ XMLRPC Format, 224 225 SPyRO Clients can use the transparent mode. 226 Non-SPyRO clients must send request to any of the following functions 227 228 ==> SPyRO_execute(options) 229 Note: SPyRO_execute has an alias called 'execute' with the same arguments 230 Execute a dictionary (xmlrpc struct) with all the information to perform 231 a remote operation. The possible arguments depends of the type of the 232 request, (See the SPyRO's Request class). 233 The basic arguments or fields are: 234 |objname| The object name (ID in the server) 235 |attrname| The name of the requested attribute 236 |reqtype| The type of the request. It can be 'BYE', 'GET', 'SET', 'DEL', 237 CALL' 238 |auth| The authentication object to the request 239 240 Advanced arguments: 241 |local_server| If Request to call a remote method and exists port we call 242 the method with the pass the arguments by reference the server receives 243 the name or id in the remote peer (the caller) and a port to connect. 244 The IP address is obtained by the socket 245 |auth| The authentication object 246 |extra| Additional info to append to message, for example routed calls 247 248 When calling methods: 249 250 |args| Positional arguments, tuple 251 |kwargs| Keyword arguments, dictionary 252 253 254 Other specific functions are: 255 ==> getAttr(object_name, attribute_name) 256 Retrieves the value of the attribute |attribute_name| from the object 257 |object_name| 258 259 ==> setAttr(object_name, attribute_name, new_value) 260 Set the value to the attribute |attribute_name| of the object |object_name| 261 262 ==> callMethod(object_name, method_name, positional_args, keyword_args, options) 263 Call remote methods 264 |object_name| The name of the object 265 |method_name| The name of the method 266 |positional_args| The position arguments (an array or list) 267 |keyword_args| The named arguments (a struct or dictionary) 268 |options| Aditional arguments (see 'SPyRO_execute' 269 """ 272317 318274 #warn.debug("LOAD:","**************" * 10, len(msg)) 275 #warn.debug(msg) 276 args, methodname = xmlrpclib.loads(msg) 277 #warn.debug("XXXXXXXX:",repr(args)) 278 return args[0]279281 #warn.debug("DUMP:","==============" * 10) 282 #warn.debug(msg) 283 y = xmlrpclib.dumps((msg,) , methodname="SPyRO_execute", allow_none=1, encoding = self.encoding) 284 return y285 286 ## server side dumps288 x = { 289 'auth': None, 'local_server': None, 290 'rettype': spyro.SendByValue, 291 'reqtype' : spyro.Request.ReqCallMethod, 292 'args' : (), 'kwargs' : {}, 'extra': None 293 } 294 args, methodname = xmlrpclib.loads(msg) 295 options = {} 296 if methodname == 'SPyRO_execute' or methodname == 'execute': 297 options = args[0] 298 elif methodname == 'getAttr': 299 x['objname'], x['attrname'], options = args 300 x['reqtype'] = 'GET' 301 elif methodname == 'setAttr': 302 x['objname'], x['attrname'], x['value'], options = args 303 x['reqtype'] = 'SET' 304 elif methodname == 'callMethod': 305 x['objname'], x['attrname'], x['args'], x['kwargs'], options = args 306 x['reqtype'] = 'CALL' 307 x.update(options) 308 #warn.debug(x) 309 return x310 314316 return self.dump_result(msg)320 """ XMLRPC Format, 321 Non - SPyRO clients must send request to procedure "SPyRO_execute" with 322 the proper arguments (Request object properties) 323 """ 326380328 #warn.debug("LOAD:","**************" * 10, len(msg)) 329 #warn.debug(msg) 330 args, methodname = xmlrpclib.loads(msg) 331 #warn.debug("XXXXXXXX:",repr(args)) 332 return args[0]333335 # fake, its not supported 336 return xmlrpclib.dumps(('',''), methodname='SPyRO_control', 337 allow_none=1, encoding = self.encoding)338340 xmlrpcargs = tuple([msg['objname']] + list(msg['args'])) 341 y = xmlrpclib.dumps(xmlrpcargs, methodname=msg['attrname'], 342 allow_none=1, encoding = self.encoding) 343 return y344 345 ## server side dumps347 args, methodname = xmlrpclib.loads(msg) 348 x = { 349 'auth': None, 'local_server': None, 350 'rettype' : spyro.SendByValue, 351 'reqtype' : spyro.Request.ReqCallMethod, 352 'objname' : args[0], 353 'args' : args[1:], 354 'attrname' : methodname, 355 'kwargs' : {}, 'extra': None, 356 } 357 # warn.debug("REQUEST:", x) 358 return x359361 return xmlrpclib.dumps((msg['retvalue'],), methodresponse=1, 362 allow_none=1, encoding = self.encoding)363365 x = xmlrpclib.dumps(xmlrpclib.Fault(msg['errcode'],msg['retvalue']), 366 encoding = self.encoding) 367 return x368370 try: 371 args, methodname = xmlrpclib.loads(msg) 372 x = {'retvalue': args[0], 373 'rettype': spyro.SendByValue, 374 'errcode': spyro.Response.Successful} 375 except xmlrpclib.Fault, err: 376 x = {'retvalue': err.faultString, 377 'rettype': spyro.SendByValue, 378 'errcode': spyro.Response.ErrorExceptionThrowed} 379 return x382 """ Choose the best format between local priorities and 383 the priorities in the msg 384 if |priorities| is None the Prolog.Priorities is used 385 """ 386 if not priorities: priorities = Prolog.Priorities 387 allentries = Prolog.EntryReader.findall(msg) 388 candidates = [] 389 for protocol, priority in allentries: 390 try: 391 candidates((priorities[protocol] * float(priority), protocol)) 392 except: 393 # the protocol does not exists or the priority is not 394 # a floating/int number 395 pass 396 candidates.sort() 397 format = None 398 try: 399 format = candidates[-1][0] 400 except: 401 warn.debug("There is not available format to perform connection: ", 402 priorities, allentries) 403 return format404406 """ The prolog of the connection """ 407 EntryReader = re.compile(r"(\w+):(\d.\d)\n?") 408 Priorities = { 409 'PICKLE2':1.0, 410 'PICKLE1':0.9, 411 'PICKLE0':0.8, 412 'MARSHAL':0.7, 413 'XMLRPC':0.6, 414 'XMLRPC-Legacy':0.6, 415 'XML':0.5, 416 'WDDX':0.5, 417 'XMLGENERIC':0.5, 418 'SOAP':0.4, 419 'SOAPpy':0.3, 420 'SOAPZSI':0.2 421 } 422449 450424 """ If |priorities| is None |Prolog.Priorities| is used instead""" 425 if priorities is None: 426 self.priorities = Prolog.Priorities 427 else: 428 self.priorities = priorities 429 self.isserver = True430 433 436 439 440 ## Server side 443 446448 return self.dump_result(msg)452 """ The Object Request Broker Format class """ 453528455 DictType.__init__(self)456458 self["MARSHAL"] = self.fmtMARSHAL 459 self["PICKLE"] = self.fmtPICKLE 460 self["PICKLE0"] = self.fmtPICKLE0 461 self["PICKLE1"] = self.fmtPICKLE1 462 self["PICKLE2"] = self.fmtPICKLE2 463 self["XML"] = self.fmtXML 464 self["WDDX"] = self.fmtWDDX 465 self["XMLGENERIC"] = self.fmtXMLGENERIC 466 self["XMLRPC"] = self.fmtXMLRPC 467 self["XMLRPC-Legacy"] = self.fmtXMLRPCLegacy 468 if _USE_SOAPpy: 469 self["SOAP"] = self.fmtSOAPpy 470 else: 471 self["SOAP"] = self.fmtZSI 472 self["SOAPpy"] = self.fmtSOAPpy 473 self["SOAPZSI"] = self.fmtZSI 474 self[""] = self.fmtDEFAULT 475 self["GUESS"] = self.fmtGUESS476478 """ Register a new format, with name |name| and |interface| is function 479 that returns a fully functional interface to manage the format (i.e. a 480 new instance of the format manager) """ 481 self[name] = generator482 485487 return XMLRPCFormat()488490 return XMLRPCFormatLegacy()491493 return SOAP_SOAPpy()494496 return SOAP_ZSI()497499 return MarshalWrapper(marshal)500502 return PickleFormat(0)503505 return PickleFormat(0)506508 return PickleFormat(1)509511 return PickleFormat(2)512514 return MarshalWrapper(xml.marshal.generic)515517 return MarshalWrapper(xml.marshal.wddx)518 521 524
Trees | Indices | Help |
---|
Generated by Epydoc 3.0beta1 on Thu Jan 31 08:15:48 2008 | http://epydoc.sourceforge.net |