[Twisted-Python] in a factory: assert not self.usedUp
exarkun at twistedmatrix.com
exarkun at twistedmatrix.com
Wed Jun 23 13:06:11 MDT 2010
On 04:23 pm, jeandaniel.browne at gmail.com wrote:
>Hello,
>
>I have three questions on a code examples, and actually I have seen
>this pattern in several places in Twisted. The code are copied from
>twisted/doc/mail/examples/imap4client.py
>
>1. In the code below, what is the purpose of an assert checking that
>the member attribute promptDeferred is empty in the prompt method? Is
>this some kind of documentation saying "the attribute is ALWAYS empty
>when this function is called"?
It's a safeguard against the method being called a second time before
the response to the first call has been received. Imagine code using
the function like this if the assert weren't there:
d1 = prompter.prompt("Answer this")
d2 = prompter.prompt("Now answer this")
>
>2. It seems that there is the protocol's deferred and the protocol are
>unlinked before the deferred is fired. What would happen if the
>defered was fired while it is still held in an attribute of the
>protocol?
Consider what would happen if there were a callback on `promptDeferred`
which called the `prompt` method.
>
>class TrivialPrompter(basic.LineReceiver):
>
> from os import linesep as delimiter
>
> promptDeferred = None
>
> def prompt(self, msg):
>
> assert self.promptDeferred is None # 1.
> self.display(msg)
> self.promptDeferred = defer.Deferred()
> return self.promptDeferred
>
> def display(self,msg):
> self.transport.write(msg)
>
> def lineReceived(self, line):
> if self.promptDeferred is None:
> return
> d, self.promptDeferred = self.promptDeferred, None # 2.
> d.callback(line)
>
>
>3. Third question, in the factory below, there is an attribute usedUp
>set at False by default and set to True late in the buildprotocol
>method. There is an assert making sure the factory is only used once,
>checking that usedUp is False at the beginning of buildprotocol(). Why
>it is so important that the factory must be used only once? What would
>happens otherwise?
>
>class SimpleIMAP4ClientFactory(protocol.ClientFactory):
> usedUp = False
>
> protocol = SimpleIMAP4Client
>
> def __init__(self, username, onConn):
> self.ctx = ssl.ClientContextFactory()
>
> self.username = username
> self.onConn = onConn
>
> def buildProtocol(self, addr):
> assert not self.usedUp # 3.
> self.usedUp = True
>
> p = self.protocol(self.ctx)
> p.factory = self
> p.greetDeferred = self.onConn
>
> auth = imap4.CramMD5ClientAuthenticator(self.username)
> p.registerAuthenticator(auth)
>
> return p
There's only one Deferred referenced by `self.onConn`. If you ever got
to a second connection, the Deferred would have its `callback` method
invoked a second time which would raise an exception.
>
>Thanks for your help,
You're welcome.
Jean-Paul
More information about the Twisted-Python
mailing list