diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b84918d..18ec8a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: + ["3.10", "3.11", "3.12", "3.13", "3.13t", "3.14", "3.14t"] steps: - uses: actions/checkout@v6 diff --git a/.python-version b/.python-version index 6324d40..a469d8f 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.14 +3.14t diff --git a/docs/requirements.txt b/docs/requirements.txt index 7c68cbe..323bff4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -31,6 +31,8 @@ docutils==0.22.4 ; python_full_version >= '3.11' # sphinx exceptiongroup==1.3.1 ; python_full_version < '3.11' # via pytest +free-threading==1.1.0 + # via pyriodicity idna==3.11 # via requests imagesize==1.4.1 diff --git a/pyproject.toml b/pyproject.toml index 63519b5..19d6ee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ classifiers = [ dependencies = [ "scipy~=1.15", "pywavelets~=1.8", + "free-threading~=1.1.0", ] [project.urls] diff --git a/src/pyriodicity/static/robustperiod.py b/src/pyriodicity/static/robustperiod.py index 8f5cadb..4afaa60 100644 --- a/src/pyriodicity/static/robustperiod.py +++ b/src/pyriodicity/static/robustperiod.py @@ -1,5 +1,4 @@ import datetime -from concurrent.futures import ProcessPoolExecutor from enum import Enum, unique from functools import partial from multiprocessing import cpu_count @@ -7,6 +6,7 @@ import numpy as np import pywt +from freethreading import WorkerPoolExecutor from numpy.typing import ArrayLike, NDArray from scipy.optimize import minimize from scipy.signal import find_peaks @@ -71,7 +71,7 @@ def compute( The Huber M-Periodogram of the input data. """ - with ProcessPoolExecutor(max_worker_count) as executor: + with WorkerPoolExecutor(max_worker_count) as executor: periodogram = list( executor.map( partial(cls._compute_element, x, delta=delta), range(len(x)) diff --git a/uv.lock b/uv.lock index 4e59b80..aa1bebc 100644 --- a/uv.lock +++ b/uv.lock @@ -326,6 +326,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] +[[package]] +name = "free-threading" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/ae/78bf0c2925e72d53c44b3f5837867250c56bc72f54f98dcf1edb373111f9/free_threading-1.1.0.tar.gz", hash = "sha256:2b54933573543ff5e30a2f02ddcd593efff0f429d34033f5882908c9d93c49d8", size = 11760, upload-time = "2025-12-29T23:33:36.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/ef/750d2d856a9086bb94d1f8d4adf099ec6684f2223c9e4308ef92b2e8353d/free_threading-1.1.0-py3-none-any.whl", hash = "sha256:30057e59e4db574ec02db17b3400850062fdc612383a9332ddb2b8a443cdab29", size = 12747, upload-time = "2025-12-29T23:33:37.01Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -821,6 +830,7 @@ name = "pyriodicity" version = "0.7.0rc0" source = { editable = "." } dependencies = [ + { name = "free-threading" }, { name = "pywavelets", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "pywavelets", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, @@ -841,6 +851,7 @@ docs = [ [package.metadata] requires-dist = [ + { name = "free-threading", specifier = "~=1.1.0" }, { name = "pywavelets", specifier = "~=1.8" }, { name = "scipy", specifier = "~=1.15" }, ]