Skip to content

chore!: drop Python 3.10 support, add Python 3.15 - #13054

Draft
julian-risch wants to merge 13 commits into
mainfrom
claude/friendly-knuth-47htxm
Draft

julian-risch wants to merge 13 commits into
mainfrom
claude/friendly-knuth-47htxm

Conversation

@julian-risch

@julian-risch julian-risch commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Related Issues

Proposed Changes:

Python 3.10 reaches end of life in October 2026, and Python 3.15.0 was released on 2026-10-09.

  • Python versions: requires-python is now >=3.11. The 3.10 classifier is replaced by a 3.15 classifier. All workflows that used 3.10 as the base version now use 3.11.
  • Dropped typing_extensions: NotRequired and Self now come from typing. The license-compliance exclusion that only existed for typing_extensions is removed.
  • 3.11+ idioms: tests use datetime.UTC instead of timezone.utc. Comments that described 3.10-only behavior in type_utils.py and filters.py are rewritten.
  • Enums: ChatRole and ConverterMimeType stay class X(str, Enum), marked # noqa: UP042. Switching to StrEnum would change str() of the members. That is user-visible for ChatRole, and MultiFileConverter.__init__() parses it to name its internal components.
  • Type serialization tests: expectations are gated on sys.version_info >= (3, 14), because from 3.14 on typing.Union/Optional serialize with PEP 604 syntax (str | None).
  • Async pipeline feature tests: six scenarios in test/core/pipeline/features/test_run.py now compare variadic inputs with AnyOrder.
    • Pipeline.run_async() writes a component's outputs when its thread finishes, so a variadic socket receives inputs in completion order.
    • On 3.15, ubuntu and Windows CI hit the swapped order in three scenarios on every run.
    • I found the other three by adding a random delay before each component run.
    • This follows the approach of the 3.14 PR feat: Updates to make Haystack compatible with python 3.14 #10634. AnyOrder gained __iter__ so it can be nested.
  • Docs: CONTRIBUTING.md and AGENTS.md are updated for the new range. Until PyPI has cp315 torch wheels, CONTRIBUTING.md explains how to build the test env on 3.15 from the PyTorch CPU index.

How did you test it?

Locally on Python 3.15.0 final (macOS arm64):

  • hatch run test:unit: 6754 passed, 10 skipped. All skips are missing-API-key or document-store capability skips.
  • hatch run test:integration-only-fast with OPENAI_API_KEY: 315 passed, 19 skipped (Azure credentials and existing skip markers).
  • hatch run test:types and hatch run fmt: clean.
  • Async feature scenarios with a random 0–10 ms delay before each component run: 40 seeds, no failures.
  • Manual: a BM25 → PromptBuilder pipeline with Optional/Union sockets, plus a Pipeline.dumps()/loads() round trip.

In CI, temporary commits switched tests.yml to Python 3.15 and were then reverted, as in #10634.

  • Unit and integration passed on ubuntu, macOS and Windows: https://github.com/deepset-ai/haystack/actions/runs/38069150959
  • actions/setup-python doesn't list 3.15.0 yet, so that run used 3.15.0rc3.
  • Workarounds in that run only:
    • torch from download.pytorch.org/whl/cpu;
    • no jq on Windows, and test_json.py ignored there;
    • pypdf<6.20 (see below).

Notes for the reviewer

  • No permanent 3.15 CI job. Like for 3.14, CI keeps testing the floor version (3.11).
  • Wheels still missing on 3.15:
    • PyTorch has not uploaded cp315 wheels to PyPI yet; they exist only on its own index.
    • jq 1.12.0 has no cp315 Windows wheel, and its sdist doesn't build on Windows. Windows users on 3.15 can't use JSONConverter with a jq_schema for now. On Linux and macOS, jq builds from sdist.
  • Unrelated CI failure: pypdf 6.20.0 (released 2026-10-09) fixed an extraction bug. test_pypdf_to_document.py::test_run_detect_paragraphs_to_be_used_in_split_passage still expects the old "inter nal" text, so it fails on any Python version. test: expect pypdf 6.20 text extraction in PyPDFToDocument test #13203 fixes it; once it merges, I merge main into this PR.
  • Found on 3.15, not addressed here: with PYTHON_LAZY_IMPORTS=all (PEP 810), with LazyImport(...) no longer catches a missing optional dependency. check() passes, and users get a raw ModuleNotFoundError at first use instead of the "pip install" hint. The global mode is opt-in, so this needs a follow-up rather than a blocker.

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

🤖 Generated with Claude Code

claude added 2 commits October 1, 2026 06:29
Python 3.10 reaches end of life in October 2026 and Python 3.15.0 is released.

- Require Python >=3.11, add the 3.15 classifier, and move floor-pinned CI workflows to 3.11
- Import Self and NotRequired from typing and drop the direct typing_extensions dependency
- Keep ChatRole and ConverterMimeType as (str, Enum): StrEnum would change their str() output
- Make two type serialization tests aware of the 3.14+ PEP 604 Union representation
- Update contributor docs and add a release note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BhTpApLrajennECwiuPc2k
@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
haystack-docs Ignored Ignored Preview Oct 10, 2026 5:07pm UTC

Request Review

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/components/converters
  multi_file_converter.py
  haystack/components/converters/image
  image_utils.py
  haystack/components/routers
  conditional_router.py
  haystack/core
  type_utils.py
  haystack/core/pipeline
  base.py
  haystack/dataclasses
  chat_message.py
  haystack/utils
  callable_serialization.py
  filters.py
Project Total  

This report was generated by python-coverage-comment-action

Comment thread releasenotes/notes/drop-python-310-add-python-315-4ec6b40f210a6d61.yaml Outdated
Comment thread CONTRIBUTING.md Outdated
Co-authored-by: Julian Risch <julianrisch@gmx.de>
@julian-risch julian-risch added this to the 3.4.0 milestone Oct 1, 2026
@julian-risch julian-risch self-assigned this Oct 1, 2026
@github-actions github-actions Bot added the P2 Medium priority, add to the next sprint if no P1 available label Oct 8, 2026
julian-risch and others added 10 commits October 10, 2026 11:48
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
To be reverted once the 3.15 run is green.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jq 1.12.0 has no cp315 Windows wheel and its sdist does not build on Windows.
To be reverted together with the 3.15 flip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n run_async

asyncio.wait returns a set, so iterating it gave variadic inputs an order that varied between runs and
platforms. Python 3.15 on Linux exposed it in the async pipeline feature tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pipeline.run_async writes each sync component's outputs when its thread finishes, so variadic
inputs arrive in completion order. Six scenarios assumed the sync order; CI on Python 3.15 hit
three of them on every run. Follows the AnyOrder approach of the Python 3.14 PR (#10634).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 3.15 run passed on all OSes: https://github.com/deepset-ai/haystack/actions/runs/38069150959
Reverts ba1409e, c9c1d0b and def2e55.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@julian-risch julian-risch changed the title chore: drop Python 3.10 support, add Python 3.15 chore!: drop Python 3.10 support, add Python 3.15 Oct 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium priority, add to the next sprint if no P1 available topic:build/distribution topic:CI topic:core topic:DX Developer Experience topic:tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Drop Python 3.10 support and add Python 3.15

2 participants