some source code about twisted

This commit is contained in:
JamesonHuang
2015-06-15 22:20:58 +08:00
parent 8791e644e5
commit dff86defdb
1113 changed files with 407155 additions and 0 deletions

View File

@ -0,0 +1,18 @@
from twisted.internet.defer import Deferred
def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with a normal result
d.callback('This poem is short.')
print "Finished"

View File

@ -0,0 +1,102 @@
from twisted.internet.defer import Deferred
print """
This example illustrates how callbacks in a deferred
chain can return deferreds themselves.
"""
# three simple callbacks
def callback_1(res):
print 'callback_1 got', res
return 1
def callback_2(res):
print 'callback_2 got', res
return 2
def callback_3(res):
print 'callback_3 got', res
return 3
# We add them all to a deferred and fire it:
d = Deferred()
d.addCallback(callback_1)
d.addCallback(callback_2)
d.addCallback(callback_3)
print """
Here we are firing a deferred with three callbacks that just print
their argument and return simple values:
"""
d.callback(0)
# And you get output like this:
# callback_1 got 0
# callback_2 got 1
# callback_3 got 2
# Now we make a callback that returns a deferred:
deferred_2 = None # NOTE: because we aren't using a reactor, we have
# to fire this deferred from the 'outside'.
# We store it in a global variable for this
# purpose. In a normal Twisted program you
# would never store a deferred in a global or
# fire it from the outside. By 'outside' we
# mean the deferred is not being fired by an
# action set in motion by the callback that
# created and returned the deferred, as is
# normally the case.
def callback_2_async(res):
print 'callback_2 got', res
global deferred_2 # never do this in a real program
deferred_2 = Deferred()
return deferred_2
# We do the same thing, but use the async callback:
d = Deferred()
d.addCallback(callback_1)
d.addCallback(callback_2_async)
d.addCallback(callback_3)
print """
Here we are firing a deferred as above but the middle callback is
returning a deferred:
"""
d.callback(0)
# And you get output like this:
# callback_1 got 0
# callback_2 got 1
print """
Notice the output from the third callback is missing. That's because
the second callback returned a deferred and now the 'outer' deferred
is paused. It's not waiting in a thread or anything like that, it just
stopped invoking the callbacks in the chain. Instead, it registered
some callbacks on the 'inner' deferred which will start the outer
deferred back up when the inner deferred is fired.
We can see this in action by firing the inner deferred:
"""
deferred_2.callback(2)
# And you get output like this:
# callback_3 got 2
print """
Note the argument to the inner deferred's callback() method became
the result passed to the next callback in the outer deferred.
"""

View File

@ -0,0 +1,63 @@
from twisted.internet.defer import Deferred
print """\
This example illustrates how deferreds can
be fired before they are returned. First we
make a new deferred, fire it, then add some
callbacks.
"""
# three simple callbacks
def callback_1(res):
print 'callback_1 got', res
return 1
def callback_2(res):
print 'callback_2 got', res
return 2
def callback_3(res):
print 'callback_3 got', res
return 3
# We create a deferred and fire it immediately:
d = Deferred()
print 'Firing empty deferred.'
d.callback(0)
# Now we add the callbacks to the deferred.
# Notice how each callback fires immediately.
print 'Adding first callback.'
d.addCallback(callback_1)
print 'Adding second callback.'
d.addCallback(callback_2)
print 'Adding third callback.'
d.addCallback(callback_3)
print"""
Because the deferred was already fired, it
invoked each callback as soon as it was added.
Now we create a deferred and fire it, but
pause it first with the pause() method.
"""
# We do the same thing, but pause the deferred:
d = Deferred()
print 'Pausing, then firing deferred.'
d.pause()
d.callback(0)
print 'Adding callbacks.'
d.addCallback(callback_1)
d.addCallback(callback_2)
d.addCallback(callback_3)
print 'Unpausing the deferred.'
d.unpause()

View File

@ -0,0 +1,19 @@
from twisted.internet.defer import Deferred
from twisted.python.failure import Failure
def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with an error result
d.errback(Failure(Exception('I have failed.')))
print "Finished"

View File

@ -0,0 +1,18 @@
from twisted.internet.defer import Deferred
def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print err.__class__
print err
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with an error result
d.errback(Exception('I have failed.'))

View File

@ -0,0 +1,7 @@
from twisted.internet.defer import Deferred
def out(s): print s
d = Deferred()
d.addCallbacks(out, out)
d.callback('First result')
d.callback('Second result')
print 'Finished'

View File

@ -0,0 +1,7 @@
from twisted.internet.defer import Deferred
def out(s): print s
d = Deferred()
d.addCallbacks(out, out)
d.callback('First result')
d.errback(Exception('First error'))
print 'Finished'

View File

@ -0,0 +1,7 @@
from twisted.internet.defer import Deferred
def out(s): print s
d = Deferred()
d.addCallbacks(out, out)
d.errback(Exception('First error'))
d.errback(Exception('Second error'))
print 'Finished'

View File

@ -0,0 +1,7 @@
from twisted.internet.defer import Deferred
def out(s): print s
d = Deferred()
d.addCallbacks(out, out)
d.errback(Exception('First error'))
d.callback('First result')
print 'Finished'

View File

@ -0,0 +1,25 @@
import sys
from twisted.internet.defer import Deferred
def got_poem(poem):
print poem
from twisted.internet import reactor
reactor.stop()
def poem_failed(err):
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
from twisted.internet import reactor
reactor.stop()
d = Deferred()
d.addCallbacks(got_poem, poem_failed)
from twisted.internet import reactor
reactor.callWhenRunning(d.callback, 'Another short poem.')
reactor.run()

View File

@ -0,0 +1,26 @@
import sys
from twisted.internet.defer import Deferred
def got_poem(poem):
print poem
def poem_failed(err):
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
def poem_done(_):
from twisted.internet import reactor
reactor.stop()
d = Deferred()
d.addCallbacks(got_poem, poem_failed)
d.addBoth(poem_done)
from twisted.internet import reactor
reactor.callWhenRunning(d.callback, 'Another short poem.')
reactor.run()

View File

@ -0,0 +1,53 @@
import sys, time
from twisted.internet.defer import Deferred
def start_chain(_):
print "The start of the callback chain."
def blocking_poem(_):
def delayed_write(s, delay):
time.sleep(delay)
sys.stdout.write(s)
sys.stdout.flush()
delayed_write('\n', 0)
delayed_write('I', .6)
delayed_write(' block', .4)
delayed_write('\n and', 1)
delayed_write(' the', .4)
delayed_write(' deferred', .6)
delayed_write('\n blocks', 1.5)
delayed_write(' with', .2)
delayed_write(' me', .2)
delayed_write('\nas does', 1)
delayed_write('\n the reactor', .6)
delayed_write('\nkeep that', 1)
delayed_write('\n factor', .6)
delayed_write('\nin', 1)
delayed_write(' mind', .4)
delayed_write('\n\n', 2)
def end_chain(_):
print "The end of the callback chain."
from twisted.internet import reactor
reactor.stop()
d = Deferred()
d.addCallback(start_chain)
d.addCallback(blocking_poem)
d.addCallback(end_chain)
def fire():
print 'Firing deferred.'
d.callback(True)
print 'Firing finished.'
from twisted.internet import reactor
reactor.callWhenRunning(fire)
print 'Starting reactor.'
reactor.run()
print 'Done.'

View File

@ -0,0 +1,12 @@
from twisted.internet.defer import Deferred
def callback(res):
raise Exception('oops')
d = Deferred()
d.addCallback(callback)
d.callback('Here is your result.')
print "Finished"

View File

@ -0,0 +1,444 @@
#!/usr/bin/env python
import optparse, sys
from twisted.internet import defer
from twisted.python.failure import Failure
__doc__ = """\
usage: %prog
A Deferred simulator. Use this to see how a particular
set of callbacks and errbacks will fire in a deferred.\
"""
class BadInput(Exception): pass
def parse_args():
parser = optparse.OptionParser(usage=__doc__)
help = "draw all three chains in one column"
parser.add_option('--narrow', action='store_true', help=help)
options, args = parser.parse_args()
if args:
parser.error('No arguments supported.')
return options
class Screen(object):
"""An ascii screen."""
def __init__(self):
self.pixels = {} # (x, y) -> char
def draw_char(self, x, y, char):
self.pixels[x,y] = char
def draw_horiz_line(self, x, y, width):
for i in range(width):
self.draw_char(x + i, y, '-')
def draw_vert_line(self, x, y, height, end_arrow=False):
for i in range(height):
self.draw_char(x, y + i, '|')
if end_arrow:
self.draw_char(x - 1, y + height - 1, '\\')
self.draw_char(x + 1, y + height - 1, '/')
def draw_text(self, x, y, text):
for i, char in enumerate(text):
self.draw_char(x + i, y, char)
def clear(self):
self.pixels.clear()
def __str__(self):
width = max([p[0] + 1 for p in self.pixels] + [0])
height = max([p[1] + 1 for p in self.pixels] + [0])
s = ''
for y in range(height):
for x in range(width):
s += self.pixels.get((x,y), ' ')
s += '\n'
return s
class Callback(object):
"""
A widget representing a single callback or errback.
Each callback widget has one of three styles:
return - a callback that returns a given value
fail - a callback that raises an Exception(value)
passthru - a callback that returns its argument unchanged
The widget is also a callable that behaves according
to the widget's style.
"""
height = 5
def __init__(self, style, value=None):
self.style = style
self.value = value
self.min_width = len('0123456*') + len('return ') + 3
def __call__(self, res):
if self.style == 'return':
return self.value
if self.style == 'fail':
return Failure(Exception(self.value))
return res
@property
def caption(self):
if self.style == 'passthru':
return 'passthru'
return self.style + ' ' + self.value
def format_value(self, res):
if isinstance(res, Failure):
return res.value.args[0] + '*'
return res
def draw_passive(self, screen, x, y, width):
self.draw_box(screen, x, y, width)
self.draw_text(screen, x, y + 2, width, self.caption)
def draw_active(self, screen, x, y, width, res):
self.draw_box(screen, x, y, width)
self.draw_text(screen, x, y + 1, width, self.format_value(res))
self.draw_text(screen, x, y + 3, width, self.format_value(self(res)))
def draw_box(self, screen, x, y, width):
screen.draw_horiz_line(x, y, width)
screen.draw_horiz_line(x, y + 4, width)
screen.draw_vert_line(x, y + 1, 3)
screen.draw_vert_line(x + width - 1, y + 1, 3)
def draw_text(self, screen, x, y, width, text):
screen.draw_text(x + 1, y, text.center(width - 2))
class Deferred(object):
"""
An widget for a deferred.
It is initialize with a non-empty list of Callback pairs,
representing a callback chain in a Twisted Deferred.
"""
def __init__(self, pairs):
assert pairs
self.pairs = pairs
self.callback_width = max([p[0].min_width for p in self.pairs] + [0])
self.callback_width = max([p[1].min_width for p in self.pairs]
+ [self.callback_width])
self.width = self.callback_width * 2 + 2
self.height = Callback.height * len(self.pairs)
self.height += 3 * len(self.pairs[1:])
def draw(self, screen, x, y):
"""
Draw a representation of the callback/errback chain
on the given screen at the given coordinates.
"""
for callback, errback in self.pairs:
callback.draw_passive(screen, x, y, self.callback_width)
errback.draw_passive(screen, x + self.callback_width + 2,
y, self.callback_width)
y += Callback.height + 3
class FiredDeferred(object):
"""
A widget for a fired deferred.
It is initialized with a Deferred widget (not a real deferred)
and the method name ('callback' or 'errback') to draw the firing
sequence for.
"""
callback_y_offset = 4
def __init__(self, deferred, method):
self.deferred = deferred
self.method = method
self.height = deferred.height + 8
self.width = deferred.width
def draw(self, screen, x, y, result='initial'):
d = self.make_drawing_deferred(screen, x, y)
if self.method == 'callback':
d.callback(result)
else:
d.errback(Exception(result))
def make_drawing_deferred(self, screen, x, y):
"""
Return a new deferred that, when fired, will draw its
firing sequence onto the given screen at the given coordinates.
"""
callback_width = self.deferred.callback_width
callback_mid_x = x - 1 + callback_width / 2
errback_left_x = x + callback_width + 2
errback_mid_x = errback_left_x - 1 + callback_width / 2
class DrawState(object):
last_x = None
last_y = None
state = DrawState()
def draw_connection(x):
if state.last_x == x:
screen.draw_vert_line(x - 1 + callback_width / 2,
state.last_y - 3, 3, True)
return
if state.last_x < x:
screen.draw_vert_line(callback_mid_x, state.last_y - 3, 2)
screen.draw_vert_line(errback_mid_x,
state.last_y - 2, 2, True)
else:
screen.draw_vert_line(errback_mid_x, state.last_y - 3, 2)
screen.draw_vert_line(callback_mid_x,
state.last_y - 2, 2, True)
screen.draw_horiz_line(callback_mid_x + 1,
state.last_y - 2,
errback_mid_x - callback_mid_x - 1)
def wrap_callback(cb, x):
def callback(res):
cb.draw_active(screen, x, state.last_y, callback_width, res)
draw_connection(x)
state.last_x = x
state.last_y += cb.height + 3
return cb(res)
return callback
def draw_value(res, y):
if isinstance(res, Failure):
text = res.value.args[0] + '*'
text = text.center(callback_width + 20)
screen.draw_text(errback_left_x - 10, y, text)
else:
screen.draw_text(x, y, res.center(callback_width))
def draw_start(res):
draw_value(res, y)
if isinstance(res, Failure):
state.last_x = errback_left_x
else:
state.last_x = x
state.last_y = y + 4
return res
def draw_end(res):
draw_value(res, state.last_y)
if isinstance(res, Failure):
draw_connection(errback_left_x)
else:
draw_connection(x)
d = defer.Deferred()
d.addBoth(draw_start)
for pair in self.deferred.pairs:
callback = wrap_callback(pair[0], x)
errback = wrap_callback(pair[1], errback_left_x)
d.addCallbacks(callback, errback)
d.addBoth(draw_end)
return d
def get_next_pair():
"""Get the next callback/errback pair from the user."""
def get_cb():
if not parts:
raise BadInput('missing command')
cmd = parts.pop(0).lower()
for command in ('return', 'fail', 'passthru'):
if command.startswith(cmd):
cmd = command
break
else:
raise BadInput('bad command: %s' % cmd)
if cmd in ('return', 'fail'):
if not parts:
raise BadInput('missing argument')
result = parts.pop(0)
if len(result) > 6:
raise BadInput('result more than 6 chars long', result)
return Callback(cmd, result)
else:
return Callback(cmd)
try:
line = raw_input()
except EOFError:
sys.exit()
if not line:
return None
parts = line.strip().split()
callback, errback = get_cb(), get_cb()
if parts:
raise BadInput('extra arguments')
return callback, errback
def get_pairs():
"""
Get the list of callback/errback pairs from the user.
They are returned as Callback widgets.
"""
print """\
Enter a list of callback/errback pairs in the form:
CALLBACK ERRBACK
Where CALLBACK and ERRBACK are one of:
return VALUE
fail VALUE
passthru
And where VALUE is a string of only letters and numbers (no spaces),
no more than 6 characters long.
Each pair should be on a single line and you can abbreviate
return/fail/passthru as r/f/p.
Examples:
r good f bad # callback returns 'good'
# and errback raises Exception('bad')
f googly p # callback raises Exception('googly')
# and errback passes its failure along
Enter a blank line when you are done, and a diagram of the deferred
will be printed next to the firing patterns for both the callback()
and errback() methods. In the diagram, a value followed by '*' is
really an Exception wrapped in a Failure, i.e:
value* == Failure(Exception(value))
You will want to make your terminal as wide as possible.
"""
pairs = []
while True:
try:
pair = get_next_pair()
except BadInput, e:
print 'ERROR:', e
continue
if pair is None:
if not pairs:
print 'You must enter at least one pair.'
continue
else:
break
pairs.append(pair)
return pairs
def draw_single_column(d, callback, errback):
screen = Screen()
screen.draw_text(0, 1, 'Deferred'.center(d.width))
screen.draw_text(0, 2, '--------'.center(d.width))
d.draw(screen, 0, 4)
print screen
screen.clear()
screen.draw_text(0, 2, 'd.callback(initial)'.center(d.width))
screen.draw_text(0, 3, '-------------------'.center(d.width))
callback.draw(screen, 0, 5)
print screen
screen.clear()
screen.draw_text(0, 2, 'd.errback(initial*)'.center(d.width))
screen.draw_text(0, 3, '-------------------'.center(d.width))
errback.draw(screen, 0, 5)
print screen
def draw_multi_column(d, callback, errback):
screen = Screen()
screen.draw_text(0, 0, 'Deferred'.center(d.width))
screen.draw_text(0, 1, '--------'.center(d.width))
screen.draw_text(d.width + 6, 0, 'd.callback(initial)'.center(d.width))
screen.draw_text(d.width + 6, 1, '-------------------'.center(d.width))
screen.draw_text(2 * (d.width + 6), 0, 'd.errback(initial*)'.center(d.width))
screen.draw_text(2 * (d.width + 6), 1, '-------------------'.center(d.width))
d.draw(screen, 0, callback.callback_y_offset + 3)
callback.draw(screen, d.width + 6, 3)
errback.draw(screen, 2 * (d.width + 6), 3)
screen.draw_vert_line(d.width + 3, 3, callback.height)
screen.draw_vert_line(d.width + 3 + d.width + 6, 3, callback.height)
print screen
def main():
options = parse_args()
d = Deferred(get_pairs())
callback = FiredDeferred(d, 'callback')
errback = FiredDeferred(d, 'errback')
if options.narrow:
draw_single_column(d, callback, errback)
else:
draw_multi_column(d, callback, errback)
if __name__ == '__main__':
main()