@@ -32,7 +32,9 @@ def foo():
3232 :func:`do_return` call. The result of a yielded Effect will be passed back
3333 into the generator as the result of the ``yield`` expression. Yielded
3434 :func:`do_return` values will provide the ultimate result of the Effect
35- that is returned by the decorated function.
35+ that is returned by the decorated function. Note that :func:`do_return` is
36+ only necessary for Python 2 compatibility; return statements can be used
37+ directly in Python 3-only code.
3638
3739 It's important to note that any generator function decorated by ``@do``
3840 will no longer return a generator, but instead it will return an Effect,
@@ -79,6 +81,9 @@ def do_return(val):
7981 @do
8082 def foo():
8183 yield do_return('hello')
84+
85+ If you're writing Python 3-only code, you don't need to use this function,
86+ and can just use the `return` statement as normal.
8287 """
8388 return _ReturnSentinel (val )
8489
@@ -89,7 +94,7 @@ def _do(result, generator, is_error):
8994 val = generator .throw (* result )
9095 else :
9196 val = generator .send (result )
92- except StopIteration :
97+ except StopIteration as stop :
9398 # If the generator we're spinning directly raises StopIteration, we'll
9499 # treat it like returning None from the function. But there may be a
95100 # case where some other code is raising StopIteration up through this
@@ -99,7 +104,12 @@ def _do(result, generator, is_error):
99104 if tb .tb_next :
100105 raise
101106 else :
102- return None
107+ # Python 3 allows you to use `return val` in a generator, which
108+ # will be translated to a `StopIteration` with a `value` attribute
109+ # set to the return value. So we'll return that value as the
110+ # ultimate result of the effect. Python 2 doesn't have the 'value'
111+ # attribute of StopIteration, so we'll fall back to None.
112+ return getattr (stop , 'value' , None )
103113 if type (val ) is _ReturnSentinel :
104114 return val .result
105115 elif type (val ) is Effect :
0 commit comments