From 97db0777ac13f3ce87506fd19a603705ba9962bc Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Sun, 1 Dec 2024 21:24:46 +0000 Subject: [PATCH] Use PyO3 `abi3-py38` feature for ABI stable wheels Produces ABI stable wheels for Python >=3.8. This simplifies the build/distribution by generating wheels that are forward compatible. --- .github/workflows/ci.yml | 21 +++++++++++---------- py-oxbow/Cargo.toml | 2 +- py-oxbow/pyproject.toml | 2 +- py-oxbow/src/lib.rs | 24 +++++++++++++----------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b03efbe..eb83442 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,29 +1,30 @@ -permissions: - contents: read +name: Test on: push: branches: [main] pull_request: -name: Test +permissions: + contents: read + +env: + # Disable incremental compilation for faster from-scratch builds + CARGO_INCREMENTAL: 0 jobs: Test: runs-on: ubuntu-latest steps: - - name: Check out repository - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - run: rustup update - name: Check formatting - run: cargo fmt --all --manifest-path ./oxbow/Cargo.toml -- --check + run: cargo fmt --all --check - name: Download fixtures run: cd fixtures && wget -i list.txt - name: Run cargo test - uses: actions-rs/cargo@v1 - with: - command: test - args: --manifest-path ./oxbow/Cargo.toml + run: cargo test diff --git a/py-oxbow/Cargo.toml b/py-oxbow/Cargo.toml index d3afecb..78aedac 100644 --- a/py-oxbow/Cargo.toml +++ b/py-oxbow/Cargo.toml @@ -11,4 +11,4 @@ crate-type = ["cdylib"] [dependencies] oxbow = { workspace = true } -pyo3 = { version = "0.23.2", features = ["extension-module"] } +pyo3 = { version = "0.23.2", features = ["abi3-py38"] } diff --git a/py-oxbow/pyproject.toml b/py-oxbow/pyproject.toml index 84dd61f..136f13e 100644 --- a/py-oxbow/pyproject.toml +++ b/py-oxbow/pyproject.toml @@ -10,7 +10,7 @@ authors = [ { name = "Oxbow Developers", email = "nabdennur@gmail.com" } ] license = { text = "MIT OR Apache-2.0" } -requires-python = ">=3.7" +requires-python = ">=3.8" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", diff --git a/py-oxbow/src/lib.rs b/py-oxbow/src/lib.rs index 496e242..f21eee1 100644 --- a/py-oxbow/src/lib.rs +++ b/py-oxbow/src/lib.rs @@ -48,7 +48,7 @@ fn read_fasta(path: &str, region: Option<&str>) -> Vec { fn read_fastq(py: Python, path_or_file_like: PyObject) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it like a path - let mut reader = FastqReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = FastqReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc().unwrap() } else { // Otherwise, treat it as file-like @@ -69,7 +69,7 @@ fn read_bam( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = BamReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = BamReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc(region).unwrap() } else { // Otherwise, treat it as file-like @@ -94,7 +94,7 @@ fn read_bam_vpos( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = BamReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = BamReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc_from_vpos(pos_lo, pos_hi).unwrap() } else { // Otherwise, treat it as file-like @@ -118,7 +118,7 @@ fn read_vcf( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = VcfReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = VcfReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc(region).unwrap() } else { // Otherwise, treat it as file-like @@ -143,7 +143,7 @@ fn read_vcf_vpos( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = VcfReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = VcfReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc_from_vpos(pos_lo, pos_hi).unwrap() } else { // Otherwise, treat it as file-like @@ -167,7 +167,7 @@ fn read_bcf( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = BcfReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = BcfReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc(region).unwrap() } else { // Otherwise, treat it as file-like @@ -192,7 +192,7 @@ fn read_bcf_vpos( ) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = VcfReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = VcfReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc_from_vpos(pos_lo, pos_hi).unwrap() } else { // Otherwise, treat it as file-like @@ -220,7 +220,8 @@ fn read_bigwig( .map(|h| h.iter().map(String::as_str).collect::>()); if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = BigWigReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = + BigWigReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); match zoom_level { Some(zoom_level) => reader .zoom_records_to_ipc(region, zoom_level, zoom_summary_columns_ref) @@ -254,7 +255,8 @@ fn read_bigbed( .map(|h| h.iter().map(String::as_str).collect::>()); if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = BigBedReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = + BigBedReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc(region, fields_ref).unwrap() } else { // Otherwise, treat it as file-like @@ -269,7 +271,7 @@ fn read_bigbed( fn read_gff(py: Python, path_or_file_like: PyObject) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = GffReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = GffReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc().unwrap() } else { // Otherwise, treat it as file-like @@ -284,7 +286,7 @@ fn read_gff(py: Python, path_or_file_like: PyObject) -> Vec { fn read_gtf(py: Python, path_or_file_like: PyObject) -> Vec { if let Ok(string_ref) = path_or_file_like.downcast_bound::(py) { // If it's a string, treat it as a path - let mut reader = GtfReader::new_from_path(string_ref.to_str().unwrap()).unwrap(); + let mut reader = GtfReader::new_from_path(string_ref.to_string_lossy().as_ref()).unwrap(); reader.records_to_ipc().unwrap() } else { // Otherwise, treat it as file-like