Commit 94d9788f authored by Jason Madden's avatar Jason Madden

Make zope.interface/event and setuptools required dependencies.

Fixes #1619
parent 706833bf
Make ``zope.interface``, ``zope.event`` and (by extension)
``setuptools`` required dependencies. The ``events`` install extra now
does nothing and will be removed in 2021.
...@@ -117,8 +117,7 @@ fall back to doing this if no binary wheel is available. See ...@@ -117,8 +117,7 @@ fall back to doing this if no binary wheel is available. See
Extra Dependencies Extra Dependencies
================== ==================
gevent has no runtime dependencies outside the standard library, There are a number
greenlet, and (on some platforms) `cffi`_. However, there are a number
of additional libraries that extend gevent's functionality and will be of additional libraries that extend gevent's functionality and will be
used if they are available. All of these may be installed using used if they are available. All of these may be installed using
`setuptools extras `setuptools extras
...@@ -126,9 +125,13 @@ used if they are available. All of these may be installed using ...@@ -126,9 +125,13 @@ used if they are available. All of these may be installed using
as named below, e.g., ``pip install gevent[events]``. as named below, e.g., ``pip install gevent[events]``.
events events
Configurable event support using `zope.event In versions of gevent up to and including 20.5.0, this provided configurable
<https://pypi.org/project/zope.event>`_ is highly recommended for event support using `zope.event
configurable event support. <https://pypi.org/project/zope.event>`_ and was highly
recommended.
In versions after that, this extra is empty and does nothing. It
will be removed in gevent 21.0.
dnspython dnspython
Enables the new pure-Python resolver, backed by `dnspython Enables the new pure-Python resolver, backed by `dnspython
......
...@@ -211,7 +211,18 @@ CFFI_REQUIRES = [ ...@@ -211,7 +211,18 @@ CFFI_REQUIRES = [
] ]
install_requires = greenlet_requires + CFFI_REQUIRES install_requires = greenlet_requires + CFFI_REQUIRES + [
# For event notification.
'zope.event',
# For event definitions, and our own interfaces; those should
# ultimately be published, but at this writing only the event
# interfaces are.
'zope.interface',
# setuptools is also used (via pkg_resources) for event
# notifications. It's a hard dependency of zope.interface
# anyway.
'setuptools',
]
# We use headers from greenlet, so it needs to be installed before we # We use headers from greenlet, so it needs to be installed before we
# can compile. If it isn't already installed before we start # can compile. If it isn't already installed before we start
...@@ -284,8 +295,9 @@ EXTRA_DNSPYTHON = [ ...@@ -284,8 +295,9 @@ EXTRA_DNSPYTHON = [
'idna', 'idna',
] ]
EXTRA_EVENTS = [ EXTRA_EVENTS = [
'zope.event', # No longer does anything, but the extra must stay around
'zope.interface', # to avoid breaking install scripts.
# Remove this in 2021.
] ]
EXTRA_PSUTIL_DEPS = [ EXTRA_PSUTIL_DEPS = [
......
...@@ -16,10 +16,11 @@ from __future__ import print_function ...@@ -16,10 +16,11 @@ from __future__ import print_function
import sys import sys
from gevent._util import Interface from zope.interface import Interface
from gevent._util import Attribute from zope.interface import Attribute
# pylint:disable=no-method-argument, unused-argument, no-self-argument # pylint:disable=no-method-argument, unused-argument, no-self-argument
# pylint:disable=inherit-non-class
__all__ = [ __all__ = [
'ILoop', 'ILoop',
......
...@@ -206,25 +206,6 @@ def gmctime(): ...@@ -206,25 +206,6 @@ def gmctime():
import time import time
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
try:
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import Attribute
except ImportError:
class Interface(object):
pass
def implementer(_iface):
def dec(c):
return c
return dec
def Attribute(s):
return s
Interface = Interface
implementer = implementer
Attribute = Attribute
### ###
# Release automation. # Release automation.
......
...@@ -11,13 +11,13 @@ parameter, the event object). ...@@ -11,13 +11,13 @@ parameter, the event object).
Higher level frameworks may take this foundation and build richer Higher level frameworks may take this foundation and build richer
models on it. models on it.
If :mod:`zope.event` is installed, then it will be used to provide the :mod:`zope.event` will be used to provide the functionality of
functionality of `notify` and `subscribers`. See `notify` and `subscribers`. See :mod:`zope.event.classhandler` for a
:mod:`zope.event.classhandler` for a simple class-based approach to simple class-based approach to subscribing to a filtered list of
subscribing to a filtered list of events, and see `zope.component events, and see `zope.component
<https://zopecomponent.readthedocs.io/en/latest/event.html>`_ for a <https://zopecomponent.readthedocs.io/en/latest/event.html>`_ for a
much higher-level, flexible system. If you are using one of these systems, much higher-level, flexible system. If you are using one of these
you generally will not want to directly modify `subscribers`. systems, you generally will not want to directly modify `subscribers`.
.. versionadded:: 1.3b1 .. versionadded:: 1.3b1
""" """
...@@ -61,61 +61,49 @@ __all__ = [ ...@@ -61,61 +61,49 @@ __all__ = [
'GeventDidPatchAllEvent', 'GeventDidPatchAllEvent',
] ]
# pylint:disable=no-self-argument # pylint:disable=no-self-argument,inherit-non-class
import platform
try: from zope.interface import Interface
from zope.event import subscribers from zope.interface import Attribute
from zope.event import notify from zope.interface import implementer
except ImportError:
#: Applications may register for notification of events by appending a from zope.event import subscribers
#: callable to the ``subscribers`` list. from zope.event import notify
#:
#: Each subscriber takes a single argument, which is the event object from pkg_resources import iter_entry_points
#: being published.
#: #: Applications may register for notification of events by appending a
#: Exceptions raised by subscribers will be propagated *without* running #: callable to the ``subscribers`` list.
#: any remaining subscribers. #:
subscribers = [] #: Each subscriber takes a single argument, which is the event object
#: being published.
def notify(event): #:
""" #: Exceptions raised by subscribers will be propagated *without* running
Notify all subscribers of ``event``. #: any remaining subscribers.
""" #:
for subscriber in subscribers: #: This is an alias for `zope.event.subscribers`; prefer to use
subscriber(event) #: that attribute directly.
subscribers = subscribers
notify = notify # export
try: try:
# pkg_resources is technically optional, we don't
# list a hard dependency on it.
__import__('pkg_resources')
except ImportError:
notify_and_call_entry_points = notify
else:
from pkg_resources import iter_entry_points
import platform
try:
# Cache the platform info. pkg_resources uses # Cache the platform info. pkg_resources uses
# platform.machine() for environment markers, and # platform.machine() for environment markers, and
# platform.machine() wants to call os.popen('uname'), which is # platform.machine() wants to call os.popen('uname'), which is
# broken on Py2 when the gevent child signal handler is # broken on Py2 when the gevent child signal handler is
# installed. (see test__monkey_sigchild_2.py) # installed. (see test__monkey_sigchild_2.py)
platform.uname() platform.uname()
except: # pylint:disable=bare-except except: # pylint:disable=bare-except
pass pass
finally: finally:
del platform del platform
def notify_and_call_entry_points(event): def notify_and_call_entry_points(event):
notify(event) notify(event)
for plugin in iter_entry_points(event.ENTRY_POINT_NAME): for plugin in iter_entry_points(event.ENTRY_POINT_NAME):
subscriber = plugin.load() subscriber = plugin.load()
subscriber(event) subscriber(event)
from gevent._util import Interface
from gevent._util import implementer
from gevent._util import Attribute
class IPeriodicMonitorThread(Interface): class IPeriodicMonitorThread(Interface):
""" """
......
...@@ -14,7 +14,8 @@ __all__ = [ ...@@ -14,7 +14,8 @@ __all__ = [
'loop', 'loop',
] ]
from gevent._util import implementer from zope.interface import implementer
from gevent._interfaces import ILoop from gevent._interfaces import ILoop
from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error
......
...@@ -10,6 +10,8 @@ from collections import namedtuple ...@@ -10,6 +10,8 @@ from collections import namedtuple
from operator import delitem from operator import delitem
import signal import signal
from zope.interface import implementer
from gevent import getcurrent from gevent import getcurrent
from gevent.exceptions import LoopExit from gevent.exceptions import LoopExit
...@@ -17,7 +19,6 @@ from gevent._ffi import _dbg # pylint: disable=unused-import ...@@ -17,7 +19,6 @@ from gevent._ffi import _dbg # pylint: disable=unused-import
from gevent._ffi.loop import AbstractLoop from gevent._ffi.loop import AbstractLoop
from gevent._ffi.loop import assign_standard_callbacks from gevent._ffi.loop import assign_standard_callbacks
from gevent._ffi.loop import AbstractCallbacks from gevent._ffi.loop import AbstractCallbacks
from gevent._util import implementer
from gevent._interfaces import ILoop from gevent._interfaces import ILoop
from gevent.libuv import _corecffi # pylint:disable=no-name-in-module,import-error from gevent.libuv import _corecffi # pylint:disable=no-name-in-module,import-error
......
...@@ -7,6 +7,8 @@ from gevent import monkey; monkey.patch_all() ...@@ -7,6 +7,8 @@ from gevent import monkey; monkey.patch_all()
from threading import local from threading import local
from threading import Thread from threading import Thread
from zope import interface
try: try:
from collections.abc import Mapping from collections.abc import Mapping
except ImportError: except ImportError:
...@@ -379,12 +381,7 @@ class TestGeventLocal(greentest.TestCase): ...@@ -379,12 +381,7 @@ class TestGeventLocal(greentest.TestCase):
x = LocalWithClassMethod() x = LocalWithClassMethod()
self.assertIs(LocalWithClassMethod, x.a_classmethod()) self.assertIs(LocalWithClassMethod, x.a_classmethod())
try:
from zope import interface
except ImportError:
interface = None
@greentest.skipIf(interface is None, "Needs zope.interface")
class TestLocalInterface(greentest.TestCase): class TestLocalInterface(greentest.TestCase):
__timeout__ = None __timeout__ = None
......
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