You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.6 KiB
Python
129 lines
3.6 KiB
Python
import sys
|
|
|
|
|
|
from greenlet import greenlet
|
|
from . import TestCase
|
|
|
|
def switch(*args):
|
|
return greenlet.getcurrent().parent.switch(*args)
|
|
|
|
|
|
class ThrowTests(TestCase):
|
|
def test_class(self):
|
|
def f():
|
|
try:
|
|
switch("ok")
|
|
except RuntimeError:
|
|
switch("ok")
|
|
return
|
|
switch("fail")
|
|
g = greenlet(f)
|
|
res = g.switch()
|
|
self.assertEqual(res, "ok")
|
|
res = g.throw(RuntimeError)
|
|
self.assertEqual(res, "ok")
|
|
|
|
def test_val(self):
|
|
def f():
|
|
try:
|
|
switch("ok")
|
|
except RuntimeError:
|
|
val = sys.exc_info()[1]
|
|
if str(val) == "ciao":
|
|
switch("ok")
|
|
return
|
|
switch("fail")
|
|
|
|
g = greenlet(f)
|
|
res = g.switch()
|
|
self.assertEqual(res, "ok")
|
|
res = g.throw(RuntimeError("ciao"))
|
|
self.assertEqual(res, "ok")
|
|
|
|
g = greenlet(f)
|
|
res = g.switch()
|
|
self.assertEqual(res, "ok")
|
|
res = g.throw(RuntimeError, "ciao")
|
|
self.assertEqual(res, "ok")
|
|
|
|
def test_kill(self):
|
|
def f():
|
|
switch("ok")
|
|
switch("fail")
|
|
g = greenlet(f)
|
|
res = g.switch()
|
|
self.assertEqual(res, "ok")
|
|
res = g.throw()
|
|
self.assertTrue(isinstance(res, greenlet.GreenletExit))
|
|
self.assertTrue(g.dead)
|
|
res = g.throw() # immediately eaten by the already-dead greenlet
|
|
self.assertTrue(isinstance(res, greenlet.GreenletExit))
|
|
|
|
def test_throw_goes_to_original_parent(self):
|
|
main = greenlet.getcurrent()
|
|
|
|
def f1():
|
|
try:
|
|
main.switch("f1 ready to catch")
|
|
except IndexError:
|
|
return "caught"
|
|
return "normal exit"
|
|
|
|
def f2():
|
|
main.switch("from f2")
|
|
|
|
g1 = greenlet(f1)
|
|
g2 = greenlet(f2, parent=g1)
|
|
with self.assertRaises(IndexError):
|
|
g2.throw(IndexError)
|
|
self.assertTrue(g2.dead)
|
|
self.assertTrue(g1.dead)
|
|
|
|
g1 = greenlet(f1)
|
|
g2 = greenlet(f2, parent=g1)
|
|
res = g1.switch()
|
|
self.assertEqual(res, "f1 ready to catch")
|
|
res = g2.throw(IndexError)
|
|
self.assertEqual(res, "caught")
|
|
self.assertTrue(g2.dead)
|
|
self.assertTrue(g1.dead)
|
|
|
|
g1 = greenlet(f1)
|
|
g2 = greenlet(f2, parent=g1)
|
|
res = g1.switch()
|
|
self.assertEqual(res, "f1 ready to catch")
|
|
res = g2.switch()
|
|
self.assertEqual(res, "from f2")
|
|
res = g2.throw(IndexError)
|
|
self.assertEqual(res, "caught")
|
|
self.assertTrue(g2.dead)
|
|
self.assertTrue(g1.dead)
|
|
|
|
def test_non_traceback_param(self):
|
|
with self.assertRaises(TypeError) as exc:
|
|
greenlet.getcurrent().throw(
|
|
Exception,
|
|
Exception(),
|
|
self
|
|
)
|
|
self.assertEqual(str(exc.exception),
|
|
"throw() third argument must be a traceback object")
|
|
|
|
def test_instance_of_wrong_type(self):
|
|
with self.assertRaises(TypeError) as exc:
|
|
greenlet.getcurrent().throw(
|
|
Exception(),
|
|
BaseException()
|
|
)
|
|
|
|
self.assertEqual(str(exc.exception),
|
|
"instance exception may not have a separate value")
|
|
|
|
def test_not_throwable(self):
|
|
with self.assertRaises(TypeError) as exc:
|
|
greenlet.getcurrent().throw(
|
|
"abc"
|
|
)
|
|
self.assertEqual(str(exc.exception),
|
|
"exceptions must be classes, or instances, not str")
|