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