From ab9579069e825d7e9f26d7e7a3ff1cadfbfc11e9 Mon Sep 17 00:00:00 2001 From: noam teyssier <22600644+noamteyssier@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:04:58 -0800 Subject: [PATCH 1/5] feat: made dependencies cleaner to reduce build times --- Cargo.toml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 15429dd..4fb2d88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ default = ["pyo3/extension-module"] [dependencies] anyhow = "1.0.64" bitvec = "1.0.1" -bon = "2.3.0" +bon = "3.0.2" chrono = "0.4.22" clap = { version = "4.0.18", features = ["derive"] } clap_complete = "4.0.3" @@ -32,8 +32,13 @@ mysql = { version = "25.0.1", default-features = false, features = [ "minimal", "rustls-tls", ] } -polars = { version = "0.43.1", default-features = false, features = ["json"] } -pyo3 = { version = "0.22.2", features = ["extension-module", "anyhow"] } +# polars = { version = "0.43.1", default-features = false, features = ["json"] } +polars-core = { version = "0.44.2", default-features = false } +polars-io = { version = "0.44.2", default-features = false, features = [ + "json", + "csv", +] } +pyo3 = { version = "0.22.6", features = ["extension-module", "anyhow"] } regex = "1.6.0" reqwest = { version = "0.12.5", default-features = false, features = [ "json", @@ -45,7 +50,7 @@ reqwest = { version = "0.12.5", default-features = false, features = [ serde = { version = "1.0.144", features = ["derive"] } serde-xml-rs = "0.6.0" serde_json = "1.0.85" -tokio = { version = "1.21.0", features = ["full"] } +tokio = { version = "1.21.0", default-features = false } [lints.clippy] pedantic = { level = "warn", priority = -1 } From 21fa3636f25a69ba2ac44eaf795540dd99e93ed5 Mon Sep 17 00:00:00 2001 From: noam teyssier <22600644+noamteyssier@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:05:17 -0800 Subject: [PATCH 2/5] dep: use specific polars modules to clean up dependency usage --- src/string/functions.rs | 3 ++- src/utils/io.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/string/functions.rs b/src/string/functions.rs index 44d5c41..0de4c2a 100644 --- a/src/string/functions.rs +++ b/src/string/functions.rs @@ -3,7 +3,8 @@ use crate::cli::{ StringInteractionsArgs, StringMappingArgs, StringNetworkArgs, StringPpiEnrichmentArgs, }; use anyhow::Result; -use polars::prelude::*; +use polars_core::prelude::*; +use polars_io::prelude::*; use reqwest::blocking::Client; use serde_json::Value; use std::io::Cursor; diff --git a/src/utils/io.rs b/src/utils/io.rs index 836087a..00001d2 100644 --- a/src/utils/io.rs +++ b/src/utils/io.rs @@ -1,6 +1,7 @@ use anyhow::Result; use clap::ValueEnum; -use polars::prelude::*; +use polars_core::prelude::*; +use polars_io::prelude::*; use std::fs::File; use std::io::{BufWriter, Write}; From d6ac7052dd38f16a013d2c0fa9387b0ad9ffecbd Mon Sep 17 00:00:00 2001 From: noam teyssier <22600644+noamteyssier@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:17:39 -0800 Subject: [PATCH 3/5] chore: update pyo3 and fix compatibility issues --- Cargo.toml | 2 +- src/blast/types/result.rs | 22 +++++++++++----------- src/info/python.rs | 2 +- src/info/types.rs | 21 +++++++++++---------- src/ucsc/types/blat.rs | 12 ++++++------ src/utils/fasta.rs | 12 ++++++------ 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4fb2d88..6560b50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ polars-io = { version = "0.44.2", default-features = false, features = [ "json", "csv", ] } -pyo3 = { version = "0.22.6", features = ["extension-module", "anyhow"] } +pyo3 = { version = "0.23.1", features = ["extension-module", "anyhow"] } regex = "1.6.0" reqwest = { version = "0.12.5", default-features = false, features = [ "json", diff --git a/src/blast/types/result.rs b/src/blast/types/result.rs index eb914ee..32076e4 100644 --- a/src/blast/types/result.rs +++ b/src/blast/types/result.rs @@ -1,6 +1,6 @@ use pyo3::{ types::{IntoPyDict, PyDict, PyDictMethods}, - Bound, + Bound, PyResult, }; use serde::{Deserialize, Serialize}; use std::fmt; @@ -19,20 +19,20 @@ impl fmt::Display for BlastResult { ) } } -impl IntoPyDict for BlastResult { - fn into_py_dict_bound(self, py: pyo3::Python<'_>) -> Bound<'_, PyDict> { - let map = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for BlastResult { + fn into_py_dict(self, py: pyo3::Python<'py>) -> PyResult> { + let map = PyDict::new(py); map.set_item("query", self.query).unwrap(); map.set_item( "results", self.results .iter() .cloned() - .map(|x| x.into_py_dict_bound(py)) - .collect::>>(), + .map(|x| x.into_py_dict(py).unwrap()) + .collect::>>(), ) .unwrap(); - map + Ok(map) } } impl BlastResult { @@ -97,9 +97,9 @@ impl BlastHit { } } } -impl IntoPyDict for BlastHit { - fn into_py_dict_bound(self, py: pyo3::Python<'_>) -> Bound<'_, PyDict> { - let map = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for BlastHit { + fn into_py_dict(self, py: pyo3::Python<'py>) -> PyResult> { + let map = PyDict::new(py); map.set_item("num", self.num).unwrap(); map.set_item("id", self.num).unwrap(); map.set_item("definition", self.num).unwrap(); @@ -114,7 +114,7 @@ impl IntoPyDict for BlastHit { map.set_item("query_end", self.num).unwrap(); map.set_item("subject_start", self.num).unwrap(); map.set_item("subject_end", self.num).unwrap(); - map + Ok(map) } } diff --git a/src/info/python.rs b/src/info/python.rs index 7b84fd4..7d9959e 100644 --- a/src/info/python.rs +++ b/src/info/python.rs @@ -23,5 +23,5 @@ pub fn python_info( let species = species.unwrap_or("homo_sapiens".to_string()); let taxon_id = taxon_id.unwrap_or(9606); let results = info(&search_terms, &species, taxon_id)?; - Ok(results.into_py_dict_bound(py)) + Ok(results.into_py_dict(py)?) } diff --git a/src/info/types.rs b/src/info/types.rs index 74fbf09..e046491 100644 --- a/src/info/types.rs +++ b/src/info/types.rs @@ -2,7 +2,7 @@ use crate::{ ensembl::types::LookupResponse, ncbi::types::NcbiResults, uniprot::UniprotInfoContainer, }; use pyo3::types::{IntoPyDict, PyDict, PyDictMethods}; -use pyo3::Bound; +use pyo3::{Bound, PyResult}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; @@ -19,13 +19,14 @@ impl fmt::Display for InfoContainer { ) } } -impl IntoPyDict for InfoContainer { - fn into_py_dict_bound(self, py: pyo3::Python<'_>) -> Bound<'_, PyDict> { - let map = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for InfoContainer { + fn into_py_dict(self, py: pyo3::Python<'py>) -> PyResult> { + let map = PyDict::new(py); self.0.iter().for_each(|(k, v)| { - map.set_item(k, v.clone().into_py_dict_bound(py)).unwrap(); + map.set_item(k, v.clone().into_py_dict(py).unwrap()) + .unwrap(); }); - map + Ok(map) } } impl InfoContainer { @@ -69,9 +70,9 @@ impl fmt::Display for Info { ) } } -impl IntoPyDict for Info { - fn into_py_dict_bound(self, py: pyo3::Python<'_>) -> Bound<'_, PyDict> { - let map = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for Info { + fn into_py_dict(self, py: pyo3::Python<'py>) -> PyResult> { + let map = PyDict::new(py); map.set_item("ensembl_id", &self.ensembl_id).unwrap(); map.set_item("uniprot_id", &self.uniprot_id).unwrap(); map.set_item("ncbi_id", &self.ncbi_id).unwrap(); @@ -85,7 +86,7 @@ impl IntoPyDict for Info { .unwrap(); map.set_item("species", &self.species).unwrap(); map.set_item("assembly_name", &self.assembly_name).unwrap(); - map + Ok(map) } } impl Info { diff --git a/src/ucsc/types/blat.rs b/src/ucsc/types/blat.rs index 6091830..a750ab2 100644 --- a/src/ucsc/types/blat.rs +++ b/src/ucsc/types/blat.rs @@ -32,9 +32,9 @@ impl BlatResults { .0 .iter() .cloned() - .map(|x| x.into_py_dict_bound(py)) + .map(|x| x.into_py_dict(py).unwrap()) .collect(); - Ok(PyList::new_bound(py, vec_dict)) + Ok(PyList::new(py, vec_dict)?) } } @@ -72,9 +72,9 @@ impl fmt::Display for Blat { ) } } -impl IntoPyDict for Blat { - fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { - let dict = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for Blat { + fn into_py_dict(self, py: Python<'py>) -> PyResult> { + let dict = PyDict::new(py); dict.set_item("matches", self.matches).unwrap(); dict.set_item("mismatches", self.mismatches).unwrap(); dict.set_item("repmatches", self.repmatches).unwrap(); @@ -96,7 +96,7 @@ impl IntoPyDict for Blat { dict.set_item("block_sizes", &self.block_sizes).unwrap(); dict.set_item("q_starts", &self.q_starts).unwrap(); dict.set_item("q_starts", &self.t_starts).unwrap(); - dict + Ok(dict) } } impl Blat { diff --git a/src/utils/fasta.rs b/src/utils/fasta.rs index c0bf418..48f329a 100644 --- a/src/utils/fasta.rs +++ b/src/utils/fasta.rs @@ -13,9 +13,9 @@ impl FastaRecords { .0 .iter() .cloned() - .map(|x| x.into_py_dict_bound(py)) + .map(|x| x.into_py_dict(py).unwrap()) .collect(); - Ok(PyList::new_bound(py, vec_dict)) + Ok(PyList::new(py, vec_dict)?) } } @@ -30,12 +30,12 @@ impl Display for FastaRecord { write!(f, ">{}\n{}\n", self.header, self.sequence) } } -impl IntoPyDict for FastaRecord { - fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { - let map = PyDict::new_bound(py); +impl<'py> IntoPyDict<'py> for FastaRecord { + fn into_py_dict(self, py: Python<'py>) -> PyResult> { + let map = PyDict::new(py); map.set_item("header", self.header).unwrap(); map.set_item("sequence", self.sequence).unwrap(); - map + Ok(map) } } impl FastaRecord { From da895317bfdb2aa6b648be4504818738412378d4 Mon Sep 17 00:00:00 2001 From: noam teyssier <22600644+noamteyssier@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:20:02 -0800 Subject: [PATCH 4/5] chore: update pyo3 deprecetations --- src/archs4/python.rs | 2 +- src/archs4/types/correlation.rs | 4 +- src/archs4/types/tissue.rs | 4 +- src/blast/python.rs | 3 +- src/cli/cli.rs | 4 +- src/cli/enrichr.rs | 2 +- src/enrichr/types/enrich.rs | 15 +++++--- src/ensembl/functions/database.rs | 4 +- src/ensembl/python.rs | 2 +- src/ensembl/types/ftpfile.rs | 2 +- src/ensembl/types/search_results.rs | 4 +- src/lib.rs | 20 +++++----- src/main.rs | 8 +++- src/ucsc/python.rs | 2 +- src/ucsc/types/blat.rs | 58 +++++++++++++++-------------- src/uniprot/functions/query.rs | 4 +- src/utils/fasta.rs | 20 +++++----- 17 files changed, 84 insertions(+), 74 deletions(-) diff --git a/src/archs4/python.rs b/src/archs4/python.rs index aa96101..c2cf54e 100644 --- a/src/archs4/python.rs +++ b/src/archs4/python.rs @@ -31,7 +31,7 @@ pub fn python_archs4_tissue<'py>( /// Wraps `ARCHS4` specific functions into a python submodule pub fn python_archs4(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { - let submodule = PyModule::new_bound(py, "archs4")?; + let submodule = PyModule::new(py, "archs4")?; submodule.add_function(wrap_pyfunction!(python_archs4_tissue, module)?)?; submodule.add_function(wrap_pyfunction!(python_archs4_correlate, module)?)?; module.add_submodule(&submodule)?; diff --git a/src/archs4/types/correlation.rs b/src/archs4/types/correlation.rs index e212677..803e4ce 100644 --- a/src/archs4/types/correlation.rs +++ b/src/archs4/types/correlation.rs @@ -52,7 +52,7 @@ impl fmt::Display for Correlations { } impl Correlations { pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item( "correlations", self.correlations @@ -90,7 +90,7 @@ impl fmt::Display for Correlation { } impl Correlation { pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("gene_symbol", &self.gene_symbol)?; dict.set_item("pearson_correlation", self.pearson_correlation)?; Ok(dict) diff --git a/src/archs4/types/tissue.rs b/src/archs4/types/tissue.rs index 165fa5c..5ce6f11 100644 --- a/src/archs4/types/tissue.rs +++ b/src/archs4/types/tissue.rs @@ -53,7 +53,7 @@ impl ResponseTissue { .collect() } pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item( "tissues", self.results @@ -124,7 +124,7 @@ impl ResultTissue { } pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("id", &self.id)?; dict.set_item("min", self.min)?; dict.set_item("q1", self.q1)?; diff --git a/src/blast/python.rs b/src/blast/python.rs index c523c69..ed11763 100644 --- a/src/blast/python.rs +++ b/src/blast/python.rs @@ -15,7 +15,6 @@ use pyo3::{ signature = (query, program = None, database = None, limit = None, expect = None, low_comp_filter = None, megablast = None) )] #[allow(clippy::too_many_arguments)] - pub fn python_blast<'py>( py: Python<'py>, query: &str, @@ -61,5 +60,5 @@ pub fn python_blast<'py>( low_comp_filter, megablast, )?; - Ok(response.into_py_dict_bound(py)) + Ok(response.into_py_dict(py)?) } diff --git a/src/cli/cli.rs b/src/cli/cli.rs index 427594f..27ad95d 100644 --- a/src/cli/cli.rs +++ b/src/cli/cli.rs @@ -116,7 +116,7 @@ pub enum Commands { #[clap(required = true)] search_terms: Vec, - /// Species name to use: currently this MUST match the taxon_id + /// Species name to use: currently this MUST match the `taxon_id` #[clap(short, long, default_value = "homo_sapiens")] species: String, @@ -129,7 +129,7 @@ pub enum Commands { output: Option, }, - /// Queries sequences from ensembl and UniProt + /// Queries sequences from ensembl and `UniProt` Seq { /// Search terms to query (can be Ensembl IDs or Gene Symbols) #[clap(value_parser, required = true)] diff --git a/src/cli/enrichr.rs b/src/cli/enrichr.rs index 3fcf067..2863227 100644 --- a/src/cli/enrichr.rs +++ b/src/cli/enrichr.rs @@ -4,7 +4,7 @@ use clap::Subcommand; pub enum ModEnrichr { /// Perform the Enrichr gene set enrichment analysis Enrichr { - /// any database listed at: https://maayanlab.cloud/Enrichr/#libraries + /// any database listed at: /// some shorthands include: pathway, transcription, ontology, diseases_drugs, celltypes, /// and kinase_interactions. #[clap(short, long)] diff --git a/src/enrichr/types/enrich.rs b/src/enrichr/types/enrich.rs index 8b97ee7..f926994 100644 --- a/src/enrichr/types/enrich.rs +++ b/src/enrichr/types/enrich.rs @@ -23,12 +23,15 @@ impl fmt::Display for ResponseEnrich { } impl ResponseEnrich { pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); for (key, results) in &self.0 { - let all_results: Vec> = results - .iter() - .map(|x| x.as_pydict(py).expect("could not create dictionary")) - .collect(); + let all_results = + results + .iter() + .try_fold(Vec::new(), |mut acc, x| -> PyResult> { + acc.push(x.as_pydict(py)?); + Ok(acc) + })?; dict.set_item(key, all_results)?; } Ok(dict) @@ -72,7 +75,7 @@ impl fmt::Display for ResultEnrichr { } impl ResultEnrichr { pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("rank", self.rank)?; dict.set_item("term_name", &self.term_name)?; dict.set_item("pvalue", self.pvalue)?; diff --git a/src/ensembl/functions/database.rs b/src/ensembl/functions/database.rs index 34a93c3..f3b499e 100644 --- a/src/ensembl/functions/database.rs +++ b/src/ensembl/functions/database.rs @@ -6,7 +6,7 @@ use mysql::{prelude::Queryable, Conn, OptsBuilder}; pub fn database(filter: &Option) -> anyhow::Result { let opts = get_mysql_options(); let mut conn = Conn::new(opts)?; - let query = build_search_query(filter); + let query = build_search_query(filter.as_ref()); let results: Vec = conn.query_map(query, Database)?; if results.is_empty() { match filter { @@ -28,7 +28,7 @@ fn get_mysql_options() -> OptsBuilder { /// Generates the search query. /// /// Searches through databases for a related token -fn build_search_query(search_term: &Option) -> String { +fn build_search_query(search_term: Option<&String>) -> String { if let Some(token) = search_term { format!("SHOW databases LIKE '%{token}%'") } else { diff --git a/src/ensembl/python.rs b/src/ensembl/python.rs index b0297bc..e172f22 100644 --- a/src/ensembl/python.rs +++ b/src/ensembl/python.rs @@ -107,7 +107,7 @@ pub fn python_ensembl_species( } pub fn python_ensembl(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { - let submodule = PyModule::new_bound(py, "ensembl")?; + let submodule = PyModule::new(py, "ensembl")?; submodule.add_function(wrap_pyfunction!(python_ensembl_search, module)?)?; submodule.add_function(wrap_pyfunction!(python_ensembl_database, module)?)?; submodule.add_function(wrap_pyfunction!(python_ensembl_release, module)?)?; diff --git a/src/ensembl/types/ftpfile.rs b/src/ensembl/types/ftpfile.rs index b1c49ef..13450f8 100644 --- a/src/ensembl/types/ftpfile.rs +++ b/src/ensembl/types/ftpfile.rs @@ -41,7 +41,7 @@ impl FtpFile { } pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("url", &self.url)?; dict.set_item("ensembl_release", self.ensembl_release)?; dict.set_item("release_date", &self.release_date)?; diff --git a/src/ensembl/types/search_results.rs b/src/ensembl/types/search_results.rs index 357881c..9c90edc 100644 --- a/src/ensembl/types/search_results.rs +++ b/src/ensembl/types/search_results.rs @@ -21,7 +21,7 @@ impl fmt::Display for SearchResults { } impl SearchResults { pub fn as_pydict<'py>(&self, py: Python<'py>) -> Result> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item( "results", self.0 @@ -82,7 +82,7 @@ impl SearchResult { } pub fn as_pydict<'py>(&self, py: Python<'py>) -> PyResult> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("stable_id", &self.stable_id)?; dict.set_item("display_label", &self.display_label)?; dict.set_item("ensembl_description", &self.ensembl_description)?; diff --git a/src/lib.rs b/src/lib.rs index 95f7fe5..c6a6f2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,18 +53,18 @@ pub mod seq; pub type RequestError = Box; #[pymodule] -fn ggetrs(py: Python<'_>, module: Bound<'_, PyModule>) -> PyResult<()> { - module.add_function(wrap_pyfunction!(enrichr::python_enrichr, &module)?)?; +fn ggetrs(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(enrichr::python_enrichr, module)?)?; module.add_function(wrap_pyfunction!( enrichr::python_enrichr_background, - &module + module )?)?; - archs4::python_archs4(py, &module)?; - ensembl::python_ensembl(py, &module)?; - ucsc::python_ucsc(py, &module)?; - module.add_function(wrap_pyfunction!(ensembl::python_ensembl_search, &module)?)?; - module.add_function(wrap_pyfunction!(seq::python_seq, &module)?)?; - module.add_function(wrap_pyfunction!(info::python_info, &module)?)?; - module.add_function(wrap_pyfunction!(blast::python_blast, &module)?)?; + archs4::python_archs4(py, module)?; + ensembl::python_ensembl(py, module)?; + ucsc::python_ucsc(py, module)?; + module.add_function(wrap_pyfunction!(ensembl::python_ensembl_search, module)?)?; + module.add_function(wrap_pyfunction!(seq::python_seq, module)?)?; + module.add_function(wrap_pyfunction!(info::python_info, module)?)?; + module.add_function(wrap_pyfunction!(blast::python_blast, module)?)?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index 727479d..7502a37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,11 @@ use ggetrs::{ ncbi::{launch_ncbi_query_ids, launch_ncbi_query_symbols, launch_ncbi_taxons}, pdb::{launch_pdb_resource, launch_pdb_structure}, seq::launch_seq, - string::*, + string::{ + launch_string_annotations, launch_string_enrichment, launch_string_homology, + launch_string_interactions, launch_string_mapping, launch_string_network, + launch_string_ppi_enrichment, + }, ucsc::launch_ucsc_blat, uniprot::launch_uniprot_query, utils::autocomplete::print_completions, @@ -250,7 +254,7 @@ fn main() -> Result<(), RequestError> { ModString::Enrichment { args, output } => launch_string_enrichment(args, output)?, ModString::Annotations { args, output } => launch_string_annotations(args, output)?, ModString::PpiEnrichment { args, output } => { - launch_string_ppi_enrichment(args, output)? + launch_string_ppi_enrichment(args, output)?; } }, Commands::Autocomplete { shell } => print_completions(*shell, &mut Cli::command()), diff --git a/src/ucsc/python.rs b/src/ucsc/python.rs index eca05e2..e326da7 100644 --- a/src/ucsc/python.rs +++ b/src/ucsc/python.rs @@ -42,7 +42,7 @@ pub fn python_ucsc_blat<'py>( } pub fn python_ucsc(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { - let submodule = PyModule::new_bound(py, "ucsc")?; + let submodule = PyModule::new(py, "ucsc")?; submodule.add_function(wrap_pyfunction!(python_ucsc_blat, module)?)?; module.add_submodule(&submodule)?; Ok(()) diff --git a/src/ucsc/types/blat.rs b/src/ucsc/types/blat.rs index a750ab2..2f8bec0 100644 --- a/src/ucsc/types/blat.rs +++ b/src/ucsc/types/blat.rs @@ -28,13 +28,15 @@ impl BlatResults { Self(results) } pub fn as_pylist<'py>(&self, py: Python<'py>) -> PyResult> { - let vec_dict: Vec> = self - .0 - .iter() - .cloned() - .map(|x| x.into_py_dict(py).unwrap()) - .collect(); - Ok(PyList::new(py, vec_dict)?) + let vec_dict = + self.0 + .iter() + .cloned() + .try_fold(Vec::new(), |mut acc, x| -> PyResult> { + acc.push(x.into_py_dict(py)?); + Ok(acc) + })?; + PyList::new(py, vec_dict) } } @@ -75,27 +77,27 @@ impl fmt::Display for Blat { impl<'py> IntoPyDict<'py> for Blat { fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); - dict.set_item("matches", self.matches).unwrap(); - dict.set_item("mismatches", self.mismatches).unwrap(); - dict.set_item("repmatches", self.repmatches).unwrap(); - dict.set_item("n_count", self.n_count).unwrap(); - dict.set_item("q_num_insert", self.q_num_insert).unwrap(); - dict.set_item("q_base_insert", self.q_base_insert).unwrap(); - dict.set_item("t_num_insert", self.t_num_insert).unwrap(); - dict.set_item("t_base_insert", self.t_base_insert).unwrap(); - dict.set_item("strand", &self.strand).unwrap(); - dict.set_item("q_name", &self.q_name).unwrap(); - dict.set_item("q_size", self.q_size).unwrap(); - dict.set_item("q_start", self.q_start).unwrap(); - dict.set_item("q_end", self.q_end).unwrap(); - dict.set_item("t_name", &self.t_name).unwrap(); - dict.set_item("t_size", self.t_size).unwrap(); - dict.set_item("t_start", self.t_start).unwrap(); - dict.set_item("t_end", self.t_end).unwrap(); - dict.set_item("block_count", self.block_count).unwrap(); - dict.set_item("block_sizes", &self.block_sizes).unwrap(); - dict.set_item("q_starts", &self.q_starts).unwrap(); - dict.set_item("q_starts", &self.t_starts).unwrap(); + dict.set_item("matches", self.matches)?; + dict.set_item("mismatches", self.mismatches)?; + dict.set_item("repmatches", self.repmatches)?; + dict.set_item("n_count", self.n_count)?; + dict.set_item("q_num_insert", self.q_num_insert)?; + dict.set_item("q_base_insert", self.q_base_insert)?; + dict.set_item("t_num_insert", self.t_num_insert)?; + dict.set_item("t_base_insert", self.t_base_insert)?; + dict.set_item("strand", &self.strand)?; + dict.set_item("q_name", &self.q_name)?; + dict.set_item("q_size", self.q_size)?; + dict.set_item("q_start", self.q_start)?; + dict.set_item("q_end", self.q_end)?; + dict.set_item("t_name", &self.t_name)?; + dict.set_item("t_size", self.t_size)?; + dict.set_item("t_start", self.t_start)?; + dict.set_item("t_end", self.t_end)?; + dict.set_item("block_count", self.block_count)?; + dict.set_item("block_sizes", &self.block_sizes)?; + dict.set_item("q_starts", &self.q_starts)?; + dict.set_item("q_starts", &self.t_starts)?; Ok(dict) } } diff --git a/src/uniprot/functions/query.rs b/src/uniprot/functions/query.rs index 3114dda..6e19db0 100644 --- a/src/uniprot/functions/query.rs +++ b/src/uniprot/functions/query.rs @@ -5,7 +5,7 @@ use reqwest::Client; use serde_json::Value; use std::collections::HashMap; -fn build_query_string(gene: &str, freeform: bool, taxon: &Option) -> String { +fn build_query_string(gene: &str, freeform: bool, taxon: Option<&usize>) -> String { let gene_query = if gene.starts_with("ENS") || freeform { format!("({gene})") } else { @@ -26,7 +26,7 @@ pub async fn async_query_uniprot( freeform: bool, taxon: &Option, ) -> Result> { - let query = build_query_string(gene, freeform, taxon); + let query = build_query_string(gene, freeform, taxon.as_ref()); let url = format!("https://rest.uniprot.org/uniprotkb/search?query={query}+AND+reviewed:true",); let value = Client::new() .get(&url) // Updated to pass the URL by reference diff --git a/src/utils/fasta.rs b/src/utils/fasta.rs index 48f329a..f59753b 100644 --- a/src/utils/fasta.rs +++ b/src/utils/fasta.rs @@ -9,13 +9,15 @@ use std::fmt::Display; pub struct FastaRecords(pub Vec); impl FastaRecords { pub fn as_pylist<'py>(&self, py: Python<'py>) -> PyResult> { - let vec_dict: Vec> = self - .0 - .iter() - .cloned() - .map(|x| x.into_py_dict(py).unwrap()) - .collect(); - Ok(PyList::new(py, vec_dict)?) + let vec_dict = + self.0 + .iter() + .cloned() + .try_fold(Vec::default(), |mut acc, x| -> PyResult> { + acc.push(x.into_py_dict(py)?); + Ok(acc) + })?; + PyList::new(py, vec_dict) } } @@ -33,8 +35,8 @@ impl Display for FastaRecord { impl<'py> IntoPyDict<'py> for FastaRecord { fn into_py_dict(self, py: Python<'py>) -> PyResult> { let map = PyDict::new(py); - map.set_item("header", self.header).unwrap(); - map.set_item("sequence", self.sequence).unwrap(); + map.set_item("header", self.header)?; + map.set_item("sequence", self.sequence)?; Ok(map) } } From d5efbe981df8954bf29eac66b659594a41618242 Mon Sep 17 00:00:00 2001 From: noam teyssier <22600644+noamteyssier@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:21:41 -0800 Subject: [PATCH 5/5] chore: bump semvar --- Cargo.toml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6560b50..82aeefd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ggetrs" -version = "0.1.86" +version = "0.1.87" edition = "2021" license = "MIT" description = "Efficient querying of biological databases from the command line" @@ -29,23 +29,23 @@ ftp = "3.0.1" futures = "0.3.24" indicatif = "0.17.5" mysql = { version = "25.0.1", default-features = false, features = [ - "minimal", - "rustls-tls", + "minimal", + "rustls-tls", ] } # polars = { version = "0.43.1", default-features = false, features = ["json"] } polars-core = { version = "0.44.2", default-features = false } polars-io = { version = "0.44.2", default-features = false, features = [ - "json", - "csv", + "json", + "csv", ] } pyo3 = { version = "0.23.1", features = ["extension-module", "anyhow"] } regex = "1.6.0" reqwest = { version = "0.12.5", default-features = false, features = [ - "json", - "multipart", - "blocking", - "stream", - "rustls-tls", + "json", + "multipart", + "blocking", + "stream", + "rustls-tls", ] } serde = { version = "1.0.144", features = ["derive"] } serde-xml-rs = "0.6.0"