From b4a01f761eec2b2df4789d0a11317943e211599b Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Mon, 13 Oct 2025 12:34:24 +0100 Subject: [PATCH 1/5] Add 3.14 to CI builds --- .buildkite/Dockerfile | 2 +- .buildkite/pipeline.yml | 5 +++-- .buildkite/run-tests | 2 +- .github/workflows/ci.yml | 2 +- noxfile.py | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.buildkite/Dockerfile b/.buildkite/Dockerfile index a68ad997d..2c6bfbe6c 100644 --- a/.buildkite/Dockerfile +++ b/.buildkite/Dockerfile @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.13 +ARG PYTHON_VERSION=3.14 FROM python:${PYTHON_VERSION} # Default UID/GID to 1000 diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index ac7c6b60a..729336bac 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -16,6 +16,7 @@ steps: - "3.11" - "3.12" - "3.13" + - "3.14" connection: - "urllib3" - "requests" @@ -23,11 +24,11 @@ steps: - "test" adjustments: - with: - python: "3.9" + python: "3.10" connection: "urllib3" nox_session: "test_otel" - with: - python: "3.13" + python: "3.14" connection: "urllib3" nox_session: "test_otel" command: ./.buildkite/run-tests diff --git a/.buildkite/run-tests b/.buildkite/run-tests index 90a95a209..8d0eb7ffd 100755 --- a/.buildkite/run-tests +++ b/.buildkite/run-tests @@ -7,7 +7,7 @@ # Default environment variables export STACK_VERSION="${STACK_VERSION:=8.0.0-SNAPSHOT}" export TEST_SUITE="${TEST_SUITE:=platinum}" -export PYTHON_VERSION="${PYTHON_VERSION:=3.13}" +export PYTHON_VERSION="${PYTHON_VERSION:=3.14}" export PYTHON_CONNECTION_CLASS="${PYTHON_CONNECTION_CLASS:=urllib3}" script_path=$(dirname $(realpath $0)) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bc43d985..b924597d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] nox-session: [""] runs-on: ["ubuntu-latest"] diff --git a/noxfile.py b/noxfile.py index d5a6099e7..01de5e4b4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -44,14 +44,14 @@ def pytest_argv(): ] -@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13"]) +@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]) def test(session): session.install("-e", ".[dev]", env=INSTALL_ENV, silent=False) session.run(*pytest_argv(), *session.posargs) -@nox.session(python=["3.9", "3.13"]) +@nox.session(python=["3.10", "3.14"]) def test_otel(session): session.install( ".[dev]", From 5e232b6a8de694f007f2bbe6e229cc9aa268f760 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Mon, 13 Oct 2025 15:28:03 +0100 Subject: [PATCH 2/5] Support Python 3.14 __annotate_func__ --- elasticsearch/dsl/document_base.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/elasticsearch/dsl/document_base.py b/elasticsearch/dsl/document_base.py index 4df900a39..47e787531 100644 --- a/elasticsearch/dsl/document_base.py +++ b/elasticsearch/dsl/document_base.py @@ -332,6 +332,21 @@ def __init__(self, name: str, bases: Tuple[type, ...], attrs: Dict[str, Any]): # # ignore attributes # field10: ClassVar[string] = "a regular class variable" annotations = attrs.get("__annotations__", {}) + if not annotations: + # Python 3.14+ uses annotationlib + try: + import annotationlib + + annotate = annotationlib.get_annotate_from_class_namespace(attrs) + if annotate: + annotations = ( + annotationlib.call_annotate_function( + annotate, format=annotationlib.Format.VALUE + ) + or {} + ) + except ImportError: + pass fields = {n for n in attrs if isinstance(attrs[n], Field)} fields.update(annotations.keys()) field_defaults = {} From 18ecf950a096cd58426f2551defe3bbcb7b6d67f Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Mon, 13 Oct 2025 15:28:20 +0100 Subject: [PATCH 3/5] Temporarily remove pyarrow --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a8e5ead9e..a9b539758 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ dev = [ "orjson", "numpy", "simsimd", - "pyarrow", + #"pyarrow", "pandas", "mapbox-vector-tile", "jinja2", From 8bf3d3adb081da7025d4ca321028b539fd4f00d4 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Tue, 14 Oct 2025 12:49:59 +0100 Subject: [PATCH 4/5] Update pyproject.toml Co-authored-by: Quentin Pradet --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a9b539758..6b4915106 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ dev = [ "orjson", "numpy", "simsimd", - #"pyarrow", + "pyarrow; python_version<'3.14'", "pandas", "mapbox-vector-tile", "jinja2", From b72ab46d4cb0f55533c50bb114abc40432ec5b6c Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Tue, 14 Oct 2025 16:54:19 +0100 Subject: [PATCH 5/5] cleanup annotationlib use --- elasticsearch/dsl/document_base.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/elasticsearch/dsl/document_base.py b/elasticsearch/dsl/document_base.py index 47e787531..72f0364a4 100644 --- a/elasticsearch/dsl/document_base.py +++ b/elasticsearch/dsl/document_base.py @@ -34,6 +34,11 @@ overload, ) +try: + import annotationlib +except ImportError: + annotationlib = None + try: from types import UnionType except ImportError: @@ -332,21 +337,16 @@ def __init__(self, name: str, bases: Tuple[type, ...], attrs: Dict[str, Any]): # # ignore attributes # field10: ClassVar[string] = "a regular class variable" annotations = attrs.get("__annotations__", {}) - if not annotations: + if not annotations and annotationlib: # Python 3.14+ uses annotationlib - try: - import annotationlib - - annotate = annotationlib.get_annotate_from_class_namespace(attrs) - if annotate: - annotations = ( - annotationlib.call_annotate_function( - annotate, format=annotationlib.Format.VALUE - ) - or {} + annotate = annotationlib.get_annotate_from_class_namespace(attrs) + if annotate: + annotations = ( + annotationlib.call_annotate_function( + annotate, format=annotationlib.Format.VALUE ) - except ImportError: - pass + or {} + ) fields = {n for n in attrs if isinstance(attrs[n], Field)} fields.update(annotations.keys()) field_defaults = {}