From 5f35844b0b93dbe9a694d366b63b3282efd38006 Mon Sep 17 00:00:00 2001 From: cxzhong Date: Wed, 1 Oct 2025 16:16:40 +0800 Subject: [PATCH 01/21] Fix Python 3.14 compatibility: Set multiprocessing start method to 'fork' Python 3.14 changed the default multiprocessing start method from 'fork' to 'forkserver' on Linux, which breaks SIGCHLD signal delivery in tests. This causes pselect tests to hang indefinitely. Changes: - Add Python 3.14 detection in conftest.py - Force multiprocessing to use 'fork' method for Python 3.14+ - Add defensive check for __test__ attribute before deletion Fixes test timeouts on Python 3.14.0rc2. All tests now pass in ~8 seconds (previously timed out at 300s+). --- src/conftest.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/conftest.py b/src/conftest.py index c8bc008f..0e300799 100755 --- a/src/conftest.py +++ b/src/conftest.py @@ -1,5 +1,6 @@ import pathlib import platform +import sys from _pytest.nodes import Collector from _pytest.doctest import DoctestModule @@ -18,6 +19,16 @@ "cysignals/tests.pyx", ] +# Python 3.14+ changed the default multiprocessing start method to 'forkserver' +# on Linux, which breaks SIGCHLD-based tests. Set it back to 'fork' for compatibility. +if sys.version_info >= (3, 14) and platform.system() != "Windows": + import multiprocessing + try: + multiprocessing.set_start_method('fork', force=True) + except RuntimeError: + # Method may already be set + pass + def pytest_collect_file( file_path: pathlib.Path, @@ -31,6 +42,7 @@ def pytest_collect_file( _, module_name = resolve_pkg_root_and_module_name(file_path) module = importlib.import_module(module_name) # delete __test__ injected by cython, to avoid duplicate tests - del module.__test__ + if hasattr(module, '__test__'): + del module.__test__ return DoctestModule.from_parent(parent, path=file_path) return None From 6153369d7e71396d13e86182b844a706fd1fa8fe Mon Sep 17 00:00:00 2001 From: cxzhong Date: Thu, 2 Oct 2025 22:13:01 +0800 Subject: [PATCH 02/21] Fix Python 3.14 compatibility: defer exception raising from signal handlers Python 3.14 changed recursion checking to use actual C stack pointers instead of counters. The old implementation called Python code from within signal handlers before siglongjmp(), causing _Py_CheckRecursiveCall() to see inconsistent stack pointers and report 'Unrecoverable stack overflow'. Solution: Never call Python code from within signal handlers. Changes: - Added signal_to_raise field to cysigs_t to store deferred signal - Modified signal handlers to only set flag and longjmp (no Python calls) - Added _sig_raise_deferred() to raise exceptions after longjmp - Updated _sig_on_postjmp() to call _sig_raise_deferred() in safe context This maintains async-signal-safety and ensures Python's stack tracking remains consistent. All 65 tests pass on Python 3.14.0rc3. Also updates: - pyproject.toml: requires-python = '>=3.9,<3.15' (was <3.14) - CI/CD: Add Python 3.14 to test matrix --- .github/workflows/ci.yml | 2 +- pyproject.toml | 2 +- src/cysignals/implementation.c | 24 ++++++++++++++++++++---- src/cysignals/macros.h | 5 ++++- src/cysignals/signals.pxd | 2 ++ src/cysignals/signals.pyx | 1 + src/cysignals/struct_signals.h | 6 ++++++ uv.lock | 14 ++++++++++++-- 8 files changed, 47 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe5cc0c8..086f0f76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: os: ['macos-13', 'macos-latest', 'ubuntu-latest', 'windows-latest'] - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - name: Set up the repository uses: actions/checkout@v4 diff --git a/pyproject.toml b/pyproject.toml index d49c04bb..b1929b92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ "Topic :: Software Development :: Debuggers", ] urls = { Homepage = "https://github.com/sagemath/cysignals" } -requires-python = ">=3.9,<3.14" +requires-python = ">=3.9,<3.15" [project.entry-points.pkg_config] cysignals = 'cysignals' diff --git a/src/cysignals/implementation.c b/src/cysignals/implementation.c index 445a40f6..cf302ae1 100644 --- a/src/cysignals/implementation.c +++ b/src/cysignals/implementation.c @@ -392,8 +392,9 @@ static void cysigs_interrupt_handler(int sig) { if (!cysigs.block_sigint && !custom_signal_is_blocked()) { - /* Raise an exception so Python can see it */ - do_raise_exception(sig); + /* Store signal number to raise exception after longjmp. + * Do NOT call Python code from signal handler! */ + cysigs.signal_to_raise = sig; #if !_WIN32 /* Jump back to sig_on() (the first one if there is a stack) */ @@ -449,8 +450,9 @@ static void cysigs_signal_handler(int sig) } #endif - /* Raise an exception so Python can see it */ - do_raise_exception(sig); + /* Store signal number to raise exception after longjmp. + * Do NOT call Python code from signal handler! */ + cysigs.signal_to_raise = sig; #if !_WIN32 /* Jump back to sig_on() (the first one if there is a stack) */ siglongjmp(trampoline, sig); @@ -616,6 +618,20 @@ static void _sig_on_recover(void) cysigs.inside_signal_handler = 0; } +/* Raise exception for signal that was deferred from signal handler. + * This MUST be called from a safe context (after longjmp), NOT from + * inside the signal handler itself. */ +static void _sig_raise_deferred(void) +{ + int sig = cysigs.signal_to_raise; + if (sig != 0) + { + cysigs.signal_to_raise = 0; + /* Now safe to call Python code - we're back in normal context */ + do_raise_exception(sig); + } +} + /* Give a warning that sig_off() was called without sig_on() */ static void _sig_off_warning(const char* file, int line) { diff --git a/src/cysignals/macros.h b/src/cysignals/macros.h index cd7b5a86..8e89c311 100644 --- a/src/cysignals/macros.h +++ b/src/cysignals/macros.h @@ -148,7 +148,10 @@ static inline int _sig_on_postjmp(int jmpret) { if (unlikely(jmpret > 0)) { - /* An exception occurred */ + /* A signal occurred and we jumped back via longjmp. + * Now we're back in a safe context (not in signal handler), + * so it's safe to call Python code to raise the exception. */ + _sig_raise_deferred(); _sig_on_recover(); return 0; } diff --git a/src/cysignals/signals.pxd b/src/cysignals/signals.pxd index 531a9a84..ad8e4247 100644 --- a/src/cysignals/signals.pxd +++ b/src/cysignals/signals.pxd @@ -91,6 +91,7 @@ cdef nogil: cysigs_t cysigs "cysigs" void _sig_on_interrupt_received "_sig_on_interrupt_received"() noexcept void _sig_on_recover "_sig_on_recover"() noexcept + void _sig_raise_deferred "_sig_raise_deferred"() noexcept void _sig_off_warning "_sig_off_warning"(const char*, int) noexcept void print_backtrace "print_backtrace"() noexcept @@ -99,5 +100,6 @@ cdef inline void __generate_declarations() noexcept: cysigs _sig_on_interrupt_received _sig_on_recover + _sig_raise_deferred _sig_off_warning print_backtrace diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index c02ca97f..19830a76 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -56,6 +56,7 @@ cdef extern from "implementation.c": void print_backtrace() nogil void _sig_on_interrupt_received() nogil void _sig_on_recover() nogil + void _sig_raise_deferred() nogil void _sig_off_warning(const char*, int) nogil # Python library functions for raising exceptions without "except" diff --git a/src/cysignals/struct_signals.h b/src/cysignals/struct_signals.h index e36ad860..d8b27370 100644 --- a/src/cysignals/struct_signals.h +++ b/src/cysignals/struct_signals.h @@ -91,6 +91,12 @@ typedef struct * been received. This is set by sig_on(). */ cyjmp_buf env; + /* Signal number to be raised as exception after longjmp. + * Set by signal handler, checked and cleared by _sig_on_postjmp. + * This allows us to defer calling Python code until we're back + * in a safe context (not inside signal handler). */ + cy_atomic_int signal_to_raise; + /* An optional string (in UTF-8 encoding) to be used as text for * the exception raised by sig_raise_exception(). If this is NULL, * use some default string depending on the type of signal. This can diff --git a/uv.lock b/uv.lock index d25ef820..843664c7 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.9, <3.14" +requires-python = ">=3.9, <3.15" resolution-markers = [ "python_full_version >= '3.12'", "python_full_version == '3.11.*'", @@ -187,6 +187,16 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bd/8c/3d0839cf0b315157974bf283d4bd658f5c30277091ad34c093f286c59e0f/cython-3.1.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8096394960d38b793545753b73781bc0ec695f0b8c22454431704b297e296045", size = 3318723, upload-time = "2025-09-16T07:22:54.322Z" }, { url = "https://files.pythonhosted.org/packages/c6/05/67b4de710a3109030d868e23d5dccf35559afa4c089b4c0aa9e22ffda1f1/cython-3.1.4-cp313-cp313-win32.whl", hash = "sha256:4e7c726ac753ca1a5aa30286cbadcd10ed4b4312ea710a8a16bb908d41e9c059", size = 2481433, upload-time = "2025-09-16T07:22:56.409Z" }, { url = "https://files.pythonhosted.org/packages/89/ef/f179b5a46185bc5550c07b328d687ee32251963a3a93e869b75fbf97181c/cython-3.1.4-cp313-cp313-win_amd64.whl", hash = "sha256:f2ee2bb77943044f301cec04d0b51d8e3810507c9c250d6cd079a3e2d6ba88f2", size = 2703057, upload-time = "2025-09-16T07:22:57.994Z" }, + { url = "https://files.pythonhosted.org/packages/38/85/f1380e8370b470b218e452ba3995555524e3652f026333e6bad6c68770b5/cython-3.1.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c7258739d5560918741cb040bd85ba7cc2f09d868de9116a637e06714fec1f69", size = 3045864, upload-time = "2025-09-16T07:22:59.854Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/54c7bc78df1e55ac311054cb2fd33908f23b8a6f350c30defeca416d8077/cython-3.1.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b2d522ee8d3528035e247ee721fb40abe92e9ea852dc9e48802cec080d5de859", size = 2967105, upload-time = "2025-09-16T07:23:01.666Z" }, + { url = "https://files.pythonhosted.org/packages/02/02/89f70e71972f796863429b159c8e8e858b85bedbc9c747d167a5c6f6417e/cython-3.1.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4e0560baeb56c29d7d8d693a050dd4d2ed922d8d7c66f5c5715c6f2be84e903", size = 3363386, upload-time = "2025-09-16T07:23:03.39Z" }, + { url = "https://files.pythonhosted.org/packages/2a/34/eda836ae260013d4dd1c7aaa8dd6f7d7862206ba3354db5d8f55a8f6ef67/cython-3.1.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4223cacc81cba0df0f06f79657c5d6286e153b9a9b989dad1cdf4666f618c073", size = 3192314, upload-time = "2025-09-16T07:23:05.354Z" }, + { url = "https://files.pythonhosted.org/packages/7e/fa/db8224f7fe7ec1ebdab0b5e71b5a8269c112645c4eac2464ef0735bb395e/cython-3.1.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ff4d1f159edee6af38572318681388fbd6448b0d08b9a47494aaf0b698e93394", size = 3312222, upload-time = "2025-09-16T07:23:07.066Z" }, + { url = "https://files.pythonhosted.org/packages/62/09/419262657800dee7202a76956cd52896a6e8793bbbecc2592a4ebba2e034/cython-3.1.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2537c53071a9a124e0bc502a716e1930d9bb101e94c26673016cf1820e4fdbd1", size = 3208798, upload-time = "2025-09-16T07:23:08.758Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d8/f140c7b9356a29660dc05591272e33062df964b9d1a072d09e89ade41087/cython-3.1.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:85416717c529fb5ccf908464657a5187753e76d7b6ffec9b1c2d91544f6c3628", size = 3379662, upload-time = "2025-09-16T07:23:10.511Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e8/83cf9a9cf64cbfe4eaf3987a633be08243f838b7d12e5739831297b77311/cython-3.1.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:18882e2f5c0e0c25f9c44f16f2fb9c48f33988885c5f9eae2856f10c6f089ffa", size = 3324255, upload-time = "2025-09-16T07:23:12.267Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f8/f2033044687cf6296275fa71cdf63a247d3646a3e276aa002e65bf505f46/cython-3.1.4-cp314-cp314-win32.whl", hash = "sha256:8ef8deadc888eaf95e5328fc176fb6c37bccee1213f07517c6ea55b5f817c457", size = 2503665, upload-time = "2025-09-16T07:23:14.372Z" }, + { url = "https://files.pythonhosted.org/packages/04/57/7af75a803d55610d570d7b7a0fdc2bfd82fae030c728089cc628562d67f9/cython-3.1.4-cp314-cp314-win_amd64.whl", hash = "sha256:acb99ddec62ba1ea5de0e0087760fa834ec42c94f0488065a4f1995584e8e94e", size = 2734608, upload-time = "2025-09-16T07:23:16.025Z" }, { url = "https://files.pythonhosted.org/packages/43/5f/17838c577a0e052073991a3ace1c380d02927bd7a15cdee7ecaa363dc093/cython-3.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95d2303ee54cf469f7c61aa94ef46c195d42e75a76881b9e33770bcf6c0a5c6", size = 3000303, upload-time = "2025-09-16T07:23:37.644Z" }, { url = "https://files.pythonhosted.org/packages/2a/7c/9f018d9011639a3e8ba5389541665a10bafab18e5118e37e0a0043fd6bb0/cython-3.1.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fc723ffca257beebe42c8e2dcb2b9771957b752d6f42684f17ca1d2a4346b21", size = 2925511, upload-time = "2025-09-16T07:23:39.325Z" }, { url = "https://files.pythonhosted.org/packages/28/14/8bfc9aeaeb480789a212af82e1793409e897ce4b868ff051b60d641c224c/cython-3.1.4-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1fb5060dd0c89f5c64002a0c44c2fcb5d066d119e2ae4d1bfa2c6482333dd42a", size = 3516323, upload-time = "2025-09-16T07:23:41.257Z" }, @@ -248,7 +258,7 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.11'" }, + { name = "zipp" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ From 1389e133e21c9f2e8264bd4c767e51f5c45fcf49 Mon Sep 17 00:00:00 2001 From: cxzhong Date: Thu, 2 Oct 2025 22:16:58 +0800 Subject: [PATCH 03/21] CI: Use specific Python 3.14.0-rc.3 version for testing --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 086f0f76..7ea2ea79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: os: ['macos-13', 'macos-latest', 'ubuntu-latest', 'windows-latest'] - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14.0-rc.3'] steps: - name: Set up the repository uses: actions/checkout@v4 From 19c9434b8058d9ee9289fc41bdf1fb58d04ec667 Mon Sep 17 00:00:00 2001 From: cxzhong Date: Fri, 3 Oct 2025 13:26:01 +0800 Subject: [PATCH 04/21] Python 3.14: Support forkserver multiprocessing start method - Remove forced fork() from conftest.py to allow Python 3.14's default forkserver multiprocessing start method - Add PSelecter.wait_for_process() method that monitors process.sentinel instead of SIGCHLD, working with any start method (fork/spawn/forkserver) - Update doctests to demonstrate both SIGCHLD-based (fork-only) and sentinel-based (universal) process monitoring approaches - Note: wait_for_process() is POSIX-only; Windows should use multiprocessing.connection.wait() instead This allows cysignals to work properly with Python 3.14's new forkserver default while maintaining backward compatibility. --- src/conftest.py | 10 ---- src/cysignals/pselect.pyx | 97 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/src/conftest.py b/src/conftest.py index 0e300799..e4346c3e 100755 --- a/src/conftest.py +++ b/src/conftest.py @@ -19,16 +19,6 @@ "cysignals/tests.pyx", ] -# Python 3.14+ changed the default multiprocessing start method to 'forkserver' -# on Linux, which breaks SIGCHLD-based tests. Set it back to 'fork' for compatibility. -if sys.version_info >= (3, 14) and platform.system() != "Windows": - import multiprocessing - try: - multiprocessing.set_start_method('fork', force=True) - except RuntimeError: - # Method may already be set - pass - def pytest_collect_file( file_path: pathlib.Path, diff --git a/src/cysignals/pselect.pyx b/src/cysignals/pselect.pyx index 07d6b14a..0a694b27 100644 --- a/src/cysignals/pselect.pyx +++ b/src/cysignals/pselect.pyx @@ -33,13 +33,31 @@ We wait for a child created using the ``subprocess`` module:: >>> p.poll() # p should be finished 0 -Now using the ``multiprocessing`` module:: +Now using the ``multiprocessing`` module with ANY start method:: >>> from cysignals.pselect import PSelecter - >>> from multiprocessing import * - >>> import time + >>> from multiprocessing import get_context + >>> import time, sys + >>> # Works with any start method - uses process sentinel + >>> ctx = get_context() # Uses default (forkserver on 3.14+, fork on older) + >>> with PSelecter() as sel: + ... p = ctx.Process(target=time.sleep, args=(0.5,)) + ... p.start() + ... # Monitor process.sentinel instead of SIGCHLD + ... r, w, x, t = sel.pselect(rlist=[p.sentinel], timeout=2) + ... p.is_alive() # p should be finished + False + +For SIGCHLD-based monitoring (requires 'fork' on Python 3.14+):: + + >>> import signal + >>> def dummy_handler(sig, frame): + ... pass + >>> _ = signal.signal(signal.SIGCHLD, dummy_handler) + >>> # Use 'fork' method for SIGCHLD to work properly + >>> ctx = get_context('fork') if sys.version_info >= (3, 14) else get_context() >>> with PSelecter([signal.SIGCHLD]) as sel: - ... p = Process(target=time.sleep, args=(1,)) + ... p = ctx.Process(target=time.sleep, args=(0.5,)) ... p.start() ... _ = sel.sleep() ... p.is_alive() # p should be finished @@ -289,12 +307,14 @@ cdef class PSelecter: Start a process which will cause a ``SIGCHLD`` signal:: - >>> import time - >>> from multiprocessing import * + >>> import time, sys + >>> from multiprocessing import get_context >>> from cysignals.pselect import PSelecter, interruptible_sleep + >>> # For SIGCHLD, must use 'fork' on Python 3.14+ + >>> ctx = get_context('fork') if sys.version_info >= (3, 14) else get_context() >>> w = PSelecter([signal.SIGCHLD]) >>> with w: - ... p = Process(target=time.sleep, args=(0.25,)) + ... p = ctx.Process(target=time.sleep, args=(0.25,)) ... t0 = time.time() ... p.start() @@ -501,3 +521,66 @@ cdef class PSelecter: """ return self.pselect(timeout=timeout)[3] + + def wait_for_process(self, process, timeout=None): + """ + Wait until a multiprocessing.Process exits or timeout occurs. + + This works with ANY multiprocessing start method (fork, spawn, forkserver) + by monitoring the process sentinel file descriptor instead of SIGCHLD. + + NOTE: This is POSIX-only. On Windows, use ``multiprocessing.connection.wait()`` + instead. + + INPUT: + + - ``process`` -- a ``multiprocessing.Process`` object + + - ``timeout`` -- (default: ``None``) a timeout in seconds, + where ``None`` stands for no timeout. + + OUTPUT: A boolean which is ``True`` if the call timed out, + False if the process exited. + + EXAMPLES: + + Works with any multiprocessing start method:: + + >>> from cysignals.pselect import PSelecter + >>> from multiprocessing import get_context + >>> import time + >>> # Use default start method (forkserver on 3.14+) + >>> ctx = get_context() + >>> sel = PSelecter() + >>> p = ctx.Process(target=time.sleep, args=(0.1,)) + >>> p.start() + >>> timed_out = sel.wait_for_process(p, timeout=1) + >>> timed_out # Should be False (process exited) + False + >>> p.is_alive() + False + + Can also be used in a with block:: + + >>> with PSelecter() as sel: + ... p = ctx.Process(target=time.sleep, args=(0.1,)) + ... p.start() + ... timed_out = sel.wait_for_process(p, timeout=1) + >>> timed_out + False + + TESTS: + + Timeout case:: + + >>> p = ctx.Process(target=time.sleep, args=(10,)) + >>> p.start() + >>> timed_out = sel.wait_for_process(p, timeout=0.1) + >>> timed_out # Should be True (timeout) + True + >>> p.terminate() + >>> p.join() + + """ + _, _, _, timed_out = self.pselect(rlist=[process.sentinel], timeout=timeout) + return timed_out From 546217f0631fedc89d30cae631bcee05d8ecb26b Mon Sep 17 00:00:00 2001 From: cxzhong Date: Fri, 3 Oct 2025 13:35:32 +0800 Subject: [PATCH 05/21] Fix Python 3.14t free-threaded build: use _Py_REFCNT() instead of ob_refcnt - Replace direct ob_refcnt access with _Py_REFCNT() macro from cpython.ref - Add NULL checks before calling _Py_REFCNT() to prevent null pointer dereference - This fixes compilation errors in Python 3.14t (free-threaded/nogil) build where ob_refcnt is not directly accessible in PyObject structure --- src/cysignals/signals.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index 19830a76..72994fef 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -25,7 +25,7 @@ See ``tests.pyx`` for extensive tests. from libc.signal cimport * from libc.stdio cimport freopen, stdin -from cpython.ref cimport Py_XINCREF, Py_CLEAR +from cpython.ref cimport Py_XINCREF, Py_CLEAR, _Py_REFCNT from cpython.exc cimport (PyErr_Occurred, PyErr_NormalizeException, PyErr_Fetch, PyErr_Restore) from cpython.version cimport PY_MAJOR_VERSION @@ -361,7 +361,7 @@ cdef void verify_exc_value() noexcept: Check that ``cysigs.exc_value`` is still the exception being raised. Clear ``cysigs.exc_value`` if not. """ - if cysigs.exc_value.ob_refcnt == 1: + if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: # No other references => exception is certainly gone Py_CLEAR(cysigs.exc_value) return @@ -409,5 +409,5 @@ cdef void verify_exc_value() noexcept: # Make sure we still have cysigs.exc_value at all; if this function was # called again during garbage collection it might have already been set # to NULL; see https://github.com/sagemath/cysignals/issues/126 - if cysigs.exc_value != NULL and cysigs.exc_value.ob_refcnt == 1: + if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: Py_CLEAR(cysigs.exc_value) From 0f15195f785cda1b7014493ddcb7bc26b1b77d83 Mon Sep 17 00:00:00 2001 From: cxzhong Date: Fri, 3 Oct 2025 14:08:52 +0800 Subject: [PATCH 06/21] Fix Python 3.14t: Use Py_REFCNT declared from Python.h instead of _Py_REFCNT - Remove _Py_REFCNT from cpython.ref import (not available in Cython) - Declare Py_REFCNT as external C function from Python.h - Replace _Py_REFCNT() calls with Py_REFCNT() (2 occurrences) - This properly supports Python 3.14t free-threaded build where ob_refcnt is not directly accessible in PyObject structure --- src/cysignals/signals.pyx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index 72994fef..e2a4c000 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -25,7 +25,7 @@ See ``tests.pyx`` for extensive tests. from libc.signal cimport * from libc.stdio cimport freopen, stdin -from cpython.ref cimport Py_XINCREF, Py_CLEAR, _Py_REFCNT +from cpython.ref cimport Py_XINCREF, Py_CLEAR from cpython.exc cimport (PyErr_Occurred, PyErr_NormalizeException, PyErr_Fetch, PyErr_Restore) from cpython.version cimport PY_MAJOR_VERSION @@ -48,6 +48,10 @@ cdef extern from *: """ pass +# Declare Py_REFCNT for Python 3.14t free-threaded build compatibility +cdef extern from "Python.h": + Py_ssize_t Py_REFCNT(PyObject *ob) + cdef extern from "implementation.c": cysigs_t cysigs int _set_debug_level(int) nogil @@ -361,7 +365,7 @@ cdef void verify_exc_value() noexcept: Check that ``cysigs.exc_value`` is still the exception being raised. Clear ``cysigs.exc_value`` if not. """ - if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: + if cysigs.exc_value != NULL and Py_REFCNT(cysigs.exc_value) == 1: # No other references => exception is certainly gone Py_CLEAR(cysigs.exc_value) return @@ -409,5 +413,5 @@ cdef void verify_exc_value() noexcept: # Make sure we still have cysigs.exc_value at all; if this function was # called again during garbage collection it might have already been set # to NULL; see https://github.com/sagemath/cysignals/issues/126 - if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: + if cysigs.exc_value != NULL and Py_REFCNT(cysigs.exc_value) == 1: Py_CLEAR(cysigs.exc_value) From 68b7713a6f784f2753991197e37394d574d4556b Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sat, 4 Oct 2025 17:37:39 +0800 Subject: [PATCH 07/21] Remove unused sys import from conftest.py Remove unused import of sys module. --- src/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/conftest.py b/src/conftest.py index e4346c3e..264bdf0e 100755 --- a/src/conftest.py +++ b/src/conftest.py @@ -1,6 +1,5 @@ import pathlib import platform -import sys from _pytest.nodes import Collector from _pytest.doctest import DoctestModule From c298389479b9d48e4ff5b6e4f3f13563be445845 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sat, 4 Oct 2025 17:57:34 +0800 Subject: [PATCH 08/21] Update reference count check for cysigs.exc_value Replaced usage of Py_REFCNT with _Py_REFCNT for compatibility with Python 3.14t free-threaded builds. --- src/cysignals/signals.pyx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index e2a4c000..72994fef 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -25,7 +25,7 @@ See ``tests.pyx`` for extensive tests. from libc.signal cimport * from libc.stdio cimport freopen, stdin -from cpython.ref cimport Py_XINCREF, Py_CLEAR +from cpython.ref cimport Py_XINCREF, Py_CLEAR, _Py_REFCNT from cpython.exc cimport (PyErr_Occurred, PyErr_NormalizeException, PyErr_Fetch, PyErr_Restore) from cpython.version cimport PY_MAJOR_VERSION @@ -48,10 +48,6 @@ cdef extern from *: """ pass -# Declare Py_REFCNT for Python 3.14t free-threaded build compatibility -cdef extern from "Python.h": - Py_ssize_t Py_REFCNT(PyObject *ob) - cdef extern from "implementation.c": cysigs_t cysigs int _set_debug_level(int) nogil @@ -365,7 +361,7 @@ cdef void verify_exc_value() noexcept: Check that ``cysigs.exc_value`` is still the exception being raised. Clear ``cysigs.exc_value`` if not. """ - if cysigs.exc_value != NULL and Py_REFCNT(cysigs.exc_value) == 1: + if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: # No other references => exception is certainly gone Py_CLEAR(cysigs.exc_value) return @@ -413,5 +409,5 @@ cdef void verify_exc_value() noexcept: # Make sure we still have cysigs.exc_value at all; if this function was # called again during garbage collection it might have already been set # to NULL; see https://github.com/sagemath/cysignals/issues/126 - if cysigs.exc_value != NULL and Py_REFCNT(cysigs.exc_value) == 1: + if cysigs.exc_value != NULL and _Py_REFCNT(cysigs.exc_value) == 1: Py_CLEAR(cysigs.exc_value) From 7dd96f13f0f977003e321cc122278b01e22c978a Mon Sep 17 00:00:00 2001 From: zhongcx Date: Sat, 4 Oct 2025 23:23:56 +0800 Subject: [PATCH 09/21] Refactor: Remove signal_to_raise global variable Eliminate redundant signal state by using only sigsetjmp/siglongjmp return values to propagate signal numbers. This simplifies the signal handling architecture and prevents potential desynchronization bugs. Changes: - Remove signal_to_raise field from cysigs_t structure - Update signal handlers to not store signal number in global variable - Remove _sig_raise_deferred() function - Modify _sig_on_postjmp() to directly use jump return value - Update Cython declarations accordingly Benefits: - Eliminates redundant state (16 lines removed) - Prevents state desynchronization issues - Signal number propagates naturally via jump mechanism - All 66 tests pass successfully The refactoring maintains full backward compatibility with no functional changes to the API or behavior. --- src/cysignals/implementation.c | 25 ++++--------------------- src/cysignals/macros.h | 9 ++++++++- src/cysignals/signals.pxd | 4 ++-- src/cysignals/signals.pyx | 2 +- src/cysignals/struct_signals.h | 6 ------ 5 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/cysignals/implementation.c b/src/cysignals/implementation.c index cf302ae1..62918017 100644 --- a/src/cysignals/implementation.c +++ b/src/cysignals/implementation.c @@ -392,12 +392,10 @@ static void cysigs_interrupt_handler(int sig) { if (!cysigs.block_sigint && !custom_signal_is_blocked()) { - /* Store signal number to raise exception after longjmp. + /* Jump back to sig_on() (the first one if there is a stack). + * The signal number is encoded in the return value of sigsetjmp. * Do NOT call Python code from signal handler! */ - cysigs.signal_to_raise = sig; - #if !_WIN32 - /* Jump back to sig_on() (the first one if there is a stack) */ siglongjmp(trampoline, sig); #endif } @@ -450,11 +448,10 @@ static void cysigs_signal_handler(int sig) } #endif - /* Store signal number to raise exception after longjmp. + /* Jump back to sig_on() (the first one if there is a stack). + * The signal number is encoded in the return value of sigsetjmp. * Do NOT call Python code from signal handler! */ - cysigs.signal_to_raise = sig; #if !_WIN32 - /* Jump back to sig_on() (the first one if there is a stack) */ siglongjmp(trampoline, sig); #endif } @@ -618,20 +615,6 @@ static void _sig_on_recover(void) cysigs.inside_signal_handler = 0; } -/* Raise exception for signal that was deferred from signal handler. - * This MUST be called from a safe context (after longjmp), NOT from - * inside the signal handler itself. */ -static void _sig_raise_deferred(void) -{ - int sig = cysigs.signal_to_raise; - if (sig != 0) - { - cysigs.signal_to_raise = 0; - /* Now safe to call Python code - we're back in normal context */ - do_raise_exception(sig); - } -} - /* Give a warning that sig_off() was called without sig_on() */ static void _sig_off_warning(const char* file, int line) { diff --git a/src/cysignals/macros.h b/src/cysignals/macros.h index 8e89c311..2982a2a8 100644 --- a/src/cysignals/macros.h +++ b/src/cysignals/macros.h @@ -143,15 +143,22 @@ static inline int _sig_on_prejmp(const char* message, CYTHON_UNUSED const char* /* * Process the return value of cysetjmp(). * Return 0 if there was an exception, 1 otherwise. + * + * This function propagates the signal number naturally via jmpret + * (the return value from sigsetjmp/cylongjmp), which is always nonzero + * when a signal occurs. This avoids using global state and eliminates + * potential desynchronization between the jump return value and any + * stored signal number. */ static inline int _sig_on_postjmp(int jmpret) { if (unlikely(jmpret > 0)) { /* A signal occurred and we jumped back via longjmp. + * jmpret contains the signal number that was passed to siglongjmp. * Now we're back in a safe context (not in signal handler), * so it's safe to call Python code to raise the exception. */ - _sig_raise_deferred(); + do_raise_exception(jmpret); _sig_on_recover(); return 0; } diff --git a/src/cysignals/signals.pxd b/src/cysignals/signals.pxd index ad8e4247..7edc6615 100644 --- a/src/cysignals/signals.pxd +++ b/src/cysignals/signals.pxd @@ -91,7 +91,7 @@ cdef nogil: cysigs_t cysigs "cysigs" void _sig_on_interrupt_received "_sig_on_interrupt_received"() noexcept void _sig_on_recover "_sig_on_recover"() noexcept - void _sig_raise_deferred "_sig_raise_deferred"() noexcept + void do_raise_exception "do_raise_exception"(int sig) noexcept void _sig_off_warning "_sig_off_warning"(const char*, int) noexcept void print_backtrace "print_backtrace"() noexcept @@ -100,6 +100,6 @@ cdef inline void __generate_declarations() noexcept: cysigs _sig_on_interrupt_received _sig_on_recover - _sig_raise_deferred + do_raise_exception _sig_off_warning print_backtrace diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index 72994fef..6865df37 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -56,7 +56,7 @@ cdef extern from "implementation.c": void print_backtrace() nogil void _sig_on_interrupt_received() nogil void _sig_on_recover() nogil - void _sig_raise_deferred() nogil + void do_raise_exception(int sig) nogil void _sig_off_warning(const char*, int) nogil # Python library functions for raising exceptions without "except" diff --git a/src/cysignals/struct_signals.h b/src/cysignals/struct_signals.h index d8b27370..e36ad860 100644 --- a/src/cysignals/struct_signals.h +++ b/src/cysignals/struct_signals.h @@ -91,12 +91,6 @@ typedef struct * been received. This is set by sig_on(). */ cyjmp_buf env; - /* Signal number to be raised as exception after longjmp. - * Set by signal handler, checked and cleared by _sig_on_postjmp. - * This allows us to defer calling Python code until we're back - * in a safe context (not inside signal handler). */ - cy_atomic_int signal_to_raise; - /* An optional string (in UTF-8 encoding) to be used as text for * the exception raised by sig_raise_exception(). If this is NULL, * use some default string depending on the type of signal. This can From b1288729b2d795ded576c328a73fb5be2b9a5ea7 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sat, 4 Oct 2025 23:37:28 +0800 Subject: [PATCH 10/21] Remove do_raise_exception declaration from signals.pxd --- src/cysignals/signals.pxd | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cysignals/signals.pxd b/src/cysignals/signals.pxd index 7edc6615..531a9a84 100644 --- a/src/cysignals/signals.pxd +++ b/src/cysignals/signals.pxd @@ -91,7 +91,6 @@ cdef nogil: cysigs_t cysigs "cysigs" void _sig_on_interrupt_received "_sig_on_interrupt_received"() noexcept void _sig_on_recover "_sig_on_recover"() noexcept - void do_raise_exception "do_raise_exception"(int sig) noexcept void _sig_off_warning "_sig_off_warning"(const char*, int) noexcept void print_backtrace "print_backtrace"() noexcept @@ -100,6 +99,5 @@ cdef inline void __generate_declarations() noexcept: cysigs _sig_on_interrupt_received _sig_on_recover - do_raise_exception _sig_off_warning print_backtrace From 1c1bcfd12765d8beb1707aba27d2f5dfcf67eb66 Mon Sep 17 00:00:00 2001 From: zhongcx Date: Sat, 4 Oct 2025 23:41:24 +0800 Subject: [PATCH 11/21] Revert "Remove do_raise_exception declaration from signals.pxd" This reverts commit b1288729b2d795ded576c328a73fb5be2b9a5ea7. --- src/cysignals/signals.pxd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cysignals/signals.pxd b/src/cysignals/signals.pxd index 531a9a84..7edc6615 100644 --- a/src/cysignals/signals.pxd +++ b/src/cysignals/signals.pxd @@ -91,6 +91,7 @@ cdef nogil: cysigs_t cysigs "cysigs" void _sig_on_interrupt_received "_sig_on_interrupt_received"() noexcept void _sig_on_recover "_sig_on_recover"() noexcept + void do_raise_exception "do_raise_exception"(int sig) noexcept void _sig_off_warning "_sig_off_warning"(const char*, int) noexcept void print_backtrace "print_backtrace"() noexcept @@ -99,5 +100,6 @@ cdef inline void __generate_declarations() noexcept: cysigs _sig_on_interrupt_received _sig_on_recover + do_raise_exception _sig_off_warning print_backtrace From e119a0c978c6ee205bf27273b416c03ad4d9344e Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sun, 5 Oct 2025 15:33:58 +0800 Subject: [PATCH 12/21] Update macOS version in CI workflow --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ea2ea79..f1c05038 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: ['macos-13', 'macos-latest', 'ubuntu-latest', 'windows-latest'] + os: ['macos-14', 'macos-latest', 'ubuntu-latest', 'windows-latest'] python-version: ['3.10', '3.11', '3.12', '3.13', '3.14.0-rc.3'] steps: - name: Set up the repository From 33533c58dc13bb99c8486b40ce9eea137ecbe4dd Mon Sep 17 00:00:00 2001 From: cxzhong Date: Sun, 5 Oct 2025 19:11:00 +0800 Subject: [PATCH 13/21] Rename do_raise_exception to _do_raise_exception for consistency with naming conventions --- src/cysignals/implementation.c | 8 ++++---- src/cysignals/macros.h | 2 +- src/cysignals/signals.pxd | 4 ++-- src/cysignals/signals.pyx | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cysignals/implementation.c b/src/cysignals/implementation.c index 62918017..88dee663 100644 --- a/src/cysignals/implementation.c +++ b/src/cysignals/implementation.c @@ -120,7 +120,7 @@ static void setup_cysignals_handlers(void); static void cysigs_interrupt_handler(int sig); static void cysigs_signal_handler(int sig); -static void do_raise_exception(int sig); +static void _do_raise_exception(int sig); static void sigdie(int sig, const char* s); #define BACKTRACELEN 1024 @@ -553,7 +553,7 @@ static void setup_trampoline(void) /* This calls sig_raise_exception() to actually raise the exception. */ -static void do_raise_exception(int sig) +static void _do_raise_exception(int sig) { #if ENABLE_DEBUG_CYSIGNALS struct timespec raisetime; @@ -561,7 +561,7 @@ static void do_raise_exception(int sig) get_monotonic_time(&raisetime); long delta_ms = (raisetime.tv_sec - sigtime.tv_sec)*1000L + (raisetime.tv_nsec - sigtime.tv_nsec)/1000000L; PyGILState_STATE gilstate = PyGILState_Ensure(); - print_stderr("do_raise_exception(sig="); + print_stderr("_do_raise_exception(sig="); print_stderr_long(sig); print_stderr(")\nPyErr_Occurred() = "); print_stderr_ptr(PyErr_Occurred()); @@ -587,7 +587,7 @@ static void _sig_on_interrupt_received(void) sigprocmask(SIG_BLOCK, &sigmask_with_sigint, &oldset); #endif - do_raise_exception(cysigs.interrupt_received); + _do_raise_exception(cysigs.interrupt_received); cysigs.sig_on_count = 0; cysigs.interrupt_received = 0; custom_set_pending_signal(0); diff --git a/src/cysignals/macros.h b/src/cysignals/macros.h index 2982a2a8..b8f8202e 100644 --- a/src/cysignals/macros.h +++ b/src/cysignals/macros.h @@ -158,7 +158,7 @@ static inline int _sig_on_postjmp(int jmpret) * jmpret contains the signal number that was passed to siglongjmp. * Now we're back in a safe context (not in signal handler), * so it's safe to call Python code to raise the exception. */ - do_raise_exception(jmpret); + _do_raise_exception(jmpret); _sig_on_recover(); return 0; } diff --git a/src/cysignals/signals.pxd b/src/cysignals/signals.pxd index 7edc6615..049a4d06 100644 --- a/src/cysignals/signals.pxd +++ b/src/cysignals/signals.pxd @@ -91,7 +91,7 @@ cdef nogil: cysigs_t cysigs "cysigs" void _sig_on_interrupt_received "_sig_on_interrupt_received"() noexcept void _sig_on_recover "_sig_on_recover"() noexcept - void do_raise_exception "do_raise_exception"(int sig) noexcept + void _do_raise_exception "_do_raise_exception"(int sig) noexcept void _sig_off_warning "_sig_off_warning"(const char*, int) noexcept void print_backtrace "print_backtrace"() noexcept @@ -100,6 +100,6 @@ cdef inline void __generate_declarations() noexcept: cysigs _sig_on_interrupt_received _sig_on_recover - do_raise_exception + _do_raise_exception _sig_off_warning print_backtrace diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index 6865df37..0a715830 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -56,7 +56,7 @@ cdef extern from "implementation.c": void print_backtrace() nogil void _sig_on_interrupt_received() nogil void _sig_on_recover() nogil - void do_raise_exception(int sig) nogil + void _do_raise_exception(int sig) nogil void _sig_off_warning(const char*, int) nogil # Python library functions for raising exceptions without "except" From 385d66cca53efcf7d57e6ea943402388ce220c47 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sun, 5 Oct 2025 21:57:15 +0800 Subject: [PATCH 14/21] Remove wait_for_process method from pselect.pyx Removed the wait_for_process method that monitored process exit using a sentinel file descriptor. --- src/cysignals/pselect.pyx | 63 --------------------------------------- 1 file changed, 63 deletions(-) diff --git a/src/cysignals/pselect.pyx b/src/cysignals/pselect.pyx index 0a694b27..c2553ec3 100644 --- a/src/cysignals/pselect.pyx +++ b/src/cysignals/pselect.pyx @@ -521,66 +521,3 @@ cdef class PSelecter: """ return self.pselect(timeout=timeout)[3] - - def wait_for_process(self, process, timeout=None): - """ - Wait until a multiprocessing.Process exits or timeout occurs. - - This works with ANY multiprocessing start method (fork, spawn, forkserver) - by monitoring the process sentinel file descriptor instead of SIGCHLD. - - NOTE: This is POSIX-only. On Windows, use ``multiprocessing.connection.wait()`` - instead. - - INPUT: - - - ``process`` -- a ``multiprocessing.Process`` object - - - ``timeout`` -- (default: ``None``) a timeout in seconds, - where ``None`` stands for no timeout. - - OUTPUT: A boolean which is ``True`` if the call timed out, - False if the process exited. - - EXAMPLES: - - Works with any multiprocessing start method:: - - >>> from cysignals.pselect import PSelecter - >>> from multiprocessing import get_context - >>> import time - >>> # Use default start method (forkserver on 3.14+) - >>> ctx = get_context() - >>> sel = PSelecter() - >>> p = ctx.Process(target=time.sleep, args=(0.1,)) - >>> p.start() - >>> timed_out = sel.wait_for_process(p, timeout=1) - >>> timed_out # Should be False (process exited) - False - >>> p.is_alive() - False - - Can also be used in a with block:: - - >>> with PSelecter() as sel: - ... p = ctx.Process(target=time.sleep, args=(0.1,)) - ... p.start() - ... timed_out = sel.wait_for_process(p, timeout=1) - >>> timed_out - False - - TESTS: - - Timeout case:: - - >>> p = ctx.Process(target=time.sleep, args=(10,)) - >>> p.start() - >>> timed_out = sel.wait_for_process(p, timeout=0.1) - >>> timed_out # Should be True (timeout) - True - >>> p.terminate() - >>> p.join() - - """ - _, _, _, timed_out = self.pselect(rlist=[process.sentinel], timeout=timeout) - return timed_out From cf49a7555d544983611660f7b3c22a781fbf0ba8 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Sun, 5 Oct 2025 22:44:41 +0800 Subject: [PATCH 15/21] Update macOS version in dist workflow --- .github/workflows/dist.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 27b8c2e5..5ff42b10 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -35,7 +35,7 @@ jobs: - ubuntu-24.04-arm - windows-latest - windows-11-arm - - macos-13 + - macos-14 - macos-latest steps: - uses: actions/checkout@v4 From 7c92255550ccfa6092dd71c51749c05c6842c2eb Mon Sep 17 00:00:00 2001 From: cxzhong Date: Mon, 6 Oct 2025 10:40:00 +0800 Subject: [PATCH 16/21] Add freethreading compatibility declaration to Cython files --- src/cysignals/alarm.pyx | 1 + src/cysignals/pselect.pyx | 1 + src/cysignals/pysignals.pyx | 1 + src/cysignals/signals.pyx | 1 + src/cysignals/tests.pyx | 1 + 5 files changed, 5 insertions(+) diff --git a/src/cysignals/alarm.pyx b/src/cysignals/alarm.pyx index eb82a0d3..ca4e6667 100644 --- a/src/cysignals/alarm.pyx +++ b/src/cysignals/alarm.pyx @@ -1,3 +1,4 @@ +# cython: freethreading_compatible = True """ Fine-grained alarm function """ diff --git a/src/cysignals/pselect.pyx b/src/cysignals/pselect.pyx index 0a694b27..968a4261 100644 --- a/src/cysignals/pselect.pyx +++ b/src/cysignals/pselect.pyx @@ -1,3 +1,4 @@ +# cython: freethreading_compatible = True """ Interface to the ``pselect()`` and ``sigprocmask()`` system calls ================================================================= diff --git a/src/cysignals/pysignals.pyx b/src/cysignals/pysignals.pyx index 997c7f5f..3508209c 100644 --- a/src/cysignals/pysignals.pyx +++ b/src/cysignals/pysignals.pyx @@ -1,3 +1,4 @@ +# cython: freethreading_compatible = True r""" Python interface to signal handlers =================================== diff --git a/src/cysignals/signals.pyx b/src/cysignals/signals.pyx index 0a715830..33dbec2c 100644 --- a/src/cysignals/signals.pyx +++ b/src/cysignals/signals.pyx @@ -1,3 +1,4 @@ +# cython: freethreading_compatible = True # cython: preliminary_late_includes_cy28=True r""" Interrupt and signal handling diff --git a/src/cysignals/tests.pyx b/src/cysignals/tests.pyx index 5aa02f04..adf7f50c 100644 --- a/src/cysignals/tests.pyx +++ b/src/cysignals/tests.pyx @@ -1,3 +1,4 @@ +# cython: freethreading_compatible = True # cython: preliminary_late_includes_cy28=True, show_performance_hints=False """ Test interrupt and signal handling From ba28e30b47d2cf50e0711b43e58af9440e1d5697 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Wed, 8 Oct 2025 09:51:48 +0800 Subject: [PATCH 17/21] Update Python version in CI workflow Updated Python version in CI workflow from '3.14.0-rc.3' to '3.14'. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1c05038..bb0efea7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: os: ['macos-14', 'macos-latest', 'ubuntu-latest', 'windows-latest'] - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14.0-rc.3'] + python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] steps: - name: Set up the repository uses: actions/checkout@v4 From d6bc361261156c86156dd6c27f44e9a0383be8ad Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Wed, 8 Oct 2025 12:06:46 +0800 Subject: [PATCH 18/21] Update Python version requirements in pyproject.toml --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b1929b92..f22d1b9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,16 +21,17 @@ classifiers = [ "Programming Language :: Cython", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.14t", "Programming Language :: Python :: Implementation :: CPython", "Topic :: System", "Topic :: Software Development :: Debuggers", ] urls = { Homepage = "https://github.com/sagemath/cysignals" } -requires-python = ">=3.9,<3.15" +requires-python = ">=3.11,<3.15" [project.entry-points.pkg_config] cysignals = 'cysignals' From 7af95ed43dba3181d1b1fa0e226f84e3467e6476 Mon Sep 17 00:00:00 2001 From: cxzhong Date: Wed, 8 Oct 2025 12:59:32 +0800 Subject: [PATCH 19/21] change pyproject.toml and uv.lock and modify redame --- README.rst | 4 +- pyproject.toml | 2 +- uv.lock | 184 +++++++------------------------------------------ 3 files changed, 26 insertions(+), 164 deletions(-) diff --git a/README.rst b/README.rst index b98fe7a5..ef24b31e 100644 --- a/README.rst +++ b/README.rst @@ -22,8 +22,8 @@ signals and errors) in Cython code. Requirements ------------ -- Python >= 3.9 -- Cython >= 0.28 +- Python >= 3.11 +- Cython >= 3.1 - Sphinx >= 1.6 (for building the documentation) Links diff --git a/pyproject.toml b/pyproject.toml index f22d1b9c..263143c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["meson-python", "cython>=0.28"] +requires = ["meson-python", "cython>=3.1"] build-backend = "mesonpy" [project] diff --git a/uv.lock b/uv.lock index 843664c7..34311f95 100644 --- a/uv.lock +++ b/uv.lock @@ -1,10 +1,9 @@ version = 1 revision = 3 -requires-python = ">=3.9, <3.15" +requires-python = ">=3.11, <3.15" resolution-markers = [ "python_full_version >= '3.12'", - "python_full_version == '3.11.*'", - "python_full_version < '3.11'", + "python_full_version < '3.12'", ] [[package]] @@ -31,10 +30,8 @@ version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, { name = "packaging" }, { name = "pyproject-hooks" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/25/1c/23e33405a7c9eac261dff640926b8b5adaed6a6eb3e1767d441ed611d0c0/build-1.3.0.tar.gz", hash = "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", size = 48544, upload-time = "2025-08-01T21:27:09.268Z" } wheels = [ @@ -43,61 +40,34 @@ wheels = [ [[package]] name = "certifi" -version = "2025.8.3" +version = "2025.10.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, ] [[package]] name = "cibuildwheel" -version = "2.23.3" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] dependencies = [ - { name = "bashlex", marker = "python_full_version < '3.11'" }, - { name = "bracex", marker = "python_full_version < '3.11'" }, - { name = "certifi", marker = "python_full_version < '3.11'" }, - { name = "dependency-groups", marker = "python_full_version < '3.11'" }, - { name = "filelock", marker = "python_full_version < '3.11'" }, - { name = "packaging", marker = "python_full_version < '3.11'" }, - { name = "platformdirs", marker = "python_full_version < '3.11'" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/f5/2c06c8229e291e121cb26ed2efa1ba5d89053a93631d8f1d795f2dacabb8/cibuildwheel-2.23.3.tar.gz", hash = "sha256:d85dd15b7eb81711900d8129e67efb32b12f99cc00fc271ab060fa6270c38397", size = 295383, upload-time = "2025-04-26T10:41:28.258Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/17/8e/127e75e087c0a55903deb447a938e97935c6a56bfd20e6070bcc26c06d1b/cibuildwheel-2.23.3-py3-none-any.whl", hash = "sha256:0fa40073ae23a56d5f995d8405e82c1206049999bb89b92aa0835ee62ab8a891", size = 91792, upload-time = "2025-04-26T10:41:26.148Z" }, -] - -[[package]] -name = "cibuildwheel" -version = "3.1.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.12'", - "python_full_version == '3.11.*'", + { name = "bashlex" }, + { name = "bracex" }, + { name = "build" }, + { name = "certifi" }, + { name = "dependency-groups" }, + { name = "filelock" }, + { name = "humanize" }, + { name = "packaging" }, + { name = "patchelf", marker = "(platform_machine == 'aarch64' and sys_platform == 'darwin') or (platform_machine == 'arm64' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'arm64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" }, + { name = "platformdirs" }, + { name = "pyelftools" }, + { name = "wheel" }, ] -dependencies = [ - { name = "bashlex", marker = "python_full_version >= '3.11'" }, - { name = "bracex", marker = "python_full_version >= '3.11'" }, - { name = "build", marker = "python_full_version >= '3.11'" }, - { name = "certifi", marker = "python_full_version >= '3.11'" }, - { name = "dependency-groups", marker = "python_full_version >= '3.11'" }, - { name = "filelock", marker = "python_full_version >= '3.11'" }, - { name = "humanize", marker = "python_full_version >= '3.11'" }, - { name = "packaging", marker = "python_full_version >= '3.11'" }, - { name = "patchelf", marker = "(python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'darwin') or (python_full_version >= '3.11' and platform_machine == 'arm64' and sys_platform == 'darwin') or (python_full_version >= '3.11' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.11' and platform_machine == 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.11' and platform_machine == 'arm64' and sys_platform == 'linux') or (python_full_version >= '3.11' and platform_machine == 'x86_64' and sys_platform == 'linux')" }, - { name = "platformdirs", marker = "python_full_version >= '3.11'" }, - { name = "pyelftools", marker = "python_full_version >= '3.11'" }, - { name = "wheel", marker = "python_full_version >= '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8e/25/69676d781cdbfc3408fe276dac900deaaa527053553b2a434aac534ed53d/cibuildwheel-3.1.4.tar.gz", hash = "sha256:549c499e21641043ad9596e6472765152fa471d1922538fa87a1a11bdcf93422", size = 354445, upload-time = "2025-08-19T18:22:52.515Z" } +sdist = { url = "https://files.pythonhosted.org/packages/42/33/c3e5884a4f996d9138ace03464d0396752ec8c81adada549421bc68d185f/cibuildwheel-3.2.0.tar.gz", hash = "sha256:03ceab277255dc6c6451b25aad78844f4c07b03e410ee7411e9045b20ef6466f", size = 354877, upload-time = "2025-09-22T20:46:24.522Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/c8/9d25944bdc5b3998082260be2baee60f33944881c9410d8c137251389e47/cibuildwheel-3.1.4-py3-none-any.whl", hash = "sha256:c8dcd74a72e5e827d385b8851fc1996d0ca879e8563b837aec29493196d0ed50", size = 126312, upload-time = "2025-08-19T18:22:49.638Z" }, + { url = "https://files.pythonhosted.org/packages/52/b0/cbf2260b9cc2fea23abd2fac607b4d3692dfd250062fba3523b8008847bd/cibuildwheel-3.2.0-py3-none-any.whl", hash = "sha256:5349f85b89ed63d53bf79315996adb9d4e507c4b69dacb480c1eef7fddde21e1", size = 126344, upload-time = "2025-09-22T20:46:22.157Z" }, ] [[package]] @@ -117,8 +87,7 @@ source = { editable = "." } [package.dev-dependencies] dev = [ { name = "build" }, - { name = "cibuildwheel", version = "2.23.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "cibuildwheel", version = "3.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "cibuildwheel" }, { name = "cython" }, { name = "meson" }, { name = "meson-python" }, @@ -147,16 +116,6 @@ version = "3.1.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a7/f6/d762df1f436a0618455d37f4e4c4872a7cd0dcfc8dec3022ee99e4389c69/cython-3.1.4.tar.gz", hash = "sha256:9aefefe831331e2d66ab31799814eae4d0f8a2d246cbaaaa14d1be29ef777683", size = 3190778, upload-time = "2025-09-16T07:20:33.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/03/90fa9c3a336bd28f93e246d2b7f8767341134d0b6ab44dbabd1259abdd1a/cython-3.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:523110241408ef6511d897e9cebbdffb99120ac82ef3aea89baacce290958f93", size = 2993775, upload-time = "2025-09-16T07:21:42.648Z" }, - { url = "https://files.pythonhosted.org/packages/5e/3b/6a694b3cda00bece130b86601148eb5091e7a9531afa598be2bbfb32c57c/cython-3.1.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd34f960c3809fa2a7c3487ce9b3cb2c5bbc5ae2107f073a1a51086885958881", size = 2918270, upload-time = "2025-09-16T07:21:44.677Z" }, - { url = "https://files.pythonhosted.org/packages/85/41/a6cf199f2011f988ca532d47e8e452a20a564ffc29c8f7a11a903853f969/cython-3.1.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90842e7fb8cddfd173478670297f6a6b3df090e029a31ea6ce93669030e67b81", size = 3511091, upload-time = "2025-09-16T07:21:46.79Z" }, - { url = "https://files.pythonhosted.org/packages/ba/43/6a3b0cabf2bb78a7f1b7714d0bce81f065c45dcefceb8a505a26c12a5527/cython-3.1.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c88234303e2c15a5a88ae21c99698c7195433280b049aa2ad0ace906e6294dab", size = 3265539, upload-time = "2025-09-16T07:21:48.979Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f6/b8c4b557f537fd26c7188444ab18b4b60049b3e6f9665e468af6ddc4a408/cython-3.1.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f06b037f7c244dda9fc38091e87a68498c85c7c27ddc19aa84b08cf42a8a84a", size = 3427305, upload-time = "2025-09-16T07:21:50.589Z" }, - { url = "https://files.pythonhosted.org/packages/b0/da/e38cbedf1eeb1b13c7d53e57b7b1516b7e51b3d125225bc38399286cf3a1/cython-3.1.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1aba748e9dcb9c0179d286cdb20215246c46b69cf227715e46287dcea8de7372", size = 3280622, upload-time = "2025-09-16T07:21:52.723Z" }, - { url = "https://files.pythonhosted.org/packages/1f/17/0b9f0e93b3470b4ab20f178b337ce443ca9699b0b9fa0a5da7b403736038/cython-3.1.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:297b6042d764f68dc6213312578ef4b69310d04c963f94a489914efbf44ab133", size = 3525244, upload-time = "2025-09-16T07:21:54.763Z" }, - { url = "https://files.pythonhosted.org/packages/8a/56/4368bbbb75f0f73ebce6f1ce4bb93717b35992b577b5e3bd654becaee243/cython-3.1.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2ecf927e73bde50043d3a9fe3159f834b0e642b97e60a21018439fd25d344888", size = 3441779, upload-time = "2025-09-16T07:21:56.743Z" }, - { url = "https://files.pythonhosted.org/packages/b7/f3/722ffaa4e2bb25b37c6581cf77afc9e0e40c4b1973d5c670633d89a23c37/cython-3.1.4-cp310-cp310-win32.whl", hash = "sha256:3d940d603f85732627795518f9dba8fa63080d8221bb5f477c7a156ee08714ad", size = 2484587, upload-time = "2025-09-16T07:21:58.718Z" }, - { url = "https://files.pythonhosted.org/packages/8d/5d/c9f54171b461ebec92d16ac5c1173f2ef345ae80c41fcd76b286c06b4189/cython-3.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:1e0671be9859bb313d8df5ca9b9c137e384f1e025831c58cee9a839ace432d3c", size = 2709502, upload-time = "2025-09-16T07:22:00.349Z" }, { url = "https://files.pythonhosted.org/packages/b5/ab/0a568bac7c4c052db4ae27edf01e16f3093cdfef04a2dfd313ef1b3c478a/cython-3.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d1d7013dba5fb0506794d4ef8947ff5ed021370614950a8d8d04e57c8c84499e", size = 3026389, upload-time = "2025-09-16T07:22:02.212Z" }, { url = "https://files.pythonhosted.org/packages/cb/b7/51f5566e1309215a7fef744975b2fabb56d3fdc5fa1922fd7e306c14f523/cython-3.1.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eed989f5c139d6550ef2665b783d86fab99372590c97f10a3c26c4523c5fce9e", size = 2955954, upload-time = "2025-09-16T07:22:03.782Z" }, { url = "https://files.pythonhosted.org/packages/28/fd/ad8314520000fe96292fb8208c640fa862baa3053d2f3453a2acb50cafb8/cython-3.1.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3df3beb8b024dfd73cfddb7f2f7456751cebf6e31655eed3189c209b634bc2f2", size = 3412005, upload-time = "2025-09-16T07:22:05.483Z" }, @@ -197,16 +156,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/e8/83cf9a9cf64cbfe4eaf3987a633be08243f838b7d12e5739831297b77311/cython-3.1.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:18882e2f5c0e0c25f9c44f16f2fb9c48f33988885c5f9eae2856f10c6f089ffa", size = 3324255, upload-time = "2025-09-16T07:23:12.267Z" }, { url = "https://files.pythonhosted.org/packages/0c/f8/f2033044687cf6296275fa71cdf63a247d3646a3e276aa002e65bf505f46/cython-3.1.4-cp314-cp314-win32.whl", hash = "sha256:8ef8deadc888eaf95e5328fc176fb6c37bccee1213f07517c6ea55b5f817c457", size = 2503665, upload-time = "2025-09-16T07:23:14.372Z" }, { url = "https://files.pythonhosted.org/packages/04/57/7af75a803d55610d570d7b7a0fdc2bfd82fae030c728089cc628562d67f9/cython-3.1.4-cp314-cp314-win_amd64.whl", hash = "sha256:acb99ddec62ba1ea5de0e0087760fa834ec42c94f0488065a4f1995584e8e94e", size = 2734608, upload-time = "2025-09-16T07:23:16.025Z" }, - { url = "https://files.pythonhosted.org/packages/43/5f/17838c577a0e052073991a3ace1c380d02927bd7a15cdee7ecaa363dc093/cython-3.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95d2303ee54cf469f7c61aa94ef46c195d42e75a76881b9e33770bcf6c0a5c6", size = 3000303, upload-time = "2025-09-16T07:23:37.644Z" }, - { url = "https://files.pythonhosted.org/packages/2a/7c/9f018d9011639a3e8ba5389541665a10bafab18e5118e37e0a0043fd6bb0/cython-3.1.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fc723ffca257beebe42c8e2dcb2b9771957b752d6f42684f17ca1d2a4346b21", size = 2925511, upload-time = "2025-09-16T07:23:39.325Z" }, - { url = "https://files.pythonhosted.org/packages/28/14/8bfc9aeaeb480789a212af82e1793409e897ce4b868ff051b60d641c224c/cython-3.1.4-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1fb5060dd0c89f5c64002a0c44c2fcb5d066d119e2ae4d1bfa2c6482333dd42a", size = 3516323, upload-time = "2025-09-16T07:23:41.257Z" }, - { url = "https://files.pythonhosted.org/packages/f7/9e/5650fab11678d9c9f84650c7471bc1f0a3522f10db645c01c715dd12d004/cython-3.1.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:077cc5881da9b48cc7b7f7952faedcea0ad9c3fcb9ba9f5fb89fdb5ded07dd70", size = 3272048, upload-time = "2025-09-16T07:23:42.976Z" }, - { url = "https://files.pythonhosted.org/packages/66/f8/997e1253c36e37a1281947c667be9dfbc7955b9c9fab0500c94abb1522e3/cython-3.1.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:33da3c03797f7b7fde371a05f9e0d63eca679875c1c75e01066893eff2ec2f12", size = 3434654, upload-time = "2025-09-16T07:23:45.222Z" }, - { url = "https://files.pythonhosted.org/packages/6e/55/7994aa724dfab53207e643f09fe0b202356a4acebf833ffbf5eed4b72dd4/cython-3.1.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daf1bde7af8202f52cfd51625a5c48de55de27786392e38a429bfe8b9a16161f", size = 3286336, upload-time = "2025-09-16T07:23:46.989Z" }, - { url = "https://files.pythonhosted.org/packages/78/52/87960bfdbdbf0a5b9cf011ef3e7d23996d2c9988e56b31a1de7695847fe2/cython-3.1.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3371af4af1aae0d46c10f8e3c1edff0361f03a5687081c8b36f61678545caff3", size = 3531157, upload-time = "2025-09-16T07:23:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/92/a5/a96e9d90a8ff7e8e06541c470627167d03bd24d5adc989d5c61fc94062cb/cython-3.1.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4e1115c6b4b848ade9d76a4e3f72c7bb2b7e7a935fcbda56f6032f50e079999", size = 3448687, upload-time = "2025-09-16T07:23:50.506Z" }, - { url = "https://files.pythonhosted.org/packages/13/bf/0ee15f57e1a103888d9e9a40cc93a5045f4180f8b07bf6d92b44fe72c9a6/cython-3.1.4-cp39-cp39-win32.whl", hash = "sha256:1b59709bcec2f38e447e53c51a20caee8c30911d4025dd3d102835f3f10b7bef", size = 2488203, upload-time = "2025-09-16T07:23:52.123Z" }, - { url = "https://files.pythonhosted.org/packages/57/1b/538cc6dd8a1282be79544053395a2d1e187cb8fa4974851c95fbecc88e4b/cython-3.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:006e2a175ba9898a7f1551e6c7c4cafd8eb9b42e53d1dfe4308caba9e8453cc3", size = 2713260, upload-time = "2025-09-16T07:23:53.78Z" }, { url = "https://files.pythonhosted.org/packages/7c/24/f7351052cf9db771fe4f32fca47fd66e6d9b53d8613b17faf7d130a9d553/cython-3.1.4-py3-none-any.whl", hash = "sha256:d194d95e4fa029a3f6c7d46bdd16d973808c7ea4797586911fdb67cb98b1a2c6", size = 1227541, upload-time = "2025-09-16T07:20:29.595Z" }, ] @@ -216,25 +165,12 @@ version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, ] -[[package]] -name = "exceptiongroup" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, -] - [[package]] name = "filelock" version = "3.19.1" @@ -253,18 +189,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/c7/316e7ca04d26695ef0635dc81683d628350810eb8e9b2299fc08ba49f366/humanize-4.13.0-py3-none-any.whl", hash = "sha256:b810820b31891813b1673e8fec7f1ed3312061eab2f26e3fa192c393d11ed25f", size = 128869, upload-time = "2025-08-25T09:39:18.54Z" }, ] -[[package]] -name = "importlib-metadata" -version = "8.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, -] - [[package]] name = "iniconfig" version = "2.1.0" @@ -276,11 +200,10 @@ wheels = [ [[package]] name = "meson" -version = "1.9.0" +version = "1.9.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/8a/8315a2711dd269533019d7fdad1cf79416aadff454c539c2da88bc6e7200/meson-1.9.0.tar.gz", hash = "sha256:cd27277649b5ed50d19875031de516e270b22e890d9db65ed9af57d18ebc498d", size = 2366082, upload-time = "2025-08-24T17:01:46.984Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/ed/a449e8fb5764a7f6df6e887a2d350001deca17efd6ecd5251d2fb6202009/meson-1.9.0-py3-none-any.whl", hash = "sha256:45e51ddc41e37d961582d06e78c48e0f9039011587f3495c4d6b0781dad92357", size = 1029634, upload-time = "2025-08-24T17:01:44.14Z" }, + { url = "https://files.pythonhosted.org/packages/9c/07/b48592d325cb86682829f05216e4efb2dc881762b8f1bafb48b57442307a/meson-1.9.1-py3-none-any.whl", hash = "sha256:f824ab770c041a202f532f69e114c971918ed2daff7ea56583d80642564598d0", size = 1030356, upload-time = "2025-09-22T18:39:37.458Z" }, ] [[package]] @@ -291,7 +214,6 @@ dependencies = [ { name = "meson" }, { name = "packaging" }, { name = "pyproject-metadata" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/26/bd/fdb26366443620f1a8a4d4ec7bfa37d1fbbe7bf737b257c205bbcf95ba95/meson_python-0.18.0.tar.gz", hash = "sha256:c56a99ec9df669a40662fe46960321af6e4b14106c14db228709c1628e23848d", size = 95630, upload-time = "2025-05-05T10:13:56.889Z" } wheels = [ @@ -354,7 +276,6 @@ version = "2.4.3.post2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/4f/27b39de8c295efed8fbc32517ee07e4b26e9eb95d0fbf8b5d698e76d7412/pkgconf-2.4.3.post2.tar.gz", hash = "sha256:73d966e18f75e89da54c83a65effc8c2e9b7316553a060c8293ee527a0834c10", size = 144454, upload-time = "2025-06-08T10:19:41.581Z" } wheels = [ @@ -440,66 +361,16 @@ version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] -[[package]] -name = "tomli" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - [[package]] name = "wheel" version = "0.45.1" @@ -508,12 +379,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef wheels = [ { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494, upload-time = "2024-11-23T00:18:21.207Z" }, ] - -[[package]] -name = "zipp" -version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, -] From b5d71e99d83223a999fe0e144a3e39be11b43f8d Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Wed, 8 Oct 2025 16:01:06 +0800 Subject: [PATCH 20/21] Remove unused --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 263143c9..075b1761 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: 3.14t", "Programming Language :: Python :: Implementation :: CPython", "Topic :: System", "Topic :: Software Development :: Debuggers", From 105ff806101387bec4e2b5e855c4ed758c2b2537 Mon Sep 17 00:00:00 2001 From: Chenxin Zhong Date: Wed, 8 Oct 2025 16:03:05 +0800 Subject: [PATCH 21/21] Update .github/workflows/ci.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb0efea7..00ed85c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: os: ['macos-14', 'macos-latest', 'ubuntu-latest', 'windows-latest'] - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + python-version: ['3.11', '3.12', '3.13', '3.14'] steps: - name: Set up the repository uses: actions/checkout@v4