From cd68c99c8b53672ea950ec72a42c677f8dfe5608 Mon Sep 17 00:00:00 2001 From: my1e5 <10064103+my1e5@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:53:21 +0000 Subject: [PATCH] Add support for Python 3.13 (#78) * add support for Python 3.13 * bumping pyo3 and rust-numpy to 0.21 * temporarily remove 3.13 from ci to test that migration of pyo3 and rust-numpy is working. * bumping to 0.22 and adding 3.13 back to ci --- .github/workflows/ci-tsdownsample.yml | 2 +- Cargo.toml | 4 +- Makefile | 6 +-- pyproject.toml | 1 + src/lib.rs | 54 +++++++++++++-------------- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci-tsdownsample.yml b/.github/workflows/ci-tsdownsample.yml index 859bbfa..263e959 100644 --- a/.github/workflows/ci-tsdownsample.yml +++ b/.github/workflows/ci-tsdownsample.yml @@ -46,7 +46,7 @@ jobs: matrix: os: ['windows-latest', 'macOS-latest', 'ubuntu-latest'] rust: ['nightly'] # ['stable', 'beta'] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', "3.13"] exclude: # Python < 3.8 is not supported on Apple Silicon ARM64 - os: macOS-latest python-version: '3.7' diff --git a/Cargo.toml b/Cargo.toml index 184e8c8..b0b2335 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,8 @@ license = "MIT" [dependencies] downsample_rs = { path = "downsample_rs", features = ["half"]} -pyo3 = { version = "0.20", features = ["extension-module"] } -numpy = { version = "0.20", features = ["half"] } +pyo3 = { version = "0.22", features = ["extension-module"] } +numpy = { version = "0.22", features = ["half"] } half = { version = "2.3.1", default-features = false } paste = { version = "1.0.14", default-features = false } diff --git a/Makefile b/Makefile index f2b3e2f..1c83953 100644 --- a/Makefile +++ b/Makefile @@ -11,13 +11,13 @@ install-dev-requirements: .PHONY: format format: - ruff --fix tsdownsample tests + ruff format tsdownsample tests $(black) cargo fmt .PHONY: lint-python lint-python: - ruff tsdownsample tests + ruff check tsdownsample tests $(black) --check --diff .PHONY: lint-rust @@ -25,7 +25,7 @@ lint-rust: cargo fmt --version cargo fmt --all -- --check cargo clippy --version - cargo clippy -- -D warnings -A incomplete_features -W clippy::dbg_macro -W clippy::print_stdout + cargo clippy -- -D warnings -A incomplete_features -W clippy::dbg_macro -W clippy::print_stdout -A clippy::empty_line_after_doc_comments .PHONY: lint lint: lint-python lint-rust diff --git a/pyproject.toml b/pyproject.toml index 074b23c..1695f9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ classifiers = [ 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Operating System :: POSIX', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows' diff --git a/src/lib.rs b/src/lib.rs index 9348e01..9cd30c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,10 +22,10 @@ macro_rules! _create_pyfunc_without_x { py: Python<'py>, y: PyReadonlyArray1<$type>, n_out: usize, - ) -> &'py PyArray1 { + ) -> Bound<'py, PyArray1> { let y = y.as_slice().unwrap(); let sampled_indices = $resample_mod::$resample_fn(y, n_out); - sampled_indices.into_pyarray(py) + sampled_indices.into_pyarray_bound(py) } // Add the function to the module $mod.add_wrapped(wrap_pyfunction!($name))?; @@ -41,10 +41,10 @@ macro_rules! _create_pyfunc_without_x_with_ratio { y: PyReadonlyArray1<$type>, n_out: usize, ratio: usize, - ) -> &'py PyArray1 { + ) -> Bound<'py, PyArray1> { let y = y.as_slice().unwrap(); let sampled_indices = $resample_mod::$resample_fn(y, n_out, ratio); - sampled_indices.into_pyarray(py) + sampled_indices.into_pyarray_bound(py) } // Add the function to the module $mod.add_wrapped(wrap_pyfunction!($name))?; @@ -80,11 +80,11 @@ macro_rules! _create_pyfunc_with_x { x: PyReadonlyArray1<$type_x>, y: PyReadonlyArray1<$type_y>, n_out: usize, - ) -> &'py PyArray1 { + ) -> Bound<'py, PyArray1> { let x = x.as_slice().unwrap(); let y = y.as_slice().unwrap(); let sampled_indices = $resample_mod::$resample_fn(x, y, n_out); - sampled_indices.into_pyarray(py) + sampled_indices.into_pyarray_bound(py) } // Add the function to the module $mod.add_wrapped(wrap_pyfunction!($name))?; @@ -101,11 +101,11 @@ macro_rules! _create_pyfunc_with_x_with_ratio { y: PyReadonlyArray1<$type_y>, n_out: usize, ratio: usize, - ) -> &'py PyArray1 { + ) -> Bound<'py, PyArray1> { let x = x.as_slice().unwrap(); let y = y.as_slice().unwrap(); let sampled_indices = $resample_mod::$resample_fn(x, y, n_out, ratio); - sampled_indices.into_pyarray(py) + sampled_indices.into_pyarray_bound(py) } // Add the function to the module $mod.add_wrapped(wrap_pyfunction!($name))?; @@ -255,10 +255,10 @@ use downsample_rs::minmax as minmax_mod; // Create a sub module for the minmax algorithm #[pymodule] -fn minmax(_py: Python<'_>, m: &PyModule) -> PyResult<()> { +fn minmax(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { // ----------------- SEQUENTIAL - let sequential_mod = PyModule::new(_py, "sequential")?; + let sequential_mod = PyModule::new_bound(_py, "sequential")?; // ----- WITHOUT X { @@ -274,7 +274,7 @@ fn minmax(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // ----------------- PARALLEL - let parallel_mod = PyModule::new(_py, "parallel")?; + let parallel_mod = PyModule::new_bound(_py, "parallel")?; // ----- WITHOUT X { @@ -289,8 +289,8 @@ fn minmax(_py: Python<'_>, m: &PyModule) -> PyResult<()> { } // Add the sub modules to the module - m.add_submodule(sequential_mod)?; - m.add_submodule(parallel_mod)?; + m.add_submodule(&sequential_mod)?; + m.add_submodule(¶llel_mod)?; Ok(()) } @@ -301,10 +301,10 @@ use downsample_rs::m4 as m4_mod; // Create a sub module for the M4 algorithm #[pymodule] -fn m4(_py: Python, m: &PyModule) -> PyResult<()> { +fn m4(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { // ----------------- SEQUENTIAL - let sequential_mod = PyModule::new(_py, "sequential")?; + let sequential_mod = PyModule::new_bound(_py, "sequential")?; // ----- WITHOUT X { @@ -320,7 +320,7 @@ fn m4(_py: Python, m: &PyModule) -> PyResult<()> { // ----------------- PARALLEL - let parallel_mod = PyModule::new(_py, "parallel")?; + let parallel_mod = PyModule::new_bound(_py, "parallel")?; // ----- WITHOUT X { @@ -335,8 +335,8 @@ fn m4(_py: Python, m: &PyModule) -> PyResult<()> { } // Add the sub modules to the module - m.add_submodule(sequential_mod)?; - m.add_submodule(parallel_mod)?; + m.add_submodule(&sequential_mod)?; + m.add_submodule(¶llel_mod)?; Ok(()) } @@ -347,10 +347,10 @@ use downsample_rs::lttb as lttb_mod; // Create a sub module for the LTTB algorithm #[pymodule] -fn lttb(_py: Python, m: &PyModule) -> PyResult<()> { +fn lttb(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { // ----------------- SEQUENTIAL - let sequential_mod = PyModule::new(_py, "sequential")?; + let sequential_mod = PyModule::new_bound(_py, "sequential")?; // Create the Python functions for the module // ----- WITHOUT X @@ -364,7 +364,7 @@ fn lttb(_py: Python, m: &PyModule) -> PyResult<()> { } // Add the sub modules to the module - m.add_submodule(sequential_mod)?; + m.add_submodule(&sequential_mod)?; Ok(()) } @@ -375,10 +375,10 @@ use downsample_rs::minmaxlttb as minmaxlttb_mod; // Create a sub module for the MINMAXLTTB algorithm #[pymodule] -fn minmaxlttb(_py: Python, m: &PyModule) -> PyResult<()> { +fn minmaxlttb(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { // ----------------- SEQUENTIAL - let sequential_mod = PyModule::new(_py, "sequential")?; + let sequential_mod = PyModule::new_bound(_py, "sequential")?; // ----- WITHOUT X { @@ -394,7 +394,7 @@ fn minmaxlttb(_py: Python, m: &PyModule) -> PyResult<()> { // ----------------- PARALLEL - let parallel_mod = PyModule::new(_py, "parallel")?; + let parallel_mod = PyModule::new_bound(_py, "parallel")?; // ----- WITHOUT X { @@ -417,8 +417,8 @@ fn minmaxlttb(_py: Python, m: &PyModule) -> PyResult<()> { } // Add the submodules to the module - m.add_submodule(sequential_mod)?; - m.add_submodule(parallel_mod)?; + m.add_submodule(&sequential_mod)?; + m.add_submodule(¶llel_mod)?; Ok(()) } @@ -427,7 +427,7 @@ fn minmaxlttb(_py: Python, m: &PyModule) -> PyResult<()> { #[pymodule] // The super module #[pyo3(name = "_tsdownsample_rs")] // How the module is imported in Python: https://github.com/PyO3/maturin/issues/256#issuecomment-1038576218 -fn tsdownsample(_py: Python<'_>, m: &PyModule) -> PyResult<()> { +fn tsdownsample(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(minmax))?; m.add_wrapped(wrap_pymodule!(m4))?; m.add_wrapped(wrap_pymodule!(lttb))?;