From 587d0a2966d043bb4c93413e55b70fa064f4530e Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Mon, 4 Nov 2024 16:16:06 +0100 Subject: [PATCH] chore: bump py-o3 (#924) --- py-rattler/Cargo.lock | 50 +++--- py-rattler/Cargo.toml | 11 +- py-rattler/src/channel/mod.rs | 4 +- py-rattler/src/index.rs | 1 + py-rattler/src/installer.rs | 11 +- py-rattler/src/lib.rs | 223 ++++++++++++-------------- py-rattler/src/lock/mod.rs | 12 +- py-rattler/src/match_spec.rs | 12 +- py-rattler/src/nameless_match_spec.rs | 12 +- py-rattler/src/networking/client.rs | 1 + py-rattler/src/networking/mod.rs | 13 +- py-rattler/src/paths_json.rs | 6 +- py-rattler/src/prefix_paths.rs | 15 +- py-rattler/src/record.rs | 36 +++-- py-rattler/src/repo_data/gateway.rs | 20 +-- py-rattler/src/shell.rs | 12 +- py-rattler/src/solver.rs | 20 ++- py-rattler/src/utils.rs | 7 +- 18 files changed, 234 insertions(+), 232 deletions(-) diff --git a/py-rattler/Cargo.lock b/py-rattler/Cargo.lock index bd20a84e8..3a171da34 100644 --- a/py-rattler/Cargo.lock +++ b/py-rattler/Cargo.lock @@ -2470,8 +2470,8 @@ dependencies = [ "openssl", "pep508_rs", "pyo3", - "pyo3-asyncio", - "pyo3-build-config 0.21.2", + "pyo3-async-runtimes", + "pyo3-build-config", "rattler", "rattler_conda_types", "rattler_digest", @@ -2493,9 +2493,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.20.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" +checksum = "3d922163ba1f79c04bc49073ba7b32fd5a8d3b76a87c955921234b8e77333c51" dependencies = [ "cfg-if", "chrono", @@ -2503,19 +2503,19 @@ dependencies = [ "inventory", "libc", "memoffset", - "parking_lot", + "once_cell", "portable-atomic", - "pyo3-build-config 0.20.3", + "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] -name = "pyo3-asyncio" -version = "0.20.0" +name = "pyo3-async-runtimes" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea6b68e93db3622f3bb3bf363246cf948ed5375afe7abff98ccbdd50b184995" +checksum = "2529f0be73ffd2be0cc43c013a640796558aa12d7ca0aab5cc14f375b4733031" dependencies = [ "futures", "once_cell", @@ -2526,19 +2526,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-build-config" -version = "0.21.2" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" +checksum = "bc38c5feeb496c8321091edf3d63e9a6829eab4b863b4a6a65f26f3e9cc6b179" dependencies = [ "once_cell", "target-lexicon", @@ -2546,19 +2536,19 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" +checksum = "94845622d88ae274d2729fcefc850e63d7a3ddff5e3ce11bd88486db9f1d357d" dependencies = [ "libc", - "pyo3-build-config 0.20.3", + "pyo3-build-config", ] [[package]] name = "pyo3-macros" -version = "0.20.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" +checksum = "e655aad15e09b94ffdb3ce3d217acf652e26bbc37697ef012f5e5e348c716e5e" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2568,13 +2558,13 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.3" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" +checksum = "ae1e3f09eecd94618f60a455a23def79f79eba4dc561a97324bf9ac8c6df30ce" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", - "pyo3-build-config 0.20.3", + "pyo3-build-config", "quote", "syn", ] diff --git a/py-rattler/Cargo.toml b/py-rattler/Cargo.toml index 2ee9a3600..1616cda75 100644 --- a/py-rattler/Cargo.toml +++ b/py-rattler/Cargo.toml @@ -10,7 +10,7 @@ name = "rattler" crate-type = ["cdylib"] [features] -default = ["native-tls"] +default = ["rustls-tls"] native-tls = ["rattler_networking/native-tls", "rattler_repodata_gateway/native-tls"] rustls-tls = ["rattler_networking/rustls-tls", "rattler_repodata_gateway/rustls-tls"] vendored-openssl = ["openssl", "openssl/vendored"] @@ -36,13 +36,14 @@ rattler_solve = { path = "../crates/rattler_solve", default-features = false, fe rattler_index = { path = "../crates/rattler_index" } rattler_lock = { path = "../crates/rattler_lock", default-features = false } rattler_package_streaming = { path = "../crates/rattler_package_streaming", default-features = false } -pyo3 = { version = "0.20", features = [ +pyo3 = { version = "0.22.5", features = [ "abi3-py38", "extension-module", "multiple-pymethods", - "chrono" + "chrono", + "gil-refs" ] } -pyo3-asyncio = { version = "0.20", features = ["tokio-runtime"] } +pyo3-async-runtimes = { version = "0.22.0", features = ["tokio-runtime"] } tokio = { version = "1.37" } reqwest = { version = "0.12.3", default-features = false } @@ -56,7 +57,7 @@ pep508_rs = "0.9.1" serde_json = "1.0.132" [build-dependencies] -pyo3-build-config = "0.21" +pyo3-build-config = "0.22.5" [patch.crates-io] diff --git a/py-rattler/src/channel/mod.rs b/py-rattler/src/channel/mod.rs index 2b9c012ea..2a6b1ecf4 100644 --- a/py-rattler/src/channel/mod.rs +++ b/py-rattler/src/channel/mod.rs @@ -83,8 +83,8 @@ impl PyChannel { } } -#[pyclass] -#[derive(Clone)] +#[pyclass(eq, eq_int)] +#[derive(Clone, PartialEq, Eq)] pub enum PyChannelPriority { /// The channel that the package is first found in will be used as the only channel /// for that package. diff --git a/py-rattler/src/index.rs b/py-rattler/src/index.rs index a551ce69c..17a04c4a3 100644 --- a/py-rattler/src/index.rs +++ b/py-rattler/src/index.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use crate::{error::PyRattlerError, platform::PyPlatform}; #[pyfunction] +#[pyo3(signature = (channel_directory, target_platform=None))] pub fn py_index( py: Python<'_>, channel_directory: PathBuf, diff --git a/py-rattler/src/installer.rs b/py-rattler/src/installer.rs index 73885575d..f6bcb3a6c 100644 --- a/py-rattler/src/installer.rs +++ b/py-rattler/src/installer.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; -use pyo3::{pyfunction, PyAny, PyResult, Python}; -use pyo3_asyncio::tokio::future_into_py; +use pyo3::{pyfunction, Bound, PyAny, PyResult, Python}; +use pyo3_async_runtimes::tokio::future_into_py; use rattler::{ install::{IndicatifReporter, Installer}, package_cache::PackageCache, @@ -16,17 +16,18 @@ use crate::{ // TODO: Accept functions to report progress #[pyfunction] #[allow(clippy::too_many_arguments)] +#[pyo3(signature = (records, target_prefix, execute_link_scripts=false, show_progress=false, platform=None, client=None, cache_dir=None, installed_packages=None))] pub fn py_install<'a>( py: Python<'a>, - records: Vec<&'a PyAny>, + records: Vec>, target_prefix: PathBuf, execute_link_scripts: bool, show_progress: bool, platform: Option, client: Option, cache_dir: Option, - installed_packages: Option>, -) -> PyResult<&'a PyAny> { + installed_packages: Option>>, +) -> PyResult> { let dependencies = records .into_iter() .map(|rdr| PyRecord::try_from(rdr)?.try_into()) diff --git a/py-rattler/src/lib.rs b/py-rattler/src/lib.rs index 3803ea5ea..0b333ed4a 100644 --- a/py-rattler/src/lib.rs +++ b/py-rattler/src/lib.rs @@ -86,158 +86,145 @@ impl Deref for Wrap { } #[pymodule] -fn rattler(py: Python<'_>, m: &PyModule) -> PyResult<()> { - m.add_class::().unwrap(); +fn rattler<'py>(py: Python<'py>, m: Bound<'py, PyModule>) -> PyResult<()> { + m.add_class::()?; - m.add_class::().unwrap(); - m.add_class::().unwrap(); + m.add_class::()?; + m.add_class::()?; - m.add_class::().unwrap(); + m.add_class::()?; - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; // Shell activation things - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - - m.add_function(wrap_pyfunction!(py_fetch_repo_data, m).unwrap()) - .unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); - m.add_class::().unwrap(); + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + m.add_class::()?; + + m.add_function(wrap_pyfunction!(py_fetch_repo_data, &m)?)?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + m.add_class::()?; + + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + m.add_class::()?; + + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + + m.add_function(wrap_pyfunction!(py_solve, &m).unwrap())?; + m.add_function(wrap_pyfunction!(py_solve_with_sparse_repodata, &m).unwrap())?; + m.add_function(wrap_pyfunction!(get_rattler_version, &m).unwrap())?; + m.add_function(wrap_pyfunction!(py_install, &m).unwrap())?; + m.add_function(wrap_pyfunction!(py_index, &m).unwrap())?; // Explicit environment specification - m.add_class::().unwrap(); - m.add_class::().unwrap(); - - m.add_function(wrap_pyfunction!(py_solve, m).unwrap()) - .unwrap(); - m.add_function(wrap_pyfunction!(py_solve_with_sparse_repodata, m).unwrap()) - .unwrap(); - m.add_function(wrap_pyfunction!(get_rattler_version, m).unwrap()) - .unwrap(); - m.add_function(wrap_pyfunction!(py_install, m).unwrap()) - .unwrap(); - m.add_function(wrap_pyfunction!(py_index, m).unwrap()) - .unwrap(); + m.add_class::()?; + m.add_class::()?; // Exceptions m.add( "InvalidVersionError", - py.get_type::(), - ) - .unwrap(); + py.get_type_bound::(), + )?; m.add( "InvalidMatchSpecError", - py.get_type::(), - ) - .unwrap(); + py.get_type_bound::(), + )?; m.add( "InvalidPackageNameError", - py.get_type::(), - ) - .unwrap(); - m.add("InvalidUrlError", py.get_type::()) - .unwrap(); + py.get_type_bound::(), + )?; + m.add( + "InvalidUrlError", + py.get_type_bound::(), + )?; m.add( "InvalidChannelError", - py.get_type::(), - ) - .unwrap(); - m.add("ActivationError", py.get_type::()) - .unwrap(); + py.get_type_bound::(), + )?; + m.add( + "ActivationError", + py.get_type_bound::(), + )?; m.add( "ParsePlatformError", - py.get_type::(), - ) - .unwrap(); - m.add("ParseArchError", py.get_type::()) - .unwrap(); - m.add("SolverError", py.get_type::()) - .unwrap(); - m.add("TransactionError", py.get_type::()) - .unwrap(); - m.add("LinkError", py.get_type::()).unwrap(); - m.add("IoError", py.get_type::()).unwrap(); + py.get_type_bound::(), + )?; + m.add("ParseArchError", py.get_type_bound::())?; + m.add("SolverError", py.get_type_bound::())?; + m.add( + "TransactionError", + py.get_type_bound::(), + )?; + m.add("LinkError", py.get_type_bound::())?; + m.add("IoError", py.get_type_bound::())?; m.add( "DetectVirtualPackageError", - py.get_type::(), - ) - .unwrap(); - m.add("CacheDirError", py.get_type::()) - .unwrap(); + py.get_type_bound::(), + )?; + m.add("CacheDirError", py.get_type_bound::())?; m.add( "FetchRepoDataError", - py.get_type::(), - ) - .unwrap(); + py.get_type_bound::(), + )?; m.add( "ConvertSubdirError", - py.get_type::(), - ) - .unwrap(); - m.add("VersionBumpError", py.get_type::()) - .unwrap(); + py.get_type_bound::(), + )?; + m.add( + "VersionBumpError", + py.get_type_bound::(), + )?; m.add( "EnvironmentCreationError", - py.get_type::(), - ) - .unwrap(); + py.get_type_bound::(), + )?; - m.add("ExtractError", py.get_type::()) - .unwrap(); + m.add("ExtractError", py.get_type_bound::())?; - m.add("GatewayError", py.get_type::()) - .unwrap(); + m.add("GatewayError", py.get_type_bound::())?; m.add( "ValidatePackageRecordsException", - py.get_type::(), - ) - .unwrap(); + py.get_type_bound::(), + )?; Ok(()) } diff --git a/py-rattler/src/lock/mod.rs b/py-rattler/src/lock/mod.rs index 37f1d3bf4..d2186fafe 100644 --- a/py-rattler/src/lock/mod.rs +++ b/py-rattler/src/lock/mod.rs @@ -5,7 +5,7 @@ use std::{ }; use pep508_rs::Requirement; -use pyo3::{pyclass, pymethods, types::PyBytes, PyResult, Python}; +use pyo3::{pyclass, pymethods, types::PyBytes, Bound, PyResult, Python}; use rattler_conda_types::{MatchSpec, ParseStrictness, RepoDataRecord}; use rattler_lock::{ Channel, Environment, LockFile, Package, PackageHashes, PypiPackageData, @@ -522,12 +522,14 @@ impl PyPackageHashes { // } #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.sha256().map(|sha256| PyBytes::new(py, sha256)) + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { + self.inner + .sha256() + .map(|sha256| PyBytes::new_bound(py, sha256)) } #[getter] - pub fn md5<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.md5().map(|md5| PyBytes::new(py, md5)) + pub fn md5<'a>(&self, py: Python<'a>) -> Option> { + self.inner.md5().map(|md5| PyBytes::new_bound(py, md5)) } } diff --git a/py-rattler/src/match_spec.rs b/py-rattler/src/match_spec.rs index 6854b4fa5..3351f95a0 100644 --- a/py-rattler/src/match_spec.rs +++ b/py-rattler/src/match_spec.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use pyo3::{pyclass, pymethods, types::PyBytes, PyResult, Python}; +use pyo3::{pyclass, pymethods, types::PyBytes, Bound, PyResult, Python}; use rattler_conda_types::{Channel, MatchSpec, Matches, PackageName, ParseStrictness}; use crate::{ @@ -102,14 +102,16 @@ impl PyMatchSpec { /// The md5 hash of the package #[getter] - pub fn md5<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.md5.map(|md5| PyBytes::new(py, &md5)) + pub fn md5<'a>(&self, py: Python<'a>) -> Option> { + self.inner.md5.map(|md5| PyBytes::new_bound(py, &md5)) } /// The sha256 hash of the package #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.sha256.map(|sha256| PyBytes::new(py, &sha256)) + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { + self.inner + .sha256 + .map(|sha256| PyBytes::new_bound(py, &sha256)) } /// Returns a string representation of MatchSpec diff --git a/py-rattler/src/nameless_match_spec.rs b/py-rattler/src/nameless_match_spec.rs index aae788d63..4a0c7179d 100644 --- a/py-rattler/src/nameless_match_spec.rs +++ b/py-rattler/src/nameless_match_spec.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use pyo3::{pyclass, pymethods, types::PyBytes, PyResult, Python}; +use pyo3::{pyclass, pymethods, types::PyBytes, Bound, PyResult, Python}; use rattler_conda_types::{Channel, MatchSpec, Matches, NamelessMatchSpec, ParseStrictness}; use crate::{channel::PyChannel, error::PyRattlerError, match_spec::PyMatchSpec, record::PyRecord}; @@ -100,14 +100,16 @@ impl PyNamelessMatchSpec { /// The md5 hash of the package #[getter] - pub fn md5<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.md5.map(|md5| PyBytes::new(py, &md5)) + pub fn md5<'a>(&self, py: Python<'a>) -> Option> { + self.inner.md5.map(|md5| PyBytes::new_bound(py, &md5)) } /// The sha256 hash of the package #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.sha256.map(|sha256| PyBytes::new(py, &sha256)) + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { + self.inner + .sha256 + .map(|sha256| PyBytes::new_bound(py, &sha256)) } /// Returns a string representation of MatchSpec diff --git a/py-rattler/src/networking/client.rs b/py-rattler/src/networking/client.rs index 2fc9835a7..fd2e76265 100644 --- a/py-rattler/src/networking/client.rs +++ b/py-rattler/src/networking/client.rs @@ -13,6 +13,7 @@ pub struct PyClientWithMiddleware { #[pymethods] impl PyClientWithMiddleware { #[new] + #[pyo3(signature = (middlewares=None))] pub fn new(middlewares: Option>) -> Self { let middlewares = middlewares.unwrap_or_default(); let client = reqwest_middleware::ClientBuilder::new(reqwest::Client::new()); diff --git a/py-rattler/src/networking/mod.rs b/py-rattler/src/networking/mod.rs index a5b2aeaf8..3cf1d3410 100644 --- a/py-rattler/src/networking/mod.rs +++ b/py-rattler/src/networking/mod.rs @@ -1,6 +1,6 @@ use futures::future::try_join_all; -use pyo3::{pyfunction, types::PyTuple, Py, PyAny, PyResult, Python, ToPyObject}; -use pyo3_asyncio::tokio::future_into_py; +use pyo3::{pyfunction, types::PyTuple, Bound, Py, PyAny, PyResult, Python, ToPyObject}; +use pyo3_async_runtimes::tokio::future_into_py; use rattler_repodata_gateway::fetch::{ fetch_repo_data, CachedRepoData, FetchRepoDataError, FetchRepoDataOptions, @@ -23,19 +23,20 @@ pub mod middleware; /// High-level function to fetch repodata for all the subdirectory of channels and platform. /// Returns a list of `PyRepoData`. #[pyfunction] +#[pyo3(signature = (channels, platforms, cache_path, callback=None, client=None))] pub fn py_fetch_repo_data<'a>( py: Python<'a>, channels: Vec, platforms: Vec, cache_path: PathBuf, - callback: Option<&'a PyAny>, + callback: Option>, client: Option, -) -> PyResult<&'a PyAny> { +) -> PyResult> { let mut meta_futures = Vec::new(); let client = client.unwrap_or(PyClientWithMiddleware::new(None)); for (subdir, chan) in get_subdir_urls(channels, platforms)? { - let callback = callback.map(|callback| { + let callback = callback.as_ref().map(|callback| { Arc::new(ProgressReporter { callback: callback.to_object(py), }) as _ @@ -87,7 +88,7 @@ impl Reporter for ProgressReporter { total_bytes: Option, ) { Python::with_gil(|py| { - let args = PyTuple::new(py, [Some(bytes_downloaded), total_bytes]); + let args = PyTuple::new_bound(py, [Some(bytes_downloaded), total_bytes]); self.callback.call1(py, args).expect("Callback failed!"); }); } diff --git a/py-rattler/src/paths_json.rs b/py-rattler/src/paths_json.rs index af3b024f7..5d1024d46 100644 --- a/py-rattler/src/paths_json.rs +++ b/py-rattler/src/paths_json.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use pyo3::{exceptions::PyValueError, pyclass, pymethods, types::PyBytes, PyResult, Python}; +use pyo3::{exceptions::PyValueError, pyclass, pymethods, types::PyBytes, Bound, PyResult, Python}; use rattler_conda_types::package::{ FileMode, PackageFile, PathType, PathsEntry, PathsJson, PrefixPlaceholder, }; @@ -186,8 +186,8 @@ impl PyPathsEntry { /// A hex representation of the SHA256 hash of the contents of the file. /// This entry is only present in version 1 of the paths.json file. #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.sha256.map(|sha| PyBytes::new(py, &sha)) + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { + self.inner.sha256.map(|sha| PyBytes::new_bound(py, &sha)) } /// The size of the file in bytes diff --git a/py-rattler/src/prefix_paths.rs b/py-rattler/src/prefix_paths.rs index 54dc02d9b..3e9fc6ad9 100644 --- a/py-rattler/src/prefix_paths.rs +++ b/py-rattler/src/prefix_paths.rs @@ -1,5 +1,5 @@ use crate::{paths_json::PyFileMode, utils::sha256_from_pybytes}; -use pyo3::{exceptions::PyValueError, pyclass, pymethods, types::PyBytes, PyResult, Python}; +use pyo3::{exceptions::PyValueError, pyclass, pymethods, types::PyBytes, Bound, PyResult, Python}; use rattler_conda_types::prefix_record::{PathType, PathsEntry, PrefixPaths}; use std::path::PathBuf; @@ -20,13 +20,14 @@ impl PyPrefixPaths { impl PyPrefixPathsEntry { #[new] #[allow(clippy::too_many_arguments)] + #[pyo3(signature = (relative_path, path_type, prefix_placeholder=None, file_mode=None, sha256=None, sha256_in_prefix=None, size_in_bytes=None, original_path=None))] pub fn new( relative_path: PathBuf, path_type: PyPrefixPathType, prefix_placeholder: Option, file_mode: Option, - sha256: Option<&PyBytes>, - sha256_in_prefix: Option<&PyBytes>, + sha256: Option>, + sha256_in_prefix: Option>, size_in_bytes: Option, original_path: Option, ) -> PyResult { @@ -251,8 +252,8 @@ impl PyPrefixPathsEntry { /// If prefix_placeholder is present, this represents the hash of the file *before* /// any placeholders were replaced #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { - self.inner.sha256.map(|sha| PyBytes::new(py, &sha)) + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { + self.inner.sha256.map(|sha| PyBytes::new_bound(py, &sha)) } // #[setter] @@ -264,10 +265,10 @@ impl PyPrefixPathsEntry { /// This will be present only if prefix_placeholder is defined. In this case, /// this is the hash of the file after the placeholder has been replaced. #[getter] - pub fn sha256_in_prefix<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { + pub fn sha256_in_prefix<'a>(&self, py: Python<'a>) -> Option> { self.inner .sha256_in_prefix - .map(|shla| PyBytes::new(py, &shla)) + .map(|shla| PyBytes::new_bound(py, &shla)) } // #[setter] diff --git a/py-rattler/src/record.rs b/py-rattler/src/record.rs index c2abf7806..7aa2a7f11 100644 --- a/py-rattler/src/record.rs +++ b/py-rattler/src/record.rs @@ -1,8 +1,9 @@ use std::path::PathBuf; +use pyo3::prelude::PyAnyMethods; use pyo3::{ - exceptions::PyTypeError, intern, pyclass, pymethods, types::PyBytes, FromPyObject, PyAny, - PyErr, PyResult, Python, + exceptions::PyTypeError, intern, pyclass, pymethods, types::PyBytes, Bound, FromPyObject, + PyAny, PyErr, PyResult, Python, }; use rattler_conda_types::{ package::{IndexJson, PackageFile}, @@ -139,6 +140,7 @@ impl From for Link { impl PyRecord { #[staticmethod] #[allow(clippy::too_many_arguments)] + #[pyo3(signature = (name, version, build, build_number, subdir, arch=None, platform=None, noarch=None))] pub fn create( name: PyPackageName, version: (PyVersion, String), @@ -202,6 +204,7 @@ impl PyRecord { } #[staticmethod] + #[pyo3(signature = (package_record, paths_data, link=None, package_tarball_full_path=None, extracted_package_dir=None, requested_spec=None, files=None))] pub fn create_prefix_record( package_record: PyRecord, paths_data: PyPrefixPaths, @@ -332,14 +335,14 @@ impl PyRecord { /// A deprecated md5 hash. #[getter] - pub fn legacy_bz2_md5<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { + pub fn legacy_bz2_md5<'a>(&self, py: Python<'a>) -> Option> { self.as_package_record() .legacy_bz2_md5 - .map(|md5| PyBytes::new(py, &md5)) + .map(|md5| PyBytes::new_bound(py, &md5)) } #[setter] - pub fn set_legacy_bz2_md5(&mut self, md5: Option<&PyBytes>) -> PyResult<()> { + pub fn set_legacy_bz2_md5(&mut self, md5: Option>) -> PyResult<()> { self.as_package_record_mut().legacy_bz2_md5 = md5.map(md5_from_pybytes).transpose()?; Ok(()) } @@ -379,14 +382,14 @@ impl PyRecord { /// Optionally a MD5 hash of the package archive. #[getter] - pub fn md5<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { + pub fn md5<'a>(&self, py: Python<'a>) -> Option> { self.as_package_record() .md5 - .map(|md5| PyBytes::new(py, &md5)) + .map(|md5| PyBytes::new_bound(py, &md5)) } #[setter] - pub fn set_md5(&mut self, md5: Option<&PyBytes>) -> PyResult<()> { + pub fn set_md5(&mut self, md5: Option>) -> PyResult<()> { self.as_package_record_mut().md5 = md5.map(md5_from_pybytes).transpose()?; Ok(()) } @@ -415,15 +418,15 @@ impl PyRecord { /// Optionally a SHA256 hash of the package archive. #[getter] - pub fn sha256<'a>(&self, py: Python<'a>) -> Option<&'a PyBytes> { + pub fn sha256<'a>(&self, py: Python<'a>) -> Option> { self.as_package_record() .sha256 - .map(|sha| PyBytes::new(py, &sha)) + .map(|sha| PyBytes::new_bound(py, &sha)) } /// Optionally a SHA256 hash of the package archive. #[setter] - pub fn set_sha256(&mut self, sha256: Option<&PyBytes>) -> PyResult<()> { + pub fn set_sha256(&mut self, sha256: Option>) -> PyResult<()> { self.as_package_record_mut().sha256 = sha256.map(sha256_from_pybytes).transpose()?; Ok(()) } @@ -640,9 +643,9 @@ impl TryFrom for PrefixRecord { } } -impl<'a> TryFrom<&'a PyAny> for PyRecord { +impl<'a> TryFrom> for PyRecord { type Error = PyErr; - fn try_from(value: &'a PyAny) -> Result { + fn try_from(value: Bound<'a, PyAny>) -> Result { let intern_val = intern!(value.py(), "_record"); if !value.hasattr(intern_val)? { return Err(PyTypeError::new_err("object is not a record type")); @@ -653,7 +656,7 @@ impl<'a> TryFrom<&'a PyAny> for PyRecord { return Err(PyTypeError::new_err("'_record' is invalid")); } - PyRecord::extract(inner) + PyRecord::extract_bound(&inner) } } @@ -736,6 +739,7 @@ impl PyRecord { impl PyRecord { /// Builds a `PyRecord` from path to an `index.json` and optionally a size. #[staticmethod] + #[pyo3(signature = (index_json, size=None, sha256=None, md5=None))] fn from_index_json( index_json: PathBuf, size: Option, @@ -765,7 +769,7 @@ impl PyRecord { /// of each package are satisfied by the other packages in the list. /// If there is a dependency that is not satisfied, this function will raise an exception. #[staticmethod] - fn validate(records: Vec<&PyAny>) -> PyResult<()> { + fn validate(records: Vec>) -> PyResult<()> { let records = records .into_iter() .map(PyRecord::try_from) @@ -780,7 +784,7 @@ impl PyRecord { /// /// Note that this function only works for packages with unique names. #[staticmethod] - fn sort_topologically(records: Vec<&PyAny>) -> PyResult> { + fn sort_topologically(records: Vec>) -> PyResult> { let records = records .into_iter() .map(PyRecord::try_from) diff --git a/py-rattler/src/repo_data/gateway.rs b/py-rattler/src/repo_data/gateway.rs index ae632ba27..d3f49a4e2 100644 --- a/py-rattler/src/repo_data/gateway.rs +++ b/py-rattler/src/repo_data/gateway.rs @@ -4,8 +4,8 @@ use crate::platform::PyPlatform; use crate::record::PyRecord; use crate::{PyChannel, Wrap}; use pyo3::exceptions::PyValueError; -use pyo3::{pyclass, pymethods, FromPyObject, PyAny, PyResult, Python}; -use pyo3_asyncio::tokio::future_into_py; +use pyo3::{pyclass, pymethods, Bound, FromPyObject, PyAny, PyResult, Python}; +use pyo3_async_runtimes::tokio::future_into_py; use rattler_repodata_gateway::fetch::CacheAction; use rattler_repodata_gateway::{ChannelConfig, Gateway, SourceConfig, SubdirSelection}; use std::collections::{HashMap, HashSet}; @@ -31,8 +31,8 @@ impl From for PyGateway { } impl<'source> FromPyObject<'source> for Wrap { - fn extract(ob: &'source PyAny) -> PyResult { - let parsed = match ob.extract::>>()? { + fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult { + let parsed = match >>::extract_bound(ob)? { Some(platforms) => SubdirSelection::Some( platforms .into_iter() @@ -48,6 +48,8 @@ impl<'source> FromPyObject<'source> for Wrap { #[pymethods] impl PyGateway { #[new] + #[pyo3(signature = (max_concurrent_requests, default_config, per_channel_config, cache_dir=None) + )] pub fn new( max_concurrent_requests: usize, default_config: PySourceConfig, @@ -86,7 +88,7 @@ impl PyGateway { platforms: Vec, specs: Vec, recursive: bool, - ) -> PyResult<&'a PyAny> { + ) -> PyResult> { let gateway = self.inner.clone(); future_into_py(py, async move { let repodatas = gateway @@ -129,9 +131,9 @@ impl From for PySourceConfig { } } -impl FromPyObject<'_> for Wrap { - fn extract(ob: &'_ PyAny) -> PyResult { - let parsed = match &*ob.extract::()? { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + let parsed = match <&'py str>::extract_bound(ob)? { "cache-or-fetch" => CacheAction::CacheOrFetch, "use-cache-only" => CacheAction::UseCacheOnly, "force-cache-only" => CacheAction::ForceCacheOnly, @@ -140,7 +142,7 @@ impl FromPyObject<'_> for Wrap { return Err(PyValueError::new_err(format!( "cache action must be one of {{'cache-or-fetch', 'use-cache-only', 'force-cache-only', 'no-cache'}}, got {v}", ))) - }, + } }; Ok(Wrap(parsed)) } diff --git a/py-rattler/src/shell.rs b/py-rattler/src/shell.rs index 4718411e3..79ab118a2 100644 --- a/py-rattler/src/shell.rs +++ b/py-rattler/src/shell.rs @@ -1,6 +1,6 @@ use crate::error::PyRattlerError; use crate::platform::PyPlatform; -use pyo3::{exceptions::PyValueError, pyclass, pymethods, FromPyObject, PyAny, PyResult}; +use pyo3::{exceptions::PyValueError, pyclass, pymethods, Bound, FromPyObject, PyAny, PyResult}; use rattler_shell::{ activation::{ActivationResult, ActivationVariables, Activator, PathModificationBehavior}, shell::{Bash, CmdExe, Fish, PowerShell, ShellEnum, Xonsh, Zsh}, @@ -23,9 +23,9 @@ impl From for PyActivationVariables { #[repr(transparent)] pub struct Wrap(pub T); -impl FromPyObject<'_> for Wrap { - fn extract(ob: &PyAny) -> PyResult { - let parsed = match ob.extract::<&str>()? { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + let parsed = match <&'py str>::extract_bound(ob)? { "prepend" => PathModificationBehavior::Prepend, "append" => PathModificationBehavior::Append, "replace" => PathModificationBehavior::Replace, @@ -98,8 +98,8 @@ impl PyActivationResult { } } -#[pyclass] -#[derive(Clone)] +#[pyclass(eq, eq_int)] +#[derive(Clone, Eq, PartialEq)] pub enum PyShellEnum { Bash, Zsh, diff --git a/py-rattler/src/solver.rs b/py-rattler/src/solver.rs index f5250330b..e75e86125 100644 --- a/py-rattler/src/solver.rs +++ b/py-rattler/src/solver.rs @@ -1,6 +1,8 @@ use chrono::DateTime; -use pyo3::{exceptions::PyValueError, pyfunction, FromPyObject, PyAny, PyErr, PyResult, Python}; -use pyo3_asyncio::tokio::future_into_py; +use pyo3::{ + exceptions::PyValueError, pyfunction, Bound, FromPyObject, PyAny, PyErr, PyResult, Python, +}; +use pyo3_async_runtimes::tokio::future_into_py; use rattler_repodata_gateway::sparse::SparseRepoData; use rattler_solve::{resolvo::Solver, RepoDataIter, SolveStrategy, SolverImpl, SolverTask}; use std::sync::Arc; @@ -17,9 +19,9 @@ use crate::{ PySparseRepoData, Wrap, }; -impl FromPyObject<'_> for Wrap { - fn extract(ob: &'_ PyAny) -> PyResult { - let parsed = match &*ob.extract::()? { +impl<'py> FromPyObject<'py> for Wrap { + fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { + let parsed = match <&'py str>::extract_bound(ob)? { "highest" => SolveStrategy::Highest, "lowest" => SolveStrategy::LowestVersion, "lowest-direct" => SolveStrategy::LowestVersionDirect, @@ -35,6 +37,8 @@ impl FromPyObject<'_> for Wrap { #[allow(clippy::too_many_arguments)] #[pyfunction] +#[pyo3(signature = (channels, platforms, specs, constraints, gateway, locked_packages, pinned_packages, virtual_packages, channel_priority, timeout=None, exclude_newer_timestamp_ms=None, strategy=None) +)] pub fn py_solve( py: Python<'_>, channels: Vec, @@ -49,7 +53,7 @@ pub fn py_solve( timeout: Option, exclude_newer_timestamp_ms: Option, strategy: Option>, -) -> PyResult<&'_ PyAny> { +) -> PyResult> { future_into_py(py, async move { let available_packages = gateway .inner @@ -110,6 +114,8 @@ pub fn py_solve( #[allow(clippy::too_many_arguments)] #[pyfunction] +#[pyo3(signature = (specs, sparse_repodata, constraints, locked_packages, pinned_packages, virtual_packages, channel_priority, timeout=None, exclude_newer_timestamp_ms=None, strategy=None) +)] pub fn py_solve_with_sparse_repodata( py: Python<'_>, specs: Vec, @@ -122,7 +128,7 @@ pub fn py_solve_with_sparse_repodata( timeout: Option, exclude_newer_timestamp_ms: Option, strategy: Option>, -) -> PyResult<&'_ PyAny> { +) -> PyResult> { future_into_py(py, async move { let exclude_newer = exclude_newer_timestamp_ms.and_then(DateTime::from_timestamp_millis); diff --git a/py-rattler/src/utils.rs b/py-rattler/src/utils.rs index ee3fb611c..3d9899807 100644 --- a/py-rattler/src/utils.rs +++ b/py-rattler/src/utils.rs @@ -1,7 +1,8 @@ -use pyo3::{exceptions::PyValueError, types::PyBytes, PyErr}; +use pyo3::prelude::PyBytesMethods; +use pyo3::{exceptions::PyValueError, types::PyBytes, Bound, PyErr}; use rattler_digest::{Md5Hash, Sha256Hash}; -pub fn sha256_from_pybytes(bytes: &PyBytes) -> Result { +pub fn sha256_from_pybytes(bytes: Bound<'_, PyBytes>) -> Result { if bytes.as_bytes().len() != 32 { return Err(PyValueError::new_err("Expected a 32 byte SHA256 digest")); } @@ -9,7 +10,7 @@ pub fn sha256_from_pybytes(bytes: &PyBytes) -> Result { Ok(*digest) } -pub fn md5_from_pybytes(bytes: &PyBytes) -> Result { +pub fn md5_from_pybytes(bytes: Bound<'_, PyBytes>) -> Result { if bytes.as_bytes().len() != 16 { return Err(PyValueError::new_err("Expected a 16 byte MD5 digest")); }