[Twisted-Python] ldaptor's LDAPClient.send_multiResponse not dealing with chained deferreds, patch

Michael Torrie torriem at gmail.com
Sat May 3 19:03:29 MDT 2008

This message is probably for Tv.

I have a situation where the callback to a
LDAPClient.send_multiResponse() call needs to do a bunch of work that I
want to split up over several functions, using deferred chaining.  What
I want to do is something like this (this in conjunction with an LDAP
proxy server I am writing using Twisted and ldaptor):

d = self.client.send_multiResponse(request, got_response)

then later:

def got_response(response):

    # get a list of other things to do with the response
    d = do_stuff_with_response(response)

    return d

def finish(response):
    # we're done

    return isinstance(response, (

However, this doesn't work, because the send_multiResponse() method of
LDAPClient isn't expecting the handler to return a deferred, even though
if I do return a deferred the reactor does handle it properly, chaining
the deferreds and their callbacks.

The problem is that in ldapclient.py, line 171, we have:

                # Return true to mark request as fully handled
                if handler(msg.value, *args, **kwargs):
                    del self.onwire[msg.id]

When handler() returns a deferred object, after the reactor processes
the chain the value is a Deferred object, not True or False, even though
the value of the deferred object may be True or False.  Hence the del
self.onwire[msg.id] always executes, which when dealing with search
result entries is a problem as they all share the same id.  I made a
quick hack to fix this:
--- /tmp/ldapclient.py  2008-05-03 18:53:26.000000000 -0600
+++ ldaptor/protocols/ldap/ldapclient.py        2008-05-03
18:58:07.000000000 -0600
@@ -168,7 +168,14 @@
                 assert args is not None
                 assert kwargs is not None
                 # Return true to mark request as fully handled
-                if handler(msg.value, *args, **kwargs):
+                result = handler(msg.value, *args, **kwargs)
+                try:
+                    result = result.result
+                except AttributeError:
+                    pass
+               if result:
                     del self.onwire[msg.id]


Is this an acceptable way to do this?

More information about the Twisted-Python mailing list