[Twisted-Python] strange bug with... something :)
Сергей Магафуров
smagafurov at naumen.ru
Thu Aug 5 21:15:11 MDT 2010
Example code 1
{{{
class Example(object):
def __init__(self, connection):
self.connection = connection
self.counter = 0
self.requests = {}
def generate_request_id(self):
self.counter += 1
return self.counter
def request(self, data, timeout=10):
deferred = defer.Deferred()
request_id = self.generate_request_id()
self.requests[request_id] = deferred
# ATTENTION: I want to see current traceback when timeout occurs
# therefore raise and catch here
try:
raise failure.TimeoutError()
except failure.TimeoutError:
failure = failure.Failure()
# charge timer
timer = reactor.callLater(timeout, self._on_timeout,
request_id, failure)
# send request
self.connection.send_request(request_id, data)
return deferred
def _on_timeout(self, request_id, failure):
deferred = self.requests.pop(request_id, None)
if deferred is not None:
deferred.errback(failure)
def on_response_received(self, request_id, response):
deferred = self.requests.pop(request_id, None)
if deferred is not None:
deferred.callback(response)
}}}
Disadvantage 1 of this code:
We construct failure.Failure() always although timeout may not occur at all.
If failure.Failure() was lazy it will be cool.
Disadvantage 2 (bug in twisted?) of this code:
This code doesn't work in some cases and I don't know why.
In some cases deferred.callback(response) does nothing although called.
But this code magically works properly in the same cases:
Example code 2 (one difference is just "lazy" failure construction using
special FailureFactory class)
{{{
class FailureFactory(object):
def __init__(self, arg):
try:
raise arg
except:
exc_info = sys.exc_info()
self.exc_info = exc_info
def __call__(self):
exc_type, exc_value, tb = self.exc_info
return Failure(exc_value, exc_type, tb)
class Example(object):
def __init__(self, connection):
self.connection = connection
self.counter = 0
self.requests = {}
def generate_request_id(self):
self.counter += 1
return self.counter
def request(self, data, timeout=10):
deferred = defer.Deferred()
request_id = self.generate_request_id()
self.requests[request_id] = deferred
# ATTENTION: I want to see current traceback when timeout occurs
# therefore raise and catch here
failure_factory = FailureFactory(failure.TimeoutError())
# charge timer
timer = reactor.callLater(timeout, self._on_timeout,
request_id, failure_factory)
# send request
self.connection.send_request(request_id, data)
return deferred
def _on_timeout(self, request_id, failure_factory):
deferred = self.requests.pop(request_id, None)
if deferred is not None:
deferred.errback(failure_factory())
def on_response_received(self, request_id, response):
deferred = self.requests.pop(request_id, None)
if deferred is not None:
deferred.callback(response)
}}}
Example 2 works but Example 1 does not.
What is wrong with example 1?
Bug in twisted?
I have posted this message as ticket but was redirected to mailing-list
http://twistedmatrix.com/trac/ticket/4628
More information about the Twisted-Python
mailing list