Hello community, here is the log from the commit of package python-eventlet for openSUSE:Factory checked in at 2016-12-04 15:08:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-eventlet (Old) and /work/SRC/openSUSE:Factory/.python-eventlet.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-eventlet" Changes: -------- --- /work/SRC/openSUSE:Factory/python-eventlet/python-eventlet.changes 2016-03-07 13:24:01.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-eventlet.new/python-eventlet.changes 2016-12-04 15:08:53.000000000 +0100 @@ -1,0 +2,11 @@ +Sat Dec 3 18:15:53 UTC 2016 - dmuel...@suse.com + +- update to 0.19.0: + * ssl: IMPORTANT DoS FIX do_handshake_connect=False in server accept(); + * green.urllib2: missing patched ssl module; + * wsgi: environ[headers_raw] tuple of unmodified name: value pairs + * test against modern pyopenssl 16.0.0 for Python 2.7+; + * wsgi: document compatibility with python `logging` + * Minor grammatical improvements and typo fixes to the docs + +------------------------------------------------------------------- Old: ---- eventlet-0.18.4.tar.gz New: ---- eventlet-0.19.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-eventlet.spec ++++++ --- /var/tmp/diff_new_pack.n9bppT/_old 2016-12-04 15:08:54.000000000 +0100 +++ /var/tmp/diff_new_pack.n9bppT/_new 2016-12-04 15:08:54.000000000 +0100 @@ -17,13 +17,13 @@ Name: python-eventlet -Version: 0.18.4 +Version: 0.19.0 Release: 0 Url: http://eventlet.net Summary: Highly concurrent networking library License: MIT Group: Development/Languages/Python -Source: http://pypi.python.org/packages/source/e/eventlet/eventlet-%{version}.tar.gz +Source: https://pypi.io/packages/source/e/eventlet/eventlet-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: python-Sphinx BuildRequires: python-devel ++++++ eventlet-0.18.4.tar.gz -> eventlet-0.19.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/AUTHORS new/eventlet-0.19.0/AUTHORS --- old/eventlet-0.18.4/AUTHORS 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/AUTHORS 2016-05-02 18:25:31.000000000 +0200 @@ -130,3 +130,6 @@ * Josh VanderLinden * Levente Polyak * Phus Lu +* Collin Stocks, fixing eventlet.green.urllib2.urlopen() so it accepts cafile, capath, or cadefault arguments +* Alexis Lee +* Steven Erenst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/NEWS new/eventlet-0.19.0/NEWS --- old/eventlet-0.18.4/NEWS 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/NEWS 2016-05-02 18:25:31.000000000 +0200 @@ -1,3 +1,13 @@ +0.19.0 +====== +* ssl: IMPORTANT DoS FIX do_handshake_connect=False in server accept(); Thanks to Garth Mollett +* patcher: patch existing threading locks; Thanks to Alexis Lee +* green.urllib2: missing patched ssl module; Thanks to Collin RM Stocks +* wsgi: environ[headers_raw] tuple of unmodified name: value pairs +* test against modern pyopenssl 16.0.0 for Python 2.7+; Thanks to Victor Stinner +* wsgi: document compatibility with python `logging` +* Minor grammatical improvements and typo fixes to the docs; Thanks to Steven Erenst + 0.18.4 ====== * wsgi: change TCP_NODELAY to TCP_QUICKACK, ignore socket error when not available diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/PKG-INFO new/eventlet-0.19.0/PKG-INFO --- old/eventlet-0.18.4/PKG-INFO 2016-02-17 18:42:50.000000000 +0100 +++ new/eventlet-0.19.0/PKG-INFO 2016-05-02 18:26:07.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: eventlet -Version: 0.18.4 +Version: 0.19.0 Summary: Highly concurrent networking library Home-page: http://eventlet.net Author: Linden Lab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/doc/modules/timeout.rst new/eventlet-0.19.0/doc/modules/timeout.rst --- old/eventlet-0.18.4/doc/modules/timeout.rst 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/doc/modules/timeout.rst 2016-05-02 18:25:31.000000000 +0200 @@ -11,7 +11,7 @@ finally: timeout.cancel() - When *exception* is omitted or ``None``, the :class:`Timeout` instance + When *exception* is omitted or is ``None``, the :class:`Timeout` instance itself is raised: >>> Timeout(0.1) @@ -48,8 +48,8 @@ * If the code block catches and doesn't re-raise :class:`BaseException` (for example, with ``except:``), then it will catch the Timeout exception, and might not abort as intended. When catching timeouts, keep in mind that the one you catch may not be the - one you have set; if you going to silence a timeout, always check that it's - the same instance that you set:: + one you set; if you plan on silencing a timeout, always check that it's the + same instance that you set:: timeout = Timeout(1) try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/doc/ssl.rst new/eventlet-0.19.0/doc/ssl.rst --- old/eventlet-0.18.4/doc/ssl.rst 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/doc/ssl.rst 2016-05-02 18:25:31.000000000 +0200 @@ -3,7 +3,7 @@ Eventlet makes it easy to use non-blocking SSL sockets. If you're using Python 2.6 or later, you're all set, eventlet wraps the built-in ssl module. If on Python 2.5 or 2.4, you have to install pyOpenSSL_ to use eventlet. -In either case, the the ``green`` modules handle SSL sockets transparently, just like their standard counterparts. As an example, :mod:`eventlet.green.urllib2` can be used to fetch https urls in as non-blocking a fashion as you please:: +In either case, the ``green`` modules handle SSL sockets transparently, just like their standard counterparts. As an example, :mod:`eventlet.green.urllib2` can be used to fetch https urls in as non-blocking a fashion as you please:: from eventlet.green import urllib2 from eventlet import spawn diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/doc/testing.rst new/eventlet-0.19.0/doc/testing.rst --- old/eventlet-0.18.4/doc/testing.rst 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/doc/testing.rst 2016-05-02 18:25:31.000000000 +0200 @@ -37,7 +37,7 @@ Standard Library Tests ---------------------- -Eventlet provides for the ability to test itself with the standard Python networking tests. This verifies that the libraries it wraps work at least as well as the standard ones do. The directory tests/stdlib contains a bunch of stubs that import the standard lib tests from your system and run them. If you do not have any tests in your python distribution, they'll simply fail to import. +Eventlet provides the ability to test itself with the standard Python networking tests. This verifies that the libraries it wraps work at least as well as the standard ones do. The directory tests/stdlib contains a bunch of stubs that import the standard lib tests from your system and run them. If you do not have any tests in your python distribution, they'll simply fail to import. There's a convenience module called all.py designed to handle the impedance mismatch between Nose and the standard tests: @@ -85,10 +85,10 @@ After running the tests to completion, this will emit a huge wodge of module names and line numbers. For some reason, the ``--cover-inclusive`` option breaks everything rather than serving its purpose of limiting the coverage to the local files, so don't use that. -The html option is quite useful because it generates nicely-formatted HTML that are much easier to read than line-number soup. Here's a command that generates the annotation, dumping the html files into a directory called "cover": +The html option is quite useful because it generates nicely-formatted HTML files that are much easier to read than line-number soup. Here's a command that generates the annotation, dumping the html files into a directory called "cover": .. code-block:: sh coverage html -d cover --omit='tempmod,<console>,tests' -(``tempmod`` and ``console`` are omitted because they gets thrown away at the completion of their unit tests and coverage.py isn't smart enough to detect this.) +(``tempmod`` and ``console`` are omitted because they get thrown away at the completion of their unit tests and coverage.py isn't smart enough to detect this.) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/__init__.py new/eventlet-0.19.0/eventlet/__init__.py --- old/eventlet-0.18.4/eventlet/__init__.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/__init__.py 2016-05-02 18:25:31.000000000 +0200 @@ -1,4 +1,4 @@ -version_info = (0, 18, 4) +version_info = (0, 19, 0) __version__ = '.'.join(map(str, version_info)) try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/green/ssl.py new/eventlet-0.19.0/eventlet/green/ssl.py --- old/eventlet-0.18.4/eventlet/green/ssl.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/green/ssl.py 2016-05-02 18:25:31.000000000 +0200 @@ -3,16 +3,17 @@ from eventlet.patcher import slurp_properties slurp_properties(__ssl, globals(), srckeys=dir(__ssl)) +import errno import functools import sys -import errno -time = __import__('time') +import time -from eventlet.support import get_errno, PY33, six -from eventlet.hubs import trampoline, IOClosed +from eventlet import greenio from eventlet.greenio import ( - set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS, + set_nonblocking, GreenSocket, CONNECT_ERR, CONNECT_SUCCESS, ) +from eventlet.hubs import trampoline, IOClosed +from eventlet.support import get_errno, PY33, six orig_socket = __import__('socket') socket = orig_socket.socket if sys.version_info >= (2, 7): @@ -181,10 +182,11 @@ except orig_socket.error as e: if self.act_non_blocking: raise - if get_errno(e) == errno.EWOULDBLOCK: + erno = get_errno(e) + if erno in greenio.SOCKET_BLOCKING: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) - if get_errno(e) in SOCKET_CLOSED: + elif erno in greenio.SOCKET_CLOSED: return '' raise @@ -204,14 +206,15 @@ except orig_socket.error as e: if self.act_non_blocking: raise - if get_errno(e) == errno.EWOULDBLOCK: + erno = get_errno(e) + if erno in greenio.SOCKET_BLOCKING: try: trampoline( self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) except IOClosed: return b'' - if get_errno(e) in SOCKET_CLOSED: + elif erno in greenio.SOCKET_CLOSED: return b'' raise @@ -318,7 +321,7 @@ set_nonblocking(newsock) break except orig_socket.error as e: - if get_errno(e) != errno.EWOULDBLOCK: + if get_errno(e) not in greenio.SOCKET_BLOCKING: raise trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) @@ -331,7 +334,7 @@ cert_reqs=self.cert_reqs, ssl_version=self.ssl_version, ca_certs=self.ca_certs, - do_handshake_on_connect=self.do_handshake_on_connect, + do_handshake_on_connect=False, suppress_ragged_eofs=self.suppress_ragged_eofs) return (new_ssl, addr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/green/urllib2.py new/eventlet-0.19.0/eventlet/green/urllib2.py --- old/eventlet-0.18.4/eventlet/green/urllib2.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/green/urllib2.py 2016-05-02 18:25:31.000000000 +0200 @@ -2,6 +2,7 @@ from eventlet.green import ftplib from eventlet.green import httplib from eventlet.green import socket +from eventlet.green import ssl from eventlet.green import time from eventlet.green import urllib @@ -10,6 +11,7 @@ globals(), ('httplib', httplib), ('socket', socket), + ('ssl', ssl), ('time', time), ('urllib', urllib)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/greenio/base.py new/eventlet-0.19.0/eventlet/greenio/base.py --- old/eventlet-0.18.4/eventlet/greenio/base.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/greenio/base.py 2016-05-02 18:25:31.000000000 +0200 @@ -11,7 +11,7 @@ __all__ = [ 'GreenSocket', '_GLOBAL_DEFAULT_TIMEOUT', 'set_nonblocking', - 'SOCKET_CLOSED', 'CONNECT_ERR', 'CONNECT_SUCCESS', + 'SOCKET_BLOCKING', 'SOCKET_CLOSED', 'CONNECT_ERR', 'CONNECT_SUCCESS', 'shutdown_safe', 'SSL', ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/patcher.py new/eventlet-0.19.0/eventlet/patcher.py --- old/eventlet-0.18.4/eventlet/patcher.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/patcher.py 2016-05-02 18:25:31.000000000 +0200 @@ -250,6 +250,9 @@ on.setdefault(modname, False) on.setdefault(modname, default_on) + if on['thread'] and not already_patched.get('thread'): + _green_existing_locks() + modules_to_patch = [] for name, modules_function in [ ('os', _green_os_modules), @@ -320,6 +323,59 @@ getattr(module, '__name__', None) in already_patched +def _green_existing_locks(): + """Make locks created before monkey-patching safe. + + RLocks rely on a Lock and on Python 2, if an unpatched Lock blocks, it + blocks the native thread. We need to replace these with green Locks. + + This was originally noticed in the stdlib logging module.""" + import gc + import threading + import eventlet.green.thread + lock_type = type(threading.Lock()) + rlock_type = type(threading.RLock()) + if sys.version_info[0] >= 3: + pyrlock_type = type(threading._PyRLock()) + # We're monkey-patching so there can't be any greenlets yet, ergo our thread + # ID is the only valid owner possible. + tid = eventlet.green.thread.get_ident() + for obj in gc.get_objects(): + if isinstance(obj, rlock_type): + if (sys.version_info[0] == 2 and + isinstance(obj._RLock__block, lock_type)): + _fix_py2_rlock(obj, tid) + elif (sys.version_info[0] >= 3 and + not isinstance(obj, pyrlock_type)): + _fix_py3_rlock(obj) + + +def _fix_py2_rlock(rlock, tid): + import eventlet.green.threading + old = rlock._RLock__block + new = eventlet.green.threading.Lock() + rlock._RLock__block = new + if old.locked(): + new.acquire() + rlock._RLock__owner = tid + + +def _fix_py3_rlock(old): + import gc + import threading + new = threading._PyRLock() + while old._is_owned(): + old.release() + new.acquire() + if old._is_owned(): + new.acquire() + gc.collect() + for ref in gc.get_referrers(old): + for k, v in vars(ref): + if v == old: + setattr(ref, k, new) + + def _green_os_modules(): from eventlet.green import os return [('os', os)] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet/wsgi.py new/eventlet-0.19.0/eventlet/wsgi.py --- old/eventlet-0.18.4/eventlet/wsgi.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/eventlet/wsgi.py 2016-05-02 18:25:31.000000000 +0200 @@ -601,9 +601,9 @@ else: headers = [h.split(':', 1) for h in headers] - for k, v in headers: + env['headers_raw'] = headers_raw = tuple((k, v.strip()) for k, v in headers) + for k, v in headers_raw: k = k.replace('-', '_').upper() - v = v.strip() if k in env: continue envk = 'HTTP_' + k @@ -799,7 +799,8 @@ :param sock: Server socket, must be already bound to a port and listening. :param site: WSGI application function. - :param log: File-like object that logs should be written to. + :param log: logging.Logger instance or file-like object that logs should be written to. + If a Logger instance is supplied, messages are sent to the INFO log level. If not specified, sys.stderr is used. :param environ: Additional parameters that go into the environ dictionary of every request. :param max_size: Maximum number of client connections opened at any time by this server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet.egg-info/PKG-INFO new/eventlet-0.19.0/eventlet.egg-info/PKG-INFO --- old/eventlet-0.18.4/eventlet.egg-info/PKG-INFO 2016-02-17 18:42:46.000000000 +0100 +++ new/eventlet-0.19.0/eventlet.egg-info/PKG-INFO 2016-05-02 18:26:01.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: eventlet -Version: 0.18.4 +Version: 0.19.0 Summary: Highly concurrent networking library Home-page: http://eventlet.net Author: Linden Lab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/eventlet.egg-info/SOURCES.txt new/eventlet-0.19.0/eventlet.egg-info/SOURCES.txt --- old/eventlet-0.18.4/eventlet.egg-info/SOURCES.txt 2016-02-17 18:42:50.000000000 +0100 +++ new/eventlet-0.19.0/eventlet.egg-info/SOURCES.txt 2016-05-02 18:26:07.000000000 +0200 @@ -192,6 +192,9 @@ tests/isolated/greenio_double_close_219.py tests/isolated/mysqldb_monkey_patch.py tests/isolated/patcher_blocking_select_methods_are_deleted.py +tests/isolated/patcher_existing_locks_early.py +tests/isolated/patcher_existing_locks_late.py +tests/isolated/patcher_existing_locks_locked.py tests/isolated/patcher_importlib_lock.py tests/isolated/patcher_socketserver_selectors.py tests/isolated/patcher_threading_condition.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/setup.cfg new/eventlet-0.19.0/setup.cfg --- old/eventlet-0.18.4/setup.cfg 2016-02-17 18:42:50.000000000 +0100 +++ new/eventlet-0.19.0/setup.cfg 2016-05-02 18:26:07.000000000 +0200 @@ -2,7 +2,7 @@ universal = True [egg_info] -tag_svn_revision = 0 -tag_build = tag_date = 0 +tag_build = +tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/__init__.py new/eventlet-0.19.0/tests/__init__.py --- old/eventlet-0.18.4/tests/__init__.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/__init__.py 2016-05-02 18:25:31.000000000 +0200 @@ -12,7 +12,10 @@ except ImportError: resource = None import signal -import subprocess +try: + import subprocess32 as subprocess # py2 +except ImportError: + import subprocess # py3 import sys import unittest import warnings @@ -320,7 +323,12 @@ stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) - output, _ = p.communicate() + try: + output, _ = p.communicate(timeout=30) + except subprocess.TimeoutExpired: + p.kill() + output, _ = p.communicate(timeout=30) + return "{0}\nFAIL - timed out".format(output) return output diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/hub_test.py new/eventlet-0.19.0/tests/hub_test.py --- old/eventlet-0.18.4/tests/hub_test.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/hub_test.py 2016-05-02 18:25:31.000000000 +0200 @@ -246,7 +246,7 @@ class TestSuspend(LimitedTestCase): - TEST_TIMEOUT = 3 + TEST_TIMEOUT = 4 longMessage = True maxDiff = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_early.py new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_early.py --- old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_early.py 1970-01-01 01:00:00.000000000 +0100 +++ new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_early.py 2016-05-02 18:25:31.000000000 +0200 @@ -0,0 +1,28 @@ +__test__ = False + + +def aaa(lock, e1, e2): + e1.set() + with lock: + e2.wait() + + +def bbb(lock, e1, e2): + e1.wait() + e2.set() + with lock: + pass + + +if __name__ == '__main__': + import threading + test_lock = threading.RLock() + import eventlet + eventlet.monkey_patch() + + e1, e2 = threading.Event(), threading.Event() + a = eventlet.spawn(aaa, test_lock, e1, e2) + b = eventlet.spawn(bbb, test_lock, e1, e2) + a.wait() + b.wait() + print('pass') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_late.py new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_late.py --- old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_late.py 1970-01-01 01:00:00.000000000 +0100 +++ new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_late.py 2016-05-02 18:25:31.000000000 +0200 @@ -0,0 +1,28 @@ +__test__ = False + + +def aaa(lock, e1, e2): + e1.set() + with lock: + e2.wait() + + +def bbb(lock, e1, e2): + e1.wait() + e2.set() + with lock: + pass + + +if __name__ == '__main__': + import threading + import eventlet + eventlet.monkey_patch() + test_lock = threading.RLock() + + e1, e2 = threading.Event(), threading.Event() + a = eventlet.spawn(aaa, test_lock, e1, e2) + b = eventlet.spawn(bbb, test_lock, e1, e2) + a.wait() + b.wait() + print('pass') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_locked.py new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_locked.py --- old/eventlet-0.18.4/tests/isolated/patcher_existing_locks_locked.py 1970-01-01 01:00:00.000000000 +0100 +++ new/eventlet-0.19.0/tests/isolated/patcher_existing_locks_locked.py 2016-05-02 18:25:31.000000000 +0200 @@ -0,0 +1,42 @@ +__test__ = False + + +def take(lock, sync1, sync2): + sync2.acquire() + sync1.release() + with lock: + sync2.release() + + +if __name__ == '__main__': + import sys + import threading + lock = threading.RLock() + lock.acquire() + import eventlet + eventlet.monkey_patch() + + lock.release() + try: + lock.release() + except RuntimeError as e: + assert e.args == ('cannot release un-acquired lock',) + lock.acquire() + + sync1 = threading.Lock() + sync2 = threading.Lock() + sync1.acquire() + eventlet.spawn(take, lock, sync1, sync2) + # Ensure sync2 has been taken + with sync1: + pass + + # an RLock should be reentrant + lock.acquire() + lock.release() + lock.release() + # To acquire sync2, 'take' must have acquired lock, which has been locked + # until now + sync2.acquire() + + print('pass') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/patcher_test.py new/eventlet-0.19.0/tests/patcher_test.py --- old/eventlet-0.18.4/tests/patcher_test.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/patcher_test.py 2016-05-02 18:25:31.000000000 +0200 @@ -498,6 +498,18 @@ self.assertEqual(lines[1], "True", lines[1]) +def test_patcher_existing_locks_early(): + tests.run_isolated('patcher_existing_locks_early.py') + + +def test_patcher_existing_locks_late(): + tests.run_isolated('patcher_existing_locks_late.py') + + +def test_patcher_existing_locks_locked(): + tests.run_isolated('patcher_existing_locks_locked.py') + + def test_importlib_lock(): tests.run_isolated('patcher_importlib_lock.py') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/ssl_test.py new/eventlet-0.19.0/tests/ssl_test.py --- old/eventlet-0.18.4/tests/ssl_test.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/ssl_test.py 2016-05-02 18:25:31.000000000 +0200 @@ -1,6 +1,5 @@ import socket import warnings -from unittest import main import eventlet from eventlet import greenio @@ -8,22 +7,23 @@ from eventlet.green import ssl except ImportError: pass -from tests import ( - LimitedTestCase, certificate_file, private_key_file, check_idle_cpu_usage, - skip_if_no_ssl -) +import tests -def listen_ssl_socket(address=('127.0.0.1', 0)): +def listen_ssl_socket(address=('localhost', 0), **kwargs): sock = ssl.wrap_socket( - socket.socket(), private_key_file, certificate_file, server_side=True) + socket.socket(), + tests.private_key_file, + tests.certificate_file, + server_side=True, + **kwargs + ) sock.bind(address) sock.listen(50) - return sock -class SSLTest(LimitedTestCase): +class SSLTest(tests.LimitedTestCase): def setUp(self): # disabling socket.ssl warnings because we're testing it here warnings.filterwarnings( @@ -33,30 +33,29 @@ super(SSLTest, self).setUp() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_duplex_response(self): def serve(listener): sock, addr = listener.accept() - sock.read(8192) - sock.write(b'response') + sock.recv(8192) + sock.sendall(b'response') sock = listen_ssl_socket() server_coro = eventlet.spawn(serve, sock) - client = ssl.wrap_socket( - eventlet.connect(('127.0.0.1', sock.getsockname()[1]))) - client.write(b'line 1\r\nline 2\r\n\r\n') - self.assertEqual(client.read(8192), b'response') + client = ssl.wrap_socket(eventlet.connect(sock.getsockname())) + client.sendall(b'line 1\r\nline 2\r\n\r\n') + self.assertEqual(client.recv(8192), b'response') server_coro.wait() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_ssl_close(self): def serve(listener): sock, addr = listener.accept() - sock.read(8192) + sock.recv(8192) try: - self.assertEqual(b"", sock.read(8192)) + self.assertEqual(b'', sock.recv(8192)) except greenio.SSL.ZeroReturnError: pass @@ -64,54 +63,54 @@ server_coro = eventlet.spawn(serve, sock) - raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1])) + raw_client = eventlet.connect(sock.getsockname()) client = ssl.wrap_socket(raw_client) - client.write(b'X') + client.sendall(b'X') greenio.shutdown_safe(client) client.close() server_coro.wait() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_ssl_connect(self): def serve(listener): sock, addr = listener.accept() - sock.read(8192) + sock.recv(8192) sock = listen_ssl_socket() server_coro = eventlet.spawn(serve, sock) raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_client = ssl.wrap_socket(raw_client) - ssl_client.connect(('127.0.0.1', sock.getsockname()[1])) - ssl_client.write(b'abc') + ssl_client.connect(sock.getsockname()) + ssl_client.sendall(b'abc') greenio.shutdown_safe(ssl_client) ssl_client.close() server_coro.wait() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_ssl_unwrap(self): def serve(): sock, addr = listener.accept() self.assertEqual(sock.recv(6), b'before') - sock_ssl = ssl.wrap_socket(sock, private_key_file, certificate_file, + sock_ssl = ssl.wrap_socket(sock, tests.private_key_file, tests.certificate_file, server_side=True) sock_ssl.do_handshake() - self.assertEqual(sock_ssl.read(6), b'during') + self.assertEqual(sock_ssl.recv(6), b'during') sock2 = sock_ssl.unwrap() self.assertEqual(sock2.recv(5), b'after') sock2.close() listener = eventlet.listen(('127.0.0.1', 0)) server_coro = eventlet.spawn(serve) - client = eventlet.connect((listener.getsockname())) - client.send(b'before') + client = eventlet.connect(listener.getsockname()) + client.sendall(b'before') client_ssl = ssl.wrap_socket(client) client_ssl.do_handshake() - client_ssl.write(b'during') + client_ssl.sendall(b'during') client2 = client_ssl.unwrap() - client2.send(b'after') + client2.sendall(b'after') server_coro.wait() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_sendall_cpu_usage(self): """SSL socket.sendall() busy loop @@ -132,8 +131,8 @@ def serve(listener): conn, _ = listener.accept() conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, BUFFER_SIZE) - self.assertEqual(conn.read(8), b'request') - conn.write(b'response') + self.assertEqual(conn.recv(8), b'request') + conn.sendall(b'response') stage_1.wait() conn.sendall(b'x' * SENDALL_SIZE) @@ -144,41 +143,73 @@ client_sock = eventlet.connect(server_sock.getsockname()) client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFER_SIZE) client = ssl.wrap_socket(client_sock) - client.write(b'request') - self.assertEqual(client.read(8), b'response') + client.sendall(b'request') + self.assertEqual(client.recv(8), b'response') stage_1.send() - check_idle_cpu_usage(0.2, 0.1) + tests.check_idle_cpu_usage(0.2, 0.1) server_coro.kill() - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_greensslobject(self): def serve(listener): sock, addr = listener.accept() - sock.write(b'content') + sock.sendall(b'content') greenio.shutdown_safe(sock) sock.close() - listener = listen_ssl_socket(('', 0)) + listener = listen_ssl_socket() eventlet.spawn(serve, listener) - client = ssl.wrap_socket( - eventlet.connect(('localhost', listener.getsockname()[1]))) - self.assertEqual(client.read(1024), b'content') - self.assertEqual(client.read(1024), b'') + client = ssl.wrap_socket(eventlet.connect(listener.getsockname())) + self.assertEqual(client.recv(1024), b'content') + self.assertEqual(client.recv(1024), b'') - @skip_if_no_ssl + @tests.skip_if_no_ssl def test_regression_gh_17(self): - def serve(listener): - sock, addr = listener.accept() - - # to simulate condition mentioned in GH-17 - sock._sslobj = None - sock.sendall(b'some data') - greenio.shutdown_safe(sock) - sock.close() - - listener = listen_ssl_socket(('', 0)) - eventlet.spawn(serve, listener) - ssl.wrap_socket(eventlet.connect(('localhost', listener.getsockname()[1]))) + # https://github.com/eventlet/eventlet/issues/17 + # ssl wrapped but unconnected socket methods go special code path + # test that path at least for syntax/typo errors + sock = ssl.wrap_socket(socket.socket()) + sock.settimeout(0.01) + try: + sock.sendall(b'') + except ssl.SSLError as e: + assert 'timed out' in str(e) + + @tests.skip_if_no_ssl + def test_no_handshake_block_accept_loop(self): + listener = listen_ssl_socket() + listener.settimeout(0.3) -if __name__ == '__main__': - main() + def serve(sock): + try: + name = sock.recv(8) + sock.sendall(b'hello ' + name) + except Exception: + # ignore evil clients + pass + finally: + greenio.shutdown_safe(sock) + sock.close() + + def accept_loop(): + while True: + try: + sock, _ = listener.accept() + except socket.error: + return + eventlet.spawn(serve, sock) + + loopt = eventlet.spawn(accept_loop) + + # evil no handshake + evil = eventlet.connect(listener.getsockname()) + good = ssl.wrap_socket(eventlet.connect(listener.getsockname())) + good.sendall(b'good') + response = good.recv(16) + good.close() + assert response == b'hello good' + evil.close() + + listener.close() + loopt.wait() + eventlet.sleep(0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/wsgi_test.py new/eventlet-0.19.0/tests/wsgi_test.py --- old/eventlet-0.18.4/tests/wsgi_test.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/wsgi_test.py 2016-05-02 18:25:31.000000000 +0200 @@ -1515,6 +1515,19 @@ finally: shutil.rmtree(tempdir) + def test_headers_raw(self): + def app(environ, start_response): + start_response('200 OK', []) + return [b'\n'.join('{0}: {1}'.format(*kv).encode() for kv in environ['headers_raw'])] + + self.spawn_server(site=app) + sock = eventlet.connect(self.server_addr) + sock.sendall(b'GET / HTTP/1.1\r\nHost: localhost\r\nx-ANY_k: one\r\nx-ANY_k: two\r\n\r\n') + result = read_http(sock) + sock.close() + assert result.status == 'HTTP/1.1 200 OK' + assert result.body == b'Host: localhost\nx-ANY_k: one\nx-ANY_k: two' + def read_headers(sock): fd = sock.makefile('rb') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tests/zmq_test.py new/eventlet-0.19.0/tests/zmq_test.py --- old/eventlet-0.18.4/tests/zmq_test.py 2016-02-17 18:40:04.000000000 +0100 +++ new/eventlet-0.19.0/tests/zmq_test.py 2016-05-02 18:25:31.000000000 +0200 @@ -1,9 +1,3 @@ -from __future__ import with_statement - -from eventlet import event, spawn, sleep, semaphore -from nose.tools import * -from tests import check_idle_cpu_usage, LimitedTestCase, using_pyevent, skip_unless - try: from eventlet.green import zmq except ImportError: @@ -11,23 +5,29 @@ else: RECV_ON_CLOSED_SOCKET_ERRNOS = (zmq.ENOTSUP, zmq.ENOTSOCK) +import eventlet +from eventlet import event, spawn, sleep, semaphore +import tests + def zmq_supported(_): try: import zmq except ImportError: return False - return not using_pyevent(_) + return not tests.using_pyevent(_) -class TestUpstreamDownStream(LimitedTestCase): - @skip_unless(zmq_supported) +class TestUpstreamDownStream(tests.LimitedTestCase): + TEST_TIMEOUT = 2 + + @tests.skip_unless(zmq_supported) def setUp(self): super(TestUpstreamDownStream, self).setUp() self.context = zmq.Context() self.sockets = [] - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def tearDown(self): self.clear_up_sockets() super(TestUpstreamDownStream, self).tearDown() @@ -65,7 +65,7 @@ else: self.fail("Function did not raise any error") - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_close_linger(self): """Socket.close() must support linger argument. @@ -75,7 +75,7 @@ sock1.close(1) sock2.close(linger=0) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_recv_spawned_before_send_is_non_blocking(self): req, rep, port = self.create_bound_pair(zmq.PAIR, zmq.PAIR) # req.connect(ipc) @@ -93,7 +93,7 @@ done.wait() self.assertEqual(msg['res'], b'test') - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_close_socket_raises_enotsup(self): req, rep, port = self.create_bound_pair(zmq.PAIR, zmq.PAIR) @@ -102,7 +102,7 @@ self.assertRaisesErrno(RECV_ON_CLOSED_SOCKET_ERRNOS, rep.recv) self.assertRaisesErrno(RECV_ON_CLOSED_SOCKET_ERRNOS, req.send, b'test') - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_close_xsocket_raises_enotsup(self): req, rep, port = self.create_bound_pair(zmq.XREQ, zmq.XREP) @@ -111,7 +111,7 @@ self.assertRaisesErrno(RECV_ON_CLOSED_SOCKET_ERRNOS, rep.recv) self.assertRaisesErrno(RECV_ON_CLOSED_SOCKET_ERRNOS, req.send, b'test') - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_send_1k_req_rep(self): req, rep, port = self.create_bound_pair(zmq.REQ, zmq.REP) sleep() @@ -137,7 +137,7 @@ final_i = done.wait() self.assertEqual(final_i, 0) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_send_1k_push_pull(self): down, up, port = self.create_bound_pair(zmq.PUSH, zmq.PULL) sleep() @@ -161,7 +161,7 @@ final_i = done.wait() self.assertEqual(final_i, 0) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_send_1k_pub_sub(self): pub, sub_all, port = self.create_bound_pair(zmq.PUB, zmq.SUB) sub1 = self.context.socket(zmq.SUB) @@ -210,46 +210,62 @@ self.assertEqual(sub2_count, 500) self.assertEqual(sub_all_count, 1000) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_change_subscription(self): + # FIXME: Extensive testing showed this particular test is the root cause + # of sporadic failures on Travis. pub, sub, port = self.create_bound_pair(zmq.PUB, zmq.SUB) sub.setsockopt(zmq.SUBSCRIBE, b'test') - - sleep(0.2) + sleep(0) + sub_ready = event.Event() + sub_last = event.Event() sub_done = event.Event() - def rx(sock, done_evt): + def rx(): + while sub.recv() != b'test BEGIN': + sleep(0) + sub_ready.send() count = 0 - sub = b'test' while True: - msg = sock.recv() - sleep() - if b'DONE' in msg: + msg = sub.recv() + if msg == b'test BEGIN': + # BEGIN may come many times + continue + if msg == b'test LAST': + sub.setsockopt(zmq.SUBSCRIBE, b'done') + sub.setsockopt(zmq.UNSUBSCRIBE, b'test') + sleep(0) + # In real application you should either sync + # or tolerate loss of messages. + sub_last.send() + if msg == b'done DONE': break - if b'LAST' in msg and sub == b'test': - sock.setsockopt(zmq.UNSUBSCRIBE, b'test') - sock.setsockopt(zmq.SUBSCRIBE, b'done') - sub = b'done' count += 1 - done_evt.send(count) + sub_done.send(count) - def tx(sock): + def tx(): + # Sync receiver ready to avoid loss of first packets + while not sub_ready.ready(): + pub.send(b'test BEGIN') + sleep(0.005) for i in range(1, 101): - msg = ("test %s" % i).encode() + msg = 'test {0}'.format(i).encode() if i != 50: - sock.send(msg) + pub.send(msg) else: - sock.send(b'test LAST') - sleep() - sock.send(b'done DONE') - - spawn(rx, sub, sub_done) - spawn(tx, pub) + pub.send(b'test LAST') + sub_last.wait() + # XXX: putting a real delay of 1ms here fixes sporadic failures on Travis + # just yield sleep(0) doesn't cut it + sleep(0.001) + pub.send(b'done DONE') + eventlet.spawn(rx) + eventlet.spawn(tx) rx_count = sub_done.wait() self.assertEqual(rx_count, 50) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_recv_multipart_bug68(self): req, rep, port = self.create_bound_pair(zmq.REQ, zmq.REP) msg = [b''] @@ -267,13 +283,13 @@ # but it's private __str__ appears to be the way to go self.assertEqual([m.bytes for m in recieved_msg], msg2) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_recv_noblock_bug76(self): req, rep, port = self.create_bound_pair(zmq.REQ, zmq.REP) self.assertRaisesErrno(zmq.EAGAIN, rep.recv, zmq.NOBLOCK) self.assertRaisesErrno(zmq.EAGAIN, rep.recv, zmq.NOBLOCK, True) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_send_during_recv(self): sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ) sleep() @@ -308,7 +324,7 @@ for evt in done_evts: self.assertEqual(evt.wait(), 0) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_send_during_recv_multipart(self): sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ) sleep() @@ -347,7 +363,7 @@ self.assertEqual(final_i, 0) # Need someway to ensure a thread is blocked on send... This isn't working - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_recv_during_send(self): sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ) sleep() @@ -376,7 +392,7 @@ final_i = done.wait() self.assertEqual(final_i, 0) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_close_during_recv(self): sender, receiver, port = self.create_bound_pair(zmq.XREQ, zmq.XREQ) sleep() @@ -396,7 +412,7 @@ done1.wait() done2.wait() - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_getsockopt_events(self): sock1, sock2, _port = self.create_bound_pair(zmq.DEALER, zmq.DEALER) sleep() @@ -415,7 +431,7 @@ events = sock2.getsockopt(zmq.EVENTS) self.assertEqual(events & zmq.POLLIN, zmq.POLLIN) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_cpu_usage_after_bind(self): """zmq eats CPU after PUB socket .bind() @@ -432,9 +448,9 @@ self.sockets.append(sock) sock.bind_to_random_port("tcp://127.0.0.1") sleep() - check_idle_cpu_usage(0.2, 0.1) + tests.check_idle_cpu_usage(0.2, 0.1) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_cpu_usage_after_pub_send_or_dealer_recv(self): """zmq eats CPU after PUB send or DEALER recv. @@ -444,18 +460,18 @@ sub.setsockopt(zmq.SUBSCRIBE, b"") sleep() pub.send(b'test_send') - check_idle_cpu_usage(0.2, 0.1) + tests.check_idle_cpu_usage(0.2, 0.1) sender, receiver, _port = self.create_bound_pair(zmq.DEALER, zmq.DEALER) sleep() sender.send(b'test_recv') msg = receiver.recv() self.assertEqual(msg, b'test_recv') - check_idle_cpu_usage(0.2, 0.1) + tests.check_idle_cpu_usage(0.2, 0.1) -class TestQueueLock(LimitedTestCase): - @skip_unless(zmq_supported) +class TestQueueLock(tests.LimitedTestCase): + @tests.skip_unless(zmq_supported) def test_queue_lock_order(self): q = zmq._QueueLock() s = semaphore.Semaphore(0) @@ -482,7 +498,7 @@ s.acquire() self.assertEqual(results, [1, 2, 3]) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_count(self): q = zmq._QueueLock() self.assertFalse(q) @@ -495,7 +511,7 @@ self.assertTrue(q) self.assertFalse(q) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_errors(self): q = zmq._QueueLock() @@ -506,7 +522,7 @@ self.assertRaises(zmq.LockReleaseError, q.release) - @skip_unless(zmq_supported) + @tests.skip_unless(zmq_supported) def test_nested_acquire(self): q = zmq._QueueLock() self.assertFalse(q) @@ -534,8 +550,8 @@ self.assertEqual(results, [1]) -class TestBlockedThread(LimitedTestCase): - @skip_unless(zmq_supported) +class TestBlockedThread(tests.LimitedTestCase): + @tests.skip_unless(zmq_supported) def test_block(self): e = zmq._BlockedThread() done = event.Event() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.18.4/tox.ini new/eventlet-0.19.0/tox.ini --- old/eventlet-0.18.4/tox.ini 2016-02-17 18:40:05.000000000 +0100 +++ new/eventlet-0.19.0/tox.ini 2016-05-02 18:25:31.000000000 +0200 @@ -43,11 +43,13 @@ deps = nose==1.3.1 setuptools==5.4.1 + py{26,27}: subprocess32==3.2.7 py27-dns: dnspython==1.12.0 py{26,27}-{selects,poll,epolls}: MySQL-python==1.2.5 py{34,py}-dns: dnspython3==1.12.0 + py26-{selects,poll,epolls}: pyopenssl==0.13 + py{27,33,34}-{selects,poll,epolls}: pyopenssl==16.0.0 {selects,poll,epolls}: psycopg2cffi-compat==1.1 - {selects,poll,epolls}: pyopenssl==0.13 {selects,poll,epolls}: pyzmq==13.1.0 commands = nosetests --verbose {posargs:tests/}