--- client.py.orig	2010-05-02 23:41:58 +0200
+++ client.py	2010-05-03 09:45:02 +0200
@@ -19,6 +19,7 @@
 See I{README.txt}
 """
 
+import cStringIO
 import suds
 import suds.metrics as metrics
 from cookielib import CookieJar
@@ -537,6 +538,26 @@
                 return (500, e)
         else:
             return client.invoke(args, kwargs)
+
+    # DRo
+    # process a reply offline
+    def processreply(self, reply, **kwargs):
+        """
+        Process a reply asynchrounously
+        @param reply: A reply object
+        @type: suds.transport.Reply
+        @return: processed reply delivering the same results as if the method was called synchrounoulsy
+           including exceptions if HTTP responses other than 200 are passed to the method
+        """
+        clientclass = self.clientclass(kwargs)
+        client = clientclass(self.client, self.method)
+        if not self.faults():
+            try:
+                return client.processreply(reply)
+            except WebFault, e:
+                return (500, e)
+        else:
+            return client.processreply(reply)
         
     def faults(self):
         """ get faults option """
@@ -601,7 +622,7 @@
                 "method '%s' invoked: %s",
                 self.method.name, timer)
         return result
-    
+
     def send(self, msg):
         """
         Send soap message.
@@ -620,17 +641,64 @@
             self.last_sent(Document(msg))
             request = Request(location, str(msg))
             request.headers = self.headers()
+            # DRo - Begin
+            # return the request if asked to do so
+            # It will be sent by the user who will later give back the reply
+            # to be processed
+            if self.options.async == True:
+                return request
+            # DRo - End
             reply = transport.send(request)
+            result = self.processreply(reply)
+        except TransportError, e:
+            log.error(self.last_sent())
+            result = self.processtransporterror(e)
+        return result
+
+    # DRo
+    # Process errors (exceptions) during transport
+    def processtransporterror(self, e):
+        """
+        Processes a transport error, be it generated by the transport or simulated
+        during the processing of an async reply
+        @param e: A transport error object
+        @type: TransportError
+        @return: None or the return value from self.failed
+        """
+        if e.httpcode in (202,204):
+            result = None
+        else:
+            result = self.failed(binding, e)
+
+        return result
+
+    # DRo
+    # Process the reply
+    def processreply(self, reply):
+        """
+        Process a reply asynchrounously
+        @param reply: A reply object
+        @type: suds.transport.Reply
+        @return: processed reply delivering the same results as if the method was called synchrounoulsy
+           including exceptions if HTTP responses other than 200 are passed to the method
+        """
+
+        result = None
+        binding = self.method.binding.input
+        retxml = self.options.retxml
+
+        log.debug('Processing asynchronous reply:\n%s', reply)
+
+        if reply.code == 200:
             if retxml:
                 result = reply.message
             else:
                 result = self.succeeded(binding, reply.message)
-        except TransportError, e:
-            if e.httpcode in (202,204):
-                result = None
-            else:
-                log.error(self.last_sent())
-                result = self.failed(binding, e)
+        else:
+            log.error('Transport error detected when processing the asynchronous reply')
+            e = TransportError('', reply.code, cStringIO.StringIO(reply.message))
+            result = self.processtransporterror(e)
+
         return result
     
     def headers(self):
@@ -701,7 +769,10 @@
         if d is None:
             return messages.get(key)
         else:
-            messages[key] = d
+            # DRo
+            # Storing the last_sent has no meaning in asynchronous mode
+            if self.options.async == False:
+                messages[key] = d
         
     def last_received(self, d=None):
         key = 'rx'
@@ -709,7 +780,10 @@
         if d is None:
             return messages.get(key)
         else:
-            messages[key] = d
+            # DRo
+            # Storing the last_received has no meaning in asynchronous mode
+            if self.options.async == False:
+                messages[key] = d
 
 
 class SimClient(SoapClient):
