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