diff --git a/crates/rattler_conda_types/src/utils/url_with_trailing_slash.rs b/crates/rattler_conda_types/src/utils/url_with_trailing_slash.rs index 470babdf1..1b9fe833b 100644 --- a/crates/rattler_conda_types/src/utils/url_with_trailing_slash.rs +++ b/crates/rattler_conda_types/src/utils/url_with_trailing_slash.rs @@ -58,3 +58,25 @@ impl Display for UrlWithTrailingSlash { write!(f, "{}", &self.0) } } + +#[cfg(test)] +mod tests { + use super::*; + use serde_json; + + #[test] + fn test_url_with_trailing_slash() { + let url = Url::parse("http://example.com").unwrap(); + let url_with_trailing_slash = UrlWithTrailingSlash::from(url.clone()); + assert_eq!( + url_with_trailing_slash, + UrlWithTrailingSlash::from(url.clone()) + ); + + let serialized = serde_json::to_string(&url_with_trailing_slash).unwrap(); + assert_eq!(serialized, "\"http://example.com/\""); + + let deserialized: UrlWithTrailingSlash = serde_json::from_str(&serialized).unwrap(); + assert_eq!(deserialized, url_with_trailing_slash); + } +} diff --git a/crates/rattler_networking/src/lib.rs b/crates/rattler_networking/src/lib.rs index c8ba7ff18..b184d3303 100644 --- a/crates/rattler_networking/src/lib.rs +++ b/crates/rattler_networking/src/lib.rs @@ -13,6 +13,7 @@ pub use gcs_middleware::GCSMiddleware; pub mod authentication_middleware; pub mod authentication_storage; +pub mod url_with_trailing_slash; pub mod mirror_middleware; pub mod oci_middleware; diff --git a/crates/rattler_networking/src/mirror_middleware.rs b/crates/rattler_networking/src/mirror_middleware.rs index 913c88915..11ba33c03 100644 --- a/crates/rattler_networking/src/mirror_middleware.rs +++ b/crates/rattler_networking/src/mirror_middleware.rs @@ -10,11 +10,13 @@ use reqwest::{Request, Response, ResponseBuilderExt}; use reqwest_middleware::{Middleware, Next, Result}; use url::Url; +use crate::url_with_trailing_slash::UrlWithTrailingSlash; + #[derive(Debug, Clone, PartialEq, Eq, Hash)] /// Settings for the specific mirror (e.g. no zstd or bz2 support) pub struct Mirror { /// The url of this mirror - pub url: Url, + pub url: UrlWithTrailingSlash, /// Disable zstd support (for repodata.json.zst files) pub no_zstd: bool, /// Disable bz2 support (for repodata.json.bz2 files) @@ -39,14 +41,14 @@ impl MirrorState { /// Middleware to handle mirrors pub struct MirrorMiddleware { - mirror_map: HashMap>, - sorted_keys: Vec<(String, Url)>, + mirror_map: HashMap>, + sorted_keys: Vec<(String, UrlWithTrailingSlash)>, } impl MirrorMiddleware { /// Create a new `MirrorMiddleware` from a map of mirrors - pub fn from_map(mirror_map: HashMap>) -> Self { - let mirror_map: HashMap> = mirror_map + pub fn from_map(mirror_map: HashMap>) -> Self { + let mirror_map: HashMap> = mirror_map .into_iter() .map(|(url, mirrors)| { let mirrors = mirrors @@ -65,7 +67,7 @@ impl MirrorMiddleware { .cloned() .sorted_by(|a, b| b.path().len().cmp(&a.path().len())) .map(|k| (k.to_string(), k.clone())) - .collect::>(); + .collect::>(); Self { mirror_map, @@ -75,7 +77,7 @@ impl MirrorMiddleware { /// Get sorted keys. The keys are sorted by length of the path, /// so the longest path comes first. - pub fn keys(&self) -> &[(String, Url)] { + pub fn keys(&self) -> &[(String, UrlWithTrailingSlash)] { &self.sorted_keys } } diff --git a/crates/rattler_networking/src/oci_middleware.rs b/crates/rattler_networking/src/oci_middleware.rs index 56f91f830..5326a26d5 100644 --- a/crates/rattler_networking/src/oci_middleware.rs +++ b/crates/rattler_networking/src/oci_middleware.rs @@ -60,15 +60,18 @@ impl Display for OciAction { async fn get_token(url: &OCIUrl, action: OciAction) -> Result { let token_url = url.token_url(action)?; - tracing::trace!("OCI Mirror: requesting token from {}", token_url); + let response = reqwest::get(token_url.clone()).await?; - let token = reqwest::get(token_url) - .await? - .json::() - .await? - .token; - - Ok(token) + match response.error_for_status() { + Ok(response) => { + let token = response.json::().await?; + Ok(token.token) + } + Err(e) => { + tracing::error!("OCI Mirror: failed to get token with URL: {}", token_url); + Err(OciMiddlewareError::Reqwest(e)) + } + } } #[derive(Debug)] diff --git a/py-rattler/Cargo.lock b/py-rattler/Cargo.lock index 2c9c92a0e..a5057f7b4 100644 --- a/py-rattler/Cargo.lock +++ b/py-rattler/Cargo.lock @@ -1805,7 +1805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2472,6 +2472,7 @@ dependencies = [ "pyo3", "pyo3-async-runtimes", "pyo3-build-config", + "pyo3-file", "rattler", "rattler_conda_types", "rattler_digest", @@ -2544,6 +2545,15 @@ dependencies = [ "pyo3-build-config", ] +[[package]] +name = "pyo3-file" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488563e2317157edd6e12c3ef23e10363bd079bf8630e3de719e368b4eb02a21" +dependencies = [ + "pyo3", +] + [[package]] name = "pyo3-macros" version = "0.22.5" @@ -2674,7 +2684,7 @@ dependencies = [ [[package]] name = "rattler" -version = "0.28.0" +version = "0.28.1" dependencies = [ "anyhow", "console", @@ -2712,7 +2722,7 @@ dependencies = [ [[package]] name = "rattler_cache" -version = "0.2.8" +version = "0.2.9" dependencies = [ "anyhow", "dashmap", @@ -2738,7 +2748,7 @@ dependencies = [ [[package]] name = "rattler_conda_types" -version = "0.29.0" +version = "0.29.1" dependencies = [ "chrono", "dirs", @@ -2787,7 +2797,7 @@ dependencies = [ [[package]] name = "rattler_index" -version = "0.19.34" +version = "0.19.35" dependencies = [ "fs-err 3.0.0", "rattler_conda_types", @@ -2800,7 +2810,7 @@ dependencies = [ [[package]] name = "rattler_lock" -version = "0.22.29" +version = "0.22.30" dependencies = [ "chrono", "file_url", @@ -2855,7 +2865,7 @@ dependencies = [ [[package]] name = "rattler_package_streaming" -version = "0.22.11" +version = "0.22.12" dependencies = [ "bzip2", "chrono", @@ -2890,7 +2900,7 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" -version = "0.21.20" +version = "0.21.21" dependencies = [ "anyhow", "async-compression", @@ -2943,7 +2953,7 @@ dependencies = [ [[package]] name = "rattler_shell" -version = "0.22.5" +version = "0.22.6" dependencies = [ "enum_dispatch", "fs-err 3.0.0", @@ -2959,7 +2969,7 @@ dependencies = [ [[package]] name = "rattler_solve" -version = "1.2.1" +version = "1.2.2" dependencies = [ "chrono", "futures", @@ -2975,7 +2985,7 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" -version = "1.1.8" +version = "1.1.9" dependencies = [ "archspec", "libloading", @@ -4224,7 +4234,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/py-rattler/Cargo.toml b/py-rattler/Cargo.toml index 63575313e..ec7422e57 100644 --- a/py-rattler/Cargo.toml +++ b/py-rattler/Cargo.toml @@ -55,6 +55,7 @@ url = "2.5.3" openssl = { version = "0.10", optional = true } pep508_rs = "0.9.1" serde_json = "1.0.132" +pyo3-file = "0.9.0" [build-dependencies] pyo3-build-config = "0.22.5" diff --git a/py-rattler/pixi.lock b/py-rattler/pixi.lock index f8994f441..3c25e9df3 100644 --- a/py-rattler/pixi.lock +++ b/py-rattler/pixi.lock @@ -592,17 +592,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.43-h4bf12b8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py38h17151c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py39hf88036b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.8.30-hbcca054_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.8.30-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.0-py38heb5c249_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py39h15c3d72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-14.2.0-h6b349bd_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/h2-4.1.0-py38h578d9bd_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/h2-4.1.0-py39hf3d152e_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.0.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_0.conda @@ -623,9 +623,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.2.3-py38hcdda232_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.2.3-py39hd4f0224_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.5.1-py38h01eb140_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.5.1-py39hd1e30aa_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.2-hb9d3cd8_0.conda @@ -633,19 +633,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-6.0.0-py38hfb59056_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-6.1.0-py39h8cd3c5a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-asyncio-0.21.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-xprocess-0.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.8.20-h4a871b0_2_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.8-5_cp38.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.9.20-h13acc7a_1_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.9-5_cp39.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.9.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py38h18b4745_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py39h7efa1f9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.81.0-h1a8d7c4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.81.0-h2c6d0dc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda @@ -662,16 +662,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py38h62bed22_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py39h08a7858_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - - pypi: https://files.pythonhosted.org/packages/98/5d/5738903efe0ecb73e51eb44feafba32bdba2081263d40c5043568ff60faf/numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/7a/7c/d7b2a0417af6428440c0ad7cb9799073e507b1a465f827d058b826236964/numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c4/83/07c5cd92ead27ecf48e3d12d0164ac0f6a7990b4d0d47c297398c285627a/types_networkx-3.3.0.20241020-py3-none-any.whl osx-64: - - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py38h940360d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py39h7c0e7c0_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-hfdf4475_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.8.30-h8857fd0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.8.30-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.0-py38hc8bcfa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.1-py39h8ddeee6_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 @@ -686,28 +686,28 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.47.0-h2f8c449_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.2.3-py38h196e9ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.2.3-py39hfa3e63f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.5.1-py38hcafd530_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.5.1-py39hdc70f33_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.3.2-hd23fc13_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-6.0.0-py38hc718529_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-6.1.0-py39h296a897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-asyncio-0.21.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-xprocess-0.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.8.20-h4f978b9_2_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.8-5_cp38.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.9.20-hf24efe3_1_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.9-5_cp39.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.9.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py38h1916ca8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py39h6792c9e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.81.0-h6c54e5d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.81.0-h38e4360_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda @@ -719,19 +719,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.12.5-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/types-requests-2.32.0.20241016-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.23.0-py38hdb7df32_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.23.0-py39hc23f734_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.6-h915ae27_0.conda - - pypi: https://files.pythonhosted.org/packages/11/10/943cfb579f1a02909ff96464c69893b1d25be3731b5d3652c2e0cf1281ea/numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9a/cd/d5b0402b801c8a8b56b04c1e85c6165efab298d2f0ab741c2406516ede3a/numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c4/83/07c5cd92ead27ecf48e3d12d0164ac0f6a7990b4d0d47c297398c285627a/types_networkx-3.3.0.20241020-py3-none-any.whl osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py38he333c0f_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py39hfa9831e_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h99b78c6_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.8.30-hf0a4a13_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.8.30-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.17.0-py38h858044d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.17.1-py39h7f933ea_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 @@ -746,28 +747,28 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.47.0-hbaaea75_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.2.3-py38h92a0862_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.2.3-py39had97604_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.5.1-py38hb192615_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.5.1-py39h0f82c59_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.3.2-h8359307_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-6.0.0-py38h3237794_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-6.1.0-py39h57695bc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-asyncio-0.21.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-xprocess-0.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.8.20-h7d35d02_2_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.8-5_cp38.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.9.20-h9e33284_1_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.9-5_cp39.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.9.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py38h5477e86_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py39hd984c07_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.81.0-h4ff7c5d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.81.0-hf6ec828_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda @@ -779,19 +780,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.12.5-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/types-requests-2.32.0.20241016-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py38h43bb1b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py39hcf1bb16_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - - pypi: https://files.pythonhosted.org/packages/a7/ae/f53b7b265fdc701e663fbb322a8e9d4b14d9cb7b2385f45ddfabfc4327e4/numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/14/27/638aaa446f39113a3ed38b37a66243e21b38110d021bfcb940c383e120f2/numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/c4/83/07c5cd92ead27ecf48e3d12d0164ac0f6a7990b4d0d47c297398c285627a/types_networkx-3.3.0.20241020-py3-none-any.whl win-64: - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py38hd3f51b4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py39ha51f57c_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h2466b09_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.8.30-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.8.30-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-1.17.0-py38h4cb3324_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-1.17.1-py39ha55e580_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 @@ -810,27 +812,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.2.3-py38hf90c7e5_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.2.3-py39h424382f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.5.1-py38h91455d4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.5.1-py39ha55989b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.3.2-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.5.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-6.0.0-py38h4cb3324_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-6.1.0-py39ha55e580_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-asyncio-0.21.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-xprocess-0.23.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.8.20-hfaddaf0_2_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.8-5_cp38.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.9.20-hfaddaf0_1_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.9-5_cp39.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.9.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py38h5e48be7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py39h756cfbc_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.81.0-hf8d6059_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.81.0-h17fc481_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-75.1.0-pyhd8ed1ab_0.conda @@ -842,6 +844,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typer-slim-standard-0.12.5-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/types-requests-2.32.0.20241016-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.12.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_22.conda @@ -850,9 +853,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.44.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py38hf92978b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py39h9bf74da_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.6-h0ea2cb4_0.conda - - pypi: https://files.pythonhosted.org/packages/69/65/0d47953afa0ad569d12de5f65d964321c208492064c38fe3b0b9744f8d44/numpy-1.24.4-cp38-cp38-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/63/38/6cc19d6b8bfa1d1a459daf2b3fe325453153ca7019976274b6f33d8b5663/numpy-1.24.4-cp39-cp39-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/c4/83/07c5cd92ead27ecf48e3d12d0164ac0f6a7990b4d0d47c297398c285627a/types_networkx-3.3.0.20241020-py3-none-any.whl packages: - kind: conda @@ -1045,91 +1048,94 @@ packages: - kind: conda name: brotli-python version: 1.1.0 - build: py38h17151c0_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py38h17151c0_1.conda - sha256: f932ae77f10885dd991b0e1f56f6effea9f19b169e8606dab0bdafd0e44db3c9 - md5: 7a5a699c8992fc51ef25e980f4502c2a + build: py39h7c0e7c0_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py39h7c0e7c0_2.conda + sha256: 3915fd4c8ebc4a7c83851479532dd5e52775f130d720016d05d728212e28c6ed + md5: a764df072b4bfa295ae771b28d284cf7 depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - __osx >=10.13 + - libcxx >=17 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 constrains: - - libbrotlicommon 1.1.0 hd590300_1 + - libbrotlicommon 1.1.0 h00291cd_2 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 350830 - timestamp: 1695990250755 + size: 362967 + timestamp: 1725268063367 - kind: conda name: brotli-python version: 1.1.0 - build: py38h940360d_1 - build_number: 1 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py38h940360d_1.conda - sha256: 0a088bff62ddd2e505bdc80cc16da009c134b9ccfa6352b0cfe9d4eeed27d8c2 - md5: ad8d4ae4e8351a2fc0fe92f13bd266d8 + build: py39ha51f57c_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py39ha51f57c_2.conda + sha256: e7640e3d3f742172a3a5ad40f1e2326893bd61bb51224e434f4ea509a527540a + md5: febb0f96eb7400bb065681117872b75e depends: - - libcxx >=15.0.7 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 constrains: - - libbrotlicommon 1.1.0 h0dc2134_1 + - libbrotlicommon 1.1.0 h2466b09_2 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 366343 - timestamp: 1695990788245 + size: 321820 + timestamp: 1725268551147 - kind: conda name: brotli-python version: 1.1.0 - build: py38hd3f51b4_1 - build_number: 1 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py38hd3f51b4_1.conda - sha256: a292d6b3118ef284cc03a99a6efe5e08ca3a6d0e37eff78eb8d87cfca3830d7b - md5: 72708ea626a2530148ea49eb743576f4 + build: py39hf88036b_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py39hf88036b_2.conda + sha256: 6b5ad1d89519f926138cd146bc475d42ccbd8239849fa8677031160e17f30202 + md5: 8ea5af6ac902f1a4429190970d9099ce depends: - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 constrains: - - libbrotlicommon 1.1.0 hcfcfb64_1 + - libbrotlicommon 1.1.0 hb9d3cd8_2 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 321650 - timestamp: 1695990817828 + size: 349166 + timestamp: 1725267838006 - kind: conda name: brotli-python version: 1.1.0 - build: py38he333c0f_1 - build_number: 1 + build: py39hfa9831e_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py38he333c0f_1.conda - sha256: 3fd1e0a4b7ea1b20f69bbc2d74c798f3eebd775ccbcdee170f68b1871f8bbb74 - md5: 29160c74d5977b1c5ecd654b00d576f0 - depends: - - libcxx >=15.0.7 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 + url: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py39hfa9831e_2.conda + sha256: 9498fa2d1f5f006980e362b545f3a85086e27714d26deba23cd002c11ff04842 + md5: e6297328cb55064f9923dbe19c354b4a + depends: + - __osx >=11.0 + - libcxx >=17 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 constrains: - - libbrotlicommon 1.1.0 hb547adb_1 + - libbrotlicommon 1.1.0 hd74edd7_2 license: MIT license_family: MIT purls: - pkg:pypi/brotli?source=hash-mapping - size: 343036 - timestamp: 1695990970956 + size: 338488 + timestamp: 1725268478900 - kind: conda name: bzip2 version: 1.0.8 @@ -1402,89 +1408,6 @@ packages: - pkg:pypi/certifi?source=hash-mapping size: 163752 timestamp: 1725278204397 -- kind: conda - name: cffi - version: 1.17.0 - build: py38h4cb3324_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/cffi-1.17.0-py38h4cb3324_0.conda - sha256: 09e73cc77c995d608647cf0e999790155c6adfd69554b148550d6acd8dc5fefc - md5: da2c9ba02e759024e994d0ecce7c860b - depends: - - pycparser - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 236272 - timestamp: 1723018796385 -- kind: conda - name: cffi - version: 1.17.0 - build: py38h858044d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.17.0-py38h858044d_0.conda - sha256: c3c1486d52eac829dfca9d7d3d5596fea66e52dccc9b33d5d7b9acee276935af - md5: 792d275788105bf78189bb55dc1e9c76 - depends: - - __osx >=11.0 - - libffi >=3.4,<4.0a0 - - pycparser - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 227934 - timestamp: 1723018694952 -- kind: conda - name: cffi - version: 1.17.0 - build: py38hc8bcfa4_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.0-py38hc8bcfa4_0.conda - sha256: dfa9d415301f9431bc298869687d76abbeded8aff27a258ce28acaf175a47e1e - md5: d2a8f77ea8b928779611d1072e9ff89d - depends: - - __osx >=10.13 - - libffi >=3.4,<4.0a0 - - pycparser - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 228572 - timestamp: 1723018629051 -- kind: conda - name: cffi - version: 1.17.0 - build: py38heb5c249_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.0-py38heb5c249_0.conda - sha256: 04f394dbebcf09f845b95e63691aa20d8fc0e65cc94c78eb334c184335788cf8 - md5: b41a6ee3a5b044185b5f46aaf6082388 - depends: - - __glibc >=2.17,<3.0.a0 - - libffi >=3.4,<4.0a0 - - libgcc-ng >=12 - - pycparser - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - license: MIT - license_family: MIT - purls: - - pkg:pypi/cffi?source=hash-mapping - size: 240463 - timestamp: 1723018485509 - kind: conda name: cffi version: 1.17.1 @@ -1579,6 +1502,89 @@ packages: license_family: MIT size: 295514 timestamp: 1725560706794 +- kind: conda + name: cffi + version: 1.17.1 + build: py39h15c3d72_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.1-py39h15c3d72_0.conda + sha256: f24486fdb31df2a7b04555093fdcbb3a314a1f29a4906b72ac9010906eb57ff8 + md5: 7e61b8777f42e00b08ff059f9e8ebc44 + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.4,<4.0a0 + - libgcc >=13 + - pycparser + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 241610 + timestamp: 1725571230934 +- kind: conda + name: cffi + version: 1.17.1 + build: py39h7f933ea_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-1.17.1-py39h7f933ea_0.conda + sha256: 9b8cb32f491b2e45033ea74e269af35ea3ad109701f11045a20f32d6b3183a18 + md5: 8d1481721ef903515e19d989fe3a9251 + depends: + - __osx >=11.0 + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 227265 + timestamp: 1725560892881 +- kind: conda + name: cffi + version: 1.17.1 + build: py39h8ddeee6_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.17.1-py39h8ddeee6_0.conda + sha256: 08e363b8c7662245ac89e864334fc76b61c6a8c1642c8404db0d2544a8566e82 + md5: ea57b55b4b6884ae7a9dcb14cd9782e9 + depends: + - __osx >=10.13 + - libffi >=3.4,<4.0a0 + - pycparser + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 229582 + timestamp: 1725560793066 +- kind: conda + name: cffi + version: 1.17.1 + build: py39ha55e580_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/cffi-1.17.1-py39ha55e580_0.conda + sha256: 9cbef6685015cef22b8f09fef6be4217018964af692251c980b5af23a28afc76 + md5: 1e0c1867544dc5f3adfad28742f4d983 + depends: + - pycparser + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 236935 + timestamp: 1725561195746 - kind: conda name: charset-normalizer version: 3.4.0 @@ -2084,22 +2090,22 @@ packages: - kind: conda name: h2 version: 4.1.0 - build: py38h578d9bd_0 + build: py39hf3d152e_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/h2-4.1.0-py38h578d9bd_0.tar.bz2 - sha256: c5e66b79c5358fae9993ed89f59231507c82a9636e11d6022df86f8187895030 - md5: aa0b1b3f33dea4c04034c1af2b63fdea + url: https://conda.anaconda.org/conda-forge/linux-64/h2-4.1.0-py39hf3d152e_0.tar.bz2 + sha256: f2aaa56f152e889f2f9d7db78f4b0534dce91c8de3e2a5b2627fbfcb01b14054 + md5: 4d6e35bbcba4f0c06f02a285f5602333 depends: - hpack >=4.0,<5 - hyperframe >=6.0,<7 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 license: MIT license_family: MIT purls: - pkg:pypi/h2?source=hash-mapping - size: 78959 - timestamp: 1633502851889 + size: 78986 + timestamp: 1633502850830 - kind: conda name: h2 version: 4.1.0 @@ -3811,86 +3817,86 @@ packages: - kind: conda name: maturin version: 1.2.3 - build: py38h196e9ca_1 + build: py39h424382f_1 build_number: 1 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.2.3-py38h196e9ca_1.conda - sha256: 6741443febe65e13ea3518d4aa39a2649f20013200db42fb5fa17df226cb2502 - md5: ff08d795c8c4ce06126fda2f16dd6f78 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.2.3-py39h424382f_1.conda + sha256: 71b434ddcfce74cbc7c3b6f34e57cb06590713a8c7e7146edde5bff50f318178 + md5: b5f0e6a385b6a7c338bd3e5797b5da04 depends: - - openssl >=3.1.3,<4.0a0 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - m2w64-gcc-libs + - m2w64-gcc-libs-core + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 license: MIT license_family: MIT purls: - pkg:pypi/maturin?source=hash-mapping - size: 4954588 - timestamp: 1695301365076 + size: 4675949 + timestamp: 1695301764687 - kind: conda name: maturin version: 1.2.3 - build: py38h92a0862_1 + build: py39had97604_1 build_number: 1 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.2.3-py38h92a0862_1.conda - sha256: 9979e134a93fd96683d77bd99787bfdb6b510bb561ad5e5fc3462b6ab4159d45 - md5: 9782b697036cb80847325d29352bc57d + url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.2.3-py39had97604_1.conda + sha256: c78f0570a39e850fde018a837ad6cbe5f6f2958eff1aa9b297dd8049a44b336c + md5: a97a03eaf3a999e935d8f1ee2c562ade depends: - openssl >=3.1.3,<4.0a0 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 license: MIT license_family: MIT purls: - pkg:pypi/maturin?source=hash-mapping - size: 4911655 - timestamp: 1695301265510 + size: 4910646 + timestamp: 1695301077802 - kind: conda name: maturin version: 1.2.3 - build: py38hcdda232_1 + build: py39hd4f0224_1 build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.2.3-py38hcdda232_1.conda - sha256: 2066be187bb36bb791ce437b8c2116d8b45c9f896fb92669fe731b84e73dff3f - md5: a2695b422d514f42b2e99cc7b4974383 + url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.2.3-py39hd4f0224_1.conda + sha256: 01b5a08fb8b92253493fb1a255bd824e54a5edda4d38035191d84573f912f964 + md5: ff48842d653dc2fc2654bcec63fb828c depends: - libgcc-ng >=12 - openssl >=3.1.3,<4.0a0 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 license: MIT license_family: MIT purls: - pkg:pypi/maturin?source=hash-mapping - size: 6347816 - timestamp: 1695300476324 + size: 6348409 + timestamp: 1695300604559 - kind: conda name: maturin version: 1.2.3 - build: py38hf90c7e5_1 + build: py39hfa3e63f_1 build_number: 1 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.2.3-py38hf90c7e5_1.conda - sha256: c5b71e011e6c1fa046a0577b73aeaf297b72c305b743315ed7272ba23fa9836d - md5: 52db8f5569b5829195ebd03570739543 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.2.3-py39hfa3e63f_1.conda + sha256: 005ce85c85c0046194fc86def62d4dd76127add8d0ef7f892b29a876ca7cc290 + md5: a1b583fca2a005457eec5e811e8e3866 depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - openssl >=3.1.3,<4.0a0 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 license: MIT license_family: MIT purls: - pkg:pypi/maturin?source=hash-mapping - size: 4675089 - timestamp: 1695301899264 + size: 4952573 + timestamp: 1695301210461 - kind: conda name: mdurl version: 0.1.2 @@ -4108,40 +4114,40 @@ packages: - kind: conda name: mypy version: 1.5.1 - build: py38h01eb140_1 + build: py39h0f82c59_1 build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.5.1-py38h01eb140_1.conda - sha256: 00eb9b837d1b6727d08ed304605469150cccc45e0b42ab0bf8e478c581336f8b - md5: 6313e5ee96b444fcd5338085813477ca + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.5.1-py39h0f82c59_1.conda + sha256: ba0b6db2251c3d6d54d533aa8cc5d3380ae74959819ee0c6e19b69097b28bc71 + md5: ef45d37d51c76e9ae8c445cec59e1dad depends: - - libgcc-ng >=12 - mypy_extensions >=1.0.0 - psutil >=4.0 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 - typing_extensions >=4.1.0 license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 16146866 - timestamp: 1695442675379 + size: 8928156 + timestamp: 1695442579842 - kind: conda name: mypy version: 1.5.1 - build: py38h91455d4_1 + build: py39ha55989b_1 build_number: 1 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/mypy-1.5.1-py38h91455d4_1.conda - sha256: 142e125d201faae4a7430c2a519bb70348b773e8a5d0249ec70d5b1f7c243f98 - md5: b50c3acf3bbadccda20ebf7fcedd5c65 + url: https://conda.anaconda.org/conda-forge/win-64/mypy-1.5.1-py39ha55989b_1.conda + sha256: 1165a900b84f2e46d71a1d081016303f1542c7814aaccbc24363bdd419ea4995 + md5: 3e1ab06301b5a14822a836a3f41856fd depends: - mypy_extensions >=1.0.0 - psutil >=4.0 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 - typing_extensions >=4.1.0 - ucrt >=10.0.20348.0 @@ -4151,53 +4157,53 @@ packages: license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 8981331 - timestamp: 1695442268532 + size: 9056384 + timestamp: 1695442384852 - kind: conda name: mypy version: 1.5.1 - build: py38hb192615_1 + build: py39hd1e30aa_1 build_number: 1 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.5.1-py38hb192615_1.conda - sha256: e7008ea5f4da4ce761070e5b2d0c6b038092aa87c54eec086e6bb5eaf1df6498 - md5: 8ecb5bafe2068a472aa2adaa97fe38db + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.5.1-py39hd1e30aa_1.conda + sha256: 001d0ebc2513d0075857490a61e25936a76e8cd72607fe40da68d9f21e5b54bf + md5: 82c414bcccf6091182c4582e95fd864d depends: + - libgcc-ng >=12 - mypy_extensions >=1.0.0 - psutil >=4.0 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 - typing_extensions >=4.1.0 license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 8908642 - timestamp: 1695442718816 + size: 16538681 + timestamp: 1695442634557 - kind: conda name: mypy version: 1.5.1 - build: py38hcafd530_1 + build: py39hdc70f33_1 build_number: 1 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.5.1-py38hcafd530_1.conda - sha256: 89099ba03417a8a68d9cbf8345b20c9b14633b972d6bd77146092be35e8ce4a1 - md5: a8de48d3c37e63914dbb3341dc4990ba + url: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.5.1-py39hdc70f33_1.conda + sha256: 453225ca3d6b18eba0bf39f0f3a5a9309e555ee71ebb3a6316242e3708321cd9 + md5: 9963b18d2820002a85c9eff4ee7b59fa depends: - mypy_extensions >=1.0.0 - psutil >=4.0 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - tomli >=1.1.0 - typing_extensions >=4.1.0 license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 11027655 - timestamp: 1695442955398 + size: 10930488 + timestamp: 1695442499484 - kind: conda name: mypy_extensions version: 1.0.0 @@ -4264,26 +4270,26 @@ packages: - kind: pypi name: numpy version: 1.24.4 - url: https://files.pythonhosted.org/packages/11/10/943cfb579f1a02909ff96464c69893b1d25be3731b5d3652c2e0cf1281ea/numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl - sha256: 1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61 + url: https://files.pythonhosted.org/packages/14/27/638aaa446f39113a3ed38b37a66243e21b38110d021bfcb940c383e120f2/numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl + sha256: 9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f requires_python: '>=3.8' - kind: pypi name: numpy version: 1.24.4 - url: https://files.pythonhosted.org/packages/69/65/0d47953afa0ad569d12de5f65d964321c208492064c38fe3b0b9744f8d44/numpy-1.24.4-cp38-cp38-win_amd64.whl - sha256: 692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706 + url: https://files.pythonhosted.org/packages/63/38/6cc19d6b8bfa1d1a459daf2b3fe325453153ca7019976274b6f33d8b5663/numpy-1.24.4-cp39-cp39-win_amd64.whl + sha256: befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8 requires_python: '>=3.8' - kind: pypi name: numpy version: 1.24.4 - url: https://files.pythonhosted.org/packages/98/5d/5738903efe0ecb73e51eb44feafba32bdba2081263d40c5043568ff60faf/numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc + url: https://files.pythonhosted.org/packages/7a/7c/d7b2a0417af6428440c0ad7cb9799073e507b1a465f827d058b826236964/numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d requires_python: '>=3.8' - kind: pypi name: numpy version: 1.24.4 - url: https://files.pythonhosted.org/packages/a7/ae/f53b7b265fdc701e663fbb322a8e9d4b14d9cb7b2385f45ddfabfc4327e4/numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl - sha256: 04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f + url: https://files.pythonhosted.org/packages/9a/cd/d5b0402b801c8a8b56b04c1e85c6165efab298d2f0ab741c2406516ede3a/numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl + sha256: 2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400 requires_python: '>=3.8' - kind: conda name: openjpeg @@ -4784,79 +4790,80 @@ packages: timestamp: 1713667175451 - kind: conda name: psutil - version: 6.0.0 - build: py38h3237794_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-6.0.0-py38h3237794_0.conda - sha256: 76e30573405195dbcedff472f7706e09765b2d49112209e7f81dfb8436e73235 - md5: f14d02d525fd9f62172c717979e2d849 + version: 6.1.0 + build: py39h296a897_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/psutil-6.1.0-py39h296a897_0.conda + sha256: 01d50f9868d73f7d40af039dc75076d286b24de58e9e1fcef1db484455976c17 + md5: 9c4a209f029dfe376ea8abb2ea4f7125 depends: - - __osx >=11.0 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 + - __osx >=10.13 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 374902 - timestamp: 1719274926745 + size: 370379 + timestamp: 1729847282307 - kind: conda name: psutil - version: 6.0.0 - build: py38h4cb3324_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/psutil-6.0.0-py38h4cb3324_0.conda - sha256: b624f4be2d0e7b956835ea8822cb9502c861819e5402fe5d02f27d8b4289e392 - md5: 00cc8acaf6d7eec51d009a0662a0cc03 + version: 6.1.0 + build: py39h57695bc_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-6.1.0-py39h57695bc_0.conda + sha256: 7caa6892871b78fd609fa24136005a2b34e711076c35abaa70a873aa1ce27fde + md5: 7521b2d7f1337893b7b9a513a264caa1 depends: - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - __osx >=11.0 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 383894 - timestamp: 1719275206477 + size: 372272 + timestamp: 1729847358451 - kind: conda name: psutil - version: 6.0.0 - build: py38hc718529_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/psutil-6.0.0-py38hc718529_0.conda - sha256: b6006e8d25ae4c8d43ca07f5ff15b2ca51bfceb92168b8f73e376d30078bb944 - md5: fc486245b64b4e03c5968915c277aabf + version: 6.1.0 + build: py39h8cd3c5a_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/psutil-6.1.0-py39h8cd3c5a_0.conda + sha256: 057765763fc2b7cc8d429e055240209ae83ae6631c80060bad590bbbc8f01f22 + md5: ef257b7ce1e1cb152639ced6bc653475 depends: - - __osx >=10.13 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 372234 - timestamp: 1719274817130 + size: 364598 + timestamp: 1729847230720 - kind: conda name: psutil - version: 6.0.0 - build: py38hfb59056_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/psutil-6.0.0-py38hfb59056_0.conda - sha256: d6d5f1ac1dc3bbddb50c093f89a425edae695754ad1ab1bc78bf720be11315ea - md5: 14d8661ec0011b79081f8429c716f46f + version: 6.1.0 + build: py39ha55e580_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/psutil-6.1.0-py39ha55e580_0.conda + sha256: 9b0b6c692e4fd9d6ece2b78340987913ae741b5a5486308d00b87f1a507bed9b + md5: 9e44ffa0f1a6bc810c6e948919a473e8 depends: - - libgcc-ng >=12 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil?source=hash-mapping - size: 366341 - timestamp: 1719274737975 + size: 380522 + timestamp: 1729847576400 - kind: conda name: pthread-stubs version: '0.4' @@ -5090,13 +5097,13 @@ packages: timestamp: 1695495262467 - kind: conda name: python - version: 3.8.20 - build: h4a871b0_2_cpython - build_number: 2 + version: 3.9.20 + build: h13acc7a_1_cpython + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python-3.8.20-h4a871b0_2_cpython.conda - sha256: 8043dcdb29e1e026d0def1056620d81b24c04f71fd98cc45888c58373b479845 - md5: 05ffff2f44ad60b94ecb53d029c6bdf7 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.9.20-h13acc7a_1_cpython.conda + sha256: 6a30aa8df1745eded1e5c24d167cb10e6f379e75d2f2fa2a212e6dab76030698 + md5: 951cff166a5f170e27908811917165f8 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 @@ -5112,24 +5119,25 @@ packages: - openssl >=3.3.2,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 + - tzdata - xz >=5.2.6,<6.0a0 constrains: - - python_abi 3.8.* *_cp38 + - python_abi 3.9.* *_cp39 license: Python-2.0 purls: [] - size: 22176012 - timestamp: 1727719857908 + size: 23684398 + timestamp: 1727719528404 - kind: conda name: python - version: 3.8.20 - build: h4f978b9_2_cpython - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python-3.8.20-h4f978b9_2_cpython.conda - sha256: 839c786f6f46eceb4b197d84ff96b134c273d60af4e55e9cbbdc08e489b6d78b - md5: a6263abf89e3162d11e63141bf25d91f + version: 3.9.20 + build: h9e33284_1_cpython + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.9.20-h9e33284_1_cpython.conda + sha256: d6c272faa05fb7524aaf59718fa27629b1875e5dfb2fa74100547e8564cce4bc + md5: 708bd3a3616e42becb50d77313def984 depends: - - __osx >=10.13 + - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - libffi >=3.4,<4.0a0 - libsqlite >=3.46.1,<4.0a0 @@ -5138,24 +5146,25 @@ packages: - openssl >=3.3.2,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 + - tzdata - xz >=5.2.6,<6.0a0 constrains: - - python_abi 3.8.* *_cp38 + - python_abi 3.9.* *_cp39 license: Python-2.0 purls: [] - size: 11338027 - timestamp: 1727718893331 + size: 11826087 + timestamp: 1727718700429 - kind: conda name: python - version: 3.8.20 - build: h7d35d02_2_cpython - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.8.20-h7d35d02_2_cpython.conda - sha256: cf8692e732697d47f0290ef83caa4b3115c7b277a3fb155b7de0f09fa1b5e27c - md5: 29ed2994beffea2a256a7e14f9468df8 + version: 3.9.20 + build: hf24efe3_1_cpython + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.9.20-hf24efe3_1_cpython.conda + sha256: d2ee8b24fa298708967c5ea9edb0fc310691200fcafe35a5caca4b3341f7b0bc + md5: 0482528eb9c88cd5f2113b1c2921c9b9 depends: - - __osx >=11.0 + - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - libffi >=3.4,<4.0a0 - libsqlite >=3.46.1,<4.0a0 @@ -5164,22 +5173,23 @@ packages: - openssl >=3.3.2,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 + - tzdata - xz >=5.2.6,<6.0a0 constrains: - - python_abi 3.8.* *_cp38 + - python_abi 3.9.* *_cp39 license: Python-2.0 purls: [] - size: 11774160 - timestamp: 1727718758277 + size: 12411513 + timestamp: 1727719187767 - kind: conda name: python - version: 3.8.20 - build: hfaddaf0_2_cpython - build_number: 2 + version: 3.9.20 + build: hfaddaf0_1_cpython + build_number: 1 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python-3.8.20-hfaddaf0_2_cpython.conda - sha256: 4cf5c93b625cc353b7bb20eb2f2840a2c24c76578ae425c017812d1b95c5225d - md5: 4e181f484d292cb273fdf456e8dc7b4a + url: https://conda.anaconda.org/conda-forge/win-64/python-3.9.20-hfaddaf0_1_cpython.conda + sha256: c4ef6a17c8065d8c653fc69cfa17b2a1b0d9a2ca1360ba67a514b450c8797fd9 + md5: 445389d1d311435a90def248c814ddd6 depends: - bzip2 >=1.0.8,<2.0a0 - libffi >=3.4,<4.0a0 @@ -5187,16 +5197,17 @@ packages: - libzlib >=1.3.1,<2.0a0 - openssl >=3.3.2,<4.0a0 - tk >=8.6.13,<8.7.0a0 + - tzdata - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 - xz >=5.2.6,<6.0a0 constrains: - - python_abi 3.8.* *_cp38 + - python_abi 3.9.* *_cp39 license: Python-2.0 purls: [] - size: 16152994 - timestamp: 1727719830490 + size: 17024927 + timestamp: 1727718943163 - kind: conda name: python version: 3.12.7 @@ -5357,68 +5368,68 @@ packages: timestamp: 1709299922152 - kind: conda name: python_abi - version: '3.8' - build: 5_cp38 + version: '3.9' + build: 5_cp39 build_number: 5 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.8-5_cp38.conda - sha256: 2be05be156f72ed7dc9569046396781cc9d818fbc03532acbf822afa65869d71 - md5: 7caf714d16205dca32687a95ae71a472 + url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.9-5_cp39.conda + sha256: 019e2f8bca1d1f1365fbb9965cd95bb395c92c89ddd03165db82f5ae89a20812 + md5: 40363a30db350596b5f225d0d5a33328 constrains: - - python 3.8.* *_cpython + - python 3.9.* *_cpython license: BSD-3-Clause license_family: BSD purls: [] - size: 6196 - timestamp: 1723823402019 + size: 6193 + timestamp: 1723823354399 - kind: conda name: python_abi - version: '3.8' - build: 5_cp38 + version: '3.9' + build: 5_cp39 build_number: 5 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.8-5_cp38.conda - sha256: 38eafb1fed264b24fe927d919ffdbdbcdee686c20b3e270d0ebc4d378a4d0a6d - md5: 2d34276cb27b093e962a8b27b62e2e05 + url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.9-5_cp39.conda + sha256: 18224feb9a5ffb1ad5ae8eac21496f399befce29aeaaf929fff44dc827e9ac16 + md5: 09ac18c0db8f06c3913fa014ec016849 constrains: - - python 3.8.* *_cpython + - python 3.9.* *_cpython license: BSD-3-Clause license_family: BSD purls: [] - size: 6295 - timestamp: 1723823073518 + size: 6294 + timestamp: 1723823176192 - kind: conda name: python_abi - version: '3.8' - build: 5_cp38 + version: '3.9' + build: 5_cp39 build_number: 5 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.8-5_cp38.conda - sha256: 13dc083232fce647dd09a0e26ca321c656353f67801776b852b0e0684c1dfdef - md5: 1aa0ca8730d24e23aa98fb720813077e + url: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.9-5_cp39.conda + sha256: a942c019a98f4c89bc3a73a6a583f65d1c8fc560ccfdbdd9cba9f5ef719026fb + md5: 1ca4a5e8290873da8963182d9673299d constrains: - - python 3.8.* *_cpython + - python 3.9.* *_cpython license: BSD-3-Clause license_family: BSD purls: [] - size: 6320 - timestamp: 1723823108855 + size: 6326 + timestamp: 1723823464252 - kind: conda name: python_abi - version: '3.8' - build: 5_cp38 + version: '3.9' + build: 5_cp39 build_number: 5 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.8-5_cp38.conda - sha256: 6a4e9ec3351af5a479b63ec6b68ccaede159de463e289f40b0d03109b0d70fa6 - md5: 109f65721058b3e6f602204cededcf4f + url: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.9-5_cp39.conda + sha256: ee9471759ba567d5a4922d4fae95f58a0070db7616cba72e3bfb22cd5c50e37a + md5: 86ba1bbcf9b259d1592201f3c345c810 constrains: - - python 3.8.* *_cpython + - python 3.9.* *_cpython license: BSD-3-Clause license_family: BSD purls: [] - size: 6701 - timestamp: 1723823237432 + size: 6706 + timestamp: 1723823197703 - kind: conda name: python_abi version: '3.12' @@ -5764,83 +5775,83 @@ packages: - kind: conda name: ruff version: 0.3.7 - build: py38h18b4745_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py38h18b4745_0.conda - sha256: b59666fc67254a8c1bf1d75d62bd56e5bf87e1140bb940fbd87b768d0f6ce244 - md5: 0494524514a6abf2a3374da514cb33fb + build: py39h6792c9e_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py39h6792c9e_0.conda + sha256: 2554f156368f9c14c268e955b283529ec4030a7b92630d3dac365c60f310485c + md5: 0698be96b482180bd538ec5cb73244fb depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - libcxx >=16 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + constrains: + - __osx >=10.12 license: MIT license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 6422629 - timestamp: 1712962234140 + size: 6191632 + timestamp: 1712963430287 - kind: conda name: ruff version: 0.3.7 - build: py38h1916ca8_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py38h1916ca8_0.conda - sha256: b06a2159cb231bbbe748709f0a25eb81ae8ae6d11a79e9349ebce3333d0f23b8 - md5: 91b30f3f41b4603b127acd177d3a30e3 + build: py39h756cfbc_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py39h756cfbc_0.conda + sha256: 15a99357df0e007cf33f647f7437742a82d2d72ea99d5b1ab348269ee1aac548 + md5: 4599d398ea355920cdd7da989804b786 depends: - - libcxx >=16 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - constrains: - - __osx >=10.12 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 license: MIT license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 6191203 - timestamp: 1712963583220 + size: 6336235 + timestamp: 1712963201277 - kind: conda name: ruff version: 0.3.7 - build: py38h5477e86_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py38h5477e86_0.conda - sha256: d9bababfff82f690c8a6df8edfd29f67f7d0ad43de8b0eb99ef9ee23343d9f07 - md5: 84949ccfe5ca54edc36275a334e80d8d + build: py39h7efa1f9_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py39h7efa1f9_0.conda + sha256: ac725078b89982a7ad3b8408aa28fdd3ddcb8d7c6c7a95122bd0acd36fa378e4 + md5: 078b4b64a101cd6da6b588cd99bd6158 depends: - - libcxx >=16 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 - constrains: - - __osx >=11.0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 license: MIT license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 5874349 - timestamp: 1712963888097 + size: 6419219 + timestamp: 1712962310889 - kind: conda name: ruff version: 0.3.7 - build: py38h5e48be7_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py38h5e48be7_0.conda - sha256: e4adb95a8e09adec41676ab6829ff555108277f2ddd0a2a2ba76ae61fda64453 - md5: 1568e1b6ab7d3e97ee6e64b9ad5206da + build: py39hd984c07_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py39hd984c07_0.conda + sha256: 4eca0c7815beda29c628414dd030554e8a190a00d40e65add723d1c4187c3205 + md5: c6db9547e4c063ead61ae6ad032998ad depends: - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - libcxx >=16 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 + constrains: + - __osx >=11.0 license: MIT license_family: MIT purls: - pkg:pypi/ruff?source=hash-mapping - size: 6343187 - timestamp: 1712963346969 + size: 5874357 + timestamp: 1712963584766 - kind: conda name: rust version: 1.81.0 @@ -6225,7 +6236,7 @@ packages: url: https://files.pythonhosted.org/packages/c4/83/07c5cd92ead27ecf48e3d12d0164ac0f6a7990b4d0d47c297398c285627a/types_networkx-3.3.0.20241020-py3-none-any.whl sha256: 4e5bd9b2a987d7b31b79c1af8675eae52ec50f634779a130cd9e81b2e94a31bd requires_dist: - - numpy<2.1.0,>=1.20 + - numpy>=1.20,<2.1.0 requires_python: '>=3.8' - kind: conda name: types-requests @@ -7033,91 +7044,95 @@ packages: - kind: conda name: zstandard version: 0.23.0 - build: py38h43bb1b3_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py38h43bb1b3_0.conda - sha256: 14c3139f32c22b61ee4dbf9f4f1e44b445a54505b3e09dd0e41146f40865afe2 - md5: be90d81878902f7c0e7bb2846fbe126c + build: py39h08a7858_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py39h08a7858_1.conda + sha256: 76a45ef349517eaab1492f17f9c807ccbf1971961c6e90d454fbedbed7e257ad + md5: cd9fa334e11886738f17254f52210bc3 depends: - - __osx >=11.0 + - __glibc >=2.17,<3.0.a0 - cffi >=1.11 - - python >=3.8,<3.9.0a0 - - python >=3.8,<3.9.0a0 *_cpython - - python_abi 3.8.* *_cp38 + - libgcc >=13 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - zstd >=1.5.6,<1.5.7.0a0 - zstd >=1.5.6,<1.6.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/zstandard?source=hash-mapping - size: 322221 - timestamp: 1721044445032 + size: 407017 + timestamp: 1725305769438 - kind: conda name: zstandard version: 0.23.0 - build: py38h62bed22_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py38h62bed22_0.conda - sha256: c91d68f07b9909138f19b6bf5acbb1acdd9bc620e4bd4b997514e646584a43ae - md5: 7cdf6cb1dcfbaf868ff42b15189f7e59 + build: py39h9bf74da_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py39h9bf74da_1.conda + sha256: 1446c0495565d6d7b364e0b2021d0309d21a34cb7d6bd19eced1a483fabfb915 + md5: 5f1f0f75ebd24882ccf44d145939b104 depends: - - __glibc >=2.17,<3.0.a0 - cffi >=1.11 - - libgcc-ng >=12 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 - zstd >=1.5.6,<1.5.7.0a0 - zstd >=1.5.6,<1.6.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/zstandard?source=hash-mapping - size: 405783 - timestamp: 1721044145927 + size: 311116 + timestamp: 1725305993710 - kind: conda name: zstandard version: 0.23.0 - build: py38hdb7df32_0 + build: py39hc23f734_1 + build_number: 1 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.23.0-py38hdb7df32_0.conda - sha256: 9bd6178c20b468985784e63e5a5752ba09c23922e9113694bb0c308f035a85aa - md5: be8ae480a2c487987fc4aeda477328dc + url: https://conda.anaconda.org/conda-forge/osx-64/zstandard-0.23.0-py39hc23f734_1.conda + sha256: a854d10abb45924bd96f2fc94ec0693663b928a2c1a9e373b4437e2662ace38b + md5: 5da66224731aea611c4bf331e057f23d depends: - __osx >=10.13 - cffi >=1.11 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 + - python >=3.9,<3.10.0a0 + - python_abi 3.9.* *_cp39 - zstd >=1.5.6,<1.5.7.0a0 - zstd >=1.5.6,<1.6.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/zstandard?source=hash-mapping - size: 401982 - timestamp: 1721044258096 + size: 401328 + timestamp: 1725305650930 - kind: conda name: zstandard version: 0.23.0 - build: py38hf92978b_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py38hf92978b_0.conda - sha256: 1a7dd43fd4d3e667521b2fb3477cd20ef6586c5696c003ef5c6bff01dca37a71 - md5: 98bd13d4c311b4c8402446c93b142f9b + build: py39hcf1bb16_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py39hcf1bb16_1.conda + sha256: c4cb4a1bb5609c16f27a3f4355cddc77e6c0e9e3083340f413f9de9b8266e03f + md5: 8cbaf074d564f304ae7fd29ba39184be depends: + - __osx >=11.0 - cffi >=1.11 - - python >=3.8,<3.9.0a0 - - python_abi 3.8.* *_cp38 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - python >=3.9,<3.10.0a0 + - python >=3.9,<3.10.0a0 *_cpython + - python_abi 3.9.* *_cp39 - zstd >=1.5.6,<1.5.7.0a0 - zstd >=1.5.6,<1.6.0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/zstandard?source=hash-mapping - size: 311395 - timestamp: 1721044412087 + size: 320027 + timestamp: 1725305723442 - kind: conda name: zstd version: 1.5.6 diff --git a/py-rattler/pixi.toml b/py-rattler/pixi.toml index 7ae76ffeb..0e02f6b5e 100644 --- a/py-rattler/pixi.toml +++ b/py-rattler/pixi.toml @@ -25,7 +25,7 @@ patchelf = "~=0.17.2" [feature.test.dependencies] # Python 3.8 is the minimum supported version, so we use that for testing -python = "3.8.*" +python = "3.9.*" ruff = ">=0.3.3,<0.4" mypy = "~=1.5.1" @@ -41,7 +41,7 @@ typer = "*" types-networkx = "*" [feature.test.tasks] -test = { cmd = "pytest --doctest-modules", depends_on = ["build"] } +test = { cmd = "pytest --doctest-modules" } #, depends_on = ["build"] } fmt-python = "ruff format rattler examples tests" fmt-rust = "cargo fmt --all" lint-python = "ruff check ." diff --git a/py-rattler/rattler/networking/client.py b/py-rattler/rattler/networking/client.py index efe58bcfb..6b95dd757 100644 --- a/py-rattler/rattler/networking/client.py +++ b/py-rattler/rattler/networking/client.py @@ -1,6 +1,6 @@ from __future__ import annotations from rattler.rattler import PyClientWithMiddleware -from rattler.networking.middleware import AuthenticationMiddleware, MirrorMiddleware +from rattler.networking.middleware import AuthenticationMiddleware, MirrorMiddleware, OciMiddleware class Client: @@ -8,7 +8,9 @@ class Client: A client that can be used to make requests. """ - def __init__(self, middlewares: list[AuthenticationMiddleware | MirrorMiddleware] | None = None) -> None: + def __init__( + self, middlewares: list[AuthenticationMiddleware | MirrorMiddleware | OciMiddleware] | None = None + ) -> None: self._client = PyClientWithMiddleware( [middleware._middleware for middleware in middlewares] if middlewares else None ) diff --git a/py-rattler/rattler/networking/middleware.py b/py-rattler/rattler/networking/middleware.py index a033d970f..7b099e22d 100644 --- a/py-rattler/rattler/networking/middleware.py +++ b/py-rattler/rattler/networking/middleware.py @@ -1,5 +1,5 @@ from __future__ import annotations -from rattler.rattler import PyMirrorMiddleware, PyAuthenticationMiddleware +from rattler.rattler import PyMirrorMiddleware, PyAuthenticationMiddleware, PyOciMiddleware class MirrorMiddleware: @@ -41,6 +41,10 @@ def __repr__(self) -> str: class AuthenticationMiddleware: + """ + Middleware to handle authentication from keychain + """ + def __init__(self) -> None: self._middleware = PyAuthenticationMiddleware() @@ -61,3 +65,30 @@ def __repr__(self) -> str: ``` """ return f"{type(self).__name__}()" + + +class OciMiddleware: + """ + Middleware to handle `oci://` URLs + """ + + def __init__(self) -> None: + self._middleware = PyOciMiddleware() + + def __repr__(self) -> str: + """ + Returns a representation of the Middleware + + Examples + -------- + ```python + >>> from rattler.networking import Client + >>> middleware = OciMiddleware() + >>> middleware + OciMiddleware() + >>> Client([middleware]) + Client() + >>> + ``` + """ + return f"{type(self).__name__}()" diff --git a/py-rattler/rattler/package/about_json.py b/py-rattler/rattler/package/about_json.py index 4ce54a720..2d2e06c0a 100644 --- a/py-rattler/rattler/package/about_json.py +++ b/py-rattler/rattler/package/about_json.py @@ -103,11 +103,18 @@ def channels(self) -> List[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.channels ['https://conda.anaconda.org/conda-forge'] + >>> about.channels = ['https://test.channel'] + >>> about.channels + ['https://test.channel'] >>> ``` """ return self._inner.channels + @channels.setter + def channels(self, value: List[str]) -> None: + self._inner.channels = value + @property def description(self) -> Optional[str]: """ @@ -119,6 +126,9 @@ def description(self) -> Optional[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.description 'A dummy description.' + >>> about.description = 'New description' + >>> about.description + 'New description' >>> ``` """ @@ -127,6 +137,10 @@ def description(self) -> Optional[str]: return None + @description.setter + def description(self, value: Optional[str]) -> None: + self._inner.description = value + @property def dev_url(self) -> List[str]: """ @@ -138,11 +152,18 @@ def dev_url(self) -> List[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.dev_url ['https://github.com/conda/rattler'] + >>> about.dev_url = ['https://test.dev'] + >>> about.dev_url + ['https://test.dev/'] >>> ``` """ return self._inner.dev_url + @dev_url.setter + def dev_url(self, value: List[str]) -> None: + self._inner.dev_url = value + @property def doc_url(self) -> List[str]: """ @@ -154,11 +175,18 @@ def doc_url(self) -> List[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.doc_url ['https://conda.github.io/rattler/py-rattler/'] + >>> about.doc_url = ['https://test.docs'] + >>> about.doc_url + ['https://test.docs/'] >>> ``` """ return self._inner.doc_url + @doc_url.setter + def doc_url(self, value: List[str]) -> None: + self._inner.doc_url = value + @property def home(self) -> List[str]: """ @@ -170,11 +198,18 @@ def home(self) -> List[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.home ['http://github.com/conda/rattler'] + >>> about.home = ['https://test.home'] + >>> about.home + ['https://test.home/'] >>> ``` """ return self._inner.home + @home.setter + def home(self, value: List[str]) -> None: + self._inner.home = value + @property def license(self) -> Optional[str]: """ @@ -186,6 +221,9 @@ def license(self) -> Optional[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.license 'BSD-3-Clause' + >>> about.license = 'MIT' + >>> about.license + 'MIT' >>> ``` """ @@ -194,6 +232,10 @@ def license(self) -> Optional[str]: return None + @license.setter + def license(self, value: Optional[str]) -> None: + self._inner.license = value + @property def license_family(self) -> Optional[str]: """ @@ -206,6 +248,9 @@ def license_family(self) -> Optional[str]: >>> about.license_family >>> type(about.license_family) + >>> about.license_family = 'BSD' + >>> about.license_family + 'BSD' >>> ``` """ @@ -214,6 +259,10 @@ def license_family(self) -> Optional[str]: return None + @license_family.setter + def license_family(self, value: Optional[str]) -> None: + self._inner.license_family = value + @property def source_url(self) -> Optional[str]: """ @@ -225,6 +274,9 @@ def source_url(self) -> Optional[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.source_url 'https://github.com/conda/rattler' + >>> about.source_url = 'https://test.source' + >>> about.source_url + 'https://test.source/' >>> ``` """ @@ -233,6 +285,10 @@ def source_url(self) -> Optional[str]: return None + @source_url.setter + def source_url(self, value: Optional[str]) -> None: + self._inner.source_url = value + @property def summary(self) -> Optional[str]: """ @@ -244,6 +300,9 @@ def summary(self) -> Optional[str]: >>> about = AboutJson.from_path("../test-data/dummy-about.json") >>> about.summary 'A dummy summary.' + >>> about.summary = 'New summary' + >>> about.summary + 'New summary' >>> ``` """ @@ -252,6 +311,10 @@ def summary(self) -> Optional[str]: return None + @summary.setter + def summary(self, value: Optional[str]) -> None: + self._inner.summary = value + @classmethod def _from_py_about_json(cls, py_about_json: PyAboutJson) -> AboutJson: about_json = cls.__new__(cls) diff --git a/py-rattler/rattler/package/index_json.py b/py-rattler/rattler/package/index_json.py index 16c19ef4f..6690015a0 100644 --- a/py-rattler/rattler/package/index_json.py +++ b/py-rattler/rattler/package/index_json.py @@ -6,6 +6,8 @@ from rattler.package.package_name import PackageName from rattler.rattler import PyIndexJson +from rattler.version.version import Version +from rattler.version.with_source import VersionWithSource class IndexJson: @@ -75,6 +77,32 @@ def package_path() -> str: """ return PyIndexJson.package_path() + @property + def version(self) -> Version: + """ + The version of the package. + + Examples + -------- + ```python + >>> idx_json = IndexJson.from_path( + ... "../test-data/conda-22.11.1-py38haa244fe_1-index.json" + ... ) + >>> idx_json.version + VersionWithSource(version="22.11.1", source="22.11.1") + >>> idx_json.version = VersionWithSource("1.02.3") + >>> idx_json.version + VersionWithSource(version="1.2.3", source="1.02.3") + >>> + ``` + """ + version, source = self._inner.version + return VersionWithSource._from_py_version(version, source) + + @version.setter + def version(self, value: VersionWithSource) -> None: + self._inner.version = (value._version, value._source) + @property def arch(self) -> Optional[str]: """ @@ -96,6 +124,10 @@ def arch(self) -> Optional[str]: return None + @arch.setter + def arch(self, value: Optional[str]) -> None: + self._inner.arch = value + @property def build(self) -> str: """ @@ -114,6 +146,10 @@ def build(self) -> str: """ return self._inner.build + @build.setter + def build(self, value: str) -> None: + self._inner.build = value + @property def build_number(self) -> int: """ @@ -133,6 +169,10 @@ def build_number(self) -> int: """ return self._inner.build_number + @build_number.setter + def build_number(self, value: int) -> None: + self._inner.build_number = value + @property def constrains(self) -> List[str]: """ @@ -151,6 +191,10 @@ def constrains(self) -> List[str]: """ return self._inner.constrains + @constrains.setter + def constrains(self, value: List[str]) -> None: + self._inner.constrains = value + @property def depends(self) -> List[str]: """ @@ -169,6 +213,10 @@ def depends(self) -> List[str]: """ return self._inner.depends + @depends.setter + def depends(self, value: List[str]) -> None: + self._inner.set_depends(value) + @property def features(self) -> Optional[str]: """ @@ -191,6 +239,10 @@ def features(self) -> Optional[str]: return None + @features.setter + def features(self, value: Optional[str]) -> None: + self._inner.set_features(value) + @property def license(self) -> Optional[str]: """ @@ -212,6 +264,10 @@ def license(self) -> Optional[str]: return None + @license.setter + def license(self, value: Optional[str]) -> None: + self._inner.set_license(value) + @property def license_family(self) -> Optional[str]: """ @@ -232,6 +288,10 @@ def license_family(self) -> Optional[str]: return None + @license_family.setter + def license_family(self, value: Optional[str]) -> None: + self._inner.set_license_family(value) + @property def name(self) -> PackageName: """ @@ -245,11 +305,18 @@ def name(self) -> PackageName: ... ) >>> idx_json.name PackageName("conda") + >>> idx_json.name = PackageName("rattler") + >>> idx_json.name + PackageName("rattler") >>> ``` """ return PackageName._from_py_package_name(self._inner.name) + @name.setter + def name(self, value: PackageName) -> None: + self._inner.name = value._name + @property def platform(self) -> Optional[str]: """ @@ -271,6 +338,10 @@ def platform(self) -> Optional[str]: return None + @platform.setter + def platform(self, value: Optional[str]) -> None: + self._inner.set_platform(value) + @property def subdir(self) -> Optional[str]: """ @@ -292,6 +363,10 @@ def subdir(self) -> Optional[str]: return None + @subdir.setter + def subdir(self, value: Optional[str]) -> None: + self._inner.set_subdir(value) + @property def timestamp(self) -> Optional[datetime.datetime]: """ @@ -305,6 +380,9 @@ def timestamp(self) -> Optional[datetime.datetime]: ... ) >>> idx_json.timestamp datetime.datetime(2022, 12, 7, 23, 45, 42, 50000, tzinfo=datetime.timezone.utc) + >>> idx_json.timestamp = datetime.datetime(2021, 1, 1, 1, 1, 1, 50000, tzinfo=datetime.timezone.utc) + >>> idx_json.timestamp + datetime.datetime(2021, 1, 1, 1, 1, 1, 50000, tzinfo=datetime.timezone.utc) >>> ``` """ @@ -313,6 +391,14 @@ def timestamp(self) -> Optional[datetime.datetime]: return None + @timestamp.setter + def timestamp(self, value: Optional[datetime.datetime]) -> None: + if value is None: + self._inner.timestamp = None + else: + # convert to integer milliseconds + self._inner.timestamp = int(value.timestamp() * 1000.0) + @property def track_features(self) -> List[str]: """ @@ -333,6 +419,10 @@ def track_features(self) -> List[str]: """ return self._inner.track_features + @track_features.setter + def track_features(self, value: List[str]) -> None: + self._inner.set_track_features(value) + @classmethod def _from_py_index_json(cls, py_index_json: PyIndexJson) -> IndexJson: index_json = cls.__new__(cls) diff --git a/py-rattler/rattler/package_streaming/__init__.py b/py-rattler/rattler/package_streaming/__init__.py new file mode 100644 index 000000000..9fb176698 --- /dev/null +++ b/py-rattler/rattler/package_streaming/__init__.py @@ -0,0 +1,26 @@ +from typing import Tuple, Optional +from os import PathLike +from rattler.networking.client import Client + +from rattler.rattler import ( + extract as py_extract, + extract_tar_bz2 as py_extract_tar_bz2, + download_and_extract as py_download_and_extract, +) + + +def extract(path: PathLike[str], dest: PathLike[str]) -> Tuple[bytes, bytes]: + """Extract a file to a destination.""" + return py_extract(path, dest) + + +def extract_tar_bz2(path: PathLike[str], dest: PathLike[str]) -> Tuple[bytes, bytes]: + """Extract a tar.bz2 file to a destination.""" + return py_extract_tar_bz2(path, dest) + + +async def download_and_extract( + client: Client, url: str, dest: PathLike[str], expected_sha: Optional[bytes] = None +) -> Tuple[bytes, bytes]: + """Download a file from a URL and extract it to a destination.""" + return await py_download_and_extract(client._client, url, dest, expected_sha) diff --git a/py-rattler/src/about_json.rs b/py-rattler/src/about_json.rs index 54709ba1c..c95f9b3be 100644 --- a/py-rattler/src/about_json.rs +++ b/py-rattler/src/about_json.rs @@ -79,12 +79,22 @@ impl PyAboutJson { self.inner.channels.clone() } + #[setter] + pub fn set_channels(&mut self, value: Vec) { + self.inner.channels = value; + } + /// Description of the package #[getter] pub fn description(&self) -> Option { self.inner.description.clone() } + #[setter] + pub fn set_description(&mut self, value: Option) { + self.inner.description = value; + } + /// URL to the development page of the package #[getter] pub fn dev_url(&self) -> Vec { @@ -96,6 +106,11 @@ impl PyAboutJson { .collect() } + #[setter] + pub fn set_dev_url(&mut self, value: Vec) { + self.inner.dev_url = value.into_iter().map(|url| url.parse().unwrap()).collect(); + } + /// URL to the documentation of the package #[getter] pub fn doc_url(&self) -> Vec { @@ -107,6 +122,11 @@ impl PyAboutJson { .collect() } + #[setter] + pub fn set_doc_url(&mut self, value: Vec) { + self.inner.doc_url = value.into_iter().map(|url| url.parse().unwrap()).collect(); + } + /// URL to the homepage of the package #[getter] pub fn home(&self) -> Vec { @@ -118,27 +138,52 @@ impl PyAboutJson { .collect() } + #[setter] + pub fn set_home(&mut self, value: Vec) { + self.inner.home = value.into_iter().map(|url| url.parse().unwrap()).collect(); + } + /// Optionally, the license #[getter] pub fn license(&self) -> Option { self.inner.license.clone() } + #[setter] + pub fn set_license(&mut self, value: Option) { + self.inner.license = value; + } + /// Optionally, the license family #[getter] pub fn license_family(&self) -> Option { self.inner.license_family.clone() } + #[setter] + pub fn set_license_family(&mut self, value: Option) { + self.inner.license_family = value; + } + /// URL to the latest source code of the package #[getter] pub fn source_url(&self) -> Option { self.inner.source_url.clone().map(|v| v.to_string()) } + #[setter] + pub fn set_source_url(&mut self, value: Option) { + self.inner.source_url = value.map(|url| url.parse().unwrap()); + } + /// Short summary description #[getter] pub fn summary(&self) -> Option { self.inner.summary.clone() } + + #[setter] + pub fn set_summary(&mut self, value: Option) { + self.inner.summary = value; + } } diff --git a/py-rattler/src/index_json.rs b/py-rattler/src/index_json.rs index 45c68c2fb..503582950 100644 --- a/py-rattler/src/index_json.rs +++ b/py-rattler/src/index_json.rs @@ -1,10 +1,13 @@ use std::path::PathBuf; use pyo3::{pyclass, pymethods, PyResult}; -use rattler_conda_types::package::{IndexJson, PackageFile}; +use rattler_conda_types::{ + package::{IndexJson, PackageFile}, + VersionWithSource, +}; use rattler_package_streaming::seek::read_package_file; -use crate::{error::PyRattlerError, package_name::PyPackageName}; +use crate::{error::PyRattlerError, package_name::PyPackageName, version::PyVersion}; #[pyclass] #[repr(transparent)] @@ -85,30 +88,55 @@ impl PyIndexJson { self.inner.arch.clone() } + #[setter] + pub fn set_arch(&mut self, arch: Option) { + self.inner.arch = arch; + } + /// The build string of the package. #[getter] pub fn build(&self) -> String { self.inner.build.clone() } + #[setter] + pub fn set_build(&mut self, build: String) { + self.inner.build = build; + } + /// The build number of the package. This is also included in the build string. #[getter] pub fn build_number(&self) -> u64 { self.inner.build_number } + #[setter] + pub fn set_build_number(&mut self, build_number: u64) { + self.inner.build_number = build_number; + } + /// The package constraints of the package #[getter] pub fn constrains(&self) -> Vec { self.inner.constrains.clone() } + #[setter] + pub fn set_constrains(&mut self, constrains: Vec) { + self.inner.constrains = constrains; + } + /// The dependencies of the package #[getter] pub fn depends(&self) -> Vec { self.inner.depends.clone() } + #[setter] + pub fn set_depends(&mut self, depends: Vec) { + self.inner.depends = depends; + } + /// Features are a deprecated way to specify different feature sets for the conda solver. This is not /// supported anymore and should not be used. Instead, `mutex` packages should be used to specify /// mutually exclusive features. @@ -117,43 +145,79 @@ impl PyIndexJson { self.inner.features.clone() } + #[setter] + pub fn set_features(&mut self, features: Option) { + self.inner.features = features; + } + /// Optionally, the license #[getter] pub fn license(&self) -> Option { self.inner.license.clone() } + #[setter] + pub fn set_license(&mut self, license: Option) { + self.inner.license = license; + } + /// Optionally, the license family #[getter] pub fn license_family(&self) -> Option { self.inner.license_family.clone() } + #[setter] + pub fn set_license_family(&mut self, license_family: Option) { + self.inner.license_family = license_family; + } + /// The lowercase name of the package #[getter] pub fn name(&self) -> PyPackageName { self.inner.name.clone().into() } + #[setter] + pub fn set_name(&mut self, name: PyPackageName) { + self.inner.name = name.into(); + } + /// Optionally, the OS the package is build for. #[getter] pub fn platform(&self) -> Option { self.inner.platform.clone() } + #[setter] + pub fn set_platform(&mut self, platform: Option) { + self.inner.platform = platform; + } + /// The subdirectory that contains this package #[getter] pub fn subdir(&self) -> Option { self.inner.subdir.clone() } + #[setter] + pub fn set_subdir(&mut self, subdir: Option) { + self.inner.subdir = subdir; + } + /// The timestamp when this package was created #[getter] pub fn timestamp(&self) -> Option { self.inner.timestamp.map(|time| time.timestamp_millis()) } - /// Track features are nowadays only used to downweight packages (ie. give them less priority). To + #[setter] + pub fn set_timestamp(&mut self, timestamp: Option) { + self.inner.timestamp = + timestamp.map(|ts| chrono::DateTime::from_timestamp_millis(ts).unwrap()); + } + + /// Track features are nowadays only used to downweigh packages (ie. give them less priority). To /// that effect, the number of track features is counted (number of commas) and the package is downweighted /// by the number of track_features. #[getter] @@ -161,9 +225,23 @@ impl PyIndexJson { self.inner.track_features.clone() } + #[setter] + pub fn set_track_features(&mut self, track_features: Vec) { + self.inner.track_features = track_features; + } + /// The version of the package #[getter] - pub fn version(&self) -> String { - self.inner.version.as_str().into_owned() + pub fn version(&self) -> (PyVersion, String) { + ( + self.inner.version.version().clone().into(), + self.inner.version.as_str().to_string(), + ) + } + + #[setter] + pub fn set_version(&mut self, version_and_source: (PyVersion, String)) { + self.inner.version = + VersionWithSource::new(version_and_source.0.inner, version_and_source.1); } } diff --git a/py-rattler/src/lib.rs b/py-rattler/src/lib.rs index 0b333ed4a..ee9e1fdd1 100644 --- a/py-rattler/src/lib.rs +++ b/py-rattler/src/lib.rs @@ -12,6 +12,7 @@ mod nameless_match_spec; mod networking; mod no_arch_type; mod package_name; +mod package_streaming; mod paths_json; mod platform; mod prefix_paths; @@ -50,7 +51,7 @@ use lock::{ use match_spec::PyMatchSpec; use meta::get_rattler_version; use nameless_match_spec::PyNamelessMatchSpec; -use networking::middleware::{PyAuthenticationMiddleware, PyMirrorMiddleware}; +use networking::middleware::{PyAuthenticationMiddleware, PyMirrorMiddleware, PyOciMiddleware}; use networking::{client::PyClientWithMiddleware, py_fetch_repo_data}; use no_arch_type::PyNoArchType; use package_name::PyPackageName; @@ -102,6 +103,7 @@ fn rattler<'py>(py: Python<'py>, m: Bound<'py, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; // Shell activation things @@ -153,6 +155,10 @@ fn rattler<'py>(py: Python<'py>, m: Bound<'py, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(py_install, &m).unwrap())?; m.add_function(wrap_pyfunction!(py_index, &m).unwrap())?; + m.add_function(wrap_pyfunction!(package_streaming::extract_tar_bz2, &m).unwrap())?; + m.add_function(wrap_pyfunction!(package_streaming::extract, &m).unwrap())?; + m.add_function(wrap_pyfunction!(package_streaming::download_and_extract, &m).unwrap())?; + // Explicit environment specification m.add_class::()?; m.add_class::()?; diff --git a/py-rattler/src/networking/client.rs b/py-rattler/src/networking/client.rs index fd2e76265..ae41e6ef0 100644 --- a/py-rattler/src/networking/client.rs +++ b/py-rattler/src/networking/client.rs @@ -1,6 +1,6 @@ use crate::networking::middleware::PyMiddleware; use pyo3::{pyclass, pymethods}; -use rattler_networking::{AuthenticationMiddleware, MirrorMiddleware}; +use rattler_networking::{AuthenticationMiddleware, MirrorMiddleware, OciMiddleware}; use reqwest_middleware::ClientWithMiddleware; #[pyclass] @@ -20,12 +20,11 @@ impl PyClientWithMiddleware { let client = middlewares .into_iter() .fold(client, |client, middleware| match middleware { - PyMiddleware::MirrorMiddleware(middleware) => { - client.with(MirrorMiddleware::from(middleware)) - } - PyMiddleware::AuthenticationMiddleware(middleware) => { + PyMiddleware::Mirror(middleware) => client.with(MirrorMiddleware::from(middleware)), + PyMiddleware::Authentication(middleware) => { client.with(AuthenticationMiddleware::from(middleware)) } + PyMiddleware::Oci(middleware) => client.with(OciMiddleware::from(middleware)), }); let client = client.build(); diff --git a/py-rattler/src/networking/middleware.rs b/py-rattler/src/networking/middleware.rs index 699ab4051..5e3bd75b2 100644 --- a/py-rattler/src/networking/middleware.rs +++ b/py-rattler/src/networking/middleware.rs @@ -1,6 +1,7 @@ use pyo3::{pyclass, pymethods, FromPyObject, PyResult}; use rattler_networking::{ - mirror_middleware::Mirror, AuthenticationMiddleware, AuthenticationStorage, MirrorMiddleware, + mirror_middleware::Mirror, url_with_trailing_slash::UrlWithTrailingSlash, + AuthenticationMiddleware, AuthenticationStorage, MirrorMiddleware, OciMiddleware, }; use std::collections::HashMap; use url::Url; @@ -9,15 +10,16 @@ use crate::error::PyRattlerError; #[derive(FromPyObject)] pub enum PyMiddleware { - MirrorMiddleware(PyMirrorMiddleware), - AuthenticationMiddleware(PyAuthenticationMiddleware), + Mirror(PyMirrorMiddleware), + Authentication(PyAuthenticationMiddleware), + Oci(PyOciMiddleware), } #[pyclass] #[repr(transparent)] #[derive(Clone)] pub struct PyMirrorMiddleware { - pub(crate) inner: HashMap>, + pub(crate) inner: HashMap>, } #[pymethods] @@ -32,7 +34,7 @@ impl PyMirrorMiddleware { .map(|url| { Url::parse(&url) .map(|url| Mirror { - url, + url: url.into(), no_zstd: false, no_bz2: false, no_jlap: false, @@ -41,7 +43,7 @@ impl PyMirrorMiddleware { .map_err(PyRattlerError::from) }) .collect::, PyRattlerError>>()?; - map.insert(key, value); + map.insert(key.into(), value); } Ok(Self { inner: map }) @@ -72,3 +74,22 @@ impl From for AuthenticationMiddleware { AuthenticationMiddleware::new(AuthenticationStorage::default()) } } + +#[pyclass] +#[repr(transparent)] +#[derive(Clone)] +pub struct PyOciMiddleware {} + +#[pymethods] +impl PyOciMiddleware { + #[new] + pub fn __init__() -> Self { + Self {} + } +} + +impl From for OciMiddleware { + fn from(_value: PyOciMiddleware) -> Self { + OciMiddleware + } +} diff --git a/py-rattler/src/package_streaming/mod.rs b/py-rattler/src/package_streaming/mod.rs new file mode 100644 index 000000000..6c8a5f769 --- /dev/null +++ b/py-rattler/src/package_streaming/mod.rs @@ -0,0 +1,82 @@ +use pyo3::{prelude::*, types::PyBytes}; +use pyo3_async_runtimes::tokio::future_into_py; +use pyo3_file::PyFileLikeObject; +use rattler_package_streaming::ExtractResult; +use std::path::{Path, PathBuf}; +use url::Url; + +use crate::{networking::client::PyClientWithMiddleware, utils::sha256_from_pybytes}; + +fn convert_result(py: Python<'_>, result: ExtractResult) -> (PyObject, PyObject) { + let sha256_bytes = PyBytes::new_bound(py, &result.sha256); + let md5_bytes = PyBytes::new_bound(py, &result.md5); + + (sha256_bytes.into(), md5_bytes.into()) +} + +#[pyfunction] +pub fn extract_tar_bz2( + py: Python<'_>, + reader: PyObject, + destination: String, +) -> PyResult<(PyObject, PyObject)> { + // Convert Python file-like object to Read implementation + let reader = PyFileLikeObject::new(reader)?; + let destination = Path::new(&destination); + + // Call the Rust function + match rattler_package_streaming::read::extract_tar_bz2(reader, destination) { + Ok(result) => Ok(convert_result(py, result)), + Err(e) => Err(PyErr::new::(e.to_string())), + } +} + +#[pyfunction] +pub fn extract( + py: Python<'_>, + source: PathBuf, + destination: PathBuf, +) -> PyResult<(PyObject, PyObject)> { + match rattler_package_streaming::fs::extract(&source, &destination) { + Ok(result) => Ok(convert_result(py, result)), + Err(e) => Err(PyErr::new::(e.to_string())), + } +} + +#[pyfunction] +#[allow(clippy::too_many_arguments)] +#[pyo3(signature = (client, url, destination, expected_sha256=None))] +pub fn download_and_extract<'a>( + py: Python<'a>, + client: PyClientWithMiddleware, + url: String, + destination: PathBuf, + expected_sha256: Option>, +) -> PyResult> { + // Parse URL + let url = Url::parse(&url).map_err(|e| { + PyErr::new::(format!("Invalid URL: {e}")) + })?; + + // Convert SHA256 if provided + let sha256 = expected_sha256 + .map(|b| sha256_from_pybytes(b)) + .transpose()?; + + // Create the async future + let future = async move { + rattler_package_streaming::reqwest::tokio::extract( + client.into(), + url, + &destination, + sha256, + None, + ) + .await + .map(|result| Python::with_gil(|py| convert_result(py, result))) + .map_err(|e| PyErr::new::(e.to_string())) + }; + + // Convert the future to a Python awaitable + future_into_py(py, future) +} diff --git a/py-rattler/tests/unit/test_package_streaming.py b/py-rattler/tests/unit/test_package_streaming.py new file mode 100644 index 000000000..8563dffe4 --- /dev/null +++ b/py-rattler/tests/unit/test_package_streaming.py @@ -0,0 +1,63 @@ +import pytest +from pathlib import Path +from rattler.networking.middleware import MirrorMiddleware, OciMiddleware +from rattler.package_streaming import extract, download_and_extract +from rattler.networking.client import Client + + +def get_test_data() -> Path: + return (Path(__file__).parent / "../../../test-data/test-server/repo/noarch/test-package-0.1-0.tar.bz2").absolute() + + +def test_extract(tmpdir: Path) -> None: + dest = Path(tmpdir) / "extract" + + extract(get_test_data(), dest) + + # sanity check that paths exist + assert (dest / "info").exists() + assert (dest / "info" / "index.json").exists() + assert (dest / "info" / "paths.json").exists() + + +@pytest.mark.asyncio +async def test_download_and_extract(tmpdir: Path) -> None: + dest = Path(tmpdir) / "download_and_extract" + dest.mkdir(parents=True, exist_ok=True) + client = Client() + + await download_and_extract( + client, "https://repo.prefix.dev/conda-forge/noarch/boltons-24.0.0-pyhd8ed1ab_0.conda", dest + ) + + # sanity check that paths exist + assert (dest / "info").exists() + assert (dest / "info" / "index.json").exists() + assert (dest / "info" / "paths.json").exists() + assert (dest / "site-packages/boltons-24.0.0.dist-info").exists() + + +@pytest.mark.asyncio +# @pytest.mark.xfail(reason="Github currently requires a PAT to get a token?") +async def test_download_from_oci(tmpdir: Path) -> None: + dest = Path(tmpdir) / "destination" + # Note: the order of middlewares matters here! The OCI middleware must come after the mirror middleware. + client = Client( + [ + # TODO somehow these URLs are very susceptible to missing last / + # Maybe we can use the new ChannelURL type or one of these. + MirrorMiddleware({"https://conda.anaconda.org/conda-forge": ["oci://ghcr.io/channel-mirrors/conda-forge"]}), + OciMiddleware(), + ] + ) + + expected_sha = bytes.fromhex("e44d07932306392372411ab1261670a552f96077f925af00c1559a18a73a1bdc") + await download_and_extract( + client, "https://conda.anaconda.org/conda-forge/noarch/boltons-24.0.0-pyhd8ed1ab_0.conda", dest, expected_sha + ) + + # sanity check that paths exist + assert (dest / "info").exists() + assert (dest / "info" / "index.json").exists() + assert (dest / "info" / "paths.json").exists() + assert (dest / "site-packages/boltons-24.0.0.dist-info").exists()