| |
@@ -0,0 +1,242 @@
|
| |
+ From beb705719827843940ecebe48ef8b8ba65d2b91c Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Wed, 9 Jun 2021 14:40:13 -0700
|
| |
+ Subject: [PATCH 1/6] Only wrap socket.timeout on Python < 3.10
|
| |
+
|
| |
+ On py310, socket.timeout is TimeoutError, which our is_timeout() helper
|
| |
+ func already knows is a timeout.
|
| |
+
|
| |
+ Note that this doesn't get us to py310 support (not by a long shot), but
|
| |
+ it's a step along the way.
|
| |
+
|
| |
+ Closes #687
|
| |
+ ---
|
| |
+ eventlet/greenio/base.py | 5 ++++-
|
| |
+ 1 file changed, 4 insertions(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/eventlet/greenio/base.py b/eventlet/greenio/base.py
|
| |
+ index 2eed86966..51a7ae13e 100644
|
| |
+ --- a/eventlet/greenio/base.py
|
| |
+ +++ b/eventlet/greenio/base.py
|
| |
+ @@ -29,7 +29,10 @@
|
| |
+ _original_socket = eventlet.patcher.original('socket').socket
|
| |
+
|
| |
+
|
| |
+ -socket_timeout = eventlet.timeout.wrap_is_timeout(socket.timeout)
|
| |
+ +if sys.version_info >= (3, 10):
|
| |
+ + socket_timeout = socket.timeout # Really, TimeoutError
|
| |
+ +else:
|
| |
+ + socket_timeout = eventlet.timeout.wrap_is_timeout(socket.timeout)
|
| |
+
|
| |
+
|
| |
+ def socket_connect(descriptor, address):
|
| |
+
|
| |
+ From c22a27ace90a55d14e8c60ff37f9832e76266441 Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Fri, 11 Jun 2021 12:56:07 -0700
|
| |
+ Subject: [PATCH 2/6] Get a working greenio._open on py310
|
| |
+
|
| |
+ _pyio.open is now a staticmethod, which means we can't get at the
|
| |
+ function code to wrap it up with a new environment.
|
| |
+
|
| |
+ Instead, create a new wrapper function which swaps out FileIO for
|
| |
+ GreenFileIO in the function's __globals__ before calling and replaces
|
| |
+ it in a finally.
|
| |
+ ---
|
| |
+ eventlet/greenio/py3.py | 30 +++++++++++++++++++++++-------
|
| |
+ 1 file changed, 23 insertions(+), 7 deletions(-)
|
| |
+
|
| |
+ diff --git a/eventlet/greenio/py3.py b/eventlet/greenio/py3.py
|
| |
+ index 7a75b52c0..c7f0aef50 100644
|
| |
+ --- a/eventlet/greenio/py3.py
|
| |
+ +++ b/eventlet/greenio/py3.py
|
| |
+ @@ -2,6 +2,7 @@
|
| |
+ import errno
|
| |
+ import os as _original_os
|
| |
+ import socket as _original_socket
|
| |
+ +import sys
|
| |
+ from io import (
|
| |
+ BufferedRandom as _OriginalBufferedRandom,
|
| |
+ BufferedReader as _OriginalBufferedReader,
|
| |
+ @@ -19,6 +20,7 @@
|
| |
+ SOCKET_BLOCKING,
|
| |
+ )
|
| |
+ from eventlet.hubs import notify_close, notify_opened, IOClosed, trampoline
|
| |
+ +from eventlet.semaphore import Semaphore
|
| |
+ from eventlet.support import get_errno
|
| |
+ import six
|
| |
+
|
| |
+ @@ -182,21 +184,35 @@ def __exit__(self, *args):
|
| |
+ self.close()
|
| |
+
|
| |
+
|
| |
+ -_open_environment = dict(globals())
|
| |
+ -_open_environment.update(dict(
|
| |
+ +_open_patching = dict(
|
| |
+ BufferedRandom=_OriginalBufferedRandom,
|
| |
+ BufferedWriter=_OriginalBufferedWriter,
|
| |
+ BufferedReader=_OriginalBufferedReader,
|
| |
+ TextIOWrapper=_OriginalTextIOWrapper,
|
| |
+ FileIO=GreenFileIO,
|
| |
+ os=_original_os,
|
| |
+ -))
|
| |
+ -
|
| |
+ -_open = FunctionType(
|
| |
+ - six.get_function_code(_original_pyio.open),
|
| |
+ - _open_environment,
|
| |
+ )
|
| |
+
|
| |
+ +if sys.version_info < (3, 10):
|
| |
+ + _open_environment = dict(globals())
|
| |
+ + _open_environment.update(_open_patching)
|
| |
+ + _open = FunctionType(
|
| |
+ + six.get_function_code(_original_pyio.open),
|
| |
+ + _open_environment,
|
| |
+ + )
|
| |
+ +else:
|
| |
+ + _open_lock = Semaphore()
|
| |
+ + _open_originals = {k: _original_pyio.open.__func__.__globals__[k]
|
| |
+ + for k in _open_patching}
|
| |
+ +
|
| |
+ + def _open(*a, **kw):
|
| |
+ + with _open_lock:
|
| |
+ + try:
|
| |
+ + _original_pyio.open.__func__.__globals__.update(_open_patching)
|
| |
+ + return _original_pyio.open(*a, **kw)
|
| |
+ + finally:
|
| |
+ + _original_pyio.open.__func__.__globals__.update(_open_originals)
|
| |
+ +
|
| |
+
|
| |
+ def GreenPipe(name, mode="r", buffering=-1, encoding=None, errors=None,
|
| |
+ newline=None, closefd=True, opener=None):
|
| |
+
|
| |
+ From ab4f8aaa704eb56b1e15730268fffbc8724c53ea Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Fri, 11 Jun 2021 13:02:52 -0700
|
| |
+ Subject: [PATCH 3/6] Test using eventlet.is_timeout
|
| |
+
|
| |
+ ...rather than requiring an is_timeout attribute on errors.
|
| |
+
|
| |
+ TimeoutErrors (which are covered by is_timeout) can't necessarily have
|
| |
+ attributes added to them.
|
| |
+ ---
|
| |
+ tests/__init__.py | 2 +-
|
| |
+ 1 file changed, 1 insertion(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/tests/__init__.py b/tests/__init__.py
|
| |
+ index c0b64fd9e..188366774 100644
|
| |
+ --- a/tests/__init__.py
|
| |
+ +++ b/tests/__init__.py
|
| |
+ @@ -383,7 +383,7 @@ def run_isolated(path, prefix='tests/isolated/', **kwargs):
|
| |
+
|
| |
+ def check_is_timeout(obj):
|
| |
+ value_text = getattr(obj, 'is_timeout', '(missing)')
|
| |
+ - assert obj.is_timeout, 'type={0} str={1} .is_timeout={2}'.format(type(obj), str(obj), value_text)
|
| |
+ + assert eventlet.is_timeout(obj), 'type={0} str={1} .is_timeout={2}'.format(type(obj), str(obj), value_text)
|
| |
+
|
| |
+
|
| |
+ @contextlib.contextmanager
|
| |
+
|
| |
+ From ceef941b6b730add07eff4a3d4da5d203e255a71 Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Fri, 11 Jun 2021 13:07:09 -0700
|
| |
+ Subject: [PATCH 4/6] Fix backdoor tests on py310
|
| |
+
|
| |
+ Python 3.10 started including build info on the version line, so the
|
| |
+ expectation in tests had to change. Also, start printing the banner as
|
| |
+ we read it to aid in future debugging.
|
| |
+ ---
|
| |
+ tests/backdoor_test.py | 17 +++++++++++++----
|
| |
+ 1 file changed, 13 insertions(+), 4 deletions(-)
|
| |
+
|
| |
+ diff --git a/tests/backdoor_test.py b/tests/backdoor_test.py
|
| |
+ index 03a569259..67a817947 100644
|
| |
+ --- a/tests/backdoor_test.py
|
| |
+ +++ b/tests/backdoor_test.py
|
| |
+ @@ -1,5 +1,6 @@
|
| |
+ import os
|
| |
+ import os.path
|
| |
+ +import sys
|
| |
+
|
| |
+ import eventlet
|
| |
+
|
| |
+ @@ -21,10 +22,18 @@ def test_server(self):
|
| |
+
|
| |
+ def _run_test_on_client_and_server(self, client, server_thread):
|
| |
+ f = client.makefile('rw')
|
| |
+ - assert 'Python' in f.readline()
|
| |
+ - f.readline() # build info
|
| |
+ - f.readline() # help info
|
| |
+ - assert 'InteractiveConsole' in f.readline()
|
| |
+ + line = f.readline()
|
| |
+ + print(line.strip('\r\n'))
|
| |
+ + assert 'Python' in line
|
| |
+ + if sys.version_info < (3, 10):
|
| |
+ + # Starting in py310, build info is included in version line
|
| |
+ + line = f.readline() # build info
|
| |
+ + print(line.strip('\r\n'))
|
| |
+ + line = f.readline() # help info
|
| |
+ + print(line.strip('\r\n'))
|
| |
+ + line = f.readline()
|
| |
+ + print(line.strip('\r\n'))
|
| |
+ + assert 'InteractiveConsole' in line
|
| |
+ self.assertEqual('>>> ', f.read(4))
|
| |
+ f.write('print("hi")\n')
|
| |
+ f.flush()
|
| |
+
|
| |
+ From aa6720a44cda816d1ac0a183ff94ebd51b6b1e53 Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Fri, 11 Jun 2021 13:12:36 -0700
|
| |
+ Subject: [PATCH 5/6] Tolerate __builtins__ being a dict (rather than module)
|
| |
+ in is_timeout
|
| |
+
|
| |
+ I'm still not sure how this happens, but somehow it does in
|
| |
+ socket_test.test_error_is_timeout. As a result, is_timeout wouldn't get
|
| |
+ a reference to TimeoutError, so the socket error would not be correctly
|
| |
+ identified as a timeout.
|
| |
+ ---
|
| |
+ eventlet/timeout.py | 5 ++++-
|
| |
+ 1 file changed, 4 insertions(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/eventlet/timeout.py b/eventlet/timeout.py
|
| |
+ index 6e1e08f63..969fdbcbd 100644
|
| |
+ --- a/eventlet/timeout.py
|
| |
+ +++ b/eventlet/timeout.py
|
| |
+ @@ -175,5 +175,8 @@ def fun(*args, **kwargs):
|
| |
+
|
| |
+
|
| |
+ def is_timeout(obj):
|
| |
+ - py3err = getattr(__builtins__, 'TimeoutError', Timeout)
|
| |
+ + if isinstance(__builtins__, dict): # seen when running tests on py310, but HOW??
|
| |
+ + py3err = __builtins__.get('TimeoutError', Timeout)
|
| |
+ + else:
|
| |
+ + py3err = getattr(__builtins__, 'TimeoutError', Timeout)
|
| |
+ return bool(getattr(obj, 'is_timeout', False)) or isinstance(obj, py3err)
|
| |
+
|
| |
+ From 900c8e195154efdae526ee7901469152141ab9d2 Mon Sep 17 00:00:00 2001
|
| |
+ From: Tim Burke <tim.burke@gmail.com>
|
| |
+ Date: Fri, 11 Jun 2021 13:33:00 -0700
|
| |
+ Subject: [PATCH 6/6] wsgi_test: Cap TLS version at 1.2
|
| |
+
|
| |
+ On py310, tests may attempt to use TLS 1.3 which apparently doesn't like
|
| |
+ the abrupt disconnect. Instead, it would complain:
|
| |
+
|
| |
+ ssl.SSLEOFError: EOF occurred in violation of protocol
|
| |
+ ---
|
| |
+ tests/wsgi_test.py | 3 ++-
|
| |
+ 1 file changed, 2 insertions(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py
|
| |
+ index 1dd754bba..4173bcefa 100644
|
| |
+ --- a/tests/wsgi_test.py
|
| |
+ +++ b/tests/wsgi_test.py
|
| |
+ @@ -579,7 +579,8 @@ def wsgi_app(environ, start_response):
|
| |
+ sock = eventlet.wrap_ssl(
|
| |
+ eventlet.listen(('localhost', 0)),
|
| |
+ certfile=certificate_file, keyfile=private_key_file,
|
| |
+ - server_side=True)
|
| |
+ + server_side=True,
|
| |
+ + ssl_version=ssl.PROTOCOL_TLSv1_2)
|
| |
+ server_coro = eventlet.spawn(server, sock, wsgi_app, self.logfile)
|
| |
+
|
| |
+ client = eventlet.connect(('localhost', sock.getsockname()[1]))
|
| |