diff --git a/.ci/test-matrix.yml b/.ci/test-matrix.yml index 809ee735..94b1f89b 100755 --- a/.ci/test-matrix.yml +++ b/.ci/test-matrix.yml @@ -12,6 +12,7 @@ PYTHON_VERSION: - 3.7 - 3.8 - 3.9 + - 3.10 PYTHON_CONNECTION_CLASS: - Urllib3HttpConnection diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a78f50db..b7cf054d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v1 - name: Set up Python 3.7 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: 3.7 - name: Install dependencies @@ -25,7 +25,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v1 - name: Set up Python 3.7 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: 3.7 - name: Install dependencies @@ -41,7 +41,7 @@ jobs: python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] experimental: [false] include: - - python-version: 3.9-dev + - python-version: 3.10.0-beta.2 experimental: true runs-on: ubuntu-latest @@ -51,7 +51,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v1 - name: Set Up Python - ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies diff --git a/dev-requirements.txt b/dev-requirements.txt index 66d63490..bacd1c72 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -6,12 +6,15 @@ mock sphinx<1.7 sphinx_rtd_theme jinja2 -numpy -pandas + +# No wheels for Python 3.10 yet! +numpy; python_version<"3.10" +pandas; python_version<"3.10" # PyYAML 5.3 dropped support for Python 3.4 while # not amending that requirement to the package. :( -pyyaml<5.3 +pyyaml>=5.4; python_version>="3.6" +pyyaml<5.3; python_version<"3.6" isort black; python_version>="3.6" diff --git a/elasticsearch/_async/http_aiohttp.py b/elasticsearch/_async/http_aiohttp.py index 161cfeb0..64060293 100644 --- a/elasticsearch/_async/http_aiohttp.py +++ b/elasticsearch/_async/http_aiohttp.py @@ -167,7 +167,10 @@ class AIOHttpConnection(AsyncConnection): self.ssl_assert_fingerprint = ssl_assert_fingerprint if self.use_ssl and ssl_context is None: - ssl_context = ssl.SSLContext(ssl_version or ssl.PROTOCOL_TLS) + if ssl_version is None: + ssl_context = ssl.create_default_context() + else: + ssl_context = ssl.SSLContext(ssl_version) # Convert all sentinel values to their actual default # values if not using an SSLContext. @@ -180,8 +183,8 @@ class AIOHttpConnection(AsyncConnection): ssl_context.verify_mode = ssl.CERT_REQUIRED ssl_context.check_hostname = True else: - ssl_context.verify_mode = ssl.CERT_NONE ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE ca_certs = CA_CERTS if ca_certs is None else ca_certs if verify_certs: diff --git a/test_elasticsearch/test_async/test_connection.py b/test_elasticsearch/test_async/test_connection.py index 0c126464..6b53adfe 100644 --- a/test_elasticsearch/test_async/test_connection.py +++ b/test_elasticsearch/test_async/test_connection.py @@ -265,7 +265,7 @@ class TestAIOHttpConnection: use_ssl=True, verify_certs=False, ssl_show_warn=False ) await con._create_aiohttp_session() - assert 0 == len(w) + assert w == [] assert isinstance(con.session, aiohttp.ClientSession) @@ -277,7 +277,7 @@ class TestAIOHttpConnection: ctx = ssl.create_default_context() with warnings.catch_warnings(record=True) as w: AIOHttpConnection(ssl_context=ctx) - assert 0 == len(w), str([x.message for x in w]) + assert w == [], str([x.message for x in w]) def test_warns_if_using_non_default_ssl_kwargs_with_ssl_context(self): for kwargs in ( diff --git a/test_elasticsearch/test_serializer.py b/test_elasticsearch/test_serializer.py index 0084c004..5f9002d5 100644 --- a/test_elasticsearch/test_serializer.py +++ b/test_elasticsearch/test_serializer.py @@ -21,8 +21,11 @@ import uuid from datetime import datetime from decimal import Decimal -import numpy as np -import pandas as pd +try: + import numpy as np + import pandas as pd +except ImportError: + np = pd = None from elasticsearch.exceptions import ImproperlyConfigured, SerializationError from elasticsearch.serializer import ( @@ -35,6 +38,11 @@ from elasticsearch.serializer import ( from .test_cases import SkipTest, TestCase +def requires_numpy_and_pandas(): + if np is None or pd is None: + raise SkipTest("Test requires numpy or pandas to be available") + + class TestJSONSerializer(TestCase): def test_datetime_serialization(self): self.assertEqual( @@ -43,6 +51,8 @@ class TestJSONSerializer(TestCase): ) def test_decimal_serialization(self): + requires_numpy_and_pandas() + if sys.version_info[:2] == (2, 6): raise SkipTest("Float rounding is broken in 2.6.") self.assertEqual('{"d":3.8}', JSONSerializer().dumps({"d": Decimal("3.8")})) @@ -56,9 +66,13 @@ class TestJSONSerializer(TestCase): ) def test_serializes_numpy_bool(self): + requires_numpy_and_pandas() + self.assertEqual('{"d":true}', JSONSerializer().dumps({"d": np.bool_(True)})) def test_serializes_numpy_integers(self): + requires_numpy_and_pandas() + ser = JSONSerializer() for np_type in ( np.int_, @@ -78,6 +92,8 @@ class TestJSONSerializer(TestCase): self.assertEqual(ser.dumps({"d": np_type(1)}), '{"d":1}') def test_serializes_numpy_floats(self): + requires_numpy_and_pandas() + ser = JSONSerializer() for np_type in ( np.float_, @@ -89,12 +105,16 @@ class TestJSONSerializer(TestCase): ) def test_serializes_numpy_datetime(self): + requires_numpy_and_pandas() + self.assertEqual( '{"d":"2010-10-01T02:30:00"}', JSONSerializer().dumps({"d": np.datetime64("2010-10-01T02:30:00")}), ) def test_serializes_numpy_ndarray(self): + requires_numpy_and_pandas() + self.assertEqual( '{"d":[0,0,0,0,0]}', JSONSerializer().dumps({"d": np.zeros((5,), dtype=np.uint8)}), @@ -106,24 +126,32 @@ class TestJSONSerializer(TestCase): ) def test_serializes_numpy_nan_to_nan(self): + requires_numpy_and_pandas() + self.assertEqual( '{"d":NaN}', JSONSerializer().dumps({"d": np.nan}), ) def test_serializes_pandas_timestamp(self): + requires_numpy_and_pandas() + self.assertEqual( '{"d":"2010-10-01T02:30:00"}', JSONSerializer().dumps({"d": pd.Timestamp("2010-10-01T02:30:00")}), ) def test_serializes_pandas_series(self): + requires_numpy_and_pandas() + self.assertEqual( '{"d":["a","b","c","d"]}', JSONSerializer().dumps({"d": pd.Series(["a", "b", "c", "d"])}), ) def test_serializes_pandas_na(self): + requires_numpy_and_pandas() + if not hasattr(pd, "NA"): # pandas.NA added in v1 raise SkipTest("pandas.NA required") self.assertEqual( @@ -132,11 +160,15 @@ class TestJSONSerializer(TestCase): ) def test_raises_serialization_error_pandas_nat(self): + requires_numpy_and_pandas() + if not hasattr(pd, "NaT"): raise SkipTest("pandas.NaT required") self.assertRaises(SerializationError, JSONSerializer().dumps, {"d": pd.NaT}) def test_serializes_pandas_category(self): + requires_numpy_and_pandas() + cat = pd.Categorical(["a", "c", "b", "a"], categories=["a", "b", "c"]) self.assertEqual( '{"d":["a","c","b","a"]}',