Commit 85a5e56b authored by Jason Madden's avatar Jason Madden

Make the CFFI backend handle the watcher's args property more like the Cython...

Make the CFFI backend handle the watcher's args property more like the Cython backend. Fixes test__core_watcher.
parent 8743c878
......@@ -23,7 +23,17 @@
- :func:`gevent.spawn_raw` now accepts keyword arguments, as
previously (incorrectly) documented. Reported in :issue:`680` by Ron
Rothman.
- PyPy: PyPy 2.6.1 or later is now required (4.0.1 or later is recommended).
- PyPy: PyPy 2.6.1 or later is now required (4.0.1 or later is
recommended).
- The CFFI backend is now built and usable on CPython implementations
(except on Windows) if ``cffi`` is installed before gevent is
installed. To use the CFFI backend, set the environment variable
``GEVENT_CORE_CFFI_ONLY`` before starting Python. This can aid
debugging in some cases and helps ensure parity across all
combinations of supported platforms.
- The CFFI backend now call the callback of a watcher whose ``args`` attribute is
set to ``None``, just like the Cython backend does. It also only
allows ``args`` to be a tuple or ``None``, again matching the Cython backend.
1.1rc1 (Nov 14, 2015)
=====================
......
......@@ -108,9 +108,14 @@ def _python_callback(handle, revents):
# is not what we want; that can permanently wedge the loop depending
# on which callback was executing
watcher = ffi.from_handle(handle)
if len(watcher.args) > 0 and watcher.args[0] == GEVENT_CORE_EVENTS:
watcher.args = (revents, ) + watcher.args[1:]
watcher.callback(*watcher.args)
args = watcher.args
if args is None:
# Legacy behaviour from corecext: convert None into ()
# See test__core_watcher.py
args = _NOARGS
if len(args) > 0 and args[0] == GEVENT_CORE_EVENTS:
args = (revents, ) + args[1:]
watcher.callback(*args)
except:
watcher._exc_info = sys.exc_info()
# Depending on when the exception happened, the watcher
......@@ -711,7 +716,7 @@ class watcher(object):
self._flags = 0
else:
self._flags = 4
self.args = None
self._args = None
self._callback = None
self._handle = ffi.new_handle(self)
self._gwatcher = ffi.new(self._watcher_struct_pointer_type)
......@@ -812,6 +817,16 @@ class watcher(object):
self._callback = cb
callback = property(_get_callback, _set_callback)
def _get_args(self):
return self._args
def _set_args(self, args):
if not isinstance(args, tuple) and args is not None:
raise TypeError("args must be a tuple or None")
self._args = args
args = property(_get_args, _set_args)
def start(self, callback, *args):
if callback is None:
raise TypeError('callback must be callable, not None')
......
......@@ -30,28 +30,16 @@ class Test(greentest.TestCase):
pass
# test that args can be changed later
io.args = (1, 2, 3)
if greentest.PYPY:
pass # on PYPY .args is just a normal property
else:
# test that only tuple and None are accepted by 'args' attribute
try:
io.args = 5
raise AssertionError('"io.args = 5" must raise TypeError')
except TypeError:
pass
self.assertEqual(io.args, (1, 2, 3))
try:
io.args = [4, 5]
raise AssertionError('"io.args = [4, 5]" must raise TypeError')
except TypeError:
pass
# test that only tuple and None are accepted by 'args' attribute
self.assertRaises(TypeError, setattr, io, 'args', 5)
self.assertEqual(io.args, (1, 2, 3))
if greentest.PYPY:
io.args = ()
else:
# None also works, means empty tuple
# XXX why?
io.args = None
self.assertRaises(TypeError, setattr, io, 'args', [4, 5])
self.assertEqual(io.args, (1, 2, 3))
# None also works, means empty tuple
# XXX why?
io.args = None
self.assertEqual(io.args, None)
start = core.time()
loop.run()
took = core.time() - start
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment