Skip to content

Commit a49f1bb

Browse files
committed
Tolerate RecursionError not being defined in Python<3.5
1 parent ff5fd9d commit a49f1bb

File tree

7 files changed

+68
-7
lines changed

7 files changed

+68
-7
lines changed

elasticsearch/_async/http_aiohttp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import urllib3 # type: ignore
2424

25-
from ..compat import urlencode
25+
from ..compat import reraise_exceptions, urlencode
2626
from ..connection.base import Connection
2727
from ..exceptions import (
2828
ConnectionError,
@@ -304,7 +304,7 @@ async def perform_request(
304304
duration = self.loop.time() - start
305305

306306
# We want to reraise a cancellation or recursion error.
307-
except (asyncio.CancelledError, RecursionError):
307+
except reraise_exceptions:
308308
raise
309309
except Exception as e:
310310
self.log_request_fail(

elasticsearch/compat.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,22 @@ def to_bytes(x, encoding="ascii"):
5858
from collections import Mapping
5959

6060

61+
try:
62+
reraise_exceptions = (RecursionError,)
63+
except NameError:
64+
reraise_exceptions = ()
65+
66+
try:
67+
import asyncio
68+
69+
reraise_exceptions += (asyncio.CancelledError,)
70+
except (ImportError, AttributeError):
71+
pass
72+
73+
6174
__all__ = [
6275
"string_types",
76+
"reraise_exceptions",
6377
"quote_plus",
6478
"quote",
6579
"urlencode",

elasticsearch/compat.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
# under the License.
1717

1818
import sys
19-
from typing import Callable, Tuple, Union
19+
from typing import Callable, Tuple, Type, Union
2020

2121
PY2: bool
2222
string_types: Tuple[type, ...]
2323

2424
to_str: Callable[[Union[str, bytes]], str]
2525
to_bytes: Callable[[Union[str, bytes]], bytes]
26+
reraise_exceptions: Tuple[Type[Exception], ...]
2627

2728
if sys.version_info[0] == 2:
2829
from itertools import imap as map

elasticsearch/connection/http_requests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import time
1919
import warnings
2020

21-
from ..compat import string_types, urlencode
21+
from ..compat import reraise_exceptions, string_types, urlencode
2222
from ..exceptions import (
2323
ConnectionError,
2424
ConnectionTimeout,
@@ -166,7 +166,7 @@ def perform_request(
166166
response = self.session.send(prepared_request, **send_kwargs)
167167
duration = time.time() - start
168168
raw_data = response.content.decode("utf-8", "surrogatepass")
169-
except RecursionError:
169+
except reraise_exceptions:
170170
raise
171171
except Exception as e:
172172
self.log_request_fail(

elasticsearch/connection/http_urllib3.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from urllib3.exceptions import SSLError as UrllibSSLError # type: ignore
2525
from urllib3.util.retry import Retry # type: ignore
2626

27-
from ..compat import urlencode
27+
from ..compat import reraise_exceptions, urlencode
2828
from ..exceptions import (
2929
ConnectionError,
3030
ConnectionTimeout,
@@ -253,7 +253,7 @@ def perform_request(
253253
)
254254
duration = time.time() - start
255255
raw_data = response.data.decode("utf-8", "surrogatepass")
256-
except RecursionError:
256+
except reraise_exceptions:
257257
raise
258258
except Exception as e:
259259
self.log_request_fail(

test_elasticsearch/test_async/test_connection.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from multidict import CIMultiDict
3030

3131
from elasticsearch import AIOHttpConnection, __versionstr__
32+
from elasticsearch.compat import reraise_exceptions
3233

3334
pytestmark = pytest.mark.asyncio
3435

@@ -318,6 +319,20 @@ async def test_surrogatepass_into_bytes(self):
318319
status, headers, data = await con.perform_request("GET", "/")
319320
assert u"你好\uda6a" == data
320321

322+
@pytest.mark.parametrize("exception_cls", reraise_exceptions)
323+
async def test_recursion_error_reraised(self, exception_cls):
324+
conn = AIOHttpConnection()
325+
326+
def request_raise(*_, **__):
327+
raise exception_cls("Wasn't modified!")
328+
329+
await conn._create_aiohttp_session()
330+
conn.session.request = request_raise
331+
332+
with pytest.raises(exception_cls) as e:
333+
await conn.perform_request("GET", "/")
334+
assert str(e.value) == "Wasn't modified!"
335+
321336

322337
class TestConnectionHttpbin:
323338
"""Tests the HTTP connection implementations against a live server E2E"""

test_elasticsearch/test_connection.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from urllib3._collections import HTTPHeaderDict
3333

3434
from elasticsearch import __versionstr__
35+
from elasticsearch.compat import reraise_exceptions
3536
from elasticsearch.connection import (
3637
Connection,
3738
RequestsHttpConnection,
@@ -466,6 +467,21 @@ def test_surrogatepass_into_bytes(self):
466467
status, headers, data = con.perform_request("GET", "/")
467468
self.assertEqual(u"你好\uda6a", data)
468469

470+
@pytest.mark.skipif(
471+
not reraise_exceptions, reason="RecursionError isn't defined in Python <3.5"
472+
)
473+
def test_recursion_error_reraised(self):
474+
conn = Urllib3HttpConnection()
475+
476+
def urlopen_raise(*_, **__):
477+
raise RecursionError("Wasn't modified!")
478+
479+
conn.pool.urlopen = urlopen_raise
480+
481+
with pytest.raises(RecursionError) as e:
482+
conn.perform_request("GET", "/")
483+
assert str(e.value) == "Wasn't modified!"
484+
469485

470486
class TestRequestsConnection(TestCase):
471487
def _get_mock_connection(
@@ -868,6 +884,21 @@ def test_surrogatepass_into_bytes(self):
868884
status, headers, data = con.perform_request("GET", "/")
869885
self.assertEqual(u"你好\uda6a", data)
870886

887+
@pytest.mark.skipif(
888+
not reraise_exceptions, reason="RecursionError isn't defined in Python <3.5"
889+
)
890+
def test_recursion_error_reraised(self):
891+
conn = RequestsHttpConnection()
892+
893+
def send_raise(*_, **__):
894+
raise RecursionError("Wasn't modified!")
895+
896+
conn.session.send = send_raise
897+
898+
with pytest.raises(RecursionError) as e:
899+
conn.perform_request("GET", "/")
900+
assert str(e.value) == "Wasn't modified!"
901+
871902

872903
class TestConnectionHttpbin:
873904
"""Tests the HTTP connection implementations against a live server E2E"""

0 commit comments

Comments
 (0)