Blob Blame History Raw
From 3fde87d6af97551ce9e18ad8835947153530e121 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/5] 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 ccf6db2df4edd1a7dda671515df20edd846a7f53 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/5] Get a working greenio._open on py310

_pyio.open is now a staticmethod, so we've got to go down to
_pyio.open.__wrapped__ to get to the python function object.
---
 eventlet/greenio/py3.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/eventlet/greenio/py3.py b/eventlet/greenio/py3.py
index 7a75b52c0..bc3dc9499 100644
--- a/eventlet/greenio/py3.py
+++ b/eventlet/greenio/py3.py
@@ -191,9 +191,12 @@ def __exit__(self, *args):
     FileIO=GreenFileIO,
     os=_original_os,
 ))
+if hasattr(_original_pyio, 'text_encoding'):
+    _open_environment['text_encoding'] = _original_pyio.text_encoding
 
+_pyio_open = getattr(_original_pyio.open, '__wrapped__', _original_pyio.open)
 _open = FunctionType(
-    six.get_function_code(_original_pyio.open),
+    six.get_function_code(_pyio_open),
     _open_environment,
 )
 

From 5641a81d5f7d588c2d452c36479391c71b012e8a 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/5] 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 2ea6991d26eef98300d27c3c5d383eccc65360c3 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/5] 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 | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/backdoor_test.py b/tests/backdoor_test.py
index 03a569259..1e09f09b6 100644
--- a/tests/backdoor_test.py
+++ b/tests/backdoor_test.py
@@ -1,5 +1,6 @@
 import os
 import os.path
+import sys
 
 import eventlet
 
@@ -22,7 +23,9 @@ 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
+        if sys.version_info < (3, 10):
+            # Starting in py310, build info is included in version line
+            f.readline()  # build info
         f.readline()  # help info
         assert 'InteractiveConsole' in f.readline()
         self.assertEqual('>>> ', f.read(4))

From bad82b6d5634d8cdfa77a2f828abdf61e859a3f4 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/5] 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 | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/eventlet/timeout.py b/eventlet/timeout.py
index 6e1e08f63..4ab893eef 100644
--- a/eventlet/timeout.py
+++ b/eventlet/timeout.py
@@ -174,6 +174,11 @@ def fun(*args, **kwargs):
     return fun
 
 
+if isinstance(__builtins__, dict):  # seen when running tests on py310, but HOW??
+    _timeout_err = __builtins__.get('TimeoutError', Timeout)
+else:
+    _timeout_err = getattr(__builtins__, 'TimeoutError', Timeout)
+
+
 def is_timeout(obj):
-    py3err = getattr(__builtins__, 'TimeoutError', Timeout)
-    return bool(getattr(obj, 'is_timeout', False)) or isinstance(obj, py3err)
+    return bool(getattr(obj, 'is_timeout', False)) or isinstance(obj, _timeout_err)