Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the free-threaded build of CPython 3.13 #1456

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
7 changes: 4 additions & 3 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ env:
PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest`
PYTHONIOENCODING: utf-8
PYTHONUTF8: 1
PYTHON_LATEST: 3.12
PYTHON_LATEST: 3.13


jobs:
Expand Down Expand Up @@ -184,6 +184,7 @@ jobs:
strategy:
matrix:
pyver:
- 3.13t
- 3.13
- 3.12
- 3.11
Expand Down Expand Up @@ -231,7 +232,7 @@ jobs:

- name: Setup Python ${{ matrix.pyver }}
id: python-install
uses: actions/setup-python@v5
uses: quansight-labs/setup-python@v5
with:
python-version: ${{ matrix.pyver }}
allow-prereleases: true
Expand Down Expand Up @@ -392,7 +393,7 @@ jobs:
- name: Install dependencies
uses: py-actions/py-dependency-install@v4
with:
path: requirements/test.txt
path: requirements/codspeed.txt
- name: Determine pre-compiled compatible wheel
env:
# NOTE: When `pip` is forced to colorize output piped into `jq`,
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ env:
PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest`
PYTHONIOENCODING: utf-8
PYTHONUTF8: 1
PYTHON_LATEST: 3.12
PYTHON_LATEST: 3.13

jobs:

Expand Down
1 change: 1 addition & 0 deletions CHANGES/1456.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implemented support for the free-threaded build of CPython 3.13 -- by :user:`lysnikolaou`.
1 change: 1 addition & 0 deletions CHANGES/1456.packaging.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Started building wheels for the free-threaded build of CPython 3.13 -- by :user:`lysnikolaou`.
1 change: 1 addition & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Bluesky
Bugfixes
CPython
Changelog
Codecov
Cython
Expand Down
11 changes: 7 additions & 4 deletions packaging/pep517_backend/_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import annotations

import os
import sysconfig
import typing as t
from contextlib import contextmanager, nullcontext, suppress
from functools import partial
Expand Down Expand Up @@ -371,10 +372,12 @@ def get_requires_for_build_wheel(
stacklevel=999,
)

c_ext_build_deps = [] if is_pure_python_build else [
'Cython ~= 3.0.0; python_version >= "3.12"',
'Cython; python_version < "3.12"',
]
if is_pure_python_build:
c_ext_build_deps = []
elif sysconfig.get_config_var("Py_GIL_DISABLED"):
c_ext_build_deps = ['Cython == 3.1.0a1']
else:
c_ext_build_deps = ['Cython ~= 3.0.0']

return _setuptools_get_requires_for_build_wheel(
config_settings=config_settings,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ linetrace = "True" # Implies `profile=True`

[tool.cibuildwheel]
build-frontend = "build"
enable = ["cpython-freethreading"]
before-test = [
# NOTE: Attempt to have pip pre-compile PyYAML wheel with our build
# NOTE: constraints unset. The hope is that pip will cache that wheel
Expand Down
3 changes: 2 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ doctest_optionflags = ALLOW_UNICODE ELLIPSIS
# Marks tests with an empty parameterset as xfail(run=False)
empty_parameter_set_mark = xfail

faulthandler_timeout = 30
faulthandler_timeout = 60

filterwarnings =
error
Expand Down Expand Up @@ -80,6 +80,7 @@ norecursedirs =
.github
.tox
*.egg
.hypothesis

testpaths = tests/

Expand Down
2 changes: 2 additions & 0 deletions requirements/codspeed.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-r test.txt
pytest-codspeed==3.1.2
3 changes: 2 additions & 1 deletion requirements/cython.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
cython==3.0.11
cython==3.1.0a1; python_version >= '3.13'
cython==3.0.11; python_version <= '3.12'
1 change: 0 additions & 1 deletion requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ propcache==0.2.1
pytest==8.3.4
pytest-cov>=2.3.1
pytest-xdist
pytest_codspeed==3.1.2
7 changes: 7 additions & 0 deletions scripts/cibw_before_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# TODO: Delete when there's a PyPI Cython release (3.1.0) that supports free-threaded Python 3.13.
FREE_THREADED_BUILD="$(python -c"import sysconfig; print(bool(sysconfig.get_config_var('Py_GIL_DISABLED')))")"
if [[ $FREE_THREADED_BUILD == "True" ]]; then
python -m pip install -U pip
python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple cython
python -m pip install setuptools expandvars
fi
37 changes: 36 additions & 1 deletion tests/test_quoting_benchmarks.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""codspeed benchmark for yarl._quoting module."""

from pytest_codspeed import BenchmarkFixture
import pytest

try:
from pytest_codspeed import BenchmarkFixture
except ImportError:
BenchmarkFixture = None

from yarl._quoting import _Quoter, _Unquoter

Expand All @@ -15,69 +20,99 @@
LONG_QUERY_WITH_PCT = LONG_QUERY + "&d=%25%2F%3F%3A%40%26%3B%3D%2B"


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_quote_query_string(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
QUERY_QUOTER("a=1&b=2&c=3&d=4&e=5&f=6&g=7&h=8&i=9&j=0")


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_quoter_ascii(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
QUOTER_SLASH_SAFE("/path/to")


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_quote_long_path(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
PATH_QUOTER(LONG_PATH)


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_quoter_pct(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
QUOTER("abc%0a")


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_long_query(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
QUERY_QUOTER(LONG_QUERY)


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_long_query_with_pct(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
QUERY_QUOTER(LONG_QUERY_WITH_PCT)


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_quoter_quote_utf8(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
PATH_QUOTER("/шлях/файл")


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_unquoter_short(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
UNQUOTER("/path/to")


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_unquoter_long_ascii(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
for _ in range(100):
UNQUOTER(LONG_QUERY)


@pytest.mark.skipif(
BenchmarkFixture is None, reason="pytest-codspeed needs to be installed"
)
def test_unquoter_long_pct(benchmark: BenchmarkFixture) -> None:
@benchmark
def _run() -> None:
Expand Down
Loading
Loading