support: do not clear sys.exc_info if can be preserved (greenlet >= 0.3.2)

This commit is contained in:
Edward George
2012-12-12 22:25:22 +00:00
committed by Sergey Shepelev
parent 2adaeb6159
commit 0195326cbe
3 changed files with 73 additions and 2 deletions

View File

@@ -1,4 +1,8 @@
import sys import sys
from eventlet.support import greenlets
def get_errno(exc): def get_errno(exc):
""" Get the error code out of socket.error objects. """ Get the error code out of socket.error objects.
socket.error in <2.5 does not have errno attribute socket.error in <2.5 does not have errno attribute
@@ -18,7 +22,7 @@ def get_errno(exc):
except IndexError: except IndexError:
return None return None
if sys.version_info[0]<3: if sys.version_info[0]<3 and not greenlets.preserves_excinfo:
from sys import exc_clear as clear_sys_exc_info from sys import exc_clear as clear_sys_exc_info
else: else:
def clear_sys_exc_info(): def clear_sys_exc_info():

View File

@@ -1,7 +1,11 @@
import distutils.version
try: try:
import greenlet import greenlet
getcurrent = greenlet.greenlet.getcurrent getcurrent = greenlet.greenlet.getcurrent
GreenletExit = greenlet.greenlet.GreenletExit GreenletExit = greenlet.greenlet.GreenletExit
preserves_excinfo = (distutils.version.LooseVersion(greenlet.__version__)
>= distutils.version.LooseVersion('0.3.2'))
greenlet = greenlet.greenlet greenlet = greenlet.greenlet
except ImportError, e: except ImportError, e:
raise raise
@@ -9,14 +13,17 @@ except ImportError, e:
from py.magic import greenlet from py.magic import greenlet
getcurrent = greenlet.getcurrent getcurrent = greenlet.getcurrent
GreenletExit = greenlet.GreenletExit GreenletExit = greenlet.GreenletExit
preserves_excinfo = False
except ImportError: except ImportError:
try: try:
from stackless import greenlet from stackless import greenlet
getcurrent = greenlet.getcurrent getcurrent = greenlet.getcurrent
GreenletExit = greenlet.GreenletExit GreenletExit = greenlet.GreenletExit
preserves_excinfo = False
except ImportError: except ImportError:
try: try:
from support.stacklesss import greenlet, getcurrent, GreenletExit from support.stacklesss import greenlet, getcurrent, GreenletExit
preserves_excinfo = False
(greenlet, getcurrent, GreenletExit) # silence pyflakes (greenlet, getcurrent, GreenletExit) # silence pyflakes
except ImportError, e: except ImportError, e:
raise ImportError("Unable to find an implementation of greenlet.") raise ImportError("Unable to find an implementation of greenlet.")

View File

@@ -1,10 +1,14 @@
from __future__ import with_statement from __future__ import with_statement
import sys
from tests import LimitedTestCase, main, skip_with_pyevent, skip_if_no_itimer from tests import LimitedTestCase, main, skip_with_pyevent, skip_if_no_itimer, skip_unless
import time import time
import eventlet import eventlet
from eventlet import hubs from eventlet import hubs
from eventlet.green import socket from eventlet.green import socket
from eventlet.event import Event
from eventlet.semaphore import Semaphore
from eventlet.support import greenlets
DELAY = 0.001 DELAY = 0.001
def noop(): def noop():
@@ -132,6 +136,62 @@ class TestExceptionInMainloop(LimitedTestCase):
assert delay >= DELAY*0.9, 'sleep returned after %s seconds (was scheduled for %s)' % (delay, DELAY) assert delay >= DELAY*0.9, 'sleep returned after %s seconds (was scheduled for %s)' % (delay, DELAY)
class TestExceptionInGreenthread(LimitedTestCase):
@skip_unless(greenlets.preserves_excinfo)
def test_exceptionpreservation(self):
# events for controlling execution order
gt1event = Event()
gt2event = Event()
def test_gt1():
try:
raise KeyError()
except KeyError:
gt1event.send('exception')
gt2event.wait()
assert sys.exc_info()[0] is KeyError
gt1event.send('test passed')
def test_gt2():
gt1event.wait()
gt1event.reset()
assert sys.exc_info()[0] is None
try:
raise ValueError()
except ValueError:
gt2event.send('exception')
gt1event.wait()
assert sys.exc_info()[0] is ValueError
g1 = eventlet.spawn(test_gt1)
g2 = eventlet.spawn(test_gt2)
try:
g1.wait()
g2.wait()
finally:
g1.kill()
g2.kill()
def test_exceptionleaks(self):
# tests expected behaviour with all versions of greenlet
def test_gt(sem):
try:
raise KeyError()
except KeyError:
sem.release()
hubs.get_hub().switch()
# semaphores for controlling execution order
sem = Semaphore()
sem.acquire()
g = eventlet.spawn(test_gt, sem)
try:
sem.acquire()
assert sys.exc_info()[0] is None
finally:
g.kill()
class TestHubSelection(LimitedTestCase): class TestHubSelection(LimitedTestCase):
def test_explicit_hub(self): def test_explicit_hub(self):
if getattr(hubs.get_hub(), 'uses_twisted_reactor', None): if getattr(hubs.get_hub(), 'uses_twisted_reactor', None):