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. |