From: <poo...@us...> - 2010-03-04 23:46:25
|
Revision: 1496 http://pywebsvcs.svn.sourceforge.net/pywebsvcs/?rev=1496&view=rev Author: pooryorick Date: 2010-03-04 23:46:17 +0000 (Thu, 04 Mar 2010) Log Message: ----------- Added timeout to client http transport change client attribute lookup so client can be pickled. Modified Paths: -------------- trunk/SOAPpy/SOAPpy/Client.py trunk/SOAPpy/SOAPpy/Types.py Modified: trunk/SOAPpy/SOAPpy/Client.py =================================================================== --- trunk/SOAPpy/SOAPpy/Client.py 2009-08-24 23:40:21 UTC (rev 1495) +++ trunk/SOAPpy/SOAPpy/Client.py 2010-03-04 23:46:17 UTC (rev 1496) @@ -41,8 +41,8 @@ # ################################################################################ """ +ident = '$Id$' -ident = '$Id$' from version import __version__ #import xml.sax @@ -50,6 +50,8 @@ from types import * import re import base64 +import socket, httplib +from httplib import HTTPConnection, HTTP import Cookie # SOAPpy modules @@ -111,7 +113,40 @@ __repr__ = __str__ +class SOAPTimeoutError(socket.timeout): + '''This exception is raised when a timeout occurs in SOAP operations''' + pass +class HTTPConnectionWithTimeout(HTTPConnection): + '''Extend HTTPConnection for timeout support''' + + def __init__(self, host, port=None, strict=None, timeout=None): + HTTPConnection.__init__(self, host, port, strict) + self._timeout = timeout + + def connect(self): + HTTPConnection.connect(self) + if self.sock and self._timeout: + self.sock.settimeout(self._timeout) + + +class HTTPWithTimeout(HTTP): + + _connection_class = HTTPConnectionWithTimeout + + ## this __init__ copied from httplib.HTML class + def __init__(self, host='', port=None, strict=None, timeout=None): + "Provide a default host, since the superclass requires one." + + # some joker passed 0 explicitly, meaning default port + if port == 0: + port = None + + # Note that we may pass an empty string as the host; this will throw + # an error when we attempt to connect. Presumably, the client code + # will call connect before then, with a proper host. + self._setup(self._connection_class(host, port, strict, timeout)) + class HTTPTransport: @@ -149,12 +184,9 @@ attrs.append('$Domain=%s' % value) r.putheader('Cookie', "; ".join(attrs)) - # Need a Timeout someday? def call(self, addr, data, namespace, soapaction = None, encoding = None, - http_proxy = None, config = Config): + http_proxy = None, config = Config, timeout=None): - import httplib - if not isinstance(addr, SOAPAddress): addr = SOAPAddress(addr, config) @@ -172,7 +204,7 @@ elif addr.proto == 'https': r = httplib.HTTPS(real_addr) else: - r = httplib.HTTP(real_addr) + r = HTTPWithTimeout(real_addr, timeout=timeout) r.putrequest("POST", real_path) @@ -309,7 +341,7 @@ header = None, methodattrs = None, transport = HTTPTransport, encoding = 'UTF-8', throw_faults = 1, unwrap_results = None, http_proxy=None, config = Config, noroot = 0, - simplify_objects=None): + simplify_objects=None, timeout=None): # Test the encoding, raising an exception if it's not known if encoding != None: @@ -338,6 +370,7 @@ self.http_proxy = http_proxy self.config = config self.noroot = noroot + self.timeout = timeout # GSI Additions if hasattr(config, "channel_mode") and \ @@ -385,12 +418,15 @@ call_retry = 0 try: - r, self.namespace = self.transport.call(self.proxy, m, ns, sa, encoding = self.encoding, - http_proxy = self.http_proxy, - config = self.config) + http_proxy = self.http_proxy, + config = self.config, + timeout = self.timeout) + except socket.timeout: + raise SOAPTimeoutError + except Exception, ex: # # Call failed. @@ -415,10 +451,14 @@ raise if call_retry: - r, self.namespace = self.transport.call(self.proxy, m, ns, sa, - encoding = self.encoding, - http_proxy = self.http_proxy, - config = self.config) + try: + r, self.namespace = self.transport.call(self.proxy, m, ns, sa, + encoding = self.encoding, + http_proxy = self.http_proxy, + config = self.config, + timeout = self.timeout) + except socket.timeout: + raise SOAPTimeoutError p, attrs = parseSOAPRPC(r, attrs = 1) @@ -465,11 +505,12 @@ return self.__call(None, body, {}) def __getattr__(self, name): # hook to catch method calls - if name == '__del__': + if name in ( '__del__', '__getinitargs__', '__getnewargs__', + '__getstate__', '__setstate__', '__reduce__', '__reduce_ex__'): raise AttributeError, name return self.__Method(self.__call, name, config = self.config) - # To handle attribute wierdness + # To handle attribute weirdness class __Method: # Some magic to bind a SOAP method to an RPC server. # Supports "nested" methods (e.g. examples.getStateName) -- concept Modified: trunk/SOAPpy/SOAPpy/Types.py =================================================================== --- trunk/SOAPpy/SOAPpy/Types.py 2009-08-24 23:40:21 UTC (rev 1495) +++ trunk/SOAPpy/SOAPpy/Types.py 2010-03-04 23:46:17 UTC (rev 1496) @@ -1648,7 +1648,7 @@ def simplify(object, level=0): """ - Convert the SOAPpy objects and thier contents to simple python types. + Convert the SOAPpy objects and their contents to simple python types. This function recursively converts the passed 'container' object, and all public subobjects. (Private subobjects have names that This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <poo...@us...> - 2010-03-08 06:07:05
|
Revision: 1497 http://pywebsvcs.svn.sourceforge.net/pywebsvcs/?rev=1497&view=rev Author: pooryorick Date: 2010-03-08 06:06:52 +0000 (Mon, 08 Mar 2010) Log Message: ----------- overhaul dump operations (dump_instance was never called under newer Python) Modified Paths: -------------- trunk/SOAPpy/SOAPpy/Parser.py trunk/SOAPpy/SOAPpy/SOAPBuilder.py Modified: trunk/SOAPpy/SOAPpy/Parser.py =================================================================== --- trunk/SOAPpy/SOAPpy/Parser.py 2010-03-04 23:46:17 UTC (rev 1496) +++ trunk/SOAPpy/SOAPpy/Parser.py 2010-03-08 06:06:52 UTC (rev 1497) @@ -820,9 +820,6 @@ zerofloatre = '[1-9]' - - - def convertType(self, d, t, attrs, config=Config): if t[0] is None and t[1] is not None: type = t[1].strip() Modified: trunk/SOAPpy/SOAPpy/SOAPBuilder.py =================================================================== --- trunk/SOAPpy/SOAPpy/SOAPBuilder.py 2010-03-04 23:46:17 UTC (rev 1496) +++ trunk/SOAPpy/SOAPpy/SOAPBuilder.py 2010-03-08 06:06:52 UTC (rev 1497) @@ -284,22 +284,7 @@ if type(tag) not in (NoneType, StringType, UnicodeType): raise KeyError, "tag must be a string or None" - try: - meth = getattr(self, "dump_" + type(obj).__name__) - except AttributeError: - if type(obj) == LongType: - obj_type = "integer" - elif pythonHasBooleanType and type(obj) == BooleanType: - obj_type = "boolean" - else: - obj_type = type(obj).__name__ - - self.out.append(self.dumper(None, obj_type, obj, tag, typed, - ns_map, self.genroot(ns_map))) - else: - meth(obj, tag, typed, ns_map) - - + self.dump_dispatch(obj, tag, typed, ns_map) self.depth -= 1 # generic dumper @@ -332,6 +317,7 @@ data = obj + return xml % {"tag": tag, "type": t, "data": data, "root": rootattr, "id": id, "attrs": a} @@ -353,10 +339,20 @@ else: obj = repr(obj) - # Note: python 'float' is actually a SOAP 'double'. - self.out.append(self.dumper(None, "double", obj, tag, typed, ns_map, - self.genroot(ns_map))) + # Note: python 'float' is actually a SOAP 'double'. + self.out.append(self.dumper( + None, "double", obj, tag, typed, ns_map, self.genroot(ns_map))) + def dump_int(self, obj, tag, typed = 1, ns_map = {}): + if Config.debug: print "In dump_int." + self.out.append(self.dumper(None, 'integer', obj, tag, typed, + ns_map, self.genroot(ns_map))) + + def dump_bool(self, obj, tag, typed = 1, ns_map = {}): + if Config.debug: print "In dump_bool." + self.out.append(self.dumper(None, 'boolean', obj, tag, typed, + ns_map, self.genroot(ns_map))) + def dump_string(self, obj, tag, typed = 0, ns_map = {}): if Config.debug: print "In dump_string." tag = tag or self.gentag() @@ -407,12 +403,12 @@ except: # preserve type if present if getattr(obj,"_typed",None) and getattr(obj,"_type",None): - if getattr(obj, "_complexType", None): + if getattr(obj, "_complexType", None): sample = typedArrayType(typed=obj._type, complexType = obj._complexType) sample._typename = obj._type if not getattr(obj,"_ns",None): obj._ns = NS.URN - else: + else: sample = typedArrayType(typed=obj._type) else: sample = structType() @@ -459,7 +455,7 @@ else: t = 'ur-type' else: - typename = type(sample).__name__ + typename = type(sample).__name__ # For Python 2.2+ if type(sample) == StringType: typename = 'string' @@ -467,10 +463,10 @@ # HACK: unicode is a SOAP string if type(sample) == UnicodeType: typename = 'string' - # HACK: python 'float' is actually a SOAP 'double'. - if typename=="float": typename="double" - t = self.genns(ns_map, self.config.typesNamespaceURI)[0] + \ - typename + # HACK: python 'float' is actually a SOAP 'double'. + if typename=="float": typename="double" + t = self.genns( + ns_map, self.config.typesNamespaceURI)[0] + typename else: t = self.genns(ns_map, self.config.typesNamespaceURI)[0] + \ @@ -524,21 +520,43 @@ dump_dict = dump_dictionary # For Python 2.2+ - def dump_instance(self, obj, tag, typed = 1, ns_map = {}): - if Config.debug: print "In dump_instance.", "obj=", obj, "tag=", tag + def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): + # watch out for order! + dumpmap = ( + (basestring, self.dump_string), + (NoneType, self.dump_None), + (bool, self.dump_bool), + (int, self.dump_int), + (long, self.dump_int), + (list, self.dump_list), + (dict, self.dump_dictionary), + (float, self.dump_float), + ) + for dtype, func in dumpmap: + if isinstance(obj, dtype): + func(obj, tag, typed, ns_map) + return + + try: + iter(obj) + except TypeError: + pass + else: + self.dump_list(obj, tag, typed, ns_map) + return + + if not tag: # If it has a name use it. if isinstance(obj, anyType) and obj._name: tag = obj._name else: tag = self.gentag() - tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding if isinstance(obj, arrayType): # Array self.dump_list(obj, tag, typed, ns_map) return - - if isinstance(obj, faultType): # Fault + elif isinstance(obj, faultType): # Fault cns, cdecl = self.genns(ns_map, NS.ENC) vns, vdecl = self.genns(ns_map, NS.ENV) self.out.append('<%sFault %sroot="1"%s%s>' % (vns, cns, vdecl, cdecl)) @@ -556,12 +574,11 @@ if isinstance(obj, voidType): # void self.out.append("<%s%s%s></%s>\n" % (tag, a, r, tag)) - return + else: + id = self.checkref(obj, tag, ns_map) + if id == None: + return - id = self.checkref(obj, tag, ns_map) - if id == None: - return - if isinstance(obj, structType): # Check for namespace ndecl = '' @@ -612,13 +629,16 @@ else: # Some Class self.out.append('<%s%s%s>\n' % (tag, id, r)) - for (k, v) in obj.__dict__.items(): - if k[0] != "_": - self.dump(v, k, 1, ns_map) + d1 = getattr(obj, '__dict__', None) + if d1 is not None: + for (k, v) in d1: + if k[0] != "_": + self.dump(v, k, 1, ns_map) self.out.append('</%s>\n' % tag) + ################################################################################ # SOAPBuilder's more public interface ################################################################################ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |