diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb4a45a..10de925 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.x - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.x - name: Install dependencies @@ -24,7 +24,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v1 - name: Set up Python 3.x - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.x - name: Install dependencies @@ -40,7 +40,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] os: ["ubuntu-latest"] experimental: [false] nox-session: [''] @@ -58,14 +58,10 @@ jobs: uses: actions/checkout@v2 - name: Set up Python - ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - - name: Set up Python 3.x to run nox - uses: actions/setup-python@v2 - with: - python-version: 3.x + allow-prereleases: true - name: Install Dependencies run: python -m pip install --upgrade nox diff --git a/CHANGELOG.md b/CHANGELOG.md index f86a258..fdc8c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 8.15.1 (2024-10-09) + +* Add explicit Python 3.13 support ([#189](https://github.com/elastic/elastic-transport-python/pull/189)) + +## 8.15.0 (2024-08-09) + +* Removed call to `raise_for_status()` when using `HttpxAsyncHttpNode` to prevent exceptions being raised for 404 responses ([#182](https://github.com/elastic/elastic-transport-python/pull/182)) +* Documented response classes ([#175](https://github.com/elastic/elastic-transport-python/pull/175)) +* Dropped support for Python 3.7 ([#179](https://github.com/elastic/elastic-transport-python/pull/179)) + ## 8.13.1 (2024-04-28) - Fixed requests 2.32 compatibility (#164) diff --git a/elastic_transport/_node/_http_aiohttp.py b/elastic_transport/_node/_http_aiohttp.py index cc5df74..be55b93 100644 --- a/elastic_transport/_node/_http_aiohttp.py +++ b/elastic_transport/_node/_http_aiohttp.py @@ -22,8 +22,9 @@ import os import re import ssl +import sys import warnings -from typing import Optional, Union +from typing import Optional, TypedDict, Union from .._compat import warn_stacklevel from .._exceptions import ConnectionError, ConnectionTimeout, SecurityWarning, TlsError @@ -55,12 +56,21 @@ # See aio-libs/aiohttp#1769 and #5012 _AIOHTTP_FIXED_HEAD_BUG = _AIOHTTP_SEMVER_VERSION >= (3, 7, 0) + + class RequestKwarg(TypedDict, total=False): + ssl: aiohttp.Fingerprint + except ImportError: # pragma: nocover _AIOHTTP_AVAILABLE = False _AIOHTTP_META_VERSION = "" _AIOHTTP_FIXED_HEAD_BUG = False +# Avoid aiohttp enabled_cleanup_closed warning: https://github.com/aio-libs/aiohttp/pull/9726 +_NEEDS_CLEANUP_CLOSED_313 = (3, 13, 0) <= sys.version_info < (3, 13, 1) +_NEEDS_CLEANUP_CLOSED = _NEEDS_CLEANUP_CLOSED_313 or sys.version_info < (3, 12, 7) + + class AiohttpHttpNode(BaseAsyncNode): """Default asynchronous node class using the ``aiohttp`` library via HTTP""" @@ -170,7 +180,7 @@ async def perform_request( # type: ignore[override] else: body_to_send = None - kwargs = {} + kwargs: RequestKwarg = {} if self._ssl_assert_fingerprint: kwargs["ssl"] = aiohttp_fingerprint(self._ssl_assert_fingerprint) @@ -258,7 +268,7 @@ def _create_aiohttp_session(self) -> None: connector=aiohttp.TCPConnector( limit_per_host=self._connections_per_node, use_dns_cache=True, - enable_cleanup_closed=True, + enable_cleanup_closed=_NEEDS_CLEANUP_CLOSED, ssl=self._ssl_context or False, ), ) diff --git a/elastic_transport/_node/_http_urllib3.py b/elastic_transport/_node/_http_urllib3.py index f9b4609..45514ae 100644 --- a/elastic_transport/_node/_http_urllib3.py +++ b/elastic_transport/_node/_http_urllib3.py @@ -199,7 +199,7 @@ def perform_request( body=body, exception=err, ) - raise err from None + raise err from e meta = ApiResponseMeta( node=self.config, diff --git a/elastic_transport/_node/_urllib3_chain_certs.py b/elastic_transport/_node/_urllib3_chain_certs.py index 30790eb..e36449b 100644 --- a/elastic_transport/_node/_urllib3_chain_certs.py +++ b/elastic_transport/_node/_urllib3_chain_certs.py @@ -105,14 +105,20 @@ def _validate_conn(self, conn: HTTPSConnection) -> None: # type: ignore[overrid fingerprints: List[bytes] try: - # 'get_verified_chain()' and 'Certificate.public_bytes()' are private APIs - # in CPython 3.10. They're not documented anywhere yet but seem to work - # and we need them for Security on by Default so... onwards we go! - # See: https://github.com/python/cpython/pull/25467 - fingerprints = [ - hash_func(cert.public_bytes(_ENCODING_DER)).digest() - for cert in conn.sock._sslobj.get_verified_chain() # type: ignore[union-attr] - ] + if sys.version_info >= (3, 13): + fingerprints = [ + hash_func(cert).digest() + for cert in conn.sock.get_verified_chain() + ] + else: + # 'get_verified_chain()' and 'Certificate.public_bytes()' are private APIs + # in CPython 3.10. They're not documented anywhere yet but seem to work + # and we need them for Security on by Default so... onwards we go! + # See: https://github.com/python/cpython/pull/25467 + fingerprints = [ + hash_func(cert.public_bytes(_ENCODING_DER)).digest() + for cert in conn.sock._sslobj.get_verified_chain() # type: ignore[union-attr] + ] except RERAISE_EXCEPTIONS: # pragma: nocover raise # Because these are private APIs we are super careful here diff --git a/elastic_transport/_version.py b/elastic_transport/_version.py index 9c93e47..83a382b 100644 --- a/elastic_transport/_version.py +++ b/elastic_transport/_version.py @@ -15,4 +15,4 @@ # specific language governing permissions and limitations # under the License. -__version__ = "8.13.1" +__version__ = "8.15.1" diff --git a/noxfile.py b/noxfile.py index 4d8a11b..141cae4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -59,7 +59,7 @@ def lint(session): session.run("mypy", "--strict", "--show-error-codes", "elastic_transport/") -@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12"]) +@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]) def test(session): session.install(".[develop]") session.run( diff --git a/setup.py b/setup.py index f55392e..da2e556 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,6 @@ install_requires=[ "urllib3>=1.26.2, <3", "certifi", - "importlib-metadata; python_version<'3.8'", ], python_requires=">=3.8", extras_require={ @@ -66,6 +65,8 @@ "requests", "aiohttp", "httpx", + # https://github.com/encode/httpx/discussions/3214#discussioncomment-10830925 + "httpcore<1.0.6", "respx", "opentelemetry-api", "opentelemetry-sdk", @@ -88,6 +89,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ],