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