[Twisted-Python] modal wxPython, Twisted, xml-rpc; example code
Andrew Dalke
dalke at dalkescientific.com
Tue Jun 3 19:43:57 MDT 2003
Me:
> I've attached some example code which shows how to use
> a modal wxPython dialog and Twisted to produce a responsive
> GUI which uses XML-RPC to query a remote XML-RPC service to
> get a US state name given it's position in a sorted list.
>
> I've also contributed this as an ActiveState recipe.
However, it fails for some cases of a modal in a modal.
I have a set of error cases in the code, which looks like this (except
the last one, which I added today).
if TEST_ERRORS:
i = self.i
if i == 3:
proxy = Proxy("http://illegal-host_name/")
elif i == 6:
proxy = Proxy("http://beatty.userland.com/")
elif i == 8:
proxy =
Proxy("http://beatty.userland.com/testing_xmlrpc_error_case")
elif i == 9:
proxy = Proxy("http://beatty.userland.com:9876/")
The last one cases an error during making the connection, and so I get
a "unable to connect to remote host" message. Now, I want to show that
message
in another modal, which doesn't use Twisted, so I just opened the modal
window.
This starts up the wxPython event loop again, which triggers another
timer
event, which calls back to the Twisted reactor to run another iteration.
It appears that my defered is still active, because I then get an
'AlreadyCalledError'.
Here's the full stack trace.
Traceback (most recent call last):
File "Progress.py", line 158, in Bad
try_again = task.bad(fail)
File "Progress.py", line 52, in bad
wxCANCEL | wxYES_NO | wxICON_QUESTION)
File "Progress.py", line 208, in OnTimer
reactor.doIteration(0)
File "E:\Python22\Lib\site-packages\twisted\internet\default.py",
line 473, in
doSelect
_logrun(selectable, _drdw, selectable, method, dict)
--- <exception caught here> ---
File "E:\Python22\Lib\site-packages\twisted\python\log.py", line 64,
in callWithLogger
callWithContext({"system": lp}, func, *args, **kw)
File "E:\Python22\Lib\site-packages\twisted\python\log.py", line 51,
in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "E:\Python22\Lib\site-packages\twisted\python\context.py", line
32, in callWithContext
return func(*args,**kw)
File "E:\Python22\Lib\site-packages\twisted\internet\default.py",
line 498, in _doReadOrWrite
selectable.connectionLost(failure.Failure(why))
File "E:\Python22\Lib\site-packages\twisted\internet\tcp.py", line
396, in connectionLost
self.failIfNotConnected(error.ConnectError())
File "E:\Python22\Lib\site-packages\twisted\internet\tcp.py", line
315, in failIfNotConnected
self.connector.connectionFailed(failure.Failure(err))
File "E:\Python22\Lib\site-packages\twisted\internet\base.py", line
527, in connectionFailed
self.factory.clientConnectionFailed(self, reason)
File "E:\Python22\Lib\site-packages\twisted\web\xmlrpc.py", line 209,
in clientConnectionLost
self.deferred.errback(reason)
File "E:\Python22\lib\site-packages\twisted\internet\defer.py", line
215, in errback
self._startRunCallbacks(fail, 1)
File "E:\Python22\lib\site-packages\twisted\internet\defer.py", line
244, in _startRunCallbacks
raise AlreadyCalledError()
twisted.internet.defer.AlreadyCalledError:
I can't figure out what's going on. The code I could find for the
reactor is very
careful to take defereds off the pending list before calling, so
there's no way to
call them twice.
There's a clue in that only the last of these trigger this error
condition. This
suggests something with how the connection is established, and not
after it's
put into place. What I think is happening is that that
twisted.internet.base.BaseConnector allows the factory to reattempt the
connection
when the intial connection failed, and there isn't a guard in case the
connectionFailed
gets called again.
I still haven't grokked how the deep part of Twisted works - tried for
the last
while to track this bug further - so I'll leave it up to you all.
In the meanwhile, since I don't need Twisted in the new (sub)modal, my
workaround
is to do
def OnTimer(self, event):
if self.recursive:
return
self.recursive = 1
try:
reactor.runUntilCurrent()
reactor.doIteration(0)
finally:
self.recursive = 0
Andrew
dalke at dalkescientific.com
More information about the Twisted-Python
mailing list