From 4dd14d9320f04d5157fbf8b5a70c33e4fa2b65c112cabe60b2849531f368d52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Fri, 7 Jun 2019 12:27:52 +0000 Subject: [PATCH] - Do not generate sphinx docu, it is online and now we have only python3 Sphinx anyway - Update to 0.25.0: * Support for new python and ssl - Remove patches that are in upstream release: * 0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch * 0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch * 0002-Fix-for-Python-3.7-506.patch * 0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-eventlet?expand=0&rev=60 --- ...mport-in-use_hub-thread-race-caused-.patch | 717 ------------------ ...-non-monotonic-time.time-for-timeout.patch | 67 -- 0002-Fix-for-Python-3.7-506.patch | 96 --- ...ty-with-Python-3.7-ssl.SSLSocket-531.patch | 165 ---- eventlet-0.24.1.tar.gz | 3 - eventlet-0.25.0.tar.gz | 3 + python-eventlet.changes | 13 + python-eventlet.spec | 43 +- 8 files changed, 29 insertions(+), 1078 deletions(-) delete mode 100644 0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch delete mode 100644 0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch delete mode 100644 0002-Fix-for-Python-3.7-506.patch delete mode 100644 0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch delete mode 100644 eventlet-0.24.1.tar.gz create mode 100644 eventlet-0.25.0.tar.gz diff --git a/0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch b/0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch deleted file mode 100644 index 9e3a9f5..0000000 --- a/0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch +++ /dev/null @@ -1,717 +0,0 @@ -From 77bccbe48d4d9a46982b2e0503e76784e76b066a Mon Sep 17 00:00:00 2001 -From: Sergey Shepelev -Date: Sun, 2 Sep 2018 01:38:23 +0500 -Subject: [PATCH] IMPORTANT: late import in `use_hub()` + thread race caused - using epolls even when it is unsupported on current platform - -Solution: eager import all built-in hubs, explicitly check support later - -https://github.com/eventlet/eventlet/issues/466 ---- - eventlet/hubs/__init__.py | 103 +++++++++++------------ - eventlet/hubs/epolls.py | 39 +++------ - eventlet/hubs/hub.py | 5 +- - eventlet/hubs/kqueue.py | 34 ++++---- - eventlet/hubs/poll.py | 38 +++++---- - eventlet/hubs/pyevent.py | 10 ++- - eventlet/hubs/selects.py | 38 +++++---- - eventlet/hubs/timer.py | 6 +- - tests/hub_test.py | 56 ++---------- - tests/isolated/hub_kqueue_unsupported.py | 28 ++++++ - tests/isolated/hub_use_hub_class.py | 13 +++ - 11 files changed, 182 insertions(+), 188 deletions(-) - create mode 100644 tests/isolated/hub_kqueue_unsupported.py - create mode 100644 tests/isolated/hub_use_hub_class.py - -diff --git a/eventlet/hubs/__init__.py b/eventlet/hubs/__init__.py -index fc5d3f3..867628c 100644 ---- a/eventlet/hubs/__init__.py -+++ b/eventlet/hubs/__init__.py -@@ -1,4 +1,7 @@ -+import importlib -+import inspect - import os -+import warnings - - from eventlet import patcher - from eventlet.support import greenlets as greenlet -@@ -11,6 +14,15 @@ threading = patcher.original('threading') - _threadlocal = threading.local() - - -+# order is important, get_default_hub returns first available from here -+builtin_hub_names = ('epolls', 'kqueue', 'poll', 'selects') -+builtin_hub_modules = tuple(importlib.import_module('eventlet.hubs.' + name) for name in builtin_hub_names) -+ -+ -+class HubError(Exception): -+ pass -+ -+ - def get_default_hub(): - """Select the default hub implementation based on what multiplexing - libraries are installed. The order that the hubs are tried is: -@@ -26,44 +38,33 @@ def get_default_hub(): - .. include:: ../doc/common.txt - .. note :: |internal| - """ -+ for mod in builtin_hub_modules: -+ if mod.is_available(): -+ return mod - -- # pyevent hub disabled for now because it is not thread-safe -- # try: -- # import eventlet.hubs.pyevent -- # return eventlet.hubs.pyevent -- # except: -- # pass -- -- select = patcher.original('select') -- try: -- import eventlet.hubs.epolls -- return eventlet.hubs.epolls -- except ImportError: -- try: -- import eventlet.hubs.kqueue -- return eventlet.hubs.kqueue -- except ImportError: -- if hasattr(select, 'poll'): -- import eventlet.hubs.poll -- return eventlet.hubs.poll -- else: -- import eventlet.hubs.selects -- return eventlet.hubs.selects -+ raise HubError('no built-in hubs are available: {}'.format(builtin_hub_modules)) - - - def use_hub(mod=None): - """Use the module *mod*, containing a class called Hub, as the - event hub. Usually not required; the default hub is usually fine. - -- Mod can be an actual module, a string, or None. If *mod* is a module, -- it uses it directly. If *mod* is a string and contains either '.' or ':' -- use_hub tries to import the hub using the 'package.subpackage.module:Class' -- convention, otherwise use_hub looks for a matching setuptools entry point -- in the 'eventlet.hubs' group to load or finally tries to import -- `eventlet.hubs.mod` and use that as the hub module. If *mod* is None, -- use_hub uses the default hub. Only call use_hub during application -- initialization, because it resets the hub's state and any existing -+ `mod` can be an actual hub class, a module, a string, or None. -+ -+ If `mod` is a class, use it directly. -+ If `mod` is a module, use `module.Hub` class -+ If `mod` is a string and contains either '.' or ':' -+ then `use_hub` uses 'package.subpackage.module:Class' convention, -+ otherwise imports `eventlet.hubs.mod`. -+ If `mod` is None, `use_hub` uses the default hub. -+ -+ Only call use_hub during application initialization, -+ because it resets the hub's state and any existing - timers or listeners will never be resumed. -+ -+ These two threadlocal attributes are not part of Eventlet public API: -+ - `threadlocal.Hub` (capital H) is hub constructor, used when no hub is currently active -+ - `threadlocal.hub` (lowercase h) is active hub instance - """ - if mod is None: - mod = os.environ.get('EVENTLET_HUB', None) -@@ -71,36 +72,30 @@ def use_hub(mod=None): - mod = get_default_hub() - if hasattr(_threadlocal, 'hub'): - del _threadlocal.hub -+ -+ classname = '' - if isinstance(mod, six.string_types): - assert mod.strip(), "Need to specify a hub" - if '.' in mod or ':' in mod: - modulename, _, classname = mod.strip().partition(':') -- mod = __import__(modulename, globals(), locals(), [classname]) -- if classname: -- mod = getattr(mod, classname) - else: -- found = False -- -- # setuptools 5.4.1 test_import_patched_defaults fail -- # https://github.com/eventlet/eventlet/issues/177 -- try: -- # try and import pkg_resources ... -- import pkg_resources -- except ImportError: -- # ... but do not depend on it -- pkg_resources = None -- if pkg_resources is not None: -- for entry in pkg_resources.iter_entry_points( -- group='eventlet.hubs', name=mod): -- mod, found = entry.load(), True -- break -- if not found: -- mod = __import__( -- 'eventlet.hubs.' + mod, globals(), locals(), ['Hub']) -- if hasattr(mod, 'Hub'): -- _threadlocal.Hub = mod.Hub -+ modulename = 'eventlet.hubs.' + mod -+ mod = importlib.import_module(modulename) -+ -+ if hasattr(mod, 'is_available'): -+ if not mod.is_available(): -+ raise Exception('selected hub is not available on this system mod={}'.format(mod)) - else: -- _threadlocal.Hub = mod -+ msg = '''Please provide `is_available()` function in your custom Eventlet hub {mod}. -+It must return bool: whether hub supports current platform. See eventlet/hubs/{{epoll,kqueue}} for example. -+'''.format(mod=mod) -+ warnings.warn(msg, DeprecationWarning, stacklevel=3) -+ -+ hubclass = mod -+ if not inspect.isclass(mod): -+ hubclass = getattr(mod, classname or 'Hub') -+ -+ _threadlocal.Hub = hubclass - - - def get_hub(): -diff --git a/eventlet/hubs/epolls.py b/eventlet/hubs/epolls.py -index c338756..07fec14 100644 ---- a/eventlet/hubs/epolls.py -+++ b/eventlet/hubs/epolls.py -@@ -1,40 +1,29 @@ - import errno --from eventlet.support import get_errno --from eventlet import patcher -+from eventlet import patcher, support -+from eventlet.hubs import hub, poll - select = patcher.original('select') --if not hasattr(select, 'epoll'): -- # TODO: remove mention of python-epoll on 2019-01 -- raise ImportError('No epoll implementation found in select module.' -- ' python-epoll (or similar) package support was removed,' -- ' please open issue on https://github.com/eventlet/eventlet/' -- ' if you must use epoll outside stdlib.') --epoll = select.epoll - --from eventlet.hubs.hub import BaseHub --from eventlet.hubs import poll --from eventlet.hubs.poll import READ, WRITE - --# NOTE: we rely on the fact that the epoll flag constants --# are identical in value to the poll constants -+def is_available(): -+ return hasattr(select, 'epoll') - - -+# NOTE: we rely on the fact that the epoll flag constants -+# are identical in value to the poll constants - class Hub(poll.Hub): - def __init__(self, clock=None): -- BaseHub.__init__(self, clock) -- self.poll = epoll() -+ super(Hub, self).__init__(clock=clock) -+ self.poll = select.epoll() - - def add(self, evtype, fileno, cb, tb, mac): -- oldlisteners = bool(self.listeners[READ].get(fileno) or -- self.listeners[WRITE].get(fileno)) -- listener = BaseHub.add(self, evtype, fileno, cb, tb, mac) -+ oldlisteners = bool(self.listeners[self.READ].get(fileno) or -+ self.listeners[self.WRITE].get(fileno)) -+ # not super() to avoid double register() -+ listener = hub.BaseHub.add(self, evtype, fileno, cb, tb, mac) - try: -- if not oldlisteners: -- # Means we've added a new listener -- self.register(fileno, new=True) -- else: -- self.register(fileno, new=False) -+ self.register(fileno, new=not oldlisteners) - except IOError as ex: # ignore EEXIST, #80 -- if get_errno(ex) != errno.EEXIST: -+ if support.get_errno(ex) != errno.EEXIST: - raise - return listener - -diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py -index 112f467..8871082 100644 ---- a/eventlet/hubs/hub.py -+++ b/eventlet/hubs/hub.py -@@ -19,7 +19,8 @@ else: - signal.alarm(math.ceil(seconds)) - arm_alarm = alarm_signal - --from eventlet.hubs import timer, IOClosed -+import eventlet.hubs -+from eventlet.hubs import timer - from eventlet.support import greenlets as greenlet, clear_sys_exc_info - import monotonic - import six -@@ -265,7 +266,7 @@ class BaseHub(object): - listener = self.closed.pop() - if not listener.greenlet.dead: - # There's no point signalling a greenlet that's already dead. -- listener.tb(IOClosed(errno.ENOTCONN, "Operation on closed file")) -+ listener.tb(eventlet.hubs.IOClosed(errno.ENOTCONN, "Operation on closed file")) - - def ensure_greenlet(self): - if self.greenlet.dead: -diff --git a/eventlet/hubs/kqueue.py b/eventlet/hubs/kqueue.py -index 0e60d33..bad4a87 100644 ---- a/eventlet/hubs/kqueue.py -+++ b/eventlet/hubs/kqueue.py -@@ -1,25 +1,24 @@ - import os - import sys - from eventlet import patcher, support -+from eventlet.hubs import hub - import six - select = patcher.original('select') - time = patcher.original('time') - --from eventlet.hubs.hub import BaseHub, READ, WRITE, noop - -+def is_available(): -+ return hasattr(select, 'kqueue') - --if getattr(select, 'kqueue', None) is None: -- raise ImportError('No kqueue implementation found in select module') - -- --FILTERS = {READ: select.KQ_FILTER_READ, -- WRITE: select.KQ_FILTER_WRITE} -- -- --class Hub(BaseHub): -+class Hub(hub.BaseHub): - MAX_EVENTS = 100 - - def __init__(self, clock=None): -+ self.FILTERS = { -+ hub.READ: select.KQ_FILTER_READ, -+ hub.WRITE: select.KQ_FILTER_WRITE, -+ } - super(Hub, self).__init__(clock) - self._events = {} - self._init_kqueue() -@@ -31,10 +30,9 @@ class Hub(BaseHub): - def _reinit_kqueue(self): - self.kqueue.close() - self._init_kqueue() -- kqueue = self.kqueue - events = [e for i in six.itervalues(self._events) - for e in six.itervalues(i)] -- kqueue.control(events, 0, 0) -+ self.kqueue.control(events, 0, 0) - - def _control(self, events, max_events, timeout): - try: -@@ -51,7 +49,7 @@ class Hub(BaseHub): - events = self._events.setdefault(fileno, {}) - if evtype not in events: - try: -- event = select.kevent(fileno, FILTERS.get(evtype), select.KQ_EV_ADD) -+ event = select.kevent(fileno, self.FILTERS.get(evtype), select.KQ_EV_ADD) - self._control([event], 0, 0) - events[evtype] = event - except ValueError: -@@ -90,8 +88,8 @@ class Hub(BaseHub): - pass - - def wait(self, seconds=None): -- readers = self.listeners[READ] -- writers = self.listeners[WRITE] -+ readers = self.listeners[self.READ] -+ writers = self.listeners[self.WRITE] - - if not readers and not writers: - if seconds: -@@ -103,10 +101,10 @@ class Hub(BaseHub): - fileno = event.ident - evfilt = event.filter - try: -- if evfilt == FILTERS[READ]: -- readers.get(fileno, noop).cb(fileno) -- if evfilt == FILTERS[WRITE]: -- writers.get(fileno, noop).cb(fileno) -+ if evfilt == select.KQ_FILTER_READ: -+ readers.get(fileno, hub.noop).cb(fileno) -+ if evfilt == select.KQ_FILTER_WRITE: -+ writers.get(fileno, hub.noop).cb(fileno) - except SYSTEM_EXCEPTIONS: - raise - except: -diff --git a/eventlet/hubs/poll.py b/eventlet/hubs/poll.py -index 17bc9e7..1bbd401 100644 ---- a/eventlet/hubs/poll.py -+++ b/eventlet/hubs/poll.py -@@ -1,21 +1,22 @@ - import errno - import sys - --from eventlet import patcher -+from eventlet import patcher, support -+from eventlet.hubs import hub - select = patcher.original('select') - time = patcher.original('time') - --from eventlet.hubs.hub import BaseHub, READ, WRITE, noop --from eventlet.support import get_errno, clear_sys_exc_info - --EXC_MASK = select.POLLERR | select.POLLHUP --READ_MASK = select.POLLIN | select.POLLPRI --WRITE_MASK = select.POLLOUT -+def is_available(): -+ return hasattr(select, 'poll') - - --class Hub(BaseHub): -+class Hub(hub.BaseHub): - def __init__(self, clock=None): - super(Hub, self).__init__(clock) -+ self.EXC_MASK = select.POLLERR | select.POLLHUP -+ self.READ_MASK = select.POLLIN | select.POLLPRI -+ self.WRITE_MASK = select.POLLOUT - self.poll = select.poll() - - def add(self, evtype, fileno, cb, tb, mac): -@@ -29,10 +30,10 @@ class Hub(BaseHub): - - def register(self, fileno, new=False): - mask = 0 -- if self.listeners[READ].get(fileno): -- mask |= READ_MASK | EXC_MASK -- if self.listeners[WRITE].get(fileno): -- mask |= WRITE_MASK | EXC_MASK -+ if self.listeners[self.READ].get(fileno): -+ mask |= self.READ_MASK | self.EXC_MASK -+ if self.listeners[self.WRITE].get(fileno): -+ mask |= self.WRITE_MASK | self.EXC_MASK - try: - if mask: - if new: -@@ -68,8 +69,8 @@ class Hub(BaseHub): - return self.poll.poll(int(seconds * 1000.0)) - - def wait(self, seconds=None): -- readers = self.listeners[READ] -- writers = self.listeners[WRITE] -+ readers = self.listeners[self.READ] -+ writers = self.listeners[self.WRITE] - - if not readers and not writers: - if seconds: -@@ -78,7 +79,7 @@ class Hub(BaseHub): - try: - presult = self.do_poll(seconds) - except (IOError, select.error) as e: -- if get_errno(e) == errno.EINTR: -+ if support.get_errno(e) == errno.EINTR: - return - raise - SYSTEM_EXCEPTIONS = self.SYSTEM_EXCEPTIONS -@@ -92,15 +93,16 @@ class Hub(BaseHub): - # polled for. It prevents one handler from invalidating - # another. - callbacks = set() -+ noop = hub.noop # shave getattr - for fileno, event in presult: -- if event & READ_MASK: -+ if event & self.READ_MASK: - callbacks.add((readers.get(fileno, noop), fileno)) -- if event & WRITE_MASK: -+ if event & self.WRITE_MASK: - callbacks.add((writers.get(fileno, noop), fileno)) - if event & select.POLLNVAL: - self.remove_descriptor(fileno) - continue -- if event & EXC_MASK: -+ if event & self.EXC_MASK: - callbacks.add((readers.get(fileno, noop), fileno)) - callbacks.add((writers.get(fileno, noop), fileno)) - -@@ -111,7 +113,7 @@ class Hub(BaseHub): - raise - except: - self.squelch_exception(fileno, sys.exc_info()) -- clear_sys_exc_info() -+ support.clear_sys_exc_info() - - if self.debug_blocking: - self.block_detect_post() -diff --git a/eventlet/hubs/pyevent.py b/eventlet/hubs/pyevent.py -index 73c0a18..8367a65 100644 ---- a/eventlet/hubs/pyevent.py -+++ b/eventlet/hubs/pyevent.py -@@ -1,12 +1,20 @@ - import sys - import traceback --import event - import types - - from eventlet.support import greenlets as greenlet - import six - from eventlet.hubs.hub import BaseHub, READ, WRITE - -+try: -+ import event -+except ImportError: -+ event = None -+ -+ -+def is_available(): -+ return event is not None -+ - - class event_wrapper(object): - -diff --git a/eventlet/hubs/selects.py b/eventlet/hubs/selects.py -index 3f04e1a..0ead5b8 100644 ---- a/eventlet/hubs/selects.py -+++ b/eventlet/hubs/selects.py -@@ -1,60 +1,64 @@ - import errno - import sys --from eventlet import patcher --from eventlet.support import get_errno, clear_sys_exc_info -+from eventlet import patcher, support -+from eventlet.hubs import hub - select = patcher.original('select') - time = patcher.original('time') - --from eventlet.hubs.hub import BaseHub, READ, WRITE, noop -- - try: - BAD_SOCK = set((errno.EBADF, errno.WSAENOTSOCK)) - except AttributeError: - BAD_SOCK = set((errno.EBADF,)) - - --class Hub(BaseHub): -+def is_available(): -+ return hasattr(select, 'select') -+ -+ -+class Hub(hub.BaseHub): - def _remove_bad_fds(self): - """ Iterate through fds, removing the ones that are bad per the - operating system. - """ -- all_fds = list(self.listeners[READ]) + list(self.listeners[WRITE]) -+ all_fds = list(self.listeners[self.READ]) + list(self.listeners[self.WRITE]) - for fd in all_fds: - try: - select.select([fd], [], [], 0) - except select.error as e: -- if get_errno(e) in BAD_SOCK: -+ if support.get_errno(e) in BAD_SOCK: - self.remove_descriptor(fd) - - def wait(self, seconds=None): -- readers = self.listeners[READ] -- writers = self.listeners[WRITE] -+ readers = self.listeners[self.READ] -+ writers = self.listeners[self.WRITE] - if not readers and not writers: - if seconds: - time.sleep(seconds) - return -- all_fds = list(readers) + list(writers) -+ reader_fds = list(readers) -+ writer_fds = list(writers) -+ all_fds = reader_fds + writer_fds - try: -- r, w, er = select.select(readers.keys(), writers.keys(), all_fds, seconds) -+ r, w, er = select.select(reader_fds, writer_fds, all_fds, seconds) - except select.error as e: -- if get_errno(e) == errno.EINTR: -+ if support.get_errno(e) == errno.EINTR: - return -- elif get_errno(e) in BAD_SOCK: -+ elif support.get_errno(e) in BAD_SOCK: - self._remove_bad_fds() - return - else: - raise - - for fileno in er: -- readers.get(fileno, noop).cb(fileno) -- writers.get(fileno, noop).cb(fileno) -+ readers.get(fileno, hub.noop).cb(fileno) -+ writers.get(fileno, hub.noop).cb(fileno) - - for listeners, events in ((readers, r), (writers, w)): - for fileno in events: - try: -- listeners.get(fileno, noop).cb(fileno) -+ listeners.get(fileno, hub.noop).cb(fileno) - except self.SYSTEM_EXCEPTIONS: - raise - except: - self.squelch_exception(fileno, sys.exc_info()) -- clear_sys_exc_info() -+ support.clear_sys_exc_info() -diff --git a/eventlet/hubs/timer.py b/eventlet/hubs/timer.py -index 9b10b00..1dfd561 100644 ---- a/eventlet/hubs/timer.py -+++ b/eventlet/hubs/timer.py -@@ -1,8 +1,8 @@ - import traceback - -+import eventlet.hubs - from eventlet.support import greenlets as greenlet - import six --from eventlet.hubs import get_hub - - """ If true, captures a stack trace for each timer when constructed. This is - useful for debugging leaking timers, to find out where the timer was set up. """ -@@ -48,7 +48,7 @@ class Timer(object): - """Schedule this timer to run in the current runloop. - """ - self.called = False -- self.scheduled_time = get_hub().add_timer(self) -+ self.scheduled_time = eventlet.hubs.get_hub().add_timer(self) - return self - - def __call__(self, *args): -@@ -69,7 +69,7 @@ class Timer(object): - """ - if not self.called: - self.called = True -- get_hub().timer_canceled(self) -+ eventlet.hubs.get_hub().timer_canceled(self) - try: - del self.tpl - except AttributeError: -diff --git a/tests/hub_test.py b/tests/hub_test.py -index 61b5b0b..d62b805 100644 ---- a/tests/hub_test.py -+++ b/tests/hub_test.py -@@ -4,7 +4,6 @@ import time - - import tests - from tests import skip_with_pyevent, skip_if_no_itimer, skip_unless --from tests.patcher_test import ProcessBase - import eventlet - from eventlet import hubs - from eventlet.support import greenlets -@@ -205,17 +204,6 @@ class TestExceptionInGreenthread(tests.LimitedTestCase): - g.kill() - - --class TestHubSelection(tests.LimitedTestCase): -- -- def test_explicit_hub(self): -- oldhub = hubs.get_hub() -- try: -- hubs.use_hub(Foo) -- assert isinstance(hubs.get_hub(), Foo), hubs.get_hub() -- finally: -- hubs._threadlocal.hub = oldhub -- -- - class TestHubBlockingDetector(tests.LimitedTestCase): - TEST_TIMEOUT = 10 - -@@ -361,43 +349,11 @@ class TestDeadRunLoop(tests.LimitedTestCase): - assert g.dead # sanity check that dummyproc has completed - - --class Foo(object): -- pass -- -- --class TestDefaultHub(ProcessBase): -- -- def test_kqueue_unsupported(self): -- # https://github.com/eventlet/eventlet/issues/38 -- # get_hub on windows broken by kqueue -- module_source = r''' --from __future__ import print_function -- --# Simulate absence of kqueue even on platforms that support it. --import select --try: -- del select.kqueue --except AttributeError: -- pass -- --from six.moves import builtins -- --original_import = builtins.__import__ -- --def fail_import(name, *args, **kwargs): -- if 'epoll' in name: -- raise ImportError('disabled for test') -- if 'kqueue' in name: -- print('kqueue tried') -- return original_import(name, *args, **kwargs) -- --builtins.__import__ = fail_import -+def test_use_hub_class(): -+ tests.run_isolated('hub_use_hub_class.py') - - --import eventlet.hubs --eventlet.hubs.get_default_hub() --print('ok') --''' -- self.write_to_tempfile('newmod', module_source) -- output, _ = self.launch_subprocess('newmod.py') -- self.assertEqual(output, 'kqueue tried\nok\n') -+def test_kqueue_unsupported(): -+ # https://github.com/eventlet/eventlet/issues/38 -+ # get_hub on windows broken by kqueue -+ tests.run_isolated('hub_kqueue_unsupported.py') -diff --git a/tests/isolated/hub_kqueue_unsupported.py b/tests/isolated/hub_kqueue_unsupported.py -new file mode 100644 -index 0000000..373df98 ---- /dev/null -+++ b/tests/isolated/hub_kqueue_unsupported.py -@@ -0,0 +1,28 @@ -+from __future__ import print_function -+__test__ = False -+ -+ -+def delattr_silent(x, name): -+ try: -+ delattr(x, name) -+ except AttributeError: -+ pass -+ -+ -+if __name__ == '__main__': -+ # Simulate absence of kqueue even on platforms that support it. -+ import select -+ delattr_silent(select, 'kqueue') -+ delattr_silent(select, 'KQ_FILTER_READ') -+ # patcher.original used in hub may reimport and return deleted kqueue attribute -+ import eventlet.patcher -+ select_original = eventlet.patcher.original('select') -+ delattr_silent(select_original, 'kqueue') -+ delattr_silent(select_original, 'KQ_FILTER_READ') -+ -+ import eventlet.hubs -+ default = eventlet.hubs.get_default_hub() -+ assert not default.__name__.endswith('kqueue') -+ import eventlet.hubs.kqueue -+ assert not eventlet.hubs.kqueue.is_available() -+ print('pass') -diff --git a/tests/isolated/hub_use_hub_class.py b/tests/isolated/hub_use_hub_class.py -new file mode 100644 -index 0000000..9f7f308 ---- /dev/null -+++ b/tests/isolated/hub_use_hub_class.py -@@ -0,0 +1,13 @@ -+from __future__ import print_function -+__test__ = False -+ -+ -+class Foo(object): -+ pass -+ -+if __name__ == '__main__': -+ import eventlet.hubs -+ eventlet.hubs.use_hub(Foo) -+ hub = eventlet.hubs.get_hub() -+ assert isinstance(hub, Foo), repr(hub) -+ print('pass') --- -2.21.0 - diff --git a/0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch b/0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch deleted file mode 100644 index d971228..0000000 --- a/0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch +++ /dev/null @@ -1,67 +0,0 @@ -From a28a275393d3c3ae3c3a5341cc4764fad21be3e5 Mon Sep 17 00:00:00 2001 -From: Sergey Shepelev -Date: Mon, 27 Aug 2018 00:22:35 +0500 -Subject: [PATCH 1/3] ssl: connect used non-monotonic time.time() for timeout - (#520) - -Origin: https://github.com/eventlet/eventlet/pull/517 - -Related: -https://github.com/eventlet/eventlet/pull/388 -https://github.com/eventlet/eventlet/pull/303 -https://github.com/eventlet/eventlet/issues/270 -https://github.com/eventlet/eventlet/issues/132 ---- - eventlet/green/ssl.py | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py -index 53ee9a3..577afba 100644 ---- a/eventlet/green/ssl.py -+++ b/eventlet/green/ssl.py -@@ -6,9 +6,8 @@ slurp_properties(__ssl, globals(), srckeys=dir(__ssl)) - import errno - import functools - import sys --import time - --from eventlet import greenio -+from eventlet import greenio, hubs - from eventlet.greenio import ( - set_nonblocking, GreenSocket, CONNECT_ERR, CONNECT_SUCCESS, - ) -@@ -264,6 +263,7 @@ class GreenSSLSocket(_original_sslsocket): - if self.act_non_blocking: - return real_connect(self, addr) - else: -+ clock = hubs.get_hub().clock - # *NOTE: gross, copied code from greenio because it's not factored - # well enough to reuse - if self.gettimeout() is None: -@@ -278,7 +278,7 @@ class GreenSSLSocket(_original_sslsocket): - else: - raise - else: -- end = time.time() + self.gettimeout() -+ end = clock() + self.gettimeout() - while True: - try: - real_connect(self, addr) -@@ -286,12 +286,12 @@ class GreenSSLSocket(_original_sslsocket): - if get_errno(exc) in CONNECT_ERR: - trampoline( - self, write=True, -- timeout=end - time.time(), timeout_exc=timeout_exc('timed out')) -+ timeout=end - clock(), timeout_exc=timeout_exc('timed out')) - elif get_errno(exc) in CONNECT_SUCCESS: - return - else: - raise -- if time.time() >= end: -+ if clock() >= end: - raise timeout_exc('timed out') - - def connect(self, addr): --- -2.21.0 - diff --git a/0002-Fix-for-Python-3.7-506.patch b/0002-Fix-for-Python-3.7-506.patch deleted file mode 100644 index 15e9441..0000000 --- a/0002-Fix-for-Python-3.7-506.patch +++ /dev/null @@ -1,96 +0,0 @@ -From cf47cb518db3e0dbdd48473fb40cf9f6ecd50e07 Mon Sep 17 00:00:00 2001 -From: Marcel Plch -Date: Fri, 28 Sep 2018 17:08:59 +0200 -Subject: [PATCH 2/3] Fix for Python 3.7 (#506) - -* Fix for Python 3.7 - -* Remove redundant piece of code. - -* Put back do_handshake_on_connect kwarg - -* Use Python 3.7 instead of 3.7-dev - -* Fix buildbot failing permissions with 3.7 - -* tests: env_tpool_zero assert details - -* setup: Python 3.7 classificator ---- - eventlet/green/ssl.py | 46 +++++++++++++++++++++++++++++++++++++------ - 1 file changed, 40 insertions(+), 6 deletions(-) - -diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py -index 577afba..53dff70 100644 ---- a/eventlet/green/ssl.py -+++ b/eventlet/green/ssl.py -@@ -23,6 +23,7 @@ __patched__ = [ - 'create_default_context', '_create_default_https_context'] - - _original_sslsocket = __ssl.SSLSocket -+_original_wrap_socket = __ssl.wrap_socket - - - class GreenSSLSocket(_original_sslsocket): -@@ -56,11 +57,41 @@ class GreenSSLSocket(_original_sslsocket): - # this assignment - self._timeout = sock.gettimeout() - -- # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled -- # even when it's on -- super(GreenSSLSocket, self).__init__( -- sock.fd, keyfile, certfile, server_side, cert_reqs, ssl_version, -- ca_certs, do_handshake_on_connect and six.PY2, *args, **kw) -+ if sys.version_info >= (3, 7): -+ # Monkey-patch the sslsocket so our modified self gets -+ # injected into its _create method. -+ def fake_new(self, cls, *args, **kwargs): -+ return self -+ -+ orig_new = _original_sslsocket.__new__ -+ try: -+ _original_sslsocket.__new__ = fake_new.__get__(self, GreenSSLSocket) -+ -+ self = _original_wrap_socket( -+ sock=sock.fd, -+ keyfile=keyfile, -+ certfile=certfile, -+ server_side=server_side, -+ cert_reqs=cert_reqs, -+ ssl_version=ssl_version, -+ ca_certs=ca_certs, -+ do_handshake_on_connect=False, -+ *args, **kw -+ ) -+ self.keyfile = keyfile -+ self.certfile = certfile -+ self.cert_reqs = cert_reqs -+ self.ssl_version = ssl_version -+ self.ca_certs = ca_certs -+ finally: -+ # Unpatch -+ _original_sslsocket.__new__ = orig_new -+ else: -+ # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled -+ # even when it's on -+ super(GreenSSLSocket, self).__init__( -+ sock.fd, keyfile, certfile, server_side, cert_reqs, ssl_version, -+ ca_certs, do_handshake_on_connect and six.PY2, *args, **kw) - - # the superclass initializer trashes the methods so we remove - # the local-object versions of them and let the actual class -@@ -323,7 +354,10 @@ class GreenSSLSocket(_original_sslsocket): - except NameError: - self._sslobj = sslobj - else: -- self._sslobj = SSLObject(sslobj, owner=self) -+ if sys.version_info < (3, 7): -+ self._sslobj = SSLObject(sslobj, owner=self) -+ else: -+ self._sslobj = sslobj - - if self.do_handshake_on_connect: - self.do_handshake() --- -2.21.0 - diff --git a/0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch b/0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch deleted file mode 100644 index 58e3b53..0000000 --- a/0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch +++ /dev/null @@ -1,165 +0,0 @@ -From a915bb642dd6cd4e92c959addff30509977a637c Mon Sep 17 00:00:00 2001 -From: Junyi -Date: Wed, 30 Jan 2019 00:10:31 -0800 -Subject: [PATCH 3/3] Fix compatibility with Python 3.7 ssl.SSLSocket (#531) - ---- - eventlet/green/ssl.py | 86 ++++++++++++++++++++++++------------------- - 1 file changed, 49 insertions(+), 37 deletions(-) - -diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py -index 53dff70..9504aef 100644 ---- a/eventlet/green/ssl.py -+++ b/eventlet/green/ssl.py -@@ -3,10 +3,7 @@ __ssl = __import__('ssl') - from eventlet.patcher import slurp_properties - slurp_properties(__ssl, globals(), srckeys=dir(__ssl)) - --import errno --import functools - import sys -- - from eventlet import greenio, hubs - from eventlet.greenio import ( - set_nonblocking, GreenSocket, CONNECT_ERR, CONNECT_SUCCESS, -@@ -14,6 +11,8 @@ from eventlet.greenio import ( - from eventlet.hubs import trampoline, IOClosed - from eventlet.support import get_errno, PY33 - import six -+from contextlib import contextmanager -+ - orig_socket = __import__('socket') - socket = orig_socket.socket - timeout_exc = SSLError -@@ -24,6 +23,21 @@ __patched__ = [ - - _original_sslsocket = __ssl.SSLSocket - _original_wrap_socket = __ssl.wrap_socket -+_original_sslcontext = getattr(__ssl, 'SSLContext', None) -+_is_under_py_3_7 = sys.version_info < (3, 7) -+ -+ -+@contextmanager -+def _original_ssl_context(*args, **kwargs): -+ tmp_sslcontext = _original_wrap_socket.__globals__.get('SSLContext', None) -+ tmp_sslsocket = _original_sslsocket._create.__globals__.get('SSLSocket', None) -+ _original_sslsocket._create.__globals__['SSLSocket'] = _original_sslsocket -+ _original_wrap_socket.__globals__['SSLContext'] = _original_sslcontext -+ try: -+ yield -+ finally: -+ _original_wrap_socket.__globals__['SSLContext'] = tmp_sslcontext -+ _original_sslsocket._create.__globals__['SSLSocket'] = tmp_sslsocket - - - class GreenSSLSocket(_original_sslsocket): -@@ -40,16 +54,43 @@ class GreenSSLSocket(_original_sslsocket): - settimeout(), and to close/reopen the connection when a timeout - occurs at an unexpected juncture in the code. - """ -+ def __new__(cls, sock=None, keyfile=None, certfile=None, -+ server_side=False, cert_reqs=CERT_NONE, -+ ssl_version=PROTOCOL_SSLv23, ca_certs=None, -+ do_handshake_on_connect=True, *args, **kw): -+ if _is_under_py_3_7: -+ return super(GreenSSLSocket, cls).__new__(cls) -+ else: -+ if not isinstance(sock, GreenSocket): -+ sock = GreenSocket(sock) -+ with _original_ssl_context(): -+ ret = _original_wrap_socket( -+ sock=sock.fd, -+ keyfile=keyfile, -+ certfile=certfile, -+ server_side=server_side, -+ cert_reqs=cert_reqs, -+ ssl_version=ssl_version, -+ ca_certs=ca_certs, -+ do_handshake_on_connect=False, -+ *args, **kw -+ ) -+ ret.keyfile = keyfile -+ ret.certfile = certfile -+ ret.cert_reqs = cert_reqs -+ ret.ssl_version = ssl_version -+ ret.ca_certs = ca_certs -+ ret.__class__ = GreenSSLSocket -+ return ret -+ - # we are inheriting from SSLSocket because its constructor calls - # do_handshake whose behavior we wish to override -- - def __init__(self, sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, *args, **kw): - if not isinstance(sock, GreenSocket): - sock = GreenSocket(sock) -- - self.act_non_blocking = sock.act_non_blocking - - if six.PY2: -@@ -57,42 +98,12 @@ class GreenSSLSocket(_original_sslsocket): - # this assignment - self._timeout = sock.gettimeout() - -- if sys.version_info >= (3, 7): -- # Monkey-patch the sslsocket so our modified self gets -- # injected into its _create method. -- def fake_new(self, cls, *args, **kwargs): -- return self -- -- orig_new = _original_sslsocket.__new__ -- try: -- _original_sslsocket.__new__ = fake_new.__get__(self, GreenSSLSocket) -- -- self = _original_wrap_socket( -- sock=sock.fd, -- keyfile=keyfile, -- certfile=certfile, -- server_side=server_side, -- cert_reqs=cert_reqs, -- ssl_version=ssl_version, -- ca_certs=ca_certs, -- do_handshake_on_connect=False, -- *args, **kw -- ) -- self.keyfile = keyfile -- self.certfile = certfile -- self.cert_reqs = cert_reqs -- self.ssl_version = ssl_version -- self.ca_certs = ca_certs -- finally: -- # Unpatch -- _original_sslsocket.__new__ = orig_new -- else: -+ if _is_under_py_3_7: - # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled - # even when it's on - super(GreenSSLSocket, self).__init__( - sock.fd, keyfile, certfile, server_side, cert_reqs, ssl_version, - ca_certs, do_handshake_on_connect and six.PY2, *args, **kw) -- - # the superclass initializer trashes the methods so we remove - # the local-object versions of them and let the actual class - # methods shine through -@@ -354,7 +365,7 @@ class GreenSSLSocket(_original_sslsocket): - except NameError: - self._sslobj = sslobj - else: -- if sys.version_info < (3, 7): -+ if _is_under_py_3_7: - self._sslobj = SSLObject(sslobj, owner=self) - else: - self._sslobj = sslobj -@@ -396,6 +407,7 @@ class GreenSSLSocket(_original_sslsocket): - def dup(self): - raise NotImplementedError("Can't dup an ssl object") - -+ - SSLSocket = GreenSSLSocket - - --- -2.21.0 - diff --git a/eventlet-0.24.1.tar.gz b/eventlet-0.24.1.tar.gz deleted file mode 100644 index 25c5bc4..0000000 --- a/eventlet-0.24.1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9d31a3c8dbcedbcce5859a919956d934685b17323fc80e1077cb344a2ffa68d -size 391579 diff --git a/eventlet-0.25.0.tar.gz b/eventlet-0.25.0.tar.gz new file mode 100644 index 0000000..f337959 --- /dev/null +++ b/eventlet-0.25.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0610bd0d3bb3d51d69f74caa4ad04fc7bce424cdb72e54d08ccda90d8c69800 +size 392105 diff --git a/python-eventlet.changes b/python-eventlet.changes index a6dfc51..6f01dce 100644 --- a/python-eventlet.changes +++ b/python-eventlet.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Fri Jun 7 12:14:00 UTC 2019 - Tomáš Chvátal + +- Do not generate sphinx docu, it is online and now we have only + python3 Sphinx anyway +- Update to 0.25.0: + * Support for new python and ssl +- Remove patches that are in upstream release: + * 0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch + * 0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch + * 0002-Fix-for-Python-3.7-506.patch + * 0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch + ------------------------------------------------------------------- Mon Apr 29 06:00:44 UTC 2019 - Thomas Bechtold diff --git a/python-eventlet.spec b/python-eventlet.spec index b925633..a649e9b 100644 --- a/python-eventlet.spec +++ b/python-eventlet.spec @@ -18,26 +18,22 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-eventlet -Version: 0.24.1 +Version: 0.25.0 Release: 0 Summary: Concurrent networking library for Python License: MIT Group: Development/Languages/Python URL: http://eventlet.net Source: https://files.pythonhosted.org/packages/source/e/eventlet/eventlet-%{version}.tar.gz -# PATCH-FIX-UPSTREAM 0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch -- https://github.com/eventlet/eventlet/commit/77bccbe48d4d9a46982b2e0503e76784e76b066a -Patch0: 0001-IMPORTANT-late-import-in-use_hub-thread-race-caused-.patch -# PATCH-FIX-UPSTREAM 0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch -- https://github.com/eventlet/eventlet/commit/a28a275393d3c3ae3c3a5341cc4764fad21be3e5 -Patch1: 0001-ssl-connect-used-non-monotonic-time.time-for-timeout.patch -# PATCH-FIX-UPSTREAM 0002-Fix-for-Python-3.7-506.patch -- https://github.com/eventlet/eventlet/commit/cf47cb518db3e0dbdd48473fb40cf9f6ecd50e07 -Patch2: 0002-Fix-for-Python-3.7-506.patch -# PATCH-FIX-UPSTREAM 0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch -- https://github.com/eventlet/eventlet/commit/a915bb642dd6cd4e92c959addff30509977a637c -Patch3: 0003-Fix-compatibility-with-Python-3.7-ssl.SSLSocket-531.patch - -BuildRequires: %{python_module Sphinx} -BuildRequires: %{python_module greenlet} +BuildRequires: %{python_module dnspython >= 1.15.0} +BuildRequires: %{python_module greenlet >= 0.3} +BuildRequires: %{python_module monotonic >= 1.4} +BuildRequires: %{python_module nose} +BuildRequires: %{python_module pyOpenSSL} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module six >= 1.10.0} BuildRequires: fdupes +BuildRequires: netcfg BuildRequires: python-rpm-macros # eventlet parses /etc/protocols which is not available in normal build envs Requires: netcfg @@ -45,6 +41,7 @@ Requires: python-dnspython >= 1.15.0 Requires: python-greenlet >= 0.3 Requires: python-monotonic >= 1.4 Requires: python-six >= 1.10.0 +Obsoletes: python-doc BuildArch: noarch %if %{python_version_nodots} < 34 Requires: python-enum34 @@ -61,38 +58,24 @@ to threading, but provide the benefits of non-blocking I/O. The event dispatch is implicit, which means Eventlet can be used from the Python interpreter, or as part of a larger application. -%package doc -Summary: Documentation for the Eventlet concurrent networking library -Group: Development/Libraries/Python -Requires: %{name} = %{version} - -%description doc -Documentation for Eventlet, which is a concurrent networking library -for Python that allows changing how code is run. - %prep %setup -q -n eventlet-%{version} -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -sed -i '/enum.compat/d' setup.py # crude way to drop the strange "enum-compat" requirement sed -i "s|^#!.*||" eventlet/support/greendns.py # Fix non-executable script %build %python_build -%python_exec setup.py build_sphinx && rm build/sphinx/html/.buildinfo %install %python_install %python_expand %fdupes %{buildroot}%{$python_sitelib} +%check +# 400 out of 600 tests either fail or error out +#%%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib} nosetests-%{$python_bin_suffix} -v + %files %{python_files} %license LICENSE %doc AUTHORS NEWS README.rst %{python_sitelib}/* -%files %{python_files doc} -%doc build/sphinx/html examples - %changelog