Author: Armin Rigo <[email protected]>
Branch: stacklet
Changeset: r46617:2f596f87d840
Date: 2011-08-18 21:54 +0200
http://bitbucket.org/pypy/pypy/changeset/2f596f87d840/
Log: continulet.throw()
diff --git a/pypy/module/_continuation/interp_continuation.py
b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -28,6 +28,7 @@
def check_sthread(self):
ec = self.space.getexecutioncontext()
if ec.stacklet_thread is not self.sthread:
+ start_state.clear()
raise geterror(self.space, "inter-thread support is missing")
return ec
@@ -47,17 +48,15 @@
start_state.clear()
raise getmemoryerror(self.space)
- def descr_switch(self, w_value=None, w_to=None):
- to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
+ def switch(self, to=None):
if self.sthread is None:
+ start_state.clear()
raise geterror(self.space, "continulet not initialized yet")
if self.sthread.is_empty_handle(self.h):
+ start_state.clear()
raise geterror(self.space, "continulet already finished")
ec = self.check_sthread()
- if self is to: # double-switch to myself: no-op
- return w_value
saved_topframeref = ec.topframeref
- start_state.w_value = w_value
#
start_state.origin = self
if to is None:
@@ -84,6 +83,28 @@
start_state.w_value = None
return w_value
+ def descr_switch(self, w_value=None, w_to=None):
+ to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
+ if self is to: # double-switch to myself: no-op
+ return w_value
+ start_state.w_value = w_value
+ return self.switch(to)
+
+ def descr_throw(self, w_type, w_val=None, w_tb=None):
+ from pypy.interpreter.pytraceback import check_traceback
+ space = self.space
+ #
+ msg = "throw() third argument must be a traceback object"
+ if space.is_w(w_tb, space.w_None):
+ tb = None
+ else:
+ tb = check_traceback(space, w_tb, msg)
+ #
+ operr = OperationError(w_type, w_val, tb)
+ operr.normalize_exception(space)
+ start_state.propagate_exception = operr
+ return self.switch()
+
def descr_is_pending(self):
valid = (self.sthread is not None
and not self.sthread.is_empty_handle(self.h))
@@ -102,6 +123,7 @@
__new__ = interp2app(W_Continulet___new__),
__init__ = interp2app(W_Continulet.descr_init),
switch = interp2app(W_Continulet.descr_switch),
+ throw = interp2app(W_Continulet.descr_throw),
is_pending = interp2app(W_Continulet.descr_is_pending),
)
diff --git a/pypy/module/_continuation/test/test_stacklet.py
b/pypy/module/_continuation/test/test_stacklet.py
--- a/pypy/module/_continuation/test/test_stacklet.py
+++ b/pypy/module/_continuation/test/test_stacklet.py
@@ -487,6 +487,61 @@
assert res == 'z'
raises(TypeError, c1.switch, to=c2) # "can't send non-None value"
+ def test_throw(self):
+ import sys
+ from _continuation import continulet
+ #
+ def f1(c1):
+ try:
+ c1.switch()
+ except KeyError:
+ res = "got keyerror"
+ try:
+ c1.switch(res)
+ except IndexError, e:
+ pass
+ try:
+ c1.switch(e)
+ except IndexError, e2:
+ pass
+ try:
+ c1.switch(e2)
+ except IndexError:
+ c1.throw(*sys.exc_info())
+ should_never_reach_here
+ #
+ c1 = continulet(f1)
+ c1.switch()
+ res = c1.throw(KeyError)
+ assert res == "got keyerror"
+ class FooError(IndexError):
+ pass
+ foo = FooError()
+ res = c1.throw(foo)
+ assert res is foo
+ res = c1.throw(IndexError, foo)
+ assert res is foo
+ #
+ def main():
+ def do_raise():
+ raise foo
+ try:
+ do_raise()
+ except IndexError:
+ tb = sys.exc_info()[2]
+ try:
+ c1.throw(IndexError, foo, tb)
+ except IndexError:
+ tb = sys.exc_info()[2]
+ return tb
+ #
+ tb = main()
+ assert tb.tb_frame.f_code.co_name == 'main'
+ assert tb.tb_next.tb_frame.f_code.co_name == 'f1'
+ assert tb.tb_next.tb_next.tb_frame.f_code.co_name == 'main'
+ assert tb.tb_next.tb_next.tb_next.tb_frame.f_code.co_name == 'do_raise'
+ assert tb.tb_next.tb_next.tb_next.tb_next is None
+
def test_various_depths(self):
skip("may fail on top of CPython")
# run it from test_translated, but not while being actually translated
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit