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