[Twisted-Python] Learning Twisted

Jason Diamond jason at injektilo.org
Sun May 16 22:04:58 EDT 2004


Jp Calderone wrote:

> Jason Diamond wrote:
>
>> This is what I came up with:
>>
>> from twisted.internet import reactor, protocol
>> from twisted.protocols import imap4
>>
>> class MyIMAP4Client(imap4.IMAP4Client):
>>
>>    def connectionMade(self):
>>        imap4.IMAP4Client.connectionMade(self)
>>        print "connectionMade"
>
>   The above works (as you noticed ;) but isn't quite as good as hooking =
> into the "serverGreeting" method, which is called after the IMAP4 
> server =
> sends its initial message (I realize this isn't well documented).

Cool! This makes perfect sense and I'll look for methods like 
serverGreeting from now on.

Here's my updated test:

from twisted.internet import reactor, protocol
from twisted.protocols import imap4

server = "xxx"
username = "yyy"
password = "zzz"

debug = 0

class MyIMAP4Client(imap4.IMAP4Client):

    def serverGreeting(self, caps):
        if debug: print "serverGreeting:", caps
        imap4.IMAP4Client.serverGreeting(self, caps)
        d = self.login(username, password)
        d.addCallback(self.loginCallback)

    def loginCallback(self, d):
        if debug: print "loginCallback:", d
        de = self.select("INBOX")
        de.addCallback(self.selectCallback)

    def selectCallback(self, d):
        if debug: print "selectCallback:", d
        print "I have %d messages in my INBOX." % d["EXISTS"]
        de = self.logout()
        de.addCallback(self.logoutCallback)

    def logoutCallback(self, d):
        if debug: print "logoutCallback:", d
        reactor.stop()

    def connectionLost(self, reason):
        if debug: print "connectionLost:", reason
        imap4.IMAP4Client.connectionLost(self)

    def sendLine(self, line):
        if debug: print "sendLine:", line
        imap4.IMAP4Client.sendLine(self, line)

    def lineReceived(self, line):
        if debug: print "lineReceived:", line
        imap4.IMAP4Client.lineReceived(self, line)

class MyIMAP4ClientFactory(protocol.ClientFactory):

    protocol = MyIMAP4Client

if __name__ == "__main__":
    f = MyIMAP4ClientFactory()
    reactor.connectTCP(server, 143, f)
    reactor.run()

>> [snip]
>>
>> Note that this is *not* a method of the MyIMAP4Client class. But it
>> worked! I got this printed to the console:
>>
>> connectionMade
>> loginCallback: ([], 'OK LOGIN Ok.')
>>
>> I don't know, however, what the tuple represents. What's that empty
>> list? In a perfect world, would this be explained in the IMAP4Client
>> documentation? (I'm assuming that every callback would be different.)
>>
>  The callback value here is something of an implementation detail.  =
> Deferreds (somewhat informally) often fall into one of two categories: =
> those which will eventually be called back with an interesting value =
> which is necessary for further computations, and those which will =
> eventually be called back with a not-so-interesting value which only =
> serves to indicate that the desired operation has completed.  login() =
> falls into the second category.

OK, this makes sense. But if the login callback doesn't have any useful 
information, why isn't it None (like the logout callback)? Or is that 
the implementation detail you're referring to that I should just forget 
about?

>> [snip]
>>
>> Am I correct in assuming that the IMAP4Client documentation needs some
>> buffing up? (Maybe I can help with that.) I didn't look at any source
>> code (other than in the HOWTOs) in implementing this so I think that's
>> a good sign. But as I mentioned above, I'm not clear on how I know
>> what the signature for my callbacks should be or what the parameters
>> to those callbacks mean in some cases.
>
>   Yep.  More documentation would be great.  The actual signature for =
> callbacks is easy.  It's always a callable that takes one argument (by =
> the way, this is why your code worked with both free functions and =
> methods - it doesn't matter what kind of callable you use, as long as 
> it =
> takes one argument).  Further documentation about the specifics of what =
> that one parameter means is definitely needed, though. 

I also just realized that a method attribute retrieved from an instance, 
even though it's declared as taking in two arguments (the first being 
self), returns a function that only has one argument--self is bound to 
the instance you used to grab the method.

-- Jason





More information about the Twisted-Python mailing list