From 12658a534dbe704d5267fd5af6d63546b3bdba59 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 27 Oct 2024 12:00:36 -0400 Subject: [PATCH 1/7] BLD: do not try to use limited API in freethreading builds --- setup.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 0b175af85..a860d5747 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ import os import platform import setuptools - +import sysconfig kwargs = {} @@ -35,6 +35,16 @@ platform.python_implementation() == "CPython" and os.environ.get("TORNADO_EXTENSION") != "0" ): + # build with Py_LIMITED_API unless in freethreading build (which does not currently + # support the limited API in py313t) + if not sysconfig.get_config_var("Py_GIL_DISABLED"): + extension_kwargs = dict( + py_limited_api=True, define_macros=[("Py_LIMITED_API", "0x03090000")] + ) + kwargs["options"] = {"bdist_wheel": {"py_limited_api": "cp39"}} + else: + extension_kwargs = {} + # This extension builds and works on pypy as well, although pypy's jit # produces equivalent performance. kwargs["ext_modules"] = [ @@ -45,14 +55,11 @@ # fall back to the pure-python implementation on any build failure. optional=os.environ.get("TORNADO_EXTENSION") != "1", # Use the stable ABI so our wheels are compatible across python - # versions. - py_limited_api=True, - define_macros=[("Py_LIMITED_API", "0x03090000")], + # versions if not in freethreading build + **extension_kwargs, ) ] - kwargs["options"] = {"bdist_wheel": {"py_limited_api": "cp39"}} - setuptools.setup( name="tornado", From 00f2b2b97743974de3c081dba9795beed245ce03 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 14:36:39 -0400 Subject: [PATCH 2/7] CI: add 3.13t to build matrix on CI --- .github/workflows/test.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e947689c3..bf5d63014 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,6 +53,8 @@ jobs: tox_env: py312-full - python: '3.13' tox_env: py313-full + - python: '3.13t' + tox_env: py313-full - python: '3.14.0-alpha.1 - 3.14' tox_env: py314-full - python: 'pypy-3.10' @@ -67,8 +69,15 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 name: Install Python + if: matrix.python != '3.13t' with: python-version: ${{ matrix.python}} + - name: Install Python + uses: deadsnakes/action@e640ac8743173a67cca4d7d77cd837e514bf98e8 # v3.2.0 + if: matrix.python == '3.13t' + with: + python-version: '3.13' + nogil: true - name: Install apt packages run: sudo apt-get update && sudo apt-get install libcurl4-openssl-dev - name: Install tox From 96eae7c951f219acaefdd330309a5a9088d54e3e Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 21:53:11 -0400 Subject: [PATCH 3/7] CI: guess missing apt dependencies for cffi --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bf5d63014..01a7a1bb2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,7 +79,7 @@ jobs: python-version: '3.13' nogil: true - name: Install apt packages - run: sudo apt-get update && sudo apt-get install libcurl4-openssl-dev + run: sudo apt-get update && sudo apt-get install libcurl4-openssl-dev pkg-config libffi-dev - name: Install tox run: python -m pip install tox -c requirements.txt From 91de41172db78ccfcc3dcadd9e24bf5f3a04c411 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 21:58:34 -0400 Subject: [PATCH 4/7] CI: try not depending on the thing that is not installing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 01a7a1bb2..347993e79 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: - python: '3.13' tox_env: py313-full - python: '3.13t' - tox_env: py313-full + tox_env: py313 - python: '3.14.0-alpha.1 - 3.14' tox_env: py314-full - python: 'pypy-3.10' From 93f133950b8437fc50674c80d6398f994e252bb5 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 22:04:08 -0400 Subject: [PATCH 5/7] TST: Force the GIL on This avoids warnings that tornado does not declare itself freethreading safe which cause failures with cp313t as other errors are expected. --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index d80f7275a..75feafc06 100644 --- a/tox.ini +++ b/tox.ini @@ -58,6 +58,8 @@ setenv = # (New in python 3.10, becomes obsolete when utf8 becomes the # default in 3.15) PYTHONWARNDEFAULTENCODING=1 + # force the GIL on + PYTHON_GIL=1 # Allow shell commands in tests allowlist_externals = sh, env From 2f65e96649b65bbc8193c17ce5d92020e68420c8 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 22:13:44 -0400 Subject: [PATCH 6/7] TST: skip gc tests on freethreaded build The GC collection rules have changed, tests may not be valid anymore. --- tornado/test/circlerefs_test.py | 3 ++- tornado/test/util.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tornado/test/circlerefs_test.py b/tornado/test/circlerefs_test.py index d5f7e9692..5ae7ccaab 100644 --- a/tornado/test/circlerefs_test.py +++ b/tornado/test/circlerefs_test.py @@ -19,7 +19,7 @@ import tornado from tornado import web, gen, httpclient -from tornado.test.util import skipNotCPython +from tornado.test.util import skipNotCPython, skipFreeThreaded def find_circular_references(garbage): @@ -102,6 +102,7 @@ def assert_no_cycle_garbage(): # GC behavior is cpython-specific @skipNotCPython +@skipFreeThreaded class CircleRefsTest(unittest.TestCase): def test_known_leak(self): # Construct a known leak scenario to make sure the test harness works. diff --git a/tornado/test/util.py b/tornado/test/util.py index 25dd2000f..394d4ca2e 100644 --- a/tornado/test/util.py +++ b/tornado/test/util.py @@ -3,6 +3,7 @@ import platform import socket import sys +import sysconfig import textwrap import typing import unittest @@ -23,6 +24,10 @@ skipNotCPython = unittest.skipIf( platform.python_implementation() != "CPython", "Not CPython implementation" ) +skipFreeThreaded = unittest.skipIf( + sysconfig.get_config_var("Py_GIL_DISABLED"), + "Freethreaded Python build" +) def _detect_ipv6(): From 93f3de22889e26495959bbab9603d740e37028fe Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 28 Oct 2024 22:35:44 -0400 Subject: [PATCH 7/7] STY: placate the linter / formatter --- tornado/test/util.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tornado/test/util.py b/tornado/test/util.py index 394d4ca2e..e205b6b69 100644 --- a/tornado/test/util.py +++ b/tornado/test/util.py @@ -25,8 +25,7 @@ platform.python_implementation() != "CPython", "Not CPython implementation" ) skipFreeThreaded = unittest.skipIf( - sysconfig.get_config_var("Py_GIL_DISABLED"), - "Freethreaded Python build" + sysconfig.get_config_var("Py_GIL_DISABLED"), "Freethreaded Python build" )