Commit c307b070 authored by Jason Madden's avatar Jason Madden

Remove the deprecated magic proxy gevent.signal.

Leave behind the actual module gevent.signal, and the callable gevent.signal_handler.

Fixes #1596
parent 33e10d8e
......@@ -49,6 +49,15 @@ Library and Dependency Updates
because of the limited amount of actual allocation that gets done
this is not expected to be a bottleneck.
Potentially Breaking Changes
----------------------------
- Remove the magic proxy object ``gevent.signal``. This served as both
a deprecated alias of `gevent.signal_handler` *and* the module
`gevent.signal`. This made it confusing to humans and static
analysis tools alike. The alias was deprecated since gevent 1.1b4.
See :issue:`1596`.
Other
-----
......@@ -78,6 +87,7 @@ Other
before the gevent resolver was initialized. Reported in
:issue:`1526` by Chris Utz and Josh Zuech.
1.5a3 (2020-01-01)
==================
......
......@@ -103,34 +103,7 @@ Working with multiple processes
Signals
=======
.. function:: signal_handler(signalnum, handler, *args, **kwargs)
Call the *handler* with the *args* and *kwargs* when the process
receives the signal *signalnum*.
The *handler* will be run in a new greenlet when the signal is delivered.
This returns an object with the useful method ``cancel``, which, when called,
will prevent future deliveries of *signalnum* from calling *handler*.
.. note::
This may not operate correctly with SIGCHLD if libev child watchers
are used (as they are by default with :func:`gevent.os.fork`).
.. versionchanged:: 1.1b4
``gevent.signal`` is an alias for this function, included for
backwards compatibility; the new module :doc:`gevent.signal <gevent.signal>`
is replacing this name. This alias will be removed in a
future release.
.. versionchanged:: 1.2a1
The *handler* is required to be callable at construction time.
.. This is also in the docstring of gevent.hub.signal, which is the
actual callable invoked
.. autofunction:: signal_handler
Timeouts
========
......
......@@ -97,8 +97,8 @@ def main():
dest = parse_address(args[1])
server = PortForwarder(source, dest)
log('Starting port forwarder %s:%s -> %s:%s', *(server.address[:2] + dest))
gevent.signal(signal.SIGTERM, server.close)
gevent.signal(signal.SIGINT, server.close)
gevent.signal_handler(signal.SIGTERM, server.close)
gevent.signal_handler(signal.SIGINT, server.close)
server.start()
gevent.wait()
......
......@@ -46,7 +46,6 @@ __all__ = [
'killall',
'reinit',
'setswitchinterval',
'signal', # deprecated
'signal_handler',
'sleep',
'spawn',
......@@ -100,60 +99,11 @@ try:
except ImportError:
__all__.remove('fork')
# See https://github.com/gevent/gevent/issues/648
# A temporary backwards compatibility shim to enable users to continue
# to treat 'from gevent import signal' as a callable, to matter whether
# the 'gevent.signal' module has been imported first
from gevent.hub import signal as _signal_class
signal_handler = _signal_class
from gevent import signal as _signal_module
# The object 'gevent.signal' must:
# - be callable, returning a gevent.hub.signal;
# - answer True to isinstance(gevent.signal(...), gevent.signal);
# - answer True to isinstance(gevent.signal(...), gevent.hub.signal)
# - have all the attributes of the module 'gevent.signal';
# - answer True to isinstance(gevent.signal, types.ModuleType) (optional)
# The only way to do this is to use a metaclass, an instance of which (a class)
# is put in sys.modules and is substituted for gevent.hub.signal.
# This handles everything except the last one.
class _signal_metaclass(type):
def __getattr__(cls, name):
return getattr(_signal_module, name)
def __setattr__(cls, name, value):
setattr(_signal_module, name, value)
def __instancecheck__(cls, instance):
return isinstance(instance, _signal_class)
def __dir__(cls):
return dir(_signal_module)
class signal(object):
__doc__ = _signal_module.__doc__
def __new__(cls, *args, **kwargs):
return _signal_class(*args, **kwargs)
# The metaclass is applied after the class declaration
# for Python 2/3 compatibility
signal = _signal_metaclass(str("signal"),
(),
dict(signal.__dict__))
sys.modules['gevent.signal'] = signal
sys.modules['gevent.hub'].signal = signal
del sys
# This used to be available as gevent.signal; that broke in 1.1b4 but
# a temporary alias was added (See
# https://github.com/gevent/gevent/issues/648). It was ugly and complex and
# caused confusion, so it was removed in 1.5. See https://github.com/gevent/gevent/issues/1529
from gevent.hub import signal as signal_handler
# the following makes hidden imports visible to freezing tools like
# py2exe. see https://github.com/gevent/gevent/issues/181
......
......@@ -213,25 +213,32 @@ def kill(greenlet, exception=GreenletExit):
class signal(object):
"""
signal_handler(signalnum, handler, *args, **kwargs) -> object
Call the *handler* with the *args* and *kwargs* when the process
receives the signal *signalnum*.
The *handler* will be run in a new greenlet when the signal is delivered.
The *handler* will be run in a new greenlet when the signal is
delivered.
This returns an object with the useful method ``cancel``, which, when called,
will prevent future deliveries of *signalnum* from calling *handler*.
This returns an object with the useful method ``cancel``, which,
when called, will prevent future deliveries of *signalnum* from
calling *handler*.
.. note::
This may not operate correctly with SIGCHLD if libev child watchers
are used (as they are by default with os.fork).
This may not operate correctly with ``SIGCHLD`` if libev child
watchers are used (as they are by default with
`gevent.os.fork`). See :mod:`gevent.signal` for a more
general purpose solution.
.. versionchanged:: 1.2a1
The ``handler`` argument is required to be callable at construction time.
"""
# XXX: This is manually documented in gevent.rst while it is aliased in
# the gevent module.
The ``handler`` argument is required to
be callable at construction time.
"""
# This is documented as a function, not a class,
# so we're free to change implementation details.
greenlet_class = None
......
......@@ -2,9 +2,9 @@
Cooperative implementation of special cases of :func:`signal.signal`.
This module is designed to work with libev's child watchers, as used
by default in :func:`gevent.os.fork` Note that each ``SIGCHLD`` handler
will be run in a new greenlet when the signal is delivered (just like
:class:`gevent.hub.signal`)
by default in :func:`gevent.os.fork` Note that each ``SIGCHLD``
handler will be run in a new greenlet when the signal is delivered
(just like :class:`gevent.hub.signal`)
The implementations in this module are only monkey patched if
:func:`gevent.os.waitpid` is being used (the default) and if
......@@ -12,6 +12,11 @@ The implementations in this module are only monkey patched if
information on configuring this not to be the case for advanced uses.
.. versionadded:: 1.1b4
.. versionchanged:: 1.5a4
Previously there was a backwards compatibility alias
``gevent.signal``, introduced in 1.1b4, that partly shadowed this
module, confusing humans and static analysis tools alike. That alias
has been removed. (See `gevent.signal_handler`.)
"""
from __future__ import absolute_import
......
from __future__ import print_function
import sys
# Using a direct import of signal (deprecated).
# We are also called from test__core_loop_run_sig_mod.py,
# which has already done 'import gevent.signal' to be sure we work
# when the module has been imported.
from gevent import core, signal
from gevent import core
from gevent import signal_handler as signal
loop = core.loop(default=False)
......
import sys
import gevent.signal
assert gevent.signal # Get gevent.signal as a module, make sure our backwards compatibility kicks in
import test__core_loop_run # this runs main tests, fails if signal() is not callable.
assert test__core_loop_run # pyflakes
from gevent.hub import signal as hub_signal
from gevent import signal as top_signal # pylint:disable=reimported
assert gevent.signal is hub_signal
assert gevent.signal is top_signal
assert hasattr(gevent.signal, 'signal')
s = top_signal(2, sys.stderr.write, 'INTERRUPT')
assert isinstance(s, top_signal)
assert isinstance(s, hub_signal)
......@@ -10,7 +10,7 @@ from gevent.testing.testcase import TimeAssertMixin
SMALL_TICK = 0.05
# setting up signal does not affect join()
gevent.signal(1, lambda: None) # wouldn't work on windows
gevent.signal_handler(1, lambda: None) # wouldn't work on windows
def repeated(func, repetitions=2):
......
......@@ -27,10 +27,11 @@ class TestSignal(greentest.TestCase):
__timeout__ = greentest.LARGE_TIMEOUT
def test_handler(self):
self.assertRaises(TypeError, gevent.signal, signal.SIGALRM, 1)
with self.assertRaises(TypeError):
gevent.signal_handler(signal.SIGALRM, 1)
def test_alarm(self):
sig = gevent.signal(signal.SIGALRM, raise_Expected)
sig = gevent.signal_handler(signal.SIGALRM, raise_Expected)
assert sig.ref is False, repr(sig.ref)
sig.ref = True
assert sig.ref is True
......
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