[Twisted-Python] in a factory: assert not self.usedUp

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"?
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?
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
Thanks for your help,

On 04:23 pm, jeandaniel.browne@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
- 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")
- 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)
- 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
participants (2)
-
exarkun@twistedmatrix.com
-
Jean Daniel