Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,35 @@ jobs:
cache-dependency-glob: uv.lock
- uses: actions/setup-python@v7
with:
python-version-file: pyproject.toml
python-version-file: .python-version
allow-prereleases: true
- run: uv sync --group=test
- name: Run tests
# opencv-python is gated out on 3.14t (no cp314t wheel yet), so skip the
# files that import cv2. Pure-Python algorithms in computer_vision/ and
# data_compression/ still run; digital_image_processing/ is almost entirely
# cv2-based so it is skipped as a tree. Re-enable when a cp314t wheel ships.
# --ignore-gil-enabled: some compiled deps (sklearn, xgboost, ...) don't
# yet ship the Py_mod_gil slot, so importing them re-enables the GIL under
# 3.14t. That's an upstream-wheel gap, not our code; the flag lets the suite
# run anyway and pytest-run-parallel still reports which tests are not
# thread-safe. Drop the flag once the scientific stack ships free-threaded wheels.
# qiskit is likewise gated out of the 3.14t deps (Qiskit/qiskit#16893), so the
# single file that imports it (quantum/q_fourier_transform.py) is skipped too.
run: uv run --with=pytest-run-parallel pytest
--iterations=8 --parallel-threads=auto
--iterations=8 --parallel-threads=auto --ignore-gil-enabled
--ignore=computer_vision/cnn_classification.py
--ignore=computer_vision/flip_augmentation.py
--ignore=computer_vision/harris_corner.py
--ignore=computer_vision/mosaic_augmentation.py
--ignore=data_compression/peak_signal_to_noise_ratio.py
--ignore=digital_image_processing/
--ignore=docs/conf.py
--ignore=dynamic_programming/k_means_clustering_tensorflow.py
--ignore=machine_learning/lstm/lstm_prediction.py
--ignore=neural_network/input_data.py
--ignore=project_euler/
--ignore=quantum/q_fourier_transform.py
--ignore=scripts/validate_solutions.py
--ignore=web_programming/current_stock_price.py
--ignore=web_programming/fetch_anime_and_play.py
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/directory_writer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v7
with:
python-version-file: pyproject.toml
python-version-file: .python-version
allow-prereleases: true
- name: Write DIRECTORY.md
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/project_euler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- uses: astral-sh/setup-uv@v7
- uses: actions/setup-python@v7
with:
python-version-file: pyproject.toml
python-version-file: .python-version
allow-prereleases: true
- run: uv sync --group=euler-validate --group=test
- run: uv run pytest --doctest-modules --cov-report=term-missing:skip-covered --cov=project_euler/ project_euler/
Expand All @@ -43,7 +43,7 @@ jobs:
- uses: astral-sh/setup-uv@v7
- uses: actions/setup-python@v7
with:
python-version-file: pyproject.toml
python-version-file: .python-version
allow-prereleases: true
- run: uv sync --group=euler-validate --group=test
- run: uv run pytest scripts/validate_solutions.py
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sphinx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- uses: astral-sh/setup-uv@v7
- uses: actions/setup-python@v7
with:
python-version-file: pyproject.toml
python-version-file: .python-version
allow-prereleases: true
- run: uv sync --group=docs
- uses: actions/configure-pages@v6
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ target/
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14t
20 changes: 18 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.14"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Free Threading :: 2 - Beta",
]
dependencies = [
"beautifulsoup4>=4.15",
Expand All @@ -18,10 +19,8 @@ dependencies = [
"lxml>=6",
"matplotlib>=3.9.3",
"numpy>=2.1.3",
"opencv-python>=4.10.0.84",
"pandas>=2.3.3",
"pillow>=11.3",
"qiskit>=2",
"rich>=13.9.4",
"scikit-learn>=1.5.2",
"scipy>=1.16.2",
Expand All @@ -42,10 +41,27 @@ docs = [
"sphinx>=8.2",
"sphinx-autoapi>=3.4",
]
# opencv-python has no free-threaded (cp314t) wheel yet and fails to build from
# source under 3.14t (CMake), which blocks `uv sync` for every job. Keep it in an
# optional group so the free-threaded CI can install everything else and actually
# run pytest-run-parallel on the pure-Python algorithms. Re-fold into core deps
# once a cp314t wheel ships (upstream: opencv/opencv#27933).
cv = [
"opencv-python>=4.10.0.84",
]
euler-validate = [
"httpx>=0.28.1",
"numpy>=2.1.3",
]
# qiskit does not yet run on free-threaded CPython: its compiled core re-enables
# the GIL under 3.14t and the team is still scoping free-threading support
# (upstream: Qiskit/qiskit#16893). Keep it in an optional group so the
# free-threaded CI can install everything else; only quantum/q_fourier_transform.py
# imports it, and that file is ignored in the 3.14t test run. Re-fold into core
# deps once qiskit supports free-threading.
quantum = [
"qiskit>=2",
]

[tool.ruff]
target-version = "py314"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
target-version = "py314"
target-version = "py314t"

and restore python-version-file: pyproject.toml in all workflows.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of these turn out to be blocked by tooling constraints rather than choices, so I left them as-is — details below in case it's useful:

target-version = "py314t" — ruff doesn't accept a free-threaded target. On ruff 0.15.21:

$ ruff check --config 'target-version = "py314t"' .
unknown variant `py314t`, expected one of `py37`, `py38`, `py39`, `py310`, `py311`, `py312`, `py313`, `py314`, `py315`

target-version is the language version (it gates which syntax/lint rules apply), and free-threading doesn't change the language — 3.14 and 3.14t parse identically. So py314 is correct here and py314t would fail the config parse in every ruff run.

python-version-file: pyproject.tomlsetup-python resolves that file via project.requires-python, which is semver, and 3.14t isn't valid semver (see actions/setup-python#973 — the t suffix is pyenv/wheel notation, not semver). So requires-python = ">=3.14" would install the GIL build, not the free-threaded one, which defeats the PR. The only version-file that can carry 3.14t is .python-version, but that's gitignored here (.gitignore:76) by convention so contributors can keep a local pin without committing it. That's why I used the explicit python-version: 3.14t — it's the minimal way to actually select the free-threaded interpreter in CI.

If you'd rather single-source it across the 4 workflows anyway, I'm happy to un-ignore .python-version, pin it to 3.14t, and switch them all to python-version-file: .python-version — that keeps the diffs small and gives one place to bump. Just let me know if the gitignore-convention change is worth it to you and I'll push it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice detective work!! Please un-ignore .python-version, pin it to 3.14t, and switch them all to python-version-file: .python-version.

Also, we should declare that we are free-threaded beta https://py-free-threading.github.io/porting/#define-and-document-thread-safety-guarantees

Expand Down