From c039e40331f99ca0b43249b963a90e3598da8d9a Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Fri, 22 Mar 2024 16:28:44 +0100 Subject: [PATCH 01/22] wip: editable installs --- Cargo.lock | 1 + Cargo.toml | 1 + src/lock_file/mod.rs | 1 + src/lock_file/pypi_editables.rs | 63 +++++++++++++++++++++++++++++++ src/project/manifest/python.rs | 66 +++++++++++++++++++++++++-------- 5 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 src/lock_file/pypi_editables.rs diff --git a/Cargo.lock b/Cargo.lock index 623586aba2..3cb5367228 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3059,6 +3059,7 @@ dependencies = [ "rattler_solve", "rattler_virtual_packages", "regex", + "requirements-txt", "reqwest", "reqwest-middleware", "reqwest-retry 0.4.0", diff --git a/Cargo.toml b/Cargo.toml index 47bfb35ccd..29d5f48a5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ rattler_solve = { version = "0.20.3", default-features = false, features = [ ] } rattler_virtual_packages = { version = "0.19.4", default-features = false } regex = "1.10.3" +requirements-txt = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } reqwest = { version = "0.11.27", default-features = false } reqwest-middleware = "0.2.5" reqwest-retry = "0.4.0" diff --git a/src/lock_file/mod.rs b/src/lock_file/mod.rs index ec716d0dd5..765750293b 100644 --- a/src/lock_file/mod.rs +++ b/src/lock_file/mod.rs @@ -2,6 +2,7 @@ mod outdated; mod package_identifier; +mod pypi_editables; mod records_by_name; mod resolve; mod satisfiability; diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs new file mode 100644 index 0000000000..07d5f79b08 --- /dev/null +++ b/src/lock_file/pypi_editables.rs @@ -0,0 +1,63 @@ +use std::path::Path; + +use distribution_types::LocalEditable; +use platform_tags::Tags; +use requirements_txt::EditableRequirement; +use uv_cache::Cache; +use uv_client::RegistryClient; +use uv_dispatch::BuildDispatch; +use uv_installer::{BuiltEditable, Downloader}; +use uv_interpreter::Interpreter; + +use crate::uv_reporter::{UvReporter, UvReporterOptions}; + +/// TODO: remove this type when the uv error is exposed in the public API. +#[derive(thiserror::Error, Debug)] +pub enum BuildEditablesError { + #[error("Failed to build editables: {source}")] + DownloadError { source: Box }, +} + +/// Build a set of editable distributions. +#[allow(clippy::too_many_arguments)] +pub async fn build_editables( + editables: &[EditableRequirement], + editable_wheel_dir: &Path, + cache: &Cache, + interpreter: &Interpreter, + tags: &Tags, + client: &RegistryClient, + build_dispatch: &BuildDispatch<'_>, +) -> Result, BuildEditablesError> { + let options = UvReporterOptions::new() + .with_length(editables.len() as u64) + .with_capacity(editables.len() + 30) + .with_starting_tasks(editables.iter().map(|d| format!("{}", d.path.display()))) + .with_top_level_message("Resolving editables"); + + let downloader = Downloader::new(cache, tags, client, build_dispatch) + .with_reporter(UvReporter::new(options)); + + let editables: Vec = editables + .iter() + .map(|editable| { + let EditableRequirement { url, extras, path } = editable; + Ok(LocalEditable { + url: url.clone(), + extras: extras.clone(), + path: path.clone(), + }) + }) + .collect::>()?; + + let editables: Vec<_> = downloader + .build_editables(editables, editable_wheel_dir) + .await + .map_err(|e| BuildEditablesError::DownloadError { + source: Box::new(e), + })? + .into_iter() + .collect(); + + Ok(editables) +} diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index 5981829ff3..aeac3f189e 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -308,6 +308,29 @@ pub enum AsPep508Error { }, } +pub enum RequirementOrEditable { + Editable(requirements_txt::EditableRequirement), + Pep508Requirement(pep508_rs::Requirement), +} + +impl RequirementOrEditable { + /// Returns an editable requirement if it is an editable requirement. + pub fn editable(&self) -> Option<&requirements_txt::EditableRequirement> { + match self { + RequirementOrEditable::Editable(e) => Some(e), + _ => None, + } + } + + /// Returns a pep508 requirement if it is a pep508 requirement. + pub fn requirement(&self) -> Option<&pep508_rs::Requirement> { + match self { + RequirementOrEditable::Pep508Requirement(e) => Some(e), + _ => None, + } + } +} + impl PyPiRequirement { pub fn extras(&self) -> &[ExtraName] { match self { @@ -324,16 +347,16 @@ impl PyPiRequirement { &self, name: &PackageName, project_root: &Path, - ) -> Result { - let version_or_url = match self { + ) -> Result { + let (version_or_url, editable) = match self { PyPiRequirement::Version { version, index: _, extras: _, - } => version.clone().into(), + } => (version.clone().into(), false), PyPiRequirement::Path { path, - editable: _, + editable, extras: _, } => { let joined = project_root.join(path); @@ -347,7 +370,10 @@ impl PyPiRequirement { .map(|s| s.to_owned()) .unwrap_or_else(String::new); let verbatim = VerbatimUrl::from_path(canonicalized).with_given(given); - Some(pep508_rs::VersionOrUrl::Url(verbatim)) + ( + Some(pep508_rs::VersionOrUrl::Url(verbatim)), + editable.unwrap_or_default(), + ) } PyPiRequirement::Git { git, @@ -367,20 +393,28 @@ impl PyPiRequirement { url: git.to_string(), } })?; - Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url(uv_url))) + ( + Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url(uv_url))), + false, + ) } - PyPiRequirement::Url { url, extras: _ } => Some(pep508_rs::VersionOrUrl::Url( - VerbatimUrl::from_url(url.clone()), - )), - PyPiRequirement::RawVersion(version) => version.clone().into(), + PyPiRequirement::Url { url, extras: _ } => ( + Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url( + url.clone(), + ))), + false, + ), + PyPiRequirement::RawVersion(version) => (version.clone().into(), false), }; - Ok(pep508_rs::Requirement { - name: name.clone(), - extras: self.extras().to_vec(), - version_or_url, - marker: None, - }) + Ok(RequirementOrEditable::Pep508Requirement( + pep508_rs::Requirement { + name: name.clone(), + extras: self.extras().to_vec(), + version_or_url, + marker: None, + }, + )) } } From 7a8c73bfb61a32e3290664322251bf1e6cc6125d Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 25 Mar 2024 12:10:20 +0100 Subject: [PATCH 02/22] wip: integration of editables --- src/lock_file/pypi_editables.rs | 4 +--- src/lock_file/resolve.rs | 24 ++++++++++++++++++++++-- src/lock_file/satisfiability.rs | 4 ++-- src/project/manifest/python.rs | 16 ++++++++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs index 07d5f79b08..578fc16a12 100644 --- a/src/lock_file/pypi_editables.rs +++ b/src/lock_file/pypi_editables.rs @@ -7,7 +7,6 @@ use uv_cache::Cache; use uv_client::RegistryClient; use uv_dispatch::BuildDispatch; use uv_installer::{BuiltEditable, Downloader}; -use uv_interpreter::Interpreter; use crate::uv_reporter::{UvReporter, UvReporterOptions}; @@ -24,7 +23,6 @@ pub async fn build_editables( editables: &[EditableRequirement], editable_wheel_dir: &Path, cache: &Cache, - interpreter: &Interpreter, tags: &Tags, client: &RegistryClient, build_dispatch: &BuildDispatch<'_>, @@ -33,7 +31,7 @@ pub async fn build_editables( .with_length(editables.len() as u64) .with_capacity(editables.len() + 30) .with_starting_tasks(editables.iter().map(|d| format!("{}", d.path.display()))) - .with_top_level_message("Resolving editables"); + .with_top_level_message("Building editables"); let downloader = Downloader::new(cache, tags, client, build_dispatch) .with_reporter(UvReporter::new(options)); diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index 2a240c9c12..0dbc109e6b 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -4,6 +4,7 @@ use crate::config::get_cache_dir; use crate::consts::PROJECT_MANIFEST; +use crate::project::manifest::python::RequirementOrEditable; use crate::uv_reporter::{UvReporter, UvReporterOptions}; use std::collections::{BTreeMap, HashMap}; use std::future::{ready, Future}; @@ -241,7 +242,8 @@ pub async fn resolve_pypi( } // Get the Pypi requirements - let requirements = dependencies + // partion the requirements into editable and non-editable requirements + let (editables, requirements): (Vec<_>, Vec<_>) = dependencies .iter() .flat_map(|(name, req)| req.iter().map(move |req| (name, req))) .map(|(name, req)| { @@ -252,7 +254,25 @@ pub async fn resolve_pypi( name )) }) - .collect::>>()?; + .collect::>>()? + .into_iter() + .partition(|req| matches!(req, RequirementOrEditable::Editable(_))); + + let _editables = editables + .into_iter() + .map(|req| { + req.into_editable() + .expect("wrong partitioning of editable and non-editable requirements") + }) + .collect::>(); + + let requirements = requirements + .into_iter() + .map(|req| { + req.into_requirement() + .expect("wrong partitioning of editable and non-editable requirements") + }) + .collect::>(); // Determine the python interpreter that is installed as part of the conda packages. let python_record = locked_conda_records diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index 3a47fdf521..a1f0377b58 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -1,5 +1,5 @@ use super::{PypiRecord, PypiRecordsByName, RepoDataRecordsByName}; -use crate::project::manifest::python::AsPep508Error; +use crate::project::manifest::python::{AsPep508Error, RequirementOrEditable}; use crate::{project::Environment, pypi_marker_env::determine_marker_environment}; use distribution_types::DirectGitUrl; use itertools::Itertools; @@ -154,7 +154,7 @@ pub fn verify_platform_satisfiability( enum Dependency { Conda(MatchSpec, Cow<'static, str>), - PyPi(Requirement, Cow<'static, str>), + PyPi(RequirementOrEditable, Cow<'static, str>), } /// Check satatisfiability of a pypi requirement against a locked pypi package diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index aeac3f189e..816a513723 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -314,6 +314,22 @@ pub enum RequirementOrEditable { } impl RequirementOrEditable { + /// Returns an editable requirement if it is an editable requirement. + pub fn into_editable(self) -> Option { + match self { + RequirementOrEditable::Editable(e) => Some(e), + _ => None, + } + } + + /// Returns a pep508 requirement if it is a pep508 requirement. + pub fn into_requirement(self) -> Option { + match self { + RequirementOrEditable::Pep508Requirement(e) => Some(e), + _ => None, + } + } + /// Returns an editable requirement if it is an editable requirement. pub fn editable(&self) -> Option<&requirements_txt::EditableRequirement> { match self { From 61a2a8782af0e2f7595db58c38a5be269ba8f6ef Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 25 Mar 2024 13:11:32 +0100 Subject: [PATCH 03/22] feat: added editable to resolve --- src/lock_file/pypi_editables.rs | 4 +++- src/lock_file/resolve.rs | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs index 578fc16a12..b69871e045 100644 --- a/src/lock_file/pypi_editables.rs +++ b/src/lock_file/pypi_editables.rs @@ -14,7 +14,9 @@ use crate::uv_reporter::{UvReporter, UvReporterOptions}; #[derive(thiserror::Error, Debug)] pub enum BuildEditablesError { #[error("Failed to build editables: {source}")] - DownloadError { source: Box }, + DownloadError { + source: Box, + }, } /// Build a set of editable distributions. diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index 0dbc109e6b..10e307387a 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -4,6 +4,7 @@ use crate::config::get_cache_dir; use crate::consts::PROJECT_MANIFEST; +use crate::lock_file::pypi_editables::build_editables; use crate::project::manifest::python::RequirementOrEditable; use crate::uv_reporter::{UvReporter, UvReporterOptions}; use std::collections::{BTreeMap, HashMap}; @@ -38,6 +39,7 @@ use rattler_solve::{resolvo, SolverImpl}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; +use tempfile::tempdir; use url::Url; use uv_cache::Cache; use uv_client::{Connectivity, FlatIndex, FlatIndexClient, RegistryClient, RegistryClientBuilder}; @@ -258,7 +260,7 @@ pub async fn resolve_pypi( .into_iter() .partition(|req| matches!(req, RequirementOrEditable::Editable(_))); - let _editables = editables + let editables = editables .into_iter() .map(|req| { req.into_editable() @@ -335,6 +337,22 @@ pub async fn resolve_pypi( }) .collect(); + // Build any editables + let built_wheel_dir = tempdir().into_diagnostic()?; + let built_editables = build_editables( + &editables, + built_wheel_dir.path(), + &context.cache, + &tags, + &context.registry_client, + &build_dispatch, + ) + .await + .into_diagnostic()? + .into_iter() + .map(|built| (built.editable, built.metadata)) + .collect_vec(); + let manifest = Manifest::new( requirements, // Vec::new(), @@ -342,7 +360,7 @@ pub async fn resolve_pypi( Vec::new(), Vec::new(), None, - Vec::new(), + built_editables, ); let fallback_provider = DefaultResolverProvider::new( From 186b933af2d108c927fd4592a3d524413631a992 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Mon, 25 Mar 2024 16:35:38 +0100 Subject: [PATCH 04/22] fix: satisfiability of editables --- Cargo.lock | 18 ---- Cargo.toml | 40 +++---- src/lock_file/pypi.rs | 123 --------------------- src/lock_file/resolve.rs | 73 ++++++++++--- src/lock_file/satisfiability.rs | 183 +++++++++++++++++++++++++++----- src/project/manifest/python.rs | 82 +++++++++----- 6 files changed, 292 insertions(+), 227 deletions(-) delete mode 100644 src/lock_file/pypi.rs diff --git a/Cargo.lock b/Cargo.lock index 3cb5367228..de54196084 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3418,8 +3418,6 @@ dependencies = [ [[package]] name = "rattler_conda_types" version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7acf750b29293ec00a014cc3b2f91ff619b0ea83127c8c193bd810a034a294" dependencies = [ "chrono", "fxhash", @@ -3448,8 +3446,6 @@ dependencies = [ [[package]] name = "rattler_digest" version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a15f14fa0e0fdf3fbacabd21d66a3d6b15af5c7c0cda2e0e29bd6605dec4569" dependencies = [ "blake2", "digest", @@ -3464,8 +3460,6 @@ dependencies = [ [[package]] name = "rattler_lock" version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c48b23055c2e967a248b83ee0b0d35d05cac174871fc8fa497687906083956" dependencies = [ "chrono", "fxhash", @@ -3488,8 +3482,6 @@ dependencies = [ [[package]] name = "rattler_macros" version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6c3aedd4fa6a50b41be9537c8abc7190ae24f1b0add0ab722275fa0ec8d6d" dependencies = [ "quote", "syn 2.0.53", @@ -3498,8 +3490,6 @@ dependencies = [ [[package]] name = "rattler_networking" version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0b9354421a0725078dfd1ba787269578a7c1121fe9a859818f8eb57fecb0b6" dependencies = [ "anyhow", "async-trait", @@ -3556,8 +3546,6 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e868842aa1bbb62e1a0c807db51e704a59901e0b4475c488595c6a05d1b5bb99" dependencies = [ "anyhow", "async-compression", @@ -3596,8 +3584,6 @@ dependencies = [ [[package]] name = "rattler_shell" version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb968709e81a30534702dad7a134f4a8c03f610946d31a1af83a6b4d81f7d377" dependencies = [ "enum_dispatch", "indexmap 2.2.5", @@ -3614,8 +3600,6 @@ dependencies = [ [[package]] name = "rattler_solve" version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4737459f58dec612af0f9145d164b0c92e4c615b3c670bc30d545834292a0c1" dependencies = [ "anyhow", "chrono", @@ -3635,8 +3619,6 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" version = "0.19.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4f8e1cc39a9052fe8d03375413659ce001c83297d797355f29be706183b0bef" dependencies = [ "cfg-if", "libloading", diff --git a/Cargo.toml b/Cargo.toml index 29d5f48a5a..365ce59d52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -160,6 +160,26 @@ toml = "0.8.12" pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# deno_task_shell = { path = "../deno_task_shell" } +# rattler = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_conda_types = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_digest = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_lock = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_networking = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_repodata_gateway = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_shell = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_solve = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_virtual_packages = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } + +rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } +rattler_digest = { path = "../rattler/crates/rattler_digest" } +rattler_networking = { path = "../rattler/crates/rattler_networking" } +rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } +rattler_shell = { path = "../rattler/crates/rattler_shell" } +rattler_solve = { path = "../rattler/crates/rattler_solve" } +rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } +rattler_lock = { path = "../rattler/crates/rattler_lock" } + # Change these lines if you want a patched version of uv [patch.'https://github.com/astral-sh/uv'] pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } @@ -179,23 +199,3 @@ install-wheel-rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks platform-tags = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } pypi-types = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } requirements-txt = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } - -# deno_task_shell = { path = "../deno_task_shell" } -# rattler = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_conda_types = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_digest = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_lock = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_networking = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_repodata_gateway = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_shell = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_solve = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_virtual_packages = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } - -# rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } -# rattler_digest = { path = "../rattler/crates/rattler_digest" } -# rattler_networking = { path = "../rattler/crates/rattler_networking" } -# rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } -# rattler_shell = { path = "../rattler/crates/rattler_shell" } -# rattler_solve = { path = "../rattler/crates/rattler_solve" } -# rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } -# rattler_lock = { path = "../rattler/crates/rattler_lock" } diff --git a/src/lock_file/pypi.rs b/src/lock_file/pypi.rs deleted file mode 100644 index de3cbd5933..0000000000 --- a/src/lock_file/pypi.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::consts::PROJECT_MANIFEST; -use crate::lock_file::{package_identifier, pypi_name_mapping}; -use crate::project::manifest::{PyPiRequirement, SystemRequirements}; -use crate::pypi_marker_env::determine_marker_environment; -use crate::pypi_tags::{is_python_record, project_platform_tags}; -use indexmap::IndexMap; -use itertools::Itertools; -use miette::{Context, IntoDiagnostic}; -use rattler_conda_types::{Platform, RepoDataRecord}; -use rip::index::PackageDb; -use rip::python_env::PythonLocation; -use rip::resolve::solve_options::{ResolveOptions, SDistResolution}; -use rip::resolve::{resolve, PinnedPackage}; -use rip::types::PackageName; -use std::path::Path; -use std::sync::Arc; -use std::{collections::HashMap, vec}; - -/// Resolve python packages for the specified project. -// TODO(nichita): extract in strunct passed args -#[allow(clippy::too_many_arguments)] -pub async fn resolve_dependencies<'db>( - package_db: Arc, - dependencies: IndexMap>, - system_requirements: SystemRequirements, - platform: Platform, - conda_packages: &[RepoDataRecord], - python_location: Option<&Path>, - sdist_resolution: SDistResolution, - env_variables: HashMap, -) -> miette::Result> { - if dependencies.is_empty() { - return Ok(vec![]); - } - - // Determine the python packages that are installed by the conda packages - let conda_python_packages = - package_identifier::PypiPackageIdentifier::from_records(conda_packages) - .into_diagnostic() - .context("failed to extract python packages from conda metadata")? - .into_iter() - .map(PinnedPackage::from) - .collect_vec(); - - if !conda_python_packages.is_empty() { - tracing::info!( - "the following python packages are assumed to be installed by conda: {conda_python_packages}", - conda_python_packages = - conda_python_packages - .iter() - .format_with(", ", |p, f| f(&format_args!( - "{name} {version}", - name = &p.name, - version = &p.version - ))) - ); - } else { - tracing::info!("there are no python packages installed by conda"); - } - - // Determine the python interpreter that is installed as part of the conda packages. - let python_record = conda_packages - .iter() - .find(|r| is_python_record(r)) - .ok_or_else(|| miette::miette!("could not resolve pypi dependencies because no python interpreter is added to the dependencies of the project.\nMake sure to add a python interpreter to the [dependencies] section of the {PROJECT_MANIFEST}, or run:\n\n\tpixi add python"))?; - - // Determine the environment markers - let marker_environment = determine_marker_environment(platform, python_record.as_ref())?; - - // Determine the compatible tags - let compatible_tags = - project_platform_tags(platform, &system_requirements, python_record.as_ref()); - - let requirements = dependencies - .iter() - .flat_map(|(name, req)| req.iter().map(move |req| (name, req))) - .map(|(name, req)| req.as_pep508(name)) - .collect::>(); - - // If we only have a system python - // we cannot resolve correctly, because we might not be able to - // build source dists correctly. Let's skip them for now - let (sdist_resolution, python_location) = match python_location { - Some(path) => (sdist_resolution, PythonLocation::Custom(path.to_path_buf())), - // Use the resolution we have been passed in - None => (sdist_resolution, PythonLocation::System), - }; - - // Resolve the PyPi dependencies - let mut result = resolve( - package_db, - &requirements, - Arc::new(marker_environment), - Some(Arc::new(compatible_tags)), - conda_python_packages - .into_iter() - .map(|p| (p.name.clone(), p)) - .collect(), - HashMap::default(), - ResolveOptions { - sdist_resolution, - python_location, - ..Default::default() - }, - env_variables.clone(), - ) - .await - .wrap_err("failed to resolve `pypi-dependencies`, due to underlying error")?; - - // Remove any conda package from the result - result.retain(|p| !p.artifacts.is_empty()); - - Ok(result) -} - -/// Amend the records with pypi purls if they are not present yet. -pub async fn amend_pypi_purls(conda_packages: &mut [RepoDataRecord]) -> miette::Result<()> { - let conda_forge_mapping = pypi_name_mapping::conda_pypi_name_mapping().await?; - for record in conda_packages.iter_mut() { - pypi_name_mapping::amend_pypi_purls(record, conda_forge_mapping)?; - } - Ok(()) -} diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index 10e307387a..01287730f0 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -34,7 +34,9 @@ use pep508_rs::{Requirement, VerbatimUrl}; use pypi_types::Metadata23; use rattler_conda_types::{GenericVirtualPackage, MatchSpec, RepoDataRecord}; use rattler_digest::{parse_digest_from_hex, Md5, Sha256}; -use rattler_lock::{PackageHashes, PypiPackageData, PypiPackageEnvironmentData, UrlOrPath}; +use rattler_lock::{ + PackageHashes, PypiPackageData, PypiPackageEnvironmentData, PypiSourceTreeHashable, UrlOrPath, +}; use rattler_solve::{resolvo, SolverImpl}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -258,7 +260,7 @@ pub async fn resolve_pypi( }) .collect::>>()? .into_iter() - .partition(|req| matches!(req, RequirementOrEditable::Editable(_))); + .partition(|req| matches!(req, RequirementOrEditable::Editable(_, _))); let editables = editables .into_iter() @@ -360,7 +362,7 @@ pub async fn resolve_pypi( Vec::new(), Vec::new(), None, - built_editables, + built_editables.clone(), ); let fallback_provider = DefaultResolverProvider::new( @@ -474,6 +476,7 @@ pub async fn resolve_pypi( version: metadata.version, requires_dist: metadata.requires_dist, requires_python: metadata.requires_python, + editable: false, url_or_path, hash, } @@ -490,9 +493,9 @@ pub async fn resolve_pypi( // Use the precise url if we got it back // otherwise try to construct it from the source - let url_or_path = match source { + let (url_or_path, hash, editable) = match source { SourceDist::Registry(reg) => { - if let Some(url) = url { + let url_or_path = if let Some(url) = url { UrlOrPath::Url(url) } else { match ®.file.url { @@ -502,22 +505,34 @@ pub async fn resolve_pypi( FileLocation::Path(path) => UrlOrPath::Path(path.clone()), _ => todo!("unsupported URL"), } - } + }; + (url_or_path, hash, false) } SourceDist::DirectUrl(direct) => { let url = direct.url.to_url(); - Url::parse(&format!("direct+{url}")) - .expect("could not create direct-url") - .into() + let direct_url = Url::parse(&format!("direct+{url}")) + .expect("could not create direct-url"); + (direct_url.into(), hash, false) } - SourceDist::Git(git) => git.url.to_url().into(), + SourceDist::Git(git) => (git.url.to_url().into(), hash, false), SourceDist::Path(path) => { - // Create the url for the lock file - path.url + // Compute the hash of the package based on the source tree. + let hash = PypiSourceTreeHashable::from_directory(&path.path) + .into_diagnostic() + .context("failed to compute hash of pypi source tree")? + .hash(); + + // Create the url for the lock file. This is based on the passed in URL + // instead of from the source path to copy the path that was passed in from + // the requirement. + let url_or_path = path + .url .given() .map(|path| UrlOrPath::Path(PathBuf::from(path))) // When using a direct url reference like https://foo/bla.whl we do not have a given - .unwrap_or_else(|| path.url.to_url().into()) + .unwrap_or_else(|| path.url.to_url().into()); + + (url_or_path, Some(hash), path.editable) } }; @@ -528,6 +543,7 @@ pub async fn resolve_pypi( requires_python: metadata.requires_python, url_or_path, hash, + editable, } } }; @@ -536,6 +552,37 @@ pub async fn resolve_pypi( locked_packages.push((pypi_package_data, PypiPackageEnvironmentData::default())); } + // Add the editables to the locked packages as well. + for (editable, metadata) in built_editables { + // Compute the hash of the package based on the source tree. + let hash = PypiSourceTreeHashable::from_directory(&editable.path) + .into_diagnostic() + .context("failed to compute hash of pypi source tree")? + .hash(); + + // Create the url for the lock file. This is based on the passed in URL + // instead of from the source path to copy the path that was passed in from + // the requirement. + let url_or_path = editable + .url + .given() + .map(|path| UrlOrPath::Path(PathBuf::from(path))) + // When using a direct url reference like https://foo/bla.whl we do not have a given + .unwrap_or_else(|| editable.url.to_url().into()); + + let pypi_package_data = PypiPackageData { + name: metadata.name, + version: metadata.version, + requires_dist: metadata.requires_dist, + requires_python: metadata.requires_python, + url_or_path, + hash: Some(hash), + editable: true, + }; + + locked_packages.push((pypi_package_data, PypiPackageEnvironmentData::default())); + } + Ok(locked_packages) } diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index a1f0377b58..24bde41cfd 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -5,12 +5,13 @@ use distribution_types::DirectGitUrl; use itertools::Itertools; use miette::Diagnostic; use pep440_rs::VersionSpecifiers; -use pep508_rs::Requirement; +use pep508_rs::{Requirement, VersionOrUrl}; use rattler_conda_types::ParseStrictness::Lenient; use rattler_conda_types::{ GenericVirtualPackage, MatchSpec, ParseMatchSpecError, Platform, RepoDataRecord, }; -use rattler_lock::{ConversionError, Package, PypiPackageData, UrlOrPath}; +use rattler_lock::{ConversionError, Package, PypiPackageData, PypiSourceTreeHashable, UrlOrPath}; +use requirements_txt::EditableRequirement; use std::path::Path; use std::str::FromStr; use std::{ @@ -33,7 +34,7 @@ pub enum PlatformUnsat { UnsatisfiableMatchSpec(MatchSpec, String), #[error("the requirement '{0}' could not be satisfied (required by '{1}')")] - UnsatisfiableRequirement(Requirement, String), + UnsatisfiableRequirement(RequirementOrEditable, String), #[error("there was a duplicate entry for '{0}'")] DuplicateEntry(String), @@ -63,6 +64,24 @@ pub enum PlatformUnsat { #[error("when converting {0} into a pep508 requirement")] AsPep508Error(PackageName, #[source] AsPep508Error), + + #[error("editable pypi dependency on conda installed package '{0}' is not supported")] + EditableDependencyOnCondaInstalledPackage(PackageName, EditableRequirement), + + #[error("direct url reference to a conda installed package '{0}' is not supported")] + DirectUrlDependencyOnCondaInstalledPackage(PackageName), + + #[error("locked package {0} should be editable")] + ExpectedEditablePackage(PackageName), + + #[error("locked package {0} should not be editable")] + UnexpectedEditablePackage(PackageName), + + #[error("failed to determine pypi source tree hash for {0}")] + FailedToDetermineSourceTreeHash(PackageName, std::io::Error), + + #[error("source tree hash for {0} does not match the hash in the lock-file")] + SourceTreeHashMismatch(PackageName), } /// Verifies that all the requirements of the specified `environment` can be satisfied with the @@ -159,8 +178,57 @@ enum Dependency { /// Check satatisfiability of a pypi requirement against a locked pypi package /// This also does an additional check for git urls when using direct url references -pub fn pypi_satifisfies(locked_data: &PypiPackageData, spec: &Requirement) -> bool { - // Check if the name matches +pub fn pypi_satifisfies_editable( + locked_data: &PypiPackageData, + spec: &EditableRequirement, +) -> bool { + let spec_url = &spec.url; + + // In the case that both the spec and the locked data are direct git urls + // we need to compare the urls to see if they are the same + let spec_git_url = DirectGitUrl::try_from(&spec_url.to_url()).ok(); + let locked_git_url = locked_data + .url_or_path + .as_url() + .and_then(|url| DirectGitUrl::try_from(url).ok()); + + // Both are git url's + if let (Some(spec_git_url), Some(locked_data_url)) = (spec_git_url, locked_git_url) { + let base_is_same = spec_git_url.url.repository() == locked_data_url.url.repository(); + + // If the spec does not specify a revision than any will do + // E.g `git.com/user/repo` is the same as `git.com/user/repo@adbdd` + if spec_git_url.url.reference().is_none() { + base_is_same + } else { + // If the spec does specify a revision than the revision must match + base_is_same && spec_git_url.url.reference() == locked_data_url.url.reference() + } + } else { + let spec_path_or_url = spec_url + .given() + .and_then(|url| UrlOrPath::from_str(url).ok()) + .unwrap_or(UrlOrPath::Url(spec_url.to_url())); + + // Strip the direct+ prefix if it exists for the direct url + // because this is not part of the `Requirement` spec + // we use this to record that it is a direct url + let locked_path_or_url = match locked_data.url_or_path.clone() { + UrlOrPath::Url(url) => UrlOrPath::Url( + url.as_ref() + .strip_prefix("direct+") + .and_then(|str| Url::parse(str).ok()) + .unwrap_or(url), + ), + UrlOrPath::Path(path) => UrlOrPath::Path(path), + }; + spec_path_or_url == locked_path_or_url + } +} + +/// Check satatisfiability of a pypi requirement against a locked pypi package +/// This also does an additional check for git urls when using direct url references +pub fn pypi_satifisfies_requirement(locked_data: &PypiPackageData, spec: &Requirement) -> bool { if spec.name != locked_data.name { return false; } @@ -168,7 +236,8 @@ pub fn pypi_satifisfies(locked_data: &PypiPackageData, spec: &Requirement) -> bo // Check if the version of the requirement matches match &spec.version_or_url { None => true, - Some(pep508_rs::VersionOrUrl::Url(spec_url)) => { + Some(VersionOrUrl::VersionSpecifier(spec)) => spec.contains(&locked_data.version), + Some(VersionOrUrl::Url(spec_url)) => { // In the case that both the spec and the locked data are direct git urls // we need to compare the urls to see if they are the same let spec_git_url = DirectGitUrl::try_from(&spec_url.to_url()).ok(); @@ -211,9 +280,6 @@ pub fn pypi_satifisfies(locked_data: &PypiPackageData, spec: &Requirement) -> bo spec_path_or_url == locked_path_or_url } } - Some(pep508_rs::VersionOrUrl::VersionSpecifier(spec)) => { - spec.contains(&locked_data.version) - } } } @@ -284,7 +350,7 @@ pub fn verify_package_platform_satisfiability( let mut pypi_requirements_visited = pypi_requirements .iter() .filter_map(|r| match r { - Dependency::PyPi(req, _) => Some(req.clone()), + Dependency::PyPi(RequirementOrEditable::Pep508Requirement(req), _) => Some(req.clone()), _ => None, }) .collect::>(); @@ -363,27 +429,69 @@ pub fn verify_package_platform_satisfiability( Dependency::PyPi(requirement, source) => { // Check if there is a pypi identifier that matches our requirement. if let Some((identifier, repodata_idx, _)) = - locked_conda_pypi_packages.get(&requirement.name) + locked_conda_pypi_packages.get(requirement.name()) { - if identifier.satisfies(&requirement) { - FoundPackage::Conda(*repodata_idx) - } else { - // The record does not match the spec, the lock-file is inconsistent. - return Err(PlatformUnsat::UnsatisfiableRequirement( - requirement, - source.into_owned(), - )); + // Check if the requirement is editable or a pep508 requirement + match requirement { + RequirementOrEditable::Editable(name, req) => { + return Err(PlatformUnsat::EditableDependencyOnCondaInstalledPackage( + name, req, + )); + } + RequirementOrEditable::Pep508Requirement(req) + if matches!(req.version_or_url, Some(VersionOrUrl::Url(_))) => + { + return Err(PlatformUnsat::DirectUrlDependencyOnCondaInstalledPackage( + req.name.clone(), + )); + } + RequirementOrEditable::Pep508Requirement(req) + if !identifier.satisfies(&req) => + { + // The record does not match the spec, the lock-file is inconsistent. + return Err(PlatformUnsat::UnsatisfiableRequirement( + RequirementOrEditable::Pep508Requirement(req), + source.into_owned(), + )); + } + _ => FoundPackage::Conda(*repodata_idx), } - } else if let Some(idx) = locked_pypi_environment.index_by_name(&requirement.name) { + } else if let Some(idx) = locked_pypi_environment.index_by_name(requirement.name()) + { let record = &locked_pypi_environment.records[idx]; - if pypi_satifisfies(&record.0, &requirement) { - FoundPackage::PyPi(idx, requirement.extras) - } else { - // The record does not match the spec, the lock-file is inconsistent. - return Err(PlatformUnsat::UnsatisfiableRequirement( - requirement, - source.into_owned(), - )); + match requirement { + RequirementOrEditable::Editable(package_name, requirement) => { + if !record.0.editable { + return Err(PlatformUnsat::ExpectedEditablePackage( + record.0.name.clone(), + )); + } + + if !pypi_satifisfies_editable(&record.0, &requirement) { + return Err(PlatformUnsat::UnsatisfiableRequirement( + RequirementOrEditable::Editable(package_name, requirement), + source.into_owned(), + )); + } + + FoundPackage::PyPi(idx, requirement.extras) + } + RequirementOrEditable::Pep508Requirement(requirement) => { + if record.0.editable { + return Err(PlatformUnsat::UnexpectedEditablePackage( + record.0.name.clone(), + )); + } + + if !pypi_satifisfies_requirement(&record.0, &requirement) { + return Err(PlatformUnsat::UnsatisfiableRequirement( + RequirementOrEditable::Pep508Requirement(requirement), + source.into_owned(), + )); + } + + FoundPackage::PyPi(idx, requirement.extras) + } } } else { // The record does not match the spec, the lock-file is inconsistent. @@ -422,6 +530,23 @@ pub fn verify_package_platform_satisfiability( }; if pypi_packages_visited.insert(idx) { + // If this is path based package we need to check if the source tree hash still matches. + if let UrlOrPath::Path(path) = &record.0.url_or_path { + let hashable = PypiSourceTreeHashable::from_directory(path) + .map_err(|e| { + PlatformUnsat::FailedToDetermineSourceTreeHash( + record.0.name.clone(), + e, + ) + })? + .hash(); + if Some(hashable) != record.0.hash { + return Err(PlatformUnsat::SourceTreeHashMismatch( + record.0.name.clone(), + )); + } + } + // Ensure that the record matches the currently selected interpreter. if let Some(python_version) = &record.0.requires_python { if !python_version.contains(&marker_environment.python_full_version.version) @@ -451,7 +576,7 @@ pub fn verify_package_platform_satisfiability( } pypi_queue.push(Dependency::PyPi( - requirement.clone(), + RequirementOrEditable::Pep508Requirement(requirement.clone()), record.0.name.as_ref().to_string().into(), )); } diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index 816a513723..23eb0d60cc 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -2,6 +2,7 @@ use pep440_rs::VersionSpecifiers; use pep508_rs::VerbatimUrl; use serde::Serializer; use serde::{de::Error, Deserialize, Deserializer, Serialize}; +use std::fmt::Display; use std::path::{Path, PathBuf}; use std::{fmt, fmt::Formatter, str::FromStr}; use thiserror::Error; @@ -308,16 +309,46 @@ pub enum AsPep508Error { }, } +#[derive(Debug, Clone, Eq, PartialEq)] pub enum RequirementOrEditable { - Editable(requirements_txt::EditableRequirement), + Editable(PackageName, requirements_txt::EditableRequirement), Pep508Requirement(pep508_rs::Requirement), } +impl Display for RequirementOrEditable { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + RequirementOrEditable::Editable(name, req) => { + write!(f, "{} = {:?}", name, req) + } + RequirementOrEditable::Pep508Requirement(req) => { + write!(f, "{}", req) + } + } + } +} + impl RequirementOrEditable { + /// Returns the name of the package that this requirement is for. + pub fn name(&self) -> &PackageName { + match self { + RequirementOrEditable::Editable(name, _) => name, + RequirementOrEditable::Pep508Requirement(req) => &req.name, + } + } + + /// Returns any extras that this requirement has. + pub fn extras(&self) -> &[ExtraName] { + match self { + RequirementOrEditable::Editable(_, req) => &req.extras, + RequirementOrEditable::Pep508Requirement(req) => &req.extras, + } + } + /// Returns an editable requirement if it is an editable requirement. pub fn into_editable(self) -> Option { match self { - RequirementOrEditable::Editable(e) => Some(e), + RequirementOrEditable::Editable(_, editable) => Some(editable), _ => None, } } @@ -331,15 +362,15 @@ impl RequirementOrEditable { } /// Returns an editable requirement if it is an editable requirement. - pub fn editable(&self) -> Option<&requirements_txt::EditableRequirement> { + pub fn as_editable(&self) -> Option<&requirements_txt::EditableRequirement> { match self { - RequirementOrEditable::Editable(e) => Some(e), + RequirementOrEditable::Editable(_name, editable) => Some(editable), _ => None, } } /// Returns a pep508 requirement if it is a pep508 requirement. - pub fn requirement(&self) -> Option<&pep508_rs::Requirement> { + pub fn as_requirement(&self) -> Option<&pep508_rs::Requirement> { match self { RequirementOrEditable::Pep508Requirement(e) => Some(e), _ => None, @@ -364,16 +395,16 @@ impl PyPiRequirement { name: &PackageName, project_root: &Path, ) -> Result { - let (version_or_url, editable) = match self { + let version_or_url = match self { PyPiRequirement::Version { version, index: _, extras: _, - } => (version.clone().into(), false), + } => version.clone().into(), PyPiRequirement::Path { path, editable, - extras: _, + extras, } => { let joined = project_root.join(path); let canonicalized = @@ -385,11 +416,20 @@ impl PyPiRequirement { .to_str() .map(|s| s.to_owned()) .unwrap_or_else(String::new); - let verbatim = VerbatimUrl::from_path(canonicalized).with_given(given); - ( - Some(pep508_rs::VersionOrUrl::Url(verbatim)), - editable.unwrap_or_default(), - ) + let verbatim = VerbatimUrl::from_path(canonicalized.clone()).with_given(given); + + if *editable == Some(true) { + return Ok(RequirementOrEditable::Editable( + name.clone(), + requirements_txt::EditableRequirement { + url: verbatim, + extras: extras.clone(), + path: canonicalized, + }, + )); + } + + Some(pep508_rs::VersionOrUrl::Url(verbatim)) } PyPiRequirement::Git { git, @@ -409,18 +449,12 @@ impl PyPiRequirement { url: git.to_string(), } })?; - ( - Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url(uv_url))), - false, - ) + Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url(uv_url))) } - PyPiRequirement::Url { url, extras: _ } => ( - Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url( - url.clone(), - ))), - false, - ), - PyPiRequirement::RawVersion(version) => (version.clone().into(), false), + PyPiRequirement::Url { url, extras: _ } => Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url( + url.clone(), + ))), + PyPiRequirement::RawVersion(version) => version.clone().into(), }; Ok(RequirementOrEditable::Pep508Requirement( From 88440bea927445f74a448a956a209b43fa21d637 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Mon, 25 Mar 2024 16:40:36 +0100 Subject: [PATCH 05/22] fix: depend on rattler revision --- Cargo.lock | 15 +++++++++++---- Cargo.toml | 34 +++++++++++++++++----------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de54196084..7fa8c6d9d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3371,8 +3371,7 @@ dependencies = [ [[package]] name = "rattler" version = "0.19.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81a68a73dd7a079ec559061d0d24343f9c7840c2226af3822a238b61a3bbf93" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "anyhow", "async-compression", @@ -3418,6 +3417,7 @@ dependencies = [ [[package]] name = "rattler_conda_types" version = "0.20.3" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "chrono", "fxhash", @@ -3446,6 +3446,7 @@ dependencies = [ [[package]] name = "rattler_digest" version = "0.19.2" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "blake2", "digest", @@ -3460,6 +3461,7 @@ dependencies = [ [[package]] name = "rattler_lock" version = "0.21.0" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "chrono", "fxhash", @@ -3482,6 +3484,7 @@ dependencies = [ [[package]] name = "rattler_macros" version = "0.19.2" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "quote", "syn 2.0.53", @@ -3490,6 +3493,7 @@ dependencies = [ [[package]] name = "rattler_networking" version = "0.20.0" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "anyhow", "async-trait", @@ -3519,8 +3523,7 @@ dependencies = [ [[package]] name = "rattler_package_streaming" version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3181493677f925cb1a5a7ba2122fa2ce263a427f597029af59e75e13a8bc78e2" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "bzip2", "chrono", @@ -3546,6 +3549,7 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" version = "0.19.4" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "anyhow", "async-compression", @@ -3584,6 +3588,7 @@ dependencies = [ [[package]] name = "rattler_shell" version = "0.19.4" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "enum_dispatch", "indexmap 2.2.5", @@ -3600,6 +3605,7 @@ dependencies = [ [[package]] name = "rattler_solve" version = "0.20.3" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "anyhow", "chrono", @@ -3619,6 +3625,7 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" version = "0.19.4" +source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" dependencies = [ "cfg-if", "libloading", diff --git a/Cargo.toml b/Cargo.toml index 365ce59d52..f19a6dd12b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -161,24 +161,24 @@ pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } # deno_task_shell = { path = "../deno_task_shell" } -# rattler = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_conda_types = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_digest = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_lock = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_networking = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_repodata_gateway = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_shell = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_solve = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } -# rattler_virtual_packages = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } + rattler = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_digest = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_lock = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_networking = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } + rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } -rattler_digest = { path = "../rattler/crates/rattler_digest" } -rattler_networking = { path = "../rattler/crates/rattler_networking" } -rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } -rattler_shell = { path = "../rattler/crates/rattler_shell" } -rattler_solve = { path = "../rattler/crates/rattler_solve" } -rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } -rattler_lock = { path = "../rattler/crates/rattler_lock" } +#rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } +#rattler_digest = { path = "../rattler/crates/rattler_digest" } +#rattler_networking = { path = "../rattler/crates/rattler_networking" } +#rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } +#rattler_shell = { path = "../rattler/crates/rattler_shell" } +#rattler_solve = { path = "../rattler/crates/rattler_solve" } +#rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } +#rattler_lock = { path = "../rattler/crates/rattler_lock" } # Change these lines if you want a patched version of uv [patch.'https://github.com/astral-sh/uv'] From 2b6906ab55d63c74e78388609d9886e97b2c0663 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Mon, 25 Mar 2024 16:44:47 +0100 Subject: [PATCH 06/22] feat: different way of building pypi deps --- Cargo.lock | 68 +++++++------- Cargo.toml | 113 +++++++++++++---------- src/lock_file/pypi_editables.rs | 153 ++++++++++++++++++++++++++------ src/lock_file/resolve.rs | 20 ++--- 4 files changed, 234 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fa8c6d9d8..ef21ec3647 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -647,7 +647,7 @@ dependencies = [ [[package]] name = "cache-key" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "hex", "seahash", @@ -1089,7 +1089,7 @@ dependencies = [ [[package]] name = "distribution-filename" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "pep440_rs", "platform-tags", @@ -1103,7 +1103,7 @@ dependencies = [ [[package]] name = "distribution-types" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "cache-key", @@ -1980,7 +1980,7 @@ dependencies = [ [[package]] name = "install-wheel-rs" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "configparser", "csv", @@ -2664,7 +2664,7 @@ dependencies = [ [[package]] name = "once-map" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "dashmap", "tokio", @@ -2877,10 +2877,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pep440_rs" version = "0.5.0" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "once_cell", - "pubgrub", "rkyv", "serde", "unicode-width", @@ -2890,13 +2889,12 @@ dependencies = [ [[package]] name = "pep508_rs" version = "0.4.2" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "derivative", "once_cell", "pep440_rs", "regex", - "rkyv", "serde", "thiserror", "unicode-width", @@ -3086,6 +3084,7 @@ dependencies = [ "tracing", "tracing-subscriber", "url", + "uv-build", "uv-cache", "uv-client", "uv-dispatch", @@ -3118,7 +3117,7 @@ dependencies = [ [[package]] name = "platform-tags" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "rustc-hash", "serde", @@ -3189,12 +3188,13 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "priority-queue" -version = "1.4.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" +checksum = "509354d8a769e8d0b567d6821b84495c60213162761a732d68ce87c964bd347f" dependencies = [ "autocfg", - "indexmap 1.9.3", + "equivalent", + "indexmap 2.2.5", ] [[package]] @@ -3252,7 +3252,7 @@ dependencies = [ [[package]] name = "pubgrub" version = "0.2.1" -source = "git+https://github.com/astral-sh/pubgrub?rev=addbaf184891d66a2dfd93d241a66d13bfe5de86#addbaf184891d66a2dfd93d241a66d13bfe5de86" +source = "git+https://github.com/astral-sh/pubgrub?rev=c26e485213e39582c6f2e4d45c0328422670e7a7#c26e485213e39582c6f2e4d45c0328422670e7a7" dependencies = [ "indexmap 2.2.5", "log", @@ -3279,7 +3279,7 @@ dependencies = [ [[package]] name = "pypi-types" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "chrono", "mailparse", @@ -3770,7 +3770,7 @@ dependencies = [ [[package]] name = "requirements-txt" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "async-recursion", "fs-err", @@ -5221,7 +5221,7 @@ dependencies = [ [[package]] name = "uv-auth" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "async-trait", "base64 0.21.7", @@ -5239,7 +5239,7 @@ dependencies = [ [[package]] name = "uv-build" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "distribution-types", @@ -5267,7 +5267,7 @@ dependencies = [ [[package]] name = "uv-cache" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "cache-key", "cachedir", @@ -5290,7 +5290,7 @@ dependencies = [ [[package]] name = "uv-client" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "async-trait", @@ -5341,7 +5341,7 @@ dependencies = [ [[package]] name = "uv-dispatch" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "distribution-types", @@ -5362,7 +5362,7 @@ dependencies = [ [[package]] name = "uv-distribution" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "cache-key", @@ -5400,7 +5400,7 @@ dependencies = [ [[package]] name = "uv-extract" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "async-compression", "async_zip", @@ -5419,7 +5419,7 @@ dependencies = [ [[package]] name = "uv-fs" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "backoff", "dunce", @@ -5438,7 +5438,7 @@ dependencies = [ [[package]] name = "uv-git" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "base64 0.21.7", @@ -5461,7 +5461,7 @@ dependencies = [ [[package]] name = "uv-installer" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "async-channel", @@ -5499,7 +5499,7 @@ dependencies = [ [[package]] name = "uv-interpreter" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "cache-key", "configparser", @@ -5527,7 +5527,7 @@ dependencies = [ [[package]] name = "uv-normalize" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "rkyv", "serde", @@ -5536,7 +5536,7 @@ dependencies = [ [[package]] name = "uv-resolver" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anstream", "anyhow", @@ -5579,7 +5579,7 @@ dependencies = [ [[package]] name = "uv-traits" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anyhow", "distribution-types", @@ -5594,13 +5594,13 @@ dependencies = [ [[package]] name = "uv-version" -version = "0.1.23" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +version = "0.1.24" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" [[package]] name = "uv-virtualenv" version = "0.0.4" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anstream", "cachedir", @@ -5619,7 +5619,7 @@ dependencies = [ [[package]] name = "uv-warnings" version = "0.0.1" -source = "git+https://github.com/wolfv/uv?branch=expose-yanks#9684ef863b725b6bc76aa87f834f8d8904176d6f" +source = "git+https://github.com/astral-sh/uv?rev=7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2#7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" dependencies = [ "anstream", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index f19a6dd12b..11380fe5b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,8 +45,8 @@ crossbeam-channel = "0.5.12" deno_task_shell = "0.14.4" dialoguer = "0.11.0" dirs = "5.0.1" -distribution-filename = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -distribution-types = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } +distribution-filename = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +distribution-types = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } dunce = "1.0.4" flate2 = "1.0.28" futures = "0.3.30" @@ -57,7 +57,7 @@ ignore = "0.4.22" indexmap = { version = "2.2.5", features = ["serde"] } indicatif = "0.17.8" -install-wheel-rs = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } +install-wheel-rs = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } is_executable = "1.0.1" itertools = "0.12.1" lazy_static = "1.4.0" @@ -71,10 +71,10 @@ miette = { version = "7.2.0", features = [ ] } minijinja = { version = "1.0.14", features = ["builtins"] } once_cell = "1.19.0" -pep440_rs = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -pep508_rs = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -platform-tags = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -pypi-types = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } +pep440_rs = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +pep508_rs = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +platform-tags = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +pypi-types = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } rattler = { version = "0.19.4", default-features = false, features = [ "cli-tools", ] } @@ -93,7 +93,7 @@ rattler_solve = { version = "0.20.3", default-features = false, features = [ ] } rattler_virtual_packages = { version = "0.19.4", default-features = false } regex = "1.10.3" -requirements-txt = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } +requirements-txt = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } reqwest = { version = "0.11.27", default-features = false } reqwest-middleware = "0.2.5" reqwest-retry = "0.4.0" @@ -120,15 +120,16 @@ toml_edit = { version = "0.22.8", features = ["serde"] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = "2.5.0" -uv-cache = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-client = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-dispatch = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-distribution = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-installer = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-interpreter = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-normalize = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-resolver = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } -uv-traits = { git = "https://github.com/astral-sh/uv", tag = "0.1.23" } +uv-build = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-cache = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-client = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-dispatch = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-distribution = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-installer = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-interpreter = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-normalize = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-resolver = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +uv-traits = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } xxhash-rust = "0.8.10" zip = { version = "0.6.6", default-features = false, features = [ "deflate", @@ -157,19 +158,19 @@ toml = "0.8.12" [patch.crates-io] # For pyproject-toml # If you change this also change the versions in the the patch section for uv -pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +pep440_rs = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } +pep508_rs = { git = "https://github.com/astral-sh/uv", rev = "7a5571fa5c4fa72a26b0754f3273f1d75f3fa7d2" } # deno_task_shell = { path = "../deno_task_shell" } - rattler = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_digest = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_lock = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_networking = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_digest = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_lock = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_networking = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } #rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } #rattler_digest = { path = "../rattler/crates/rattler_digest" } @@ -182,20 +183,42 @@ pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } # Change these lines if you want a patched version of uv [patch.'https://github.com/astral-sh/uv'] -pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-cache = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-client = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-dispatch = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-distribution = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-installer = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-interpreter = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-normalize = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-resolver = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -uv-traits = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -distribution-filename = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -distribution-types = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -install-wheel-rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -platform-tags = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -pypi-types = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } -requirements-txt = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# pep440_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# pep508_rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-build = { git = "https://github.com/wolfv/uv", tag = "expose-yanks" } +# uv-cache = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-client = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-dispatch = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-distribution = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-installer = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-interpreter = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-normalize = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-resolver = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# uv-traits = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# distribution-filename = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# distribution-types = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# install-wheel-rs = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# platform-tags = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# pypi-types = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } +# requirements-txt = { git = "https://github.com/wolfv/uv", branch = "expose-yanks" } + +# deno_task_shell = { path = "../deno_task_shell" } +# rattler = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_conda_types = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_digest = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_lock = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_networking = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_repodata_gateway = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_shell = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_solve = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } +# rattler_virtual_packages = { git = "https://github.com/mamba-org/rattler", rev = "2fb7fc1f60b250985e0674b22c5d42fd31798826" } + + +# rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } +# rattler_digest = { path = "../rattler/crates/rattler_digest" } +# rattler_networking = { path = "../rattler/crates/rattler_networking" } +# rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } +# rattler_shell = { path = "../rattler/crates/rattler_shell" } +# rattler_solve = { path = "../rattler/crates/rattler_solve" } +# rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } +# rattler_lock = { path = "../rattler/crates/rattler_lock" } diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs index b69871e045..a422928aaa 100644 --- a/src/lock_file/pypi_editables.rs +++ b/src/lock_file/pypi_editables.rs @@ -1,63 +1,164 @@ -use std::path::Path; +use std::{path::Path, str::FromStr, sync::Arc}; +use distribution_filename::WheelFilename; use distribution_types::LocalEditable; -use platform_tags::Tags; +use futures::StreamExt; +use install_wheel_rs::metadata::read_archive_metadata; +use itertools::Itertools; +use pypi_types::Metadata23; use requirements_txt::EditableRequirement; use uv_cache::Cache; -use uv_client::RegistryClient; use uv_dispatch::BuildDispatch; -use uv_installer::{BuiltEditable, Downloader}; +use uv_installer::{BuiltEditable, DownloadReporter, Downloader}; +use uv_traits::{BuildContext, BuildKind, SourceBuildTrait}; +use zip::ZipArchive; use crate::uv_reporter::{UvReporter, UvReporterOptions}; -/// TODO: remove this type when the uv error is exposed in the public API. #[derive(thiserror::Error, Debug)] pub enum BuildEditablesError { - #[error("Failed to build editables: {source}")] - DownloadError { + #[error("error during setting up of editable build environment")] + BuildSetupError { + // Because of anyhow error source: Box, }, + #[error("error during editable metadata extraction")] + MetadataError { + // Because of anyhow error + source: Box, + }, + + #[error("error during editable build")] + BuildError { + #[from] + source: uv_build::Error, + }, + + #[error("error during parsing of editable metadata")] + MetadataParseError { + #[from] + source: pypi_types::Error, + }, + + #[error("error creating tempory dir for editable wheel build")] + IoError { + #[from] + source: std::io::Error, + }, + + #[error("error reading wheel metadata for editable")] + WheelMetadataError { + #[from] + source: install_wheel_rs::Error, + }, + + #[error("error open wheel archive for editable built wheel")] + ZipError { + #[from] + source: zip::result::ZipError, + }, + + #[error("error parsing wheel filename for editable")] + WheelFilenameError { + #[from] + source: distribution_filename::WheelFilenameError, + }, +} + +/// Read the [`Metadata23`] from a built wheel. +fn read_wheel_metadata( + filename: &WheelFilename, + wheel: &Path, +) -> Result { + let file = std::fs::File::open(wheel)?; + let reader = std::io::BufReader::new(file); + let mut archive = ZipArchive::new(reader)?; + let dist_info = read_archive_metadata(filename, &mut archive)?; + Ok(Metadata23::parse_metadata(&dist_info)?) +} + +async fn build_editable( + cache: &Cache, + local_editable: &LocalEditable, + build_dispatch: &BuildDispatch<'_>, +) -> Result { + let mut source_build = build_dispatch + .setup_build( + &local_editable.path, + None, + &local_editable.to_string(), + None, + BuildKind::Editable, + ) + .await + .map_err(|err| BuildEditablesError::BuildSetupError { source: err.into() })?; + + let disk_filename = source_build + .metadata() + .await + .map_err(|err| BuildEditablesError::MetadataError { source: err.into() })?; + + // Check if we have the metadata director + // if this is None we have no option to build the wheel + if let Some(metadata_directory) = disk_filename { + let content = std::fs::read(metadata_directory.join("METADATA")) + .map_err(|e| BuildEditablesError::MetadataError { source: e.into() })?; + Ok(Metadata23::parse_metadata(&content)?) + } else { + let temp_dir = tempfile::tempdir_in(cache.root())?; + let wheel = source_build + .build(temp_dir.path()) + .await + .map_err(|e| BuildEditablesError::BuildError { source: e })?; + Ok(read_wheel_metadata( + &WheelFilename::from_str(&wheel)?, + &temp_dir.path().join(wheel), + )?) + } } /// Build a set of editable distributions. #[allow(clippy::too_many_arguments)] pub async fn build_editables( editables: &[EditableRequirement], - editable_wheel_dir: &Path, cache: &Cache, - tags: &Tags, - client: &RegistryClient, build_dispatch: &BuildDispatch<'_>, -) -> Result, BuildEditablesError> { +) -> Result, BuildEditablesError> { let options = UvReporterOptions::new() .with_length(editables.len() as u64) .with_capacity(editables.len() + 30) .with_starting_tasks(editables.iter().map(|d| format!("{}", d.path.display()))) .with_top_level_message("Building editables"); - let downloader = Downloader::new(cache, tags, client, build_dispatch) - .with_reporter(UvReporter::new(options)); - let editables: Vec = editables .iter() .map(|editable| { let EditableRequirement { url, extras, path } = editable; - Ok(LocalEditable { + LocalEditable { url: url.clone(), extras: extras.clone(), path: path.clone(), - }) + } }) - .collect::>()?; + .collect_vec(); - let editables: Vec<_> = downloader - .build_editables(editables, editable_wheel_dir) - .await - .map_err(|e| BuildEditablesError::DownloadError { - source: Box::new(e), - })? - .into_iter() - .collect(); + let reporter = Arc::new(UvReporter::new(options)); + let mut editables_and_metadata = Vec::new(); + + let reporter_clone = reporter.clone(); + let mut build_stream = futures::stream::iter(editables) + .map(|editable| async { + let task = reporter_clone.on_editable_build_start(&editable); + let metadata = build_editable(cache, &editable, build_dispatch).await?; + Ok::<_, BuildEditablesError>((editable, metadata, task)) + }) + .buffer_unordered(10); + + let reporter_clone = reporter.clone(); + while let Some((local_editable, metadata, task)) = build_stream.next().await.transpose()? { + reporter_clone.on_editable_build_complete(&local_editable, task); + editables_and_metadata.push((local_editable, metadata)); + } - Ok(editables) + Ok(editables_and_metadata) } diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index 01287730f0..ccd1da199d 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -340,24 +340,14 @@ pub async fn resolve_pypi( .collect(); // Build any editables - let built_wheel_dir = tempdir().into_diagnostic()?; - let built_editables = build_editables( - &editables, - built_wheel_dir.path(), - &context.cache, - &tags, - &context.registry_client, - &build_dispatch, - ) - .await - .into_diagnostic()? - .into_iter() - .map(|built| (built.editable, built.metadata)) - .collect_vec(); + let built_editables = build_editables(&editables, &context.cache, &build_dispatch) + .await + .into_diagnostic()? + .into_iter() + .collect_vec(); let manifest = Manifest::new( requirements, - // Vec::new(), constraints, Vec::new(), Vec::new(), From cae1a65c01a99a825f9d0618602c80baa479bb4c Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 11:46:11 +0100 Subject: [PATCH 07/22] wip: installation of editables --- examples/pypi-source-deps/pixi.lock | 119 +++++++++--------- examples/pypi-source-deps/pixi.toml | 2 +- src/install_pypi.rs | 183 +++++++++++++++++++++++++--- src/lock_file/satisfiability.rs | 1 + src/project/manifest/python.rs | 6 +- 5 files changed, 234 insertions(+), 77 deletions(-) diff --git a/examples/pypi-source-deps/pixi.lock b/examples/pypi-source-deps/pixi.lock index c0272b2f60..2eede6f312 100644 --- a/examples/pypi-source-deps/pixi.lock +++ b/examples/pypi-source-deps/pixi.lock @@ -41,7 +41,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - - pypi: git+https://github.com/pytest-dev/pytest.git@c650e3a94fb7e64001ada05ed9b0855d65693395 + - pypi: git+https://github.com/pytest-dev/pytest.git@12e061e2e838fb2c17d54df40a4a11aeb8723c6b - pypi: git+https://github.com/psf/requests.git@0106aced5faa299e6ede89d1230bd6784f2c3660 - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -76,7 +76,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - - pypi: git+https://github.com/pytest-dev/pytest.git@c650e3a94fb7e64001ada05ed9b0855d65693395 + - pypi: git+https://github.com/pytest-dev/pytest.git@12e061e2e838fb2c17d54df40a4a11aeb8723c6b - pypi: git+https://github.com/psf/requests.git@0106aced5faa299e6ede89d1230bd6784f2c3660 - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -111,7 +111,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - - pypi: git+https://github.com/pytest-dev/pytest.git@c650e3a94fb7e64001ada05ed9b0855d65693395 + - pypi: git+https://github.com/pytest-dev/pytest.git@12e061e2e838fb2c17d54df40a4a11aeb8723c6b - pypi: git+https://github.com/psf/requests.git@0106aced5faa299e6ede89d1230bd6784f2c3660 - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -149,7 +149,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a5/5b/0cc789b59e8cc1bf288b38111d002d8c5917123194d45b29dcdac64723cc/pluggy-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - - pypi: git+https://github.com/pytest-dev/pytest.git@c650e3a94fb7e64001ada05ed9b0855d65693395 + - pypi: git+https://github.com/pytest-dev/pytest.git@12e061e2e838fb2c17d54df40a4a11aeb8723c6b - pypi: git+https://github.com/psf/requests.git@0106aced5faa299e6ede89d1230bd6784f2c3660 - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -303,12 +303,6 @@ packages: url: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl sha256: dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 requires_python: '>=3.6' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl - sha256: ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b - requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 @@ -327,6 +321,12 @@ packages: url: https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl sha256: 96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl + sha256: ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b + requires_python: '>=3.7.0' - kind: pypi name: click version: 8.1.7 @@ -346,13 +346,13 @@ packages: version: 3.0.2 url: git+ssh://git@github.com/pallets/flask@b90a4f1f4a370e92054b9cc9db0efcb864f87ebe requires_dist: - - werkzeug >=3.0.0 - - jinja2 >=3.1.2 - - itsdangerous >=2.1.2 - - click >=8.1.3 - - blinker >=1.6.2 - - importlib-metadata >=3.6.0 ; python_version < '3.10' - - asgiref >=3.2 ; extra == 'async' + - werkzeug>=3.0.0 + - jinja2>=3.1.2 + - itsdangerous>=2.1.2 + - click>=8.1.3 + - blinker>=1.6.2 + - importlib-metadata>=3.6.0 ; python_version < '3.10' + - asgiref>=3.2 ; extra == 'async' - python-dotenv ; extra == 'dotenv' requires_python: '>=3.8' - kind: pypi @@ -379,8 +379,8 @@ packages: url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa requires_dist: - - markupsafe >=2.0 - - babel >=2.7 ; extra == 'i18n' + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' requires_python: '>=3.7' - kind: conda name: ld_impl_linux-64 @@ -721,17 +721,17 @@ packages: url: https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl sha256: 355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 requires_dist: - - mdurl ~=0.1 + - mdurl~=0.1 - psutil ; extra == 'benchmarking' - pytest ; extra == 'benchmarking' - pytest-benchmark ; extra == 'benchmarking' - - pre-commit ~=3.0 ; extra == 'code_style' - - commonmark ~=0.9 ; extra == 'compare' - - markdown ~=3.4 ; extra == 'compare' - - mistletoe ~=1.0 ; extra == 'compare' - - mistune ~=2.0 ; extra == 'compare' - - panflute ~=2.3 ; extra == 'compare' - - linkify-it-py >=1, <3 ; extra == 'linkify' + - pre-commit~=3.0 ; extra == 'code_style' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=2.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' - mdit-py-plugins ; extra == 'plugins' - gprof2dot ; extra == 'profiling' - mdit-py-plugins ; extra == 'rtd' @@ -747,12 +747,6 @@ packages: - pytest-cov ; extra == 'testing' - pytest-regressions ; extra == 'testing' requires_python: '>=3.8' -- kind: pypi - name: markupsafe - version: 2.1.5 - url: https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl - sha256: 3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 - requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 @@ -771,6 +765,12 @@ packages: url: https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl sha256: 823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl + sha256: 3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 + requires_python: '>=3.7' - kind: pypi name: mdurl version: 0.1.2 @@ -781,6 +781,7 @@ packages: name: minimal-project version: '0.1' path: ./minimal-project + sha256: da92a0ee5711eac83d5dc7202a9efe19a829a4cb3c09cb9f74e045eec4590036 - kind: conda name: ncurses version: 6.4.20240210 @@ -916,24 +917,24 @@ packages: sha256: b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c requires_dist: - importlib-metadata ; python_version < '3.8' and extra == 'plugins' - - colorama >=0.4.6 ; extra == 'windows-terminal' + - colorama>=0.4.6 ; extra == 'windows-terminal' requires_python: '>=3.7' - kind: pypi name: pytest - version: 8.2.0.dev51+gc650e3a94 - url: git+https://github.com/pytest-dev/pytest.git@c650e3a94fb7e64001ada05ed9b0855d65693395 + version: 8.2.0.dev60+g12e061e2e + url: git+https://github.com/pytest-dev/pytest.git@12e061e2e838fb2c17d54df40a4a11aeb8723c6b requires_dist: - iniconfig - packaging - - pluggy <2.0, >=1.4 - - exceptiongroup >=1.0.0rc8 ; python_version < '3.11' - - tomli >=1 ; python_version < '3.11' + - pluggy<2.0,>=1.4 + - exceptiongroup>=1.0.0rc8 ; python_version < '3.11' + - tomli>=1 ; python_version < '3.11' - colorama ; sys_platform == 'win32' - argcomplete ; extra == 'dev' - - attrs >=19.2 ; extra == 'dev' - - hypothesis >=3.56 ; extra == 'dev' + - attrs>=19.2 ; extra == 'dev' + - hypothesis>=3.56 ; extra == 'dev' - mock ; extra == 'dev' - - pygments >=2.7.2 ; extra == 'dev' + - pygments>=2.7.2 ; extra == 'dev' - requests ; extra == 'dev' - setuptools ; extra == 'dev' - xmlschema ; extra == 'dev' @@ -1099,12 +1100,12 @@ packages: version: 2.31.0 url: git+https://github.com/psf/requests.git@0106aced5faa299e6ede89d1230bd6784f2c3660 requires_dist: - - charset-normalizer <4, >=2 - - idna <4, >=2.5 - - urllib3 <3, >=1.21.1 - - certifi >=2017.4.17 - - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' - - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' + - charset-normalizer<4,>=2 + - idna<4,>=2.5 + - urllib3<3,>=1.21.1 + - certifi>=2017.4.17 + - pysocks!=1.5.7,>=1.5.6 ; extra == 'socks' + - chardet<6,>=3.0.2 ; extra == 'use_chardet_on_py3' requires_python: '>=3.7' - kind: pypi name: rich @@ -1112,10 +1113,10 @@ packages: url: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl sha256: 4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222 requires_dist: - - ipywidgets >=7.5.1, <9 ; extra == 'jupyter' - - markdown-it-py >=2.2.0 - - pygments >=2.13.0, <3.0.0 - - typing-extensions >=4.0.0, <5.0 ; python_version < '3.9' + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + - typing-extensions>=4.0.0,<5.0 ; python_version < '3.9' requires_python: '>=3.7.0' - kind: conda name: tk @@ -1214,11 +1215,11 @@ packages: url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d requires_dist: - - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2 <5, >=4 ; extra == 'h2' - - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' - - zstandard >=0.18.0 ; extra == 'zstd' + - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2<5,>=4 ; extra == 'h2' + - pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks' + - zstandard>=0.18.0 ; extra == 'zstd' requires_python: '>=3.8' - kind: conda name: vc @@ -1275,8 +1276,8 @@ packages: url: https://files.pythonhosted.org/packages/c3/fc/254c3e9b5feb89ff5b9076a23218dafbc99c96ac5941e900b71206e6313b/werkzeug-3.0.1-py3-none-any.whl sha256: 90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10 requires_dist: - - markupsafe >=2.1.1 - - watchdog >=2.3 ; extra == 'watchdog' + - markupsafe>=2.1.1 + - watchdog>=2.3 ; extra == 'watchdog' requires_python: '>=3.8' - kind: conda name: xz diff --git a/examples/pypi-source-deps/pixi.toml b/examples/pypi-source-deps/pixi.toml index 80e7de0e78..3bd5f0cb99 100644 --- a/examples/pypi-source-deps/pixi.toml +++ b/examples/pypi-source-deps/pixi.toml @@ -24,7 +24,7 @@ requests = { git = "https://github.com/psf/requests.git", rev = "0106aced5faa299 # TODO: will support later -> or use branch = '' or tag = '' to specify a branch or tag # You can also directly add a source dependency from file -minimal-project = { path = "./minimal-project" } +minimal-project = { path = "./minimal-project", editable = true } # You can also use a direct url, to either a `.tar.gz` or `.zip`, or a `.whl` file click = { url = "https://github.com/pallets/click/releases/download/8.1.7/click-8.1.7-py3-none-any.whl" } diff --git a/src/install_pypi.rs b/src/install_pypi.rs index 00fcaec1a1..f9d328e01a 100644 --- a/src/install_pypi.rs +++ b/src/install_pypi.rs @@ -5,10 +5,15 @@ use std::borrow::Cow; use distribution_filename::DistFilename; -use miette::{IntoDiagnostic, WrapErr}; +use itertools::Itertools; +use miette::{miette, IntoDiagnostic, WrapErr}; use pep440_rs::Version; use pep508_rs::VerbatimUrl; +use platform_tags::Tags; +use requirements_txt::EditableRequirement; +use tempfile::{tempdir, TempDir}; use url::Url; +use uv_build::PyProjectToml; use uv_cache::{ArchiveTarget, ArchiveTimestamp, Cache}; use uv_resolver::InMemoryIndex; @@ -17,13 +22,15 @@ use crate::lock_file::UvResolutionContext; use crate::project::manifest::SystemRequirements; use crate::pypi_tags::{get_pypi_tags, is_python_record}; -use distribution_types::{CachedDist, DirectGitUrl, Dist, IndexUrl, InstalledDist, Name}; +use distribution_types::{ + CachedDist, DirectGitUrl, Dist, IndexUrl, InstalledDist, LocalEditable, Name, +}; use install_wheel_rs::linker::LinkMode; use rattler_conda_types::{Platform, RepoDataRecord}; use rattler_lock::{PypiPackageData, PypiPackageEnvironmentData, UrlOrPath}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::path::Path; use std::str::FromStr; use std::time::Duration; @@ -31,7 +38,7 @@ use std::time::Duration; use uv_client::{FlatIndex, FlatIndexClient}; use uv_dispatch::BuildDispatch; use uv_distribution::RegistryWheelIndex; -use uv_installer::{Downloader, SitePackages}; +use uv_installer::{Downloader, ResolvedEditable, SitePackages}; use uv_interpreter::{Interpreter, PythonEnvironment}; use uv_normalize::PackageName; @@ -385,7 +392,7 @@ fn need_reinstall( /// and what we need to download from the registry. /// Also determine what we need to remove. fn whats_the_plan<'a>( - required: &'a [CombinedPypiPackageData], + required: &'a [&'a CombinedPypiPackageData], installed: &SitePackages<'_>, registry_index: &'a mut RegistryWheelIndex<'a>, uv_cache: &Cache, @@ -396,20 +403,25 @@ fn whats_the_plan<'a>( let mut required_map: std::collections::HashMap<&PackageName, &PypiPackageData> = required.iter().map(|(pkg, _)| (&pkg.name, pkg)).collect(); - // Filter out packages not installed by uv - let installed = installed.iter().filter(|dist| { - dist.installer() - .unwrap_or_default() - .is_some_and(|installer| installer == "uv") - }); - + // Packages to be removed let mut extraneous = vec![]; + // Packages to be installed directly from the cache let mut local = vec![]; + // Try to install from the registry or direct url or w/e let mut remote = vec![]; + // Packages that need to be reinstalled + // i.e. need to be removed before being installed let mut reinstalls = vec![]; // TODO: Do something with editable packages + // Filter out packages not installed by uv + let installed = installed.iter().filter(|dist| { + dist.installer() + .unwrap_or_default() + .is_some_and(|installer| installer == "uv") + }); + // Walk over all installed packages and check if they are required for dist in installed { if let Some(pkg) = required_map.remove(&dist.name()) { @@ -507,6 +519,142 @@ async fn uninstall_outdated_site_packages(site_packages: &Path) -> miette::Resul Ok(()) } +/// Wrapper around ResolvedEditable +/// but also contains a boolean to indicate if the editable is present in the prefix +/// this makes the subsequent code a bit easier +struct ResolvedEditableExt { + resolved_editable: ResolvedEditable, + present_in_prefix: bool, +} + +/// Result of resolving editables +/// we need to store the temp_dir until the install is finished +struct ResolvedEditableExts { + resolved_editables: Vec, + // In the uv code they are also keeping track of the temp_dir + // which I do not completely understand because the wheels + // should already be in the cache + // But lets follow their lead for now + temp_dir: Option, +} + +/// Function to figure out what we should do with any editables +/// +/// # Description +/// +/// So we need to figure out if the editables still need to be built, or if they are *ready* to be installed +/// Because an editable install is metadata and a .pth file containt the path the building of it is a bit different when compared to +/// regular wheels. +/// +/// UV has the concept of a `ResolvedEditable`, which is an editable that has just been built or is already installed. +/// We can use this to figure out what we need to do with an editable in the prefix. +/// +async fn resolve_editables( + lock_file_dir: &Path, + editables: &[&CombinedPypiPackageData], + site_packages: &SitePackages<'_>, + uv_context: &UvResolutionContext, + tags: &Tags, + build_dispatch: &BuildDispatch<'_>, +) -> miette::Result { + let mut editable_present_in_prefix = HashSet::new(); + let mut to_build = vec![]; + let mut installed = vec![]; + + for (pkg, _) in editables { + let absolute_path = dunce::canonicalize( + lock_file_dir.join( + pkg.url_or_path + .as_path() + .expect("editable can only be a path"), + ), + ) + .into_diagnostic()?; + let url = + Url::from_file_path(&absolute_path).map_err(|_| miette!("invalid editable path"))?; + let existing = site_packages.get_editables(&url); + + let editable = LocalEditable { + url: VerbatimUrl::from_url(url.clone()), + // We do not have any extras for an editable coming from the lock + // But I'm unsure if its ever used for metadata building + // as we do take it into account for resolution + extras: vec![], + path: absolute_path, + }; + + // Check if the editable is present in the site-packages + // If it is, we need to check if it is up to date + // We keep track of an extra bool to check if it is present in the prefix + match existing.as_slice() { + // The editable is not present in the site-packages + // Build it + [] => to_build.push(editable), + [dist] => { + // Check if the editable is up to date + // with the installed distribution + if ArchiveTimestamp::up_to_date_with(&editable.path, ArchiveTarget::Install(dist)) + .into_diagnostic()? + // If the editable is dynamic, we need to rebuild it + && !uv_installer::is_dynamic(&EditableRequirement { + url: VerbatimUrl::from_url(url.clone()), + extras: vec![], + // Only this field is actually used in the `is_dynamic` function + path: editable.path.clone(), + }) + { + installed.push((*dist).clone()); + } else { + // The editable is not up to date + // but present + editable_present_in_prefix.insert(editable.path.clone()); + to_build.push(editable); + } + } + _ => { + editable_present_in_prefix.insert(editable.path.clone()); + // Somehow gives us multiple editables + // let's just build it + to_build.push(editable); + } + } + } + + // Now we need to build the editables + let (built_dists, temp_dir) = if !to_build.is_empty() { + let options = UvReporterOptions::new() + .with_length(editables.len() as u64) + .with_capacity(editables.len() + 30) + .with_starting_tasks( + editables + .iter() + .map(|(pkg, _)| format!("building: {}", pkg.name)), + ) + .with_top_level_message("Resolving editables"); + + // Create a tempdir to store the built editables + let temp = tempdir().into_diagnostic()?; + let built_editables = Downloader::new( + &uv_context.cache, + &tags, + &uv_context.registry_client, + build_dispatch, + ) + .with_reporter(UvReporter::new(options)) + .build_editables(to_build, temp.path()) + .await + .into_diagnostic()?; + (built_editables, Some(temp)) + } else { + (vec![], None) + }; + + Ok(ResolvedEditableExts { + resolved_editables: vec![], + temp_dir, + }) +} + /// Installs and/or remove python distributions. // TODO: refactor arguments in struct #[allow(clippy::too_many_arguments)] @@ -582,7 +730,14 @@ pub async fn update_python_distributions( .with_build_extra_env_vars(environment_variables.iter()); let _lock = venv.lock().into_diagnostic()?; - // TODO: need to resolve editables? + + // Partition into editables and non-editables + + let (editables, python_packages) = python_packages + .into_iter() + .partition::, _>(|(pkg, _)| pkg.editable); + + // Build the editable packages let installed = SitePackages::from_executable(&venv).expect("could not create site-packages"); let mut registry_index = @@ -595,7 +750,7 @@ pub async fn update_python_distributions( reinstalls, extraneous, } = whats_the_plan( - python_packages, + python_packages.as_slice(), &installed, &mut registry_index, &uv_context.cache, diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index 24bde41cfd..a1f3cfd798 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -749,6 +749,7 @@ mod tests { hash: None, requires_dist: vec![], requires_python: None, + editable: false, }; let spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg@abcd").unwrap(); // This should satisfy: diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index 23eb0d60cc..2c92b54316 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -451,9 +451,9 @@ impl PyPiRequirement { })?; Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url(uv_url))) } - PyPiRequirement::Url { url, extras: _ } => Some(pep508_rs::VersionOrUrl::Url(VerbatimUrl::from_url( - url.clone(), - ))), + PyPiRequirement::Url { url, extras: _ } => Some(pep508_rs::VersionOrUrl::Url( + VerbatimUrl::from_url(url.clone()), + )), PyPiRequirement::RawVersion(version) => version.clone().into(), }; From 12e1a36735d5cf00cade36e126c454302e16cb6f Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 13:35:03 +0100 Subject: [PATCH 08/22] feat: now uses editables for installation --- src/install_pypi.rs | 111 +++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/src/install_pypi.rs b/src/install_pypi.rs index f9d328e01a..d62bf9440a 100644 --- a/src/install_pypi.rs +++ b/src/install_pypi.rs @@ -392,8 +392,9 @@ fn need_reinstall( /// and what we need to download from the registry. /// Also determine what we need to remove. fn whats_the_plan<'a>( - required: &'a [&'a CombinedPypiPackageData], - installed: &SitePackages<'_>, + required: &Vec<&'a CombinedPypiPackageData>, + editables: &Vec, + mut site_packages: &mut SitePackages<'_>, registry_index: &'a mut RegistryWheelIndex<'a>, uv_cache: &Cache, python_version: &Version, @@ -413,10 +414,40 @@ fn whats_the_plan<'a>( // i.e. need to be removed before being installed let mut reinstalls = vec![]; - // TODO: Do something with editable packages + for resolved_editable in editables { + match resolved_editable { + ResolvedEditable::Installed(dist) => { + tracing::debug!("Treating editable requirement as immutable: {dist}"); + + // Remove from the site-packages index, to avoid marking as extraneous. + let Some(editable) = dist.as_editable() else { + tracing::warn!("Editable requirement is not editable: {dist}"); + continue; + }; + let existing = site_packages.remove_editables(editable); + if existing.is_empty() { + tracing::error!("Editable requirement is not installed: {dist}"); + continue; + } + } + ResolvedEditable::Built(built) => { + tracing::debug!("Treating editable requirement as mutable: {built}"); + + // Remove any editable installs. + let existing = site_packages.remove_editables(built.editable.raw()); + reinstalls.extend(existing); + + // Remove any non-editable installs of the same package. + let existing = site_packages.remove_packages(built.name()); + reinstalls.extend(existing); + + local.push(built.wheel.clone()); + } + } + } // Filter out packages not installed by uv - let installed = installed.iter().filter(|dist| { + let installed = site_packages.iter().filter(|dist| { dist.installer() .unwrap_or_default() .is_some_and(|installer| installer == "uv") @@ -519,18 +550,10 @@ async fn uninstall_outdated_site_packages(site_packages: &Path) -> miette::Resul Ok(()) } -/// Wrapper around ResolvedEditable -/// but also contains a boolean to indicate if the editable is present in the prefix -/// this makes the subsequent code a bit easier -struct ResolvedEditableExt { - resolved_editable: ResolvedEditable, - present_in_prefix: bool, -} - /// Result of resolving editables /// we need to store the temp_dir until the install is finished -struct ResolvedEditableExts { - resolved_editables: Vec, +struct EditablesWithTemp { + resolved_editables: Vec, // In the uv code they are also keeping track of the temp_dir // which I do not completely understand because the wheels // should already be in the cache @@ -551,13 +574,12 @@ struct ResolvedEditableExts { /// async fn resolve_editables( lock_file_dir: &Path, - editables: &[&CombinedPypiPackageData], + editables: Vec<&CombinedPypiPackageData>, site_packages: &SitePackages<'_>, uv_context: &UvResolutionContext, tags: &Tags, build_dispatch: &BuildDispatch<'_>, -) -> miette::Result { - let mut editable_present_in_prefix = HashSet::new(); +) -> miette::Result { let mut to_build = vec![]; let mut installed = vec![]; @@ -607,14 +629,12 @@ async fn resolve_editables( } else { // The editable is not up to date // but present - editable_present_in_prefix.insert(editable.path.clone()); to_build.push(editable); } } + // Somehow gives us multiple editables + // let's just build it _ => { - editable_present_in_prefix.insert(editable.path.clone()); - // Somehow gives us multiple editables - // let's just build it to_build.push(editable); } } @@ -622,18 +642,21 @@ async fn resolve_editables( // Now we need to build the editables let (built_dists, temp_dir) = if !to_build.is_empty() { + // Set-up the reporter let options = UvReporterOptions::new() - .with_length(editables.len() as u64) - .with_capacity(editables.len() + 30) + .with_length(to_build.len() as u64) + .with_capacity(to_build.len() + 30) .with_starting_tasks( - editables + to_build .iter() - .map(|(pkg, _)| format!("building: {}", pkg.name)), + .map(|local| format!("building: {}", local.path.display())), ) .with_top_level_message("Resolving editables"); // Create a tempdir to store the built editables let temp = tempdir().into_diagnostic()?; + + // Build the editables let built_editables = Downloader::new( &uv_context.cache, &tags, @@ -649,8 +672,18 @@ async fn resolve_editables( (vec![], None) }; - Ok(ResolvedEditableExts { - resolved_editables: vec![], + // Map into the ResolvedEditableExt struct + // Contains InstalledDist or BuiltDist + // for previously installed and currently built distributions respectively + let built_editables = built_dists + .into_iter() + .map(|dist| ResolvedEditable::Built(dist)); + let installed_editables = installed + .into_iter() + .map(|dist| ResolvedEditable::Installed(dist)); + + Ok(EditablesWithTemp { + resolved_editables: built_editables.chain(installed_editables).collect(), temp_dir, }) } @@ -732,16 +765,29 @@ pub async fn update_python_distributions( let _lock = venv.lock().into_diagnostic()?; // Partition into editables and non-editables - let (editables, python_packages) = python_packages .into_iter() .partition::, _>(|(pkg, _)| pkg.editable); - // Build the editable packages + // Find out what packages are already installed + let mut site_packages = + SitePackages::from_executable(&venv).expect("could not create site-packages"); - let installed = SitePackages::from_executable(&venv).expect("could not create site-packages"); + // Resolve the editable packages first, as they need to be built beforehand + let editables_with_temp = resolve_editables( + lock_file_dir, + editables, + &site_packages, + &uv_context, + &tags, + &build_dispatch, + ) + .await?; + + // This is used to find wheels that are available from the registry let mut registry_index = RegistryWheelIndex::new(&uv_context.cache, &tags, &uv_context.index_locations); + // Partition into those that should be linked from the cache (`local`), those that need to be // downloaded (`remote`), and those that should be removed (`extraneous`). let PixiInstallPlan { @@ -750,8 +796,9 @@ pub async fn update_python_distributions( reinstalls, extraneous, } = whats_the_plan( - python_packages.as_slice(), - &installed, + &python_packages, + &editables_with_temp.resolved_editables, + &mut site_packages, &mut registry_index, &uv_context.cache, venv.interpreter().python_version(), From 0eaa8398bdb825de4f035e2341dc7e3847b46c81 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Tue, 26 Mar 2024 14:03:20 +0100 Subject: [PATCH 09/22] fix: test --- src/lock_file/satisfiability.rs | 6 +++--- ...failing_satisiability@missing-pypi-extra__pixi.toml.snap | 6 +++--- ..._failing_satisiability@solve-groups-pypi__pixi.toml.snap | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index a1f3cfd798..a60ae1aa69 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -753,13 +753,13 @@ mod tests { }; let spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg@abcd").unwrap(); // This should satisfy: - assert!(pypi_satifisfies(&locked_data, &spec)); + assert!(pypi_satifisfies_requirement(&locked_data, &spec)); let non_matching_spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg@defgd").unwrap(); // This should not - assert!(!pypi_satifisfies(&locked_data, &non_matching_spec)); + assert!(!pypi_satifisfies_requirement(&locked_data, &non_matching_spec)); // Removing the rev from the Requirement should satisfy any revision let spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg").unwrap(); - assert!(pypi_satifisfies(&locked_data, &spec)); + assert!(pypi_satifisfies_requirement(&locked_data, &spec)); } } diff --git a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap index 2918b48e72..81a4b9fa12 100644 --- a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap +++ b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap @@ -1,9 +1,9 @@ --- source: src/lock_file/satisfiability.rs -assertion_line: 532 -expression: "format!(\"{err:?}\")" +assertion_line: 736 +expression: s input_file: tests/non-satisfiability/missing-pypi-extra/pixi.toml --- environment 'default' does not satisfy the requirements of the project for platform 'win-64 Diagnostic severity: error - Caused by: the requirement 'ipython >=7.8.0 ; extra == 'jupyter'' could not be satisfied (required by 'black') + Caused by: the requirement 'ipython>=7.8.0 ; extra == 'jupyter'' could not be satisfied (required by 'black') diff --git a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap index b3168f346c..d3b929e3cc 100644 --- a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap +++ b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap @@ -1,9 +1,9 @@ --- source: src/lock_file/satisfiability.rs -assertion_line: 532 -expression: "format!(\"{err:?}\")" +assertion_line: 736 +expression: s input_file: tests/non-satisfiability/solve-groups-pypi/pixi.toml --- environment 'default' does not satisfy the requirements of the project for platform 'win-64 Diagnostic severity: error - Caused by: the requirement 'packaging >=20.0' could not be satisfied (required by 'matplotlib') + Caused by: the requirement 'packaging>=20.0' could not be satisfied (required by 'matplotlib') From aa6cd43e80db2e88b01fdce6e993c5bf15c4f757 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 14:05:01 +0100 Subject: [PATCH 10/22] fix: some small fixes --- examples/pypi-source-deps/pixi.lock | 49 ++++++++--------------------- examples/pypi-source-deps/pixi.toml | 2 +- src/install_pypi.rs | 46 +++++++++++++++------------ src/lock_file/pypi_editables.rs | 2 +- src/lock_file/resolve.rs | 2 +- 5 files changed, 42 insertions(+), 59 deletions(-) diff --git a/examples/pypi-source-deps/pixi.lock b/examples/pypi-source-deps/pixi.lock index 2eede6f312..941822cf9e 100644 --- a/examples/pypi-source-deps/pixi.lock +++ b/examples/pypi-source-deps/pixi.lock @@ -200,8 +200,6 @@ packages: url: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda sha256: 61fb2b488928a54d9472113e1280b468a309561caa54f33825a3593da390b242 md5: 6097a6ca9ada32699b5fc4312dd6ef18 - arch: x86_64 - platform: osx license: bzip2-1.0.6 license_family: BSD size: 127885 @@ -270,8 +268,6 @@ packages: url: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda sha256: 54a794aedbb4796afeabdf54287b06b1d27f7b13b3814520925f4c2c80f58ca9 md5: f2eacee8c33c43692f1ccfd33d0f50b1 - arch: x86_64 - platform: osx license: ISC size: 155665 timestamp: 1706843838227 @@ -309,12 +305,6 @@ packages: url: https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl sha256: 55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b - requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 @@ -327,6 +317,12 @@ packages: url: https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl sha256: ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b + requires_python: '>=3.7.0' - kind: pypi name: click version: 8.1.7 @@ -436,8 +432,6 @@ packages: md5: 3d1d51c8f716d97c864d12f7af329526 constrains: - expat 2.6.2.* - arch: x86_64 - platform: osx license: MIT license_family: MIT size: 69246 @@ -465,8 +459,6 @@ packages: url: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 sha256: 7a2d27a936ceee6942ea4d397f9c7d136f12549d86f7617e8b6bad51e01a941f md5: ccb34fb14960ad8b125962d3d79b31a9 - arch: x86_64 - platform: osx license: MIT license_family: MIT size: 51348 @@ -599,8 +591,6 @@ packages: md5: 086f56e13a96a6cfb1bf640505ae6b70 depends: - libzlib >=1.2.13,<1.3.0a0 - arch: x86_64 - platform: osx license: Unlicense size: 902355 timestamp: 1710254991672 @@ -673,8 +663,6 @@ packages: md5: 4a3ad23f6e16f99c04e166767193d700 constrains: - zlib 1.2.13 *_5 - arch: x86_64 - platform: osx license: Zlib license_family: Other size: 59404 @@ -753,12 +741,6 @@ packages: url: https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl sha256: 8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 requires_python: '>=3.7' -- kind: pypi - name: markupsafe - version: 2.1.5 - url: https://files.pythonhosted.org/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 - requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 @@ -771,6 +753,12 @@ packages: url: https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl sha256: 3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 + requires_python: '>=3.7' - kind: pypi name: mdurl version: 0.1.2 @@ -782,6 +770,7 @@ packages: version: '0.1' path: ./minimal-project sha256: da92a0ee5711eac83d5dc7202a9efe19a829a4cb3c09cb9f74e045eec4590036 + editable: true - kind: conda name: ncurses version: 6.4.20240210 @@ -814,8 +803,6 @@ packages: url: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.4.20240210-h73e2aa4_0.conda sha256: 50b72acf08acbc4e5332807653e2ca6b26d4326e8af16fad1fd3f2ce9ea55503 md5: 50f28c512e9ad78589e3eab34833f762 - arch: x86_64 - platform: osx license: X11 AND BSD-3-Clause size: 823010 timestamp: 1710866856626 @@ -887,8 +874,6 @@ packages: - ca-certificates constrains: - pyopenssl >=22.1 - arch: x86_64 - platform: osx license: Apache-2.0 license_family: Apache size: 2506344 @@ -987,8 +972,6 @@ packages: - xz >=5.2.6,<6.0a0 constrains: - python_abi 3.12.* *_cp312 - arch: x86_64 - platform: osx license: Python-2.0 size: 14596811 timestamp: 1708118065292 @@ -1089,8 +1072,6 @@ packages: md5: f17f77f2acf4d344734bda76829ce14e depends: - ncurses >=6.3,<7.0a0 - arch: x86_64 - platform: osx license: GPL-3.0-only license_family: GPL size: 255870 @@ -1129,8 +1110,6 @@ packages: md5: bf830ba5afc507c6232d4ef0fb1a882d depends: - libzlib >=1.2.13,<1.3.0a0 - arch: x86_64 - platform: osx license: TCL license_family: BSD size: 3270220 @@ -1311,8 +1290,6 @@ packages: url: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 sha256: eb09823f34cc2dd663c0ec4ab13f246f45dcd52e5b8c47b9864361de5204a1c8 md5: a72f9d4ea13d55d745ff1ed594747f10 - arch: x86_64 - platform: osx license: LGPL-2.1 and GPL-2.0 size: 238119 timestamp: 1660346964847 diff --git a/examples/pypi-source-deps/pixi.toml b/examples/pypi-source-deps/pixi.toml index 3bd5f0cb99..f1226a0e52 100644 --- a/examples/pypi-source-deps/pixi.toml +++ b/examples/pypi-source-deps/pixi.toml @@ -24,7 +24,7 @@ requests = { git = "https://github.com/psf/requests.git", rev = "0106aced5faa299 # TODO: will support later -> or use branch = '' or tag = '' to specify a branch or tag # You can also directly add a source dependency from file -minimal-project = { path = "./minimal-project", editable = true } +minimal-project = { path = "./minimal-project", editable = true} # You can also use a direct url, to either a `.tar.gz` or `.zip`, or a `.whl` file click = { url = "https://github.com/pallets/click/releases/download/8.1.7/click-8.1.7-py3-none-any.whl" } diff --git a/src/install_pypi.rs b/src/install_pypi.rs index d62bf9440a..ab104a38f0 100644 --- a/src/install_pypi.rs +++ b/src/install_pypi.rs @@ -5,7 +5,6 @@ use std::borrow::Cow; use distribution_filename::DistFilename; -use itertools::Itertools; use miette::{miette, IntoDiagnostic, WrapErr}; use pep440_rs::Version; use pep508_rs::VerbatimUrl; @@ -13,7 +12,7 @@ use platform_tags::Tags; use requirements_txt::EditableRequirement; use tempfile::{tempdir, TempDir}; use url::Url; -use uv_build::PyProjectToml; + use uv_cache::{ArchiveTarget, ArchiveTimestamp, Cache}; use uv_resolver::InMemoryIndex; @@ -30,7 +29,7 @@ use install_wheel_rs::linker::LinkMode; use rattler_conda_types::{Platform, RepoDataRecord}; use rattler_lock::{PypiPackageData, PypiPackageEnvironmentData, UrlOrPath}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::path::Path; use std::str::FromStr; use std::time::Duration; @@ -282,7 +281,7 @@ fn need_reinstall( }; match direct_url_json { - pypi_types::DirectUrl::LocalDirectory { url, dir_info: _ } => { + pypi_types::DirectUrl::LocalDirectory { url, dir_info } => { // Recreate file url let result = Url::parse(&url); match result { @@ -300,6 +299,10 @@ fn need_reinstall( return Ok(ValidateInstall::Reinstall); } } + // If editable status changed also re-install + if dir_info.editable.unwrap_or_default() != locked.editable { + return Ok(ValidateInstall::Reinstall); + } } pypi_types::DirectUrl::ArchiveUrl { url, @@ -394,7 +397,7 @@ fn need_reinstall( fn whats_the_plan<'a>( required: &Vec<&'a CombinedPypiPackageData>, editables: &Vec, - mut site_packages: &mut SitePackages<'_>, + site_packages: &mut SitePackages<'_>, registry_index: &'a mut RegistryWheelIndex<'a>, uv_cache: &Cache, python_version: &Version, @@ -414,14 +417,15 @@ fn whats_the_plan<'a>( // i.e. need to be removed before being installed let mut reinstalls = vec![]; + // First decide what we need to do with any editables for resolved_editable in editables { match resolved_editable { ResolvedEditable::Installed(dist) => { - tracing::debug!("Treating editable requirement as immutable: {dist}"); + tracing::debug!("Treating editable install as non-mutated: {dist}"); // Remove from the site-packages index, to avoid marking as extraneous. let Some(editable) = dist.as_editable() else { - tracing::warn!("Editable requirement is not editable: {dist}"); + tracing::warn!("Requested editable is actually not editable"); continue; }; let existing = site_packages.remove_editables(editable); @@ -498,7 +502,7 @@ fn whats_the_plan<'a>( continue; } - // Do we have in the cache? + // Do we have in the registry cache? let wheel = registry_index .get(&pkg.name) .find(|(version, _)| **version == pkg.version); @@ -558,18 +562,17 @@ struct EditablesWithTemp { // which I do not completely understand because the wheels // should already be in the cache // But lets follow their lead for now + #[allow(dead_code)] temp_dir: Option, } -/// Function to figure out what we should do with any editables -/// -/// # Description +/// Function to figure out what we should do with any editables: /// /// So we need to figure out if the editables still need to be built, or if they are *ready* to be installed -/// Because an editable install is metadata and a .pth file containt the path the building of it is a bit different when compared to -/// regular wheels. +/// Because an editable install is metadata and a .pth file containing the path the building of it is a bit different when compared to +/// regular wheels. They are kind of stripped wheels essentially. /// -/// UV has the concept of a `ResolvedEditable`, which is an editable that has just been built or is already installed. +/// UV has the concept of a `ResolvedEditable`, which is an editable that has either jsut been built or is already installed. /// We can use this to figure out what we need to do with an editable in the prefix. /// async fn resolve_editables( @@ -617,23 +620,26 @@ async fn resolve_editables( // with the installed distribution if ArchiveTimestamp::up_to_date_with(&editable.path, ArchiveTarget::Install(dist)) .into_diagnostic()? - // If the editable is dynamic, we need to rebuild it + // If the editable is dynamic, we need to rebuild it && !uv_installer::is_dynamic(&EditableRequirement { url: VerbatimUrl::from_url(url.clone()), extras: vec![], // Only this field is actually used in the `is_dynamic` function path: editable.path.clone(), }) + // And the dist is already editable + && dist.is_editable() { + // Keep it as is installed.push((*dist).clone()); } else { - // The editable is not up to date - // but present + // The editable is not up to date but present + // rebuild it to_build.push(editable); } } - // Somehow gives us multiple editables - // let's just build it + // Somehow `existing` gives us multiple editables + // let's just build it and re-install all _ => { to_build.push(editable); } @@ -773,7 +779,7 @@ pub async fn update_python_distributions( let mut site_packages = SitePackages::from_executable(&venv).expect("could not create site-packages"); - // Resolve the editable packages first, as they need to be built beforehand + // Resolve the editable packages first, as they need to be built before-hand let editables_with_temp = resolve_editables( lock_file_dir, editables, diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs index a422928aaa..de6189cb87 100644 --- a/src/lock_file/pypi_editables.rs +++ b/src/lock_file/pypi_editables.rs @@ -9,7 +9,7 @@ use pypi_types::Metadata23; use requirements_txt::EditableRequirement; use uv_cache::Cache; use uv_dispatch::BuildDispatch; -use uv_installer::{BuiltEditable, DownloadReporter, Downloader}; +use uv_installer::{DownloadReporter}; use uv_traits::{BuildContext, BuildKind, SourceBuildTrait}; use zip::ZipArchive; diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index ccd1da199d..b3f96d49e9 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -41,7 +41,7 @@ use rattler_solve::{resolvo, SolverImpl}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; -use tempfile::tempdir; + use url::Url; use uv_cache::Cache; use uv_client::{Connectivity, FlatIndex, FlatIndexClient, RegistryClient, RegistryClientBuilder}; From df5a652385abf9b43a06fabb0303b708133e7553 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 14:24:45 +0100 Subject: [PATCH 11/22] feat: changed docker example to use local editable --- examples/docker/pixi.lock | 171 +++++++++++++++------------- examples/docker/pixi.toml | 4 +- examples/pypi-source-deps/pixi.lock | 24 ++-- 3 files changed, 107 insertions(+), 92 deletions(-) diff --git a/examples/docker/pixi.lock b/examples/docker/pixi.lock index 3d9b720eff..b981f458ae 100644 --- a/examples/docker/pixi.lock +++ b/examples/docker/pixi.lock @@ -7,9 +7,21 @@ environments: linux-64: - 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/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/build-0.7.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_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/editables-0.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gunicorn-21.2.0-py312h7900ff3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 @@ -23,41 +35,42 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.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/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/build-0.7.0-pyhd8ed1ab_0.tar.bz2 - - 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/editables-0.5-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/build-0.7.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_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/editables-0.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gunicorn-21.2.0-py312h996f985_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.5.0-hd600fc2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 @@ -71,77 +84,67 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.5-py312h9ef2f89_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.2-h43d1f9e_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.12-4_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/build-0.7.0-pyhd8ed1ab_0.tar.bz2 - - 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/editables-0.5-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.2-h43d1f9e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/build-0.7.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_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/editables-0.5-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . prod: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -149,9 +152,15 @@ environments: linux-64: - 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/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_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/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gunicorn-21.2.0-py312h7900ff3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 @@ -165,29 +174,30 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.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/noarch/blinker-1.7.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/flask-3.0.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_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/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gunicorn-21.2.0-py312h996f985_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.5.0-hd600fc2_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 @@ -201,41 +211,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.5-py312h9ef2f89_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.2-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.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/flask-3.0.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_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/flask-3.0.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda @@ -243,11 +241,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - pypi: . packages: - kind: conda name: _libgcc_mutex @@ -436,6 +442,13 @@ packages: license_family: BSD size: 25170 timestamp: 1666700778190 +- kind: pypi + name: docker-project + version: 0.1.0 + path: . + sha256: 1c9c0660f3d510cf366b8cfcd3a04edbf0a449e1d4db9c1ef59dd1488d06569f + requires_python: '>=3.12' + editable: true - kind: conda name: editables version: '0.5' diff --git a/examples/docker/pixi.toml b/examples/docker/pixi.toml index 43af5462d7..0b0d137a7f 100644 --- a/examples/docker/pixi.toml +++ b/examples/docker/pixi.toml @@ -12,6 +12,9 @@ python = ">=3.12" flask = ">=3.0.2,<3.1" gunicorn = ">=21.2.0,<21.3" +[pypi-dependencies] +docker-project = { path = ".", editable = true } + [host-dependencies] pip = "*" @@ -24,7 +27,6 @@ test = "pytest" build = "*" hatchling = "*" [feature.build.tasks] -postinstall = "pip install --no-build-isolation --no-deps --disable-pip-version-check -e ." build-wheel = "python -m build --no-isolation --wheel ." [feature.prod.tasks] diff --git a/examples/pypi-source-deps/pixi.lock b/examples/pypi-source-deps/pixi.lock index 941822cf9e..72c2d5a386 100644 --- a/examples/pypi-source-deps/pixi.lock +++ b/examples/pypi-source-deps/pixi.lock @@ -302,20 +302,20 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl - sha256: 55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 + url: https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl + sha256: ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl - sha256: 96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 + url: https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl + sha256: 55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl - sha256: ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b + url: https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl + sha256: 96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -738,20 +738,20 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl - sha256: 8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 + url: https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl + sha256: 3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl - sha256: 823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb + url: https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl + sha256: 8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl - sha256: 3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 + url: https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl + sha256: 823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb requires_python: '>=3.7' - kind: pypi name: markupsafe From 52bf729d897b9776b28b0ebdc7ac03a0b02494c3 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 14:54:16 +0100 Subject: [PATCH 12/22] fix: clippy fixes --- src/install_pypi.rs | 18 +++++++----------- src/lock_file/pypi_editables.rs | 28 ++++++++++++++-------------- src/lock_file/satisfiability.rs | 14 +++++++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/install_pypi.rs b/src/install_pypi.rs index ab104a38f0..7f78de2ab0 100644 --- a/src/install_pypi.rs +++ b/src/install_pypi.rs @@ -395,7 +395,7 @@ fn need_reinstall( /// and what we need to download from the registry. /// Also determine what we need to remove. fn whats_the_plan<'a>( - required: &Vec<&'a CombinedPypiPackageData>, + required: &[&'a CombinedPypiPackageData], editables: &Vec, site_packages: &mut SitePackages<'_>, registry_index: &'a mut RegistryWheelIndex<'a>, @@ -572,7 +572,7 @@ struct EditablesWithTemp { /// Because an editable install is metadata and a .pth file containing the path the building of it is a bit different when compared to /// regular wheels. They are kind of stripped wheels essentially. /// -/// UV has the concept of a `ResolvedEditable`, which is an editable that has either jsut been built or is already installed. +/// UV has the concept of a `ResolvedEditable`, which is an editable that has either just been built or is already installed. /// We can use this to figure out what we need to do with an editable in the prefix. /// async fn resolve_editables( @@ -665,7 +665,7 @@ async fn resolve_editables( // Build the editables let built_editables = Downloader::new( &uv_context.cache, - &tags, + tags, &uv_context.registry_client, build_dispatch, ) @@ -679,14 +679,10 @@ async fn resolve_editables( }; // Map into the ResolvedEditableExt struct - // Contains InstalledDist or BuiltDist + // contains InstalledDist or BuiltDist // for previously installed and currently built distributions respectively - let built_editables = built_dists - .into_iter() - .map(|dist| ResolvedEditable::Built(dist)); - let installed_editables = installed - .into_iter() - .map(|dist| ResolvedEditable::Installed(dist)); + let built_editables = built_dists.into_iter().map(ResolvedEditable::Built); + let installed_editables = installed.into_iter().map(ResolvedEditable::Installed); Ok(EditablesWithTemp { resolved_editables: built_editables.chain(installed_editables).collect(), @@ -772,7 +768,7 @@ pub async fn update_python_distributions( // Partition into editables and non-editables let (editables, python_packages) = python_packages - .into_iter() + .iter() .partition::, _>(|(pkg, _)| pkg.editable); // Find out what packages are already installed diff --git a/src/lock_file/pypi_editables.rs b/src/lock_file/pypi_editables.rs index de6189cb87..ff5269bc12 100644 --- a/src/lock_file/pypi_editables.rs +++ b/src/lock_file/pypi_editables.rs @@ -9,7 +9,7 @@ use pypi_types::Metadata23; use requirements_txt::EditableRequirement; use uv_cache::Cache; use uv_dispatch::BuildDispatch; -use uv_installer::{DownloadReporter}; +use uv_installer::DownloadReporter; use uv_traits::{BuildContext, BuildKind, SourceBuildTrait}; use zip::ZipArchive; @@ -18,48 +18,48 @@ use crate::uv_reporter::{UvReporter, UvReporterOptions}; #[derive(thiserror::Error, Debug)] pub enum BuildEditablesError { #[error("error during setting up of editable build environment")] - BuildSetupError { + BuildSetup { // Because of anyhow error source: Box, }, #[error("error during editable metadata extraction")] - MetadataError { + Metadata { // Because of anyhow error source: Box, }, #[error("error during editable build")] - BuildError { + Build { #[from] source: uv_build::Error, }, #[error("error during parsing of editable metadata")] - MetadataParseError { + MetadataParse { #[from] source: pypi_types::Error, }, - #[error("error creating tempory dir for editable wheel build")] - IoError { + #[error("error creating temporary dir for editable wheel build")] + Io { #[from] source: std::io::Error, }, #[error("error reading wheel metadata for editable")] - WheelMetadataError { + WheelMetadata { #[from] source: install_wheel_rs::Error, }, #[error("error open wheel archive for editable built wheel")] - ZipError { + Zip { #[from] source: zip::result::ZipError, }, #[error("error parsing wheel filename for editable")] - WheelFilenameError { + WheelFilename { #[from] source: distribution_filename::WheelFilenameError, }, @@ -91,25 +91,25 @@ async fn build_editable( BuildKind::Editable, ) .await - .map_err(|err| BuildEditablesError::BuildSetupError { source: err.into() })?; + .map_err(|err| BuildEditablesError::BuildSetup { source: err.into() })?; let disk_filename = source_build .metadata() .await - .map_err(|err| BuildEditablesError::MetadataError { source: err.into() })?; + .map_err(|err| BuildEditablesError::Metadata { source: err.into() })?; // Check if we have the metadata director // if this is None we have no option to build the wheel if let Some(metadata_directory) = disk_filename { let content = std::fs::read(metadata_directory.join("METADATA")) - .map_err(|e| BuildEditablesError::MetadataError { source: e.into() })?; + .map_err(|e| BuildEditablesError::Metadata { source: e.into() })?; Ok(Metadata23::parse_metadata(&content)?) } else { let temp_dir = tempfile::tempdir_in(cache.root())?; let wheel = source_build .build(temp_dir.path()) .await - .map_err(|e| BuildEditablesError::BuildError { source: e })?; + .map_err(|e| BuildEditablesError::Build { source: e })?; Ok(read_wheel_metadata( &WheelFilename::from_str(&wheel)?, &temp_dir.path().join(wheel), diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index a60ae1aa69..1f64bfd689 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -65,10 +65,10 @@ pub enum PlatformUnsat { #[error("when converting {0} into a pep508 requirement")] AsPep508Error(PackageName, #[source] AsPep508Error), - #[error("editable pypi dependency on conda installed package '{0}' is not supported")] - EditableDependencyOnCondaInstalledPackage(PackageName, EditableRequirement), + #[error("editable pypi dependency on conda resolved package '{0}' is not supported")] + EditableDependencyOnCondaInstalledPackage(PackageName, Box), - #[error("direct url reference to a conda installed package '{0}' is not supported")] + #[error("direct pypi url dependency to a conda installed package '{0}' is not supported")] DirectUrlDependencyOnCondaInstalledPackage(PackageName), #[error("locked package {0} should be editable")] @@ -435,7 +435,8 @@ pub fn verify_package_platform_satisfiability( match requirement { RequirementOrEditable::Editable(name, req) => { return Err(PlatformUnsat::EditableDependencyOnCondaInstalledPackage( - name, req, + name, + Box::new(req), )); } RequirementOrEditable::Pep508Requirement(req) @@ -757,7 +758,10 @@ mod tests { let non_matching_spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg@defgd").unwrap(); // This should not - assert!(!pypi_satifisfies_requirement(&locked_data, &non_matching_spec)); + assert!(!pypi_satifisfies_requirement( + &locked_data, + &non_matching_spec + )); // Removing the rev from the Requirement should satisfy any revision let spec = Requirement::from_str("mypkg @ git+https://github.com/mypkg").unwrap(); assert!(pypi_satifisfies_requirement(&locked_data, &spec)); From aca787010e25e6dea64151db8c71f534137c69b6 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 15:13:52 +0100 Subject: [PATCH 13/22] feat: added example for editable with extras --- examples/editable-with-extras/.gitattributes | 2 + examples/editable-with-extras/.gitignore | 2 + .../package_with_extras/README.md | 3 + .../package_with_extras/__init__.py | 0 .../package_with_extras/hello.py | 2 + .../package_with_extras/pyproject.toml | 26 + examples/editable-with-extras/pixi.lock | 883 ++++++++++++++++++ examples/editable-with-extras/pixi.toml | 15 + 8 files changed, 933 insertions(+) create mode 100644 examples/editable-with-extras/.gitattributes create mode 100644 examples/editable-with-extras/.gitignore create mode 100644 examples/editable-with-extras/package_with_extras/README.md create mode 100644 examples/editable-with-extras/package_with_extras/package_with_extras/__init__.py create mode 100644 examples/editable-with-extras/package_with_extras/package_with_extras/hello.py create mode 100644 examples/editable-with-extras/package_with_extras/pyproject.toml create mode 100644 examples/editable-with-extras/pixi.lock create mode 100644 examples/editable-with-extras/pixi.toml diff --git a/examples/editable-with-extras/.gitattributes b/examples/editable-with-extras/.gitattributes new file mode 100644 index 0000000000..d5799bd69d --- /dev/null +++ b/examples/editable-with-extras/.gitattributes @@ -0,0 +1,2 @@ +# GitHub syntax highlighting +pixi.lock linguist-language=YAML diff --git a/examples/editable-with-extras/.gitignore b/examples/editable-with-extras/.gitignore new file mode 100644 index 0000000000..c9314b7c26 --- /dev/null +++ b/examples/editable-with-extras/.gitignore @@ -0,0 +1,2 @@ +# pixi environments +.pixi diff --git a/examples/editable-with-extras/package_with_extras/README.md b/examples/editable-with-extras/package_with_extras/README.md new file mode 100644 index 0000000000..4f283b6530 --- /dev/null +++ b/examples/editable-with-extras/package_with_extras/README.md @@ -0,0 +1,3 @@ +# PACKAGE WITH EXTRAS + +This package is created for testing purposes of editable install with extras. diff --git a/examples/editable-with-extras/package_with_extras/package_with_extras/__init__.py b/examples/editable-with-extras/package_with_extras/package_with_extras/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/editable-with-extras/package_with_extras/package_with_extras/hello.py b/examples/editable-with-extras/package_with_extras/package_with_extras/hello.py new file mode 100644 index 0000000000..4a3aefefdc --- /dev/null +++ b/examples/editable-with-extras/package_with_extras/package_with_extras/hello.py @@ -0,0 +1,2 @@ +def say_hello(): + print("HELLO") diff --git a/examples/editable-with-extras/package_with_extras/pyproject.toml b/examples/editable-with-extras/package_with_extras/pyproject.toml new file mode 100644 index 0000000000..223e185e3b --- /dev/null +++ b/examples/editable-with-extras/package_with_extras/pyproject.toml @@ -0,0 +1,26 @@ +[project] +name = "package_with_extras" +version = "0.0.2" +authors = [ + { name="Nichita Morcotilo", email="nmorkotilo@gmail.com" }, +] +description = "A small source package with extras" +readme = "README.md" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] + +dependencies = [ + "boltons", +] + +[project.optional-dependencies] +color = ["rich"] +cli = ["click"] + +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" diff --git a/examples/editable-with-extras/pixi.lock b/examples/editable-with-extras/pixi.lock new file mode 100644 index 0000000000..45d8427a01 --- /dev/null +++ b/examples/editable-with-extras/pixi.lock @@ -0,0 +1,883 @@ +version: 4 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - 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/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.0-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - pypi: https://files.pythonhosted.org/packages/07/89/5330d7634333f8d6ba0fdcc5f12c0726b427b5cc3e3c97494cbb525c434f/boltons-23.1.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl + - pypi: ./package_with_extras + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.0-h47c9636_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - pypi: https://files.pythonhosted.org/packages/07/89/5330d7634333f8d6ba0fdcc5f12c0726b427b5cc3e3c97494cbb525c434f/boltons-23.1.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl + - pypi: ./package_with_extras + win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.0-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - pypi: https://files.pythonhosted.org/packages/07/89/5330d7634333f8d6ba0fdcc5f12c0726b427b5cc3e3c97494cbb525c434f/boltons-23.1.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl + - pypi: ./package_with_extras +packages: +- kind: conda + name: _libgcc_mutex + version: '0.1' + build: conda_forge + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + size: 2562 + timestamp: 1578324546067 +- kind: conda + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- kind: pypi + name: boltons + version: 23.1.1 + url: https://files.pythonhosted.org/packages/07/89/5330d7634333f8d6ba0fdcc5f12c0726b427b5cc3e3c97494cbb525c434f/boltons-23.1.1-py2.py3-none-any.whl + sha256: 80a8cd930ff21fbf03545b9863e5799d0c3e7e0e3b2546bdaf2efccd7b3708cc +- kind: conda + name: bzip2 + version: 1.0.8 + build: h93a5062_5 + build_number: 5 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + sha256: bfa84296a638bea78a8bb29abc493ee95f2a0218775642474a840411b950fe5f + md5: 1bbc659ca658bfd49a481b5ef7a0f40f + license: bzip2-1.0.6 + license_family: BSD + size: 122325 + timestamp: 1699280294368 +- kind: conda + name: bzip2 + version: 1.0.8 + build: hcfcfb64_5 + build_number: 5 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + sha256: ae5f47a5c86fd6db822931255dcf017eb12f60c77f07dc782ccb477f7808aab2 + md5: 26eb8ca6ea332b675e11704cce84a3be + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: bzip2-1.0.6 + license_family: BSD + size: 124580 + timestamp: 1699280668742 +- kind: conda + name: bzip2 + version: 1.0.8 + build: hd590300_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + sha256: 242c0c324507ee172c0e0dd2045814e746bb303d1eb78870d182ceb0abc726a8 + md5: 69b8b6202a07720f448be700e300ccf4 + depends: + - libgcc-ng >=12 + license: bzip2-1.0.6 + license_family: BSD + size: 254228 + timestamp: 1699279927352 +- kind: conda + name: ca-certificates + version: 2024.2.2 + build: h56e8100_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + sha256: 4d587088ecccd393fec3420b64f1af4ee1a0e6897a45cfd5ef38055322cea5d0 + md5: 63da060240ab8087b60d1357051ea7d6 + license: ISC + size: 155886 + timestamp: 1706843918052 +- kind: conda + name: ca-certificates + version: 2024.2.2 + build: hbcca054_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + sha256: 91d81bfecdbb142c15066df70cc952590ae8991670198f92c66b62019b251aeb + md5: 2f4327a1cbe7f022401b236e915a5fef + license: ISC + size: 155432 + timestamp: 1706843687645 +- kind: conda + name: ca-certificates + version: 2024.2.2 + build: hf0a4a13_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + sha256: 49bc3439816ac72d0c0e0f144b8cc870fdcc4adec2e861407ec818d8116b2204 + md5: fb416a1795f18dcc5a038bc2dc54edf9 + license: ISC + size: 155725 + timestamp: 1706844034242 +- kind: pypi + name: click + version: 8.1.7 + url: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + sha256: ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 + requires_dist: + - colorama ; platform_system == 'Windows' + - importlib-metadata ; python_version < '3.8' + requires_python: '>=3.7' +- kind: pypi + name: colorama + version: 0.4.6 + url: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7' +- kind: conda + name: ld_impl_linux-64 + version: '2.40' + build: h41732ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda + sha256: f6cc89d887555912d6c61b295d398cff9ec982a3417d38025c45d5dd9b9e79cd + md5: 7aca3059a1729aa76c597603f10b0dd3 + constrains: + - binutils_impl_linux-64 2.40 + license: GPL-3.0-only + license_family: GPL + size: 704696 + timestamp: 1674833944779 +- kind: conda + name: libexpat + version: 2.6.2 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 73730 + timestamp: 1710362120304 +- kind: conda + name: libexpat + version: 2.6.2 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + sha256: 79f612f75108f3e16bbdc127d4885bb74729cf66a8702fca0373dad89d40c4b7 + md5: bc592d03f62779511d392c175dcece64 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 139224 + timestamp: 1710362609641 +- kind: conda + name: libexpat + version: 2.6.2 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 63655 + timestamp: 1710362424980 +- kind: conda + name: libffi + version: 3.4.2 + build: h3422bc3_5 + build_number: 5 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + sha256: 41b3d13efb775e340e4dba549ab5c029611ea6918703096b2eaa9c015c0750ca + md5: 086914b672be056eb70fd4285b6783b6 + license: MIT + license_family: MIT + size: 39020 + timestamp: 1636488587153 +- kind: conda + name: libffi + version: 3.4.2 + build: h7f98852_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e + md5: d645c6d2ac96843a2bfaccd2d62b3ac3 + depends: + - libgcc-ng >=9.4.0 + license: MIT + license_family: MIT + size: 58292 + timestamp: 1636488182923 +- kind: conda + name: libffi + version: 3.4.2 + build: h8ffe710_5 + build_number: 5 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + sha256: 1951ab740f80660e9bc07d2ed3aefb874d78c107264fd810f24a1a6211d4b1a5 + md5: 2c96d1b6915b408893f9472569dee135 + depends: + - vc >=14.1,<15.0a0 + - vs2015_runtime >=14.16.27012 + license: MIT + license_family: MIT + size: 42063 + timestamp: 1636489106777 +- kind: conda + name: libgcc-ng + version: 13.2.0 + build: h807b86a_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda + sha256: d32f78bfaac282cfe5205f46d558704ad737b8dbf71f9227788a5ca80facaba4 + md5: d4ff227c46917d3b4565302a2bbb276b + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 13.2.0 h807b86a_5 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 770506 + timestamp: 1706819192021 +- kind: conda + name: libgomp + version: 13.2.0 + build: h807b86a_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda + sha256: 0d3d4b1b0134283ea02d58e8eb5accf3655464cf7159abf098cc694002f8d34e + md5: d211c42b9ce49aee3734fdc828731689 + depends: + - _libgcc_mutex 0.1 conda_forge + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 419751 + timestamp: 1706819107383 +- kind: conda + name: libnsl + version: 2.0.1 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + sha256: 26d77a3bb4dceeedc2a41bd688564fe71bf2d149fdcf117049970bc02ff1add6 + md5: 30fd6e37fe21f86f4bd26d6ee73eeec7 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + license_family: GPL + size: 33408 + timestamp: 1697359010159 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h091b4b1_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e + md5: 9d07427ee5bd9afd1e11ce14368a48d6 + depends: + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 825300 + timestamp: 1710255078823 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h2797004_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 + md5: 866983a220e27a80cb75e85cb30466a1 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 857489 + timestamp: 1710254744982 +- kind: conda + name: libsqlite + version: 3.45.2 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + sha256: 4bb24b986550275a6d02835150d943c4c675808d05c0efc5c2a22154d007a69f + md5: f95359f8dc5abf7da7776ece9ef10bc5 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Unlicense + size: 869606 + timestamp: 1710255095740 +- kind: conda + name: libuuid + version: 2.38.1 + build: h0b41bf4_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18 + md5: 40b61aab5c7ba9ff276c41cfffe6b80b + depends: + - libgcc-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 33601 + timestamp: 1680112270483 +- kind: conda + name: libzlib + version: 1.2.13 + build: h53f4e23_5 + build_number: 5 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + sha256: ab1c8aefa2d54322a63aaeeefe9cf877411851738616c4068e0dccc66b9c758a + md5: 1a47f5236db2e06a320ffa0392f81bd8 + constrains: + - zlib 1.2.13 *_5 + license: Zlib + license_family: Other + size: 48102 + timestamp: 1686575426584 +- kind: conda + name: libzlib + version: 1.2.13 + build: hcfcfb64_5 + build_number: 5 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda + sha256: c161822ee8130b71e08b6d282b9919c1de2c5274b29921a867bca0f7d30cad26 + md5: 5fdb9c6a113b6b6cb5e517fd972d5f41 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - zlib 1.2.13 *_5 + license: Zlib + license_family: Other + size: 55800 + timestamp: 1686575452215 +- kind: conda + name: libzlib + version: 1.2.13 + build: hd590300_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda + sha256: 370c7c5893b737596fd6ca0d9190c9715d89d888b8c88537ae1ef168c25e82e4 + md5: f36c115f1ee199da648e0597ec2047ad + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.2.13 *_5 + license: Zlib + license_family: Other + size: 61588 + timestamp: 1686575217516 +- kind: pypi + name: markdown-it-py + version: 3.0.0 + url: https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl + sha256: 355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - pre-commit~=3.0 ; extra == 'code_style' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=2.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + requires_python: '>=3.8' +- kind: pypi + name: mdurl + version: 0.1.2 + url: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + requires_python: '>=3.7' +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h078ce10_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + sha256: 06f0905791575e2cd3aa961493c56e490b3d82ad9eb49f1c332bd338b0216911 + md5: 616ae8691e6608527d0071e6766dcb81 + license: X11 AND BSD-3-Clause + size: 820249 + timestamp: 1710866874348 +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + sha256: aa0f005b6727aac6507317ed490f0904430584fa8ca722657e7f0fb94741de81 + md5: 97da8860a0da5413c7c98a3b3838a645 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + size: 895669 + timestamp: 1710866638986 +- kind: conda + name: openssl + version: 3.2.1 + build: h0d3ecfb_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + sha256: 519dc941d7ab0ebf31a2878d85c2f444450e7c5f6f41c4d07252c6bb3417b78b + md5: eb580fb888d93d5d550c557323ac5cee + depends: + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2855250 + timestamp: 1710793435903 +- kind: conda + name: openssl + version: 3.2.1 + build: hcfcfb64_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_1.conda + sha256: 61ce4e11c3c26ed4e4d9b7e7e2483121a1741ad0f9c8db0a91a28b6e05182ce6 + md5: 958e0418e93e50c575bff70fbcaa12d8 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 8230112 + timestamp: 1710796158475 +- kind: conda + name: openssl + version: 3.2.1 + build: hd590300_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + sha256: 2c689444ed19a603be457284cf2115ee728a3fafb7527326e96054dee7cdc1a7 + md5: 9d731343cff6ee2e5a25c4a091bf8e2a + depends: + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2865379 + timestamp: 1710793235846 +- kind: pypi + name: package-with-extras + version: 0.0.2 + path: ./package_with_extras + sha256: 19df16358ffb05b4c85aa41db2d677c133f4a37decb265a5050d13ebefa7bf49 + requires_dist: + - boltons + - click ; extra == 'cli' + - rich ; extra == 'color' + requires_python: '>=3.7' + editable: true +- kind: pypi + name: pygments + version: 2.17.2 + url: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + sha256: b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c + requires_dist: + - importlib-metadata ; python_version < '3.8' and extra == 'plugins' + - colorama>=0.4.6 ; extra == 'windows-terminal' + requires_python: '>=3.7' +- kind: conda + name: python + version: 3.12.0 + build: h2628c8c_0_cpython + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/python-3.12.0-h2628c8c_0_cpython.conda + sha256: 90553586879bf328f2f9efb8d8faa958ecba822faf379f0a20c3461467b9b955 + md5: defd5d375853a2caff36a19d2d81a28e + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.43.0,<4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.1.3,<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.12.* *_cp312 + license: Python-2.0 + size: 16140836 + timestamp: 1696321871976 +- kind: conda + name: python + version: 3.12.0 + build: h47c9636_0_cpython + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.0-h47c9636_0_cpython.conda + sha256: eb66f8f249caa9d5a956c3a407f079e4779d652ebfc2a4b4f50dcea078e84fa8 + md5: ed8ae98b1b510de68392971b9367d18c + depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libsqlite >=3.43.0,<4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ncurses >=6.4,<7.0a0 + - openssl >=3.1.3,<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.12.* *_cp312 + license: Python-2.0 + size: 13306758 + timestamp: 1696322682581 +- kind: conda + name: python + version: 3.12.0 + build: hab00c5b_0_cpython + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.0-hab00c5b_0_cpython.conda + sha256: 5398ebae6a1ccbfd3f76361eac75f3ac071527a8072627c4bf9008c689034f48 + md5: 7f97faab5bebcc2580f4f299285323da + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.0,<2.1.0a0 + - libsqlite >=3.43.0,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ncurses >=6.4,<7.0a0 + - openssl >=3.1.3,<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.12.* *_cp312 + license: Python-2.0 + size: 32123473 + timestamp: 1696324522323 +- kind: conda + name: readline + version: '8.2' + build: h8228510_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7 + md5: 47d31b792659ce70f470b5c82fdfb7a4 + depends: + - libgcc-ng >=12 + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 281456 + timestamp: 1679532220005 +- kind: conda + name: readline + version: '8.2' + build: h92ec313_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + sha256: a1dfa679ac3f6007362386576a704ad2d0d7a02e98f5d0b115f207a2da63e884 + md5: 8cbb776a2f641b943d413b3e19df71f4 + depends: + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 250351 + timestamp: 1679532511311 +- kind: pypi + name: rich + version: 13.7.1 + url: https://files.pythonhosted.org/packages/87/67/a37f6214d0e9fe57f6ae54b2956d550ca8365857f42a1ce0392bb21d9410/rich-13.7.1-py3-none-any.whl + sha256: 4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222 + requires_dist: + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + - typing-extensions>=4.0.0,<5.0 ; python_version < '3.9' + requires_python: '>=3.7.0' +- kind: conda + name: tk + version: 8.6.13 + build: h5083fa2_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + sha256: 72457ad031b4c048e5891f3f6cb27a53cb479db68a52d965f796910e71a403a8 + md5: b50a57ba89c32b62428b71a875291c9b + depends: + - libzlib >=1.2.13,<1.3.0a0 + license: TCL + license_family: BSD + size: 3145523 + timestamp: 1699202432999 +- kind: conda + name: tk + version: 8.6.13 + build: h5226925_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + sha256: 2c4e914f521ccb2718946645108c9bd3fc3216ba69aea20c2c3cedbd8db32bb1 + md5: fc048363eb8f03cd1737600a5d08aafe + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: TCL + license_family: BSD + size: 3503410 + timestamp: 1699202577803 +- kind: conda + name: tk + version: 8.6.13 + build: noxft_h4845f30_101 + build_number: 101 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e + md5: d453b98d9c83e71da0741bb0ff4d76bc + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: TCL + license_family: BSD + size: 3318875 + timestamp: 1699202167581 +- kind: conda + name: tzdata + version: 2024a + build: h0c530f3_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + sha256: 7b2b69c54ec62a243eb6fba2391b5e443421608c3ae5dbff938ad33ca8db5122 + md5: 161081fc7cec0bfda0d86d7cb595f8d8 + license: LicenseRef-Public-Domain + size: 119815 + timestamp: 1706886945727 +- kind: conda + name: ucrt + version: 10.0.22621.0 + build: h57928b3_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + sha256: f29cdaf8712008f6b419b8b1a403923b00ab2504bfe0fb2ba8eb60e72d4f14c6 + md5: 72608f6cd3e5898229c3ea16deb1ac43 + constrains: + - vs2015_runtime >=14.29.30037 + license: LicenseRef-Proprietary + license_family: PROPRIETARY + size: 1283972 + timestamp: 1666630199266 +- kind: conda + name: vc + version: '14.3' + build: hcf57466_18 + build_number: 18 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda + sha256: 447a8d8292a7b2107dcc18afb67f046824711a652725fc0f522c368e7a7b8318 + md5: 20e1e652a4c740fa719002a8449994a2 + depends: + - vc14_runtime >=14.38.33130 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + size: 16977 + timestamp: 1702511255313 +- kind: conda + name: vc14_runtime + version: 14.38.33130 + build: h82b7239_18 + build_number: 18 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda + sha256: bf94c9af4b2e9cba88207001197e695934eadc96a5c5e4cd7597e950aae3d8ff + md5: 8be79fdd2725ddf7bbf8a27a4c1f79ba + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.38.33130.* *_18 + license: LicenseRef-ProprietaryMicrosoft + license_family: Proprietary + size: 749868 + timestamp: 1702511239004 +- kind: conda + name: vs2015_runtime + version: 14.38.33130 + build: hcb4865c_18 + build_number: 18 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda + sha256: a2fec221f361d6263c117f4ea6d772b21c90a2f8edc6f3eb0eadec6bfe8843db + md5: 10d42885e3ed84e575b454db30f1aa93 + depends: + - vc14_runtime >=14.38.33130 + license: BSD-3-Clause + license_family: BSD + size: 16988 + timestamp: 1702511261442 +- kind: conda + name: xz + version: 5.2.6 + build: h166bdaf_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162 + md5: 2161070d867d1b1204ea749c8eec4ef0 + depends: + - libgcc-ng >=12 + license: LGPL-2.1 and GPL-2.0 + size: 418368 + timestamp: 1660346797927 +- kind: conda + name: xz + version: 5.2.6 + build: h57fd34a_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + sha256: 59d78af0c3e071021cfe82dc40134c19dab8cdf804324b62940f5c8cd71803ec + md5: 39c6b54e94014701dd157f4f576ed211 + license: LGPL-2.1 and GPL-2.0 + size: 235693 + timestamp: 1660346961024 +- kind: conda + name: xz + version: 5.2.6 + build: h8d14728_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + sha256: 54d9778f75a02723784dc63aff4126ff6e6749ba21d11a6d03c1f4775f269fe0 + md5: 515d77642eaa3639413c6b1bc3f94219 + depends: + - vc >=14.1,<15 + - vs2015_runtime >=14.16.27033 + license: LGPL-2.1 and GPL-2.0 + size: 217804 + timestamp: 1660346976440 diff --git a/examples/editable-with-extras/pixi.toml b/examples/editable-with-extras/pixi.toml new file mode 100644 index 0000000000..d6e56a4262 --- /dev/null +++ b/examples/editable-with-extras/pixi.toml @@ -0,0 +1,15 @@ +[project] +name = "editable-with-extras" +version = "0.1.0" +description = "Add a short description here" +authors = ["Tim de Jager "] +channels = ["conda-forge"] +platforms = ["osx-arm64", "linux-64", "win-64"] + +[tasks] + +[dependencies] +python = "3.12" + +[pypi-dependencies] +package_with_extras = { path = "./package_with_extras", editable = true, extras = ["cli", "color"]} From 9dcc59180605b8c59ddf3d74625e1b3d71143d66 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 15:23:11 +0100 Subject: [PATCH 14/22] fix: typo --- src/lock_file/resolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index b3f96d49e9..6d8a832e78 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -246,7 +246,7 @@ pub async fn resolve_pypi( } // Get the Pypi requirements - // partion the requirements into editable and non-editable requirements + // partition the requirements into editable and non-editable requirements let (editables, requirements): (Vec<_>, Vec<_>) = dependencies .iter() .flat_map(|(name, req)| req.iter().map(move |req| (name, req))) From 54c6356d0f5e65cd362d0f82c66a77343f14eeaf Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 15:51:17 +0100 Subject: [PATCH 15/22] feat: fix the case where the path is not a directory --- src/lock_file/resolve.rs | 22 +++++++++++++--------- src/lock_file/satisfiability.rs | 25 ++++++++++++++----------- src/project/manifest/python.rs | 6 ++++++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/lock_file/resolve.rs b/src/lock_file/resolve.rs index 6d8a832e78..5844deb1a8 100644 --- a/src/lock_file/resolve.rs +++ b/src/lock_file/resolve.rs @@ -450,8 +450,7 @@ pub async fn resolve_pypi( dist.url .given() .map(|path| UrlOrPath::Path(PathBuf::from(path))) - // When using a direct url reference like https://foo/bla.whl we do not have a given - .unwrap_or_else(|| UrlOrPath::Url(dist.url.to_url())), + .expect("path should be given"), None, ), }; @@ -507,10 +506,16 @@ pub async fn resolve_pypi( SourceDist::Git(git) => (git.url.to_url().into(), hash, false), SourceDist::Path(path) => { // Compute the hash of the package based on the source tree. - let hash = PypiSourceTreeHashable::from_directory(&path.path) - .into_diagnostic() - .context("failed to compute hash of pypi source tree")? - .hash(); + let hash = if path.path.is_dir() { + Some( + PypiSourceTreeHashable::from_directory(&path.path) + .into_diagnostic() + .context("failed to compute hash of pypi source tree")? + .hash(), + ) + } else { + None + }; // Create the url for the lock file. This is based on the passed in URL // instead of from the source path to copy the path that was passed in from @@ -519,10 +524,9 @@ pub async fn resolve_pypi( .url .given() .map(|path| UrlOrPath::Path(PathBuf::from(path))) - // When using a direct url reference like https://foo/bla.whl we do not have a given - .unwrap_or_else(|| path.url.to_url().into()); + .expect("path should be given"); - (url_or_path, Some(hash), path.editable) + (url_or_path, hash, path.editable) } }; diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index 1f64bfd689..efb553d47a 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -532,19 +532,22 @@ pub fn verify_package_platform_satisfiability( if pypi_packages_visited.insert(idx) { // If this is path based package we need to check if the source tree hash still matches. + // and if it is a directory if let UrlOrPath::Path(path) = &record.0.url_or_path { - let hashable = PypiSourceTreeHashable::from_directory(path) - .map_err(|e| { - PlatformUnsat::FailedToDetermineSourceTreeHash( + if path.is_dir() { + let hashable = PypiSourceTreeHashable::from_directory(path) + .map_err(|e| { + PlatformUnsat::FailedToDetermineSourceTreeHash( + record.0.name.clone(), + e, + ) + })? + .hash(); + if Some(hashable) != record.0.hash { + return Err(PlatformUnsat::SourceTreeHashMismatch( record.0.name.clone(), - e, - ) - })? - .hash(); - if Some(hashable) != record.0.hash { - return Err(PlatformUnsat::SourceTreeHashMismatch( - record.0.name.clone(), - )); + )); + } } } diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index 2c92b54316..4011c514aa 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -307,6 +307,8 @@ pub enum AsPep508Error { source: url::ParseError, url: String, }, + #[error("using an editable flag for a path that is not a directory: {path}")] + EditableIsNotDir { path: PathBuf }, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -419,6 +421,10 @@ impl PyPiRequirement { let verbatim = VerbatimUrl::from_path(canonicalized.clone()).with_given(given); if *editable == Some(true) { + if !path.is_dir() { + return Err(AsPep508Error::EditableIsNotDir { path: path.clone() }); + } + return Ok(RequirementOrEditable::Editable( name.clone(), requirements_txt::EditableRequirement { From 8e3b34a6d31cc910d4018256d539e3f111b4a790 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 16:04:22 +0100 Subject: [PATCH 16/22] feat: add editable to schema --- schema/model.py | 2 ++ schema/schema.json | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/schema/model.py b/schema/model.py index 87fafa89ff..499ecda15d 100644 --- a/schema/model.py +++ b/schema/model.py @@ -125,6 +125,8 @@ class PyPIPathRequirement(_PyPIRequirement): None, description="A path to a local source or wheel", ) + editable: Optional[bool] = Field(None, description="If true the package will be installed as editable") + class PyPIUrlRequirement(_PyPIRequirement): diff --git a/schema/schema.json b/schema/schema.json index 561cbdd0d1..fe8a0a9549 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -774,6 +774,19 @@ "minLength": 1, "title": "Path", "type": "string" + }, + "editable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "If true the package will be installed as editable", + "title": "Editable" } }, "title": "PyPIPathRequirement", From 7861593d9bc40a9032183f729ab0f07df45d2bc0 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 16:06:41 +0100 Subject: [PATCH 17/22] fix: sort cargo file --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 11380fe5b8..13b2935842 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,6 @@ rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } - #rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } #rattler_digest = { path = "../rattler/crates/rattler_digest" } #rattler_networking = { path = "../rattler/crates/rattler_networking" } From 29178442e2e94bc11df885553a16c6f566384daa Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 16:19:20 +0100 Subject: [PATCH 18/22] fix: remove vendored function --- src/install_pypi.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/install_pypi.rs b/src/install_pypi.rs index 7f78de2ab0..7b8da6f5cc 100644 --- a/src/install_pypi.rs +++ b/src/install_pypi.rs @@ -208,17 +208,6 @@ enum ValidateInstall { Reinstall, } -//TODO(tim): Vendored this function from uv there is a PR #2510 that exposes this function -/// Read the `direct_url.json` file from a `.dist-info` directory. -fn direct_url_json(path: &Path) -> miette::Result> { - let path = path.join("direct_url.json"); - let Ok(file) = std::fs::File::open(path) else { - return Ok(None); - }; - let direct_url = serde_json::from_reader(file).into_diagnostic()?; - Ok(Some(direct_url)) -} - /// Check freshness of a locked url against an installed dist fn check_url_freshness(locked_url: &Url, installed_dist: &InstalledDist) -> miette::Result { if let Ok(archive) = locked_url.to_file_path() { @@ -261,7 +250,7 @@ fn need_reinstall( // For installed distributions check the direct_url.json to check if a re-install is needed InstalledDist::Url(direct_url) => { - let direct_url_json = match direct_url_json(&direct_url.path) { + let direct_url_json = match InstalledDist::direct_url(&direct_url.path) { Ok(Some(direct_url)) => direct_url, Ok(None) => { tracing::warn!( From 16f1701773b13078135213c81751ce059721c100 Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Tue, 26 Mar 2024 16:36:39 +0100 Subject: [PATCH 19/22] fix: satifies not using correct path in some cases --- examples/docker/pixi.lock | 442 ++++++++++-------- .../package_with_extras/pyproject.toml | 4 +- examples/editable-with-extras/pixi.lock | 2 +- src/lock_file/satisfiability.rs | 1 + src/project/manifest/python.rs | 2 +- 5 files changed, 250 insertions(+), 201 deletions(-) diff --git a/examples/docker/pixi.lock b/examples/docker/pixi.lock index b981f458ae..75f17330bb 100644 --- a/examples/docker/pixi.lock +++ b/examples/docker/pixi.lock @@ -17,40 +17,40 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gunicorn-21.2.0-py312h7900ff3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.22.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - 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.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.3.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -66,40 +66,40 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gunicorn-21.2.0-py312h996f985_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.22.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.5.0-hd600fc2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.1-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.5-py312h9ef2f89_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4.20240210-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.2-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.3.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -114,34 +114,34 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.22.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pep517-0.13.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.3.25-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -158,32 +158,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gunicorn-21.2.0-py312h7900ff3_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - 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.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h98912ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -195,32 +195,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gunicorn-21.2.0-py312h996f985_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.5.0-hd600fc2_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.1-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.5-py312h9ef2f89_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4.20240210-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.12.2-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -231,26 +231,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.0.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gunicorn-21.2.0-py312h81bd7bf_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.1.2-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py312he37b823_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.0.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.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/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - pypi: . @@ -314,6 +314,8 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/blinker size: 17886 timestamp: 1698890303249 - kind: conda @@ -425,6 +427,8 @@ packages: - python >=3.8 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/click size: 84437 timestamp: 1692311973840 - kind: conda @@ -440,6 +444,8 @@ packages: - python >=3.7 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/colorama size: 25170 timestamp: 1666700778190 - kind: pypi @@ -462,6 +468,8 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/editables size: 10988 timestamp: 1705857085102 - kind: conda @@ -477,6 +485,8 @@ packages: depends: - python >=3.7 license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup size: 20551 timestamp: 1704921321122 - kind: conda @@ -498,6 +508,8 @@ packages: - werkzeug >=3.0.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/flask size: 80485 timestamp: 1707044052869 - kind: conda @@ -516,6 +528,8 @@ packages: - setuptools >=3.0 license: MIT license_family: MIT + purls: + - pkg:pypi/gunicorn size: 175766 timestamp: 1695414940887 - kind: conda @@ -535,6 +549,8 @@ packages: - setuptools >=3.0 license: MIT license_family: MIT + purls: + - pkg:pypi/gunicorn size: 177170 timestamp: 1695415163069 - kind: conda @@ -554,17 +570,19 @@ packages: - setuptools >=3.0 license: MIT license_family: MIT + purls: + - pkg:pypi/gunicorn size: 176702 timestamp: 1695415096357 - kind: conda name: hatchling - version: 1.21.1 + version: 1.22.4 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.21.1-pyhd8ed1ab_0.conda - sha256: ca648490ba47939ff43b880935a4968ea2b18d2c25281129185bb6b4aa7f1c9b - md5: 06f93e43be153b8de3955bdf636cb0ef + url: https://conda.anaconda.org/conda-forge/noarch/hatchling-1.22.4-pyhd8ed1ab_0.conda + sha256: e047a6fb6dd790f0cb5dd904809c81d38bdeee974726442f9274f6ac367f68a3 + md5: 8320faf2e07543de1e3968b733c44da1 depends: - editables >=0.3 - importlib-metadata @@ -576,24 +594,26 @@ packages: - trove-classifiers license: MIT license_family: MIT - size: 58374 - timestamp: 1706161223269 + purls: + - pkg:pypi/hatchling + size: 62671 + timestamp: 1711286880652 - kind: conda name: importlib-metadata - version: 7.0.1 + version: 7.1.0 build: pyha770c72_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.1-pyha770c72_0.conda - sha256: e72d05f171f4567004c9360a838e9d5df21e23dcfeb945066b53a6e5f754b861 - md5: 746623a787e06191d80a2133e5daff17 + url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda + sha256: cc2e7d1f7f01cede30feafc1118b7aefa244d0a12224513734e24165ae12ba49 + md5: 0896606848b2dc5cebdf111b6543aa04 depends: - python >=3.8 - zipp >=0.5 license: Apache-2.0 license_family: APACHE - size: 26450 - timestamp: 1703269427097 + size: 27043 + timestamp: 1710971498183 - kind: conda name: iniconfig version: 2.0.0 @@ -607,6 +627,8 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/iniconfig size: 11101 timestamp: 1673103208955 - kind: conda @@ -622,6 +644,8 @@ packages: - python >=3.7 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/itsdangerous size: 16377 timestamp: 1648147263536 - kind: conda @@ -638,6 +662,8 @@ packages: - python >=3.7 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/jinja2 size: 111589 timestamp: 1704967140287 - kind: conda @@ -670,53 +696,50 @@ packages: timestamp: 1674833843183 - kind: conda name: libexpat - version: 2.5.0 - build: hb7217d7_1 - build_number: 1 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.5.0-hb7217d7_1.conda - sha256: 7d143a9c991579ad4207f84c632650a571c66329090daa32b3c87cf7311c3381 - md5: 5a097ad3d17e42c148c9566280481317 + version: 2.6.2 + build: h2f0025b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + sha256: 07453df3232a649f39fb4d1e68cfe1c78c3457764f85225f6f3ccd1bdd9818a4 + md5: 1b9f46b804a2c3c5d7fd6a80b77c35f9 + depends: + - libgcc-ng >=12 constrains: - - expat 2.5.0.* + - expat 2.6.2.* license: MIT license_family: MIT - size: 63442 - timestamp: 1680190916539 + size: 72544 + timestamp: 1710362309065 - kind: conda name: libexpat - version: 2.5.0 - build: hcb278e6_1 - build_number: 1 + version: 2.6.2 + build: h59595ed_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - sha256: 74c98a563777ae2ad71f1f74d458a8ab043cee4a513467c159ccf159d0e461f3 - md5: 6305a3dd2752c76335295da4e581f2fd + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d depends: - libgcc-ng >=12 constrains: - - expat 2.5.0.* + - expat 2.6.2.* license: MIT license_family: MIT - size: 77980 - timestamp: 1680190528313 + size: 73730 + timestamp: 1710362120304 - kind: conda name: libexpat - version: 2.5.0 - build: hd600fc2_1 - build_number: 1 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.5.0-hd600fc2_1.conda - sha256: b4651d196d5adb0637c678d874160a318078d963caec264bda7ac07ff6a1cbc7 - md5: 6cd3d0a28437b3845c260f9d71d434d7 - depends: - - libgcc-ng >=12 + version: 2.6.2 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 constrains: - - expat 2.5.0.* + - expat 2.6.2.* license: MIT license_family: MIT - size: 77194 - timestamp: 1680190675750 + size: 63655 + timestamp: 1710362424980 - kind: conda name: libffi version: 3.4.2 @@ -853,45 +876,45 @@ packages: timestamp: 1697359010159 - kind: conda name: libsqlite - version: 3.45.1 + version: 3.45.2 build: h091b4b1_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.1-h091b4b1_0.conda - sha256: 64befc456a38907d1334fb58eb604a96625d3a23a2f34fbd203e0b307a4a141e - md5: a153a40a253962373b5330eb9d182da9 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e + md5: 9d07427ee5bd9afd1e11ce14368a48d6 depends: - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 824677 - timestamp: 1707495428497 + size: 825300 + timestamp: 1710255078823 - kind: conda name: libsqlite - version: 3.45.1 + version: 3.45.2 build: h194ca79_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.1-h194ca79_0.conda - sha256: 2aeb33230d074c9c91605def8296475dc0c064c23bd50ccfacb8336ec4bfc422 - md5: 4190198deb1ed253eb938f6a6d92ff4f + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + sha256: 0ce6de6369c04386cfc8696b1f795f425843789609ae2e04e7a1eb7deae62a8b + md5: bf4c96a21fbfc6a6ef6a7781a534a4e0 depends: - libgcc-ng >=12 - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 1034865 - timestamp: 1707495102245 + size: 1038462 + timestamp: 1710253998432 - kind: conda name: libsqlite - version: 3.45.1 + version: 3.45.2 build: h2797004_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda - sha256: 1b379d1c652b25d0540251d422ef767472e768fd36b77261045e97f9ba6d3faa - md5: fc4ccadfbf6d4784de88c41704792562 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 + md5: 866983a220e27a80cb75e85cb30466a1 depends: - libgcc-ng >=12 - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 859346 - timestamp: 1707495156652 + size: 857489 + timestamp: 1710254744982 - kind: conda name: libuuid version: 2.38.1 @@ -1013,6 +1036,8 @@ packages: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/markupsafe size: 26685 timestamp: 1706900070330 - kind: conda @@ -1031,6 +1056,8 @@ packages: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/markupsafe size: 27435 timestamp: 1706901498578 - kind: conda @@ -1049,74 +1076,73 @@ packages: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/markupsafe size: 26382 timestamp: 1706900495057 - kind: conda name: ncurses - version: '6.4' - build: h0425590_2 - build_number: 2 + version: 6.4.20240210 + build: h0425590_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda - sha256: d71cf2f2b1a9fae7ee2455a35a890423838e9594294beb4a002fe7c7b10bc086 - md5: 4ff0a396150dedad4269e16e5810f769 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4.20240210-h0425590_0.conda + sha256: 4223dc34e2bddd37bf995158ae481e00be375b287d539bc7a0532634c0fc63b7 + md5: c1a1612ddaee95c83abfa0b2ec858626 depends: - libgcc-ng >=12 license: X11 AND BSD-3-Clause - size: 920540 - timestamp: 1698751239554 + size: 926594 + timestamp: 1710866633409 - kind: conda name: ncurses - version: '6.4' - build: h463b476_2 - build_number: 2 + version: 6.4.20240210 + build: h078ce10_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4-h463b476_2.conda - sha256: f6890634f815e8408d08f36503353f8dfd7b055e4c3b9ea2ee52180255cf4b0a - md5: 52b6f254a7b9663e854f44b6570ed982 - depends: - - __osx >=10.9 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + sha256: 06f0905791575e2cd3aa961493c56e490b3d82ad9eb49f1c332bd338b0216911 + md5: 616ae8691e6608527d0071e6766dcb81 license: X11 AND BSD-3-Clause - size: 794741 - timestamp: 1698751574074 + size: 820249 + timestamp: 1710866874348 - kind: conda name: ncurses - version: '6.4' - build: h59595ed_2 - build_number: 2 + version: 6.4.20240210 + build: h59595ed_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda - sha256: 91cc03f14caf96243cead96c76fe91ab5925a695d892e83285461fb927dece5e - md5: 7dbaa197d7ba6032caf7ae7f32c1efa0 + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + sha256: aa0f005b6727aac6507317ed490f0904430584fa8ca722657e7f0fb94741de81 + md5: 97da8860a0da5413c7c98a3b3838a645 depends: - libgcc-ng >=12 license: X11 AND BSD-3-Clause - size: 884434 - timestamp: 1698751260967 + size: 895669 + timestamp: 1710866638986 - kind: conda name: openssl version: 3.2.1 - build: h0d3ecfb_0 + build: h0d3ecfb_1 + build_number: 1 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - sha256: 13663fcd4abc8681b31ccbad39800fee2127cb6159b51a989ed48a816af36cf5 - md5: 421cc6e8715447b73c2c57dcf78cb9d2 + url: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + sha256: 519dc941d7ab0ebf31a2878d85c2f444450e7c5f6f41c4d07252c6bb3417b78b + md5: eb580fb888d93d5d550c557323ac5cee depends: - ca-certificates constrains: - pyopenssl >=22.1 license: Apache-2.0 license_family: Apache - size: 2862719 - timestamp: 1706635779319 + size: 2855250 + timestamp: 1710793435903 - kind: conda name: openssl version: 3.2.1 - build: h31becfc_0 + build: h31becfc_1 + build_number: 1 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - sha256: 952ef5de4e3913621a89ca2eb8186683bb73832527219c6443c260a6b46cd149 - md5: b7e7c53240214ae96f52a440c0b0126a + url: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + sha256: 055a26e99ebc12ae0cf23266a0e62e71b59b8ce8cafb1ebb87e375ef9c758d7b + md5: e95eb18d256edc72058e0dc9be5338a0 depends: - ca-certificates - libgcc-ng >=12 @@ -1124,16 +1150,17 @@ packages: - pyopenssl >=22.1 license: Apache-2.0 license_family: Apache - size: 3382700 - timestamp: 1706635800272 + size: 3380844 + timestamp: 1710793424665 - kind: conda name: openssl version: 3.2.1 - build: hd590300_0 + build: hd590300_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - sha256: c02c12bdb898daacf7eb3d09859f93ea8f285fd1a6132ff6ff0493ab52c7fe57 - md5: 51a753e64a3027bd7e23a189b1f6e91e + url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + sha256: 2c689444ed19a603be457284cf2115ee728a3fafb7527326e96054dee7cdc1a7 + md5: 9d731343cff6ee2e5a25c4a091bf8e2a depends: - ca-certificates - libgcc-ng >=12 @@ -1141,23 +1168,25 @@ packages: - pyopenssl >=22.1 license: Apache-2.0 license_family: Apache - size: 2863069 - timestamp: 1706635653339 + size: 2865379 + timestamp: 1710793235846 - kind: conda name: packaging - version: '23.2' + version: '24.0' build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - sha256: 69b3ace6cca2dab9047b2c24926077d81d236bef45329d264b394001e3c3e52f - md5: 79002079284aa895f883c6b7f3f88fd6 + url: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + sha256: a390182d74c31dfd713c16db888c92c277feeb6d1fe96ff9d9c105f9564be48a + md5: 248f521b64ce055e7feae3105e7abeb8 depends: - - python >=3.7 + - python >=3.8 license: Apache-2.0 license_family: APACHE - size: 49452 - timestamp: 1696202521121 + purls: + - pkg:pypi/packaging + size: 49832 + timestamp: 1710076089469 - kind: conda name: pathspec version: 0.12.1 @@ -1171,6 +1200,8 @@ packages: - python >=3.7 license: MPL-2.0 license_family: MOZILLA + purls: + - pkg:pypi/pathspec size: 41173 timestamp: 1702250135032 - kind: conda @@ -1204,6 +1235,8 @@ packages: - wheel license: MIT license_family: MIT + purls: + - pkg:pypi/pip size: 1398245 timestamp: 1706960660581 - kind: conda @@ -1219,32 +1252,35 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/pluggy size: 23384 timestamp: 1706116931972 - kind: conda name: pytest - version: 8.0.1 - build: pyhd8ed1ab_1 - build_number: 1 + version: 8.1.1 + build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.1-pyhd8ed1ab_1.conda - sha256: b429ba053376757d9ee5da455f205aade2d21ef6de1cd39192f0f398bbd9db75 - md5: 246e33679291d4e85111d812e5103de7 + url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + sha256: 3c481d6b54af1a33c32a3f3eaa3e0971955431e7023db55808740cd062271c73 + md5: 94ff09cdedcb7b17e9cd5097ee2cfcff depends: - colorama - exceptiongroup >=1.0.0rc8 - iniconfig - packaging - - pluggy <2.0,>=1.3.0 + - pluggy <2.0,>=1.4 - python >=3.8 - - tomli >=1.0.0 + - tomli >=1 constrains: - pytest-faulthandler >=2 license: MIT license_family: MIT - size: 251405 - timestamp: 1708433025645 + purls: + - pkg:pypi/pytest + size: 255523 + timestamp: 1709992719691 - kind: conda name: python version: 3.12.2 @@ -1424,19 +1460,21 @@ packages: timestamp: 1679532511311 - kind: conda name: setuptools - version: 69.1.1 + version: 69.2.0 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.1.1-pyhd8ed1ab_0.conda - sha256: 7a6dca60efcaa42d0ebb784950bc16230a968256cb5048a4441cb34653b5ec58 - md5: 576de899521b7d43674ba3ef6eae9142 + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + sha256: 78a75c75a5dacda6de5f4056c9c990141bdaf4f64245673a590594d00bc63713 + md5: da214ecd521a720a9d521c68047682dc depends: - python >=3.8 license: MIT license_family: MIT - size: 469644 - timestamp: 1708702431036 + purls: + - pkg:pypi/setuptools + size: 471183 + timestamp: 1710344615844 - kind: conda name: tk version: 8.6.13 @@ -1496,23 +1534,27 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/tomli size: 15940 timestamp: 1644342331069 - kind: conda name: trove-classifiers - version: 2024.2.23 + version: 2024.3.25 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.2.23-pyhd8ed1ab_0.conda - sha256: 396c9c0cb125ad04179d90d8bb51b19efd8ac2798e1d2eb1005f46cad1d63995 - md5: da7095027cb05a436b4bd15e5f804a26 + url: https://conda.anaconda.org/conda-forge/noarch/trove-classifiers-2024.3.25-pyhd8ed1ab_0.conda + sha256: 909b4288bd2be8566f6d0a311d75a7e0e1cf81c42c19c97b1fc7d043c3db3301 + md5: e565e537d9760fc5d6d02ae4521a144b depends: - python >=3.7 license: Apache-2.0 license_family: Apache - size: 18423 - timestamp: 1708761937727 + purls: + - pkg:pypi/trove-classifiers + size: 18393 + timestamp: 1711440195159 - kind: conda name: tzdata version: 2024a @@ -1539,23 +1581,27 @@ packages: - python >=3.8 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/werkzeug size: 241704 timestamp: 1698235401441 - kind: conda name: wheel - version: 0.42.0 + version: 0.43.0 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda - sha256: 80be0ccc815ce22f80c141013302839b0ed938a2edb50b846cf48d8a8c1cfa01 - md5: 1cdea58981c5cbc17b51973bcaddcea7 + url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.43.0-pyhd8ed1ab_0.conda + sha256: 14ebc6f098ebc796669fa6e7d437086a0ee527c8694ff2062a8bcb6dbd9b1581 + md5: 6e43a94e0ee67523b5e781f0faba5c45 depends: - python >=3.7 license: MIT license_family: MIT - size: 57553 - timestamp: 1701013309664 + purls: + - pkg:pypi/wheel + size: 58048 + timestamp: 1711016334007 - kind: conda name: xz version: 5.2.6 @@ -1606,5 +1652,7 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/zipp size: 18954 timestamp: 1695255262261 diff --git a/examples/editable-with-extras/package_with_extras/pyproject.toml b/examples/editable-with-extras/package_with_extras/pyproject.toml index 223e185e3b..26edc62d06 100644 --- a/examples/editable-with-extras/package_with_extras/pyproject.toml +++ b/examples/editable-with-extras/package_with_extras/pyproject.toml @@ -22,5 +22,5 @@ color = ["rich"] cli = ["click"] [build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" +requires = ["hatchling"] +build-backend = "hatchling.build" diff --git a/examples/editable-with-extras/pixi.lock b/examples/editable-with-extras/pixi.lock index 45d8427a01..4e48226e9e 100644 --- a/examples/editable-with-extras/pixi.lock +++ b/examples/editable-with-extras/pixi.lock @@ -582,7 +582,7 @@ packages: name: package-with-extras version: 0.0.2 path: ./package_with_extras - sha256: 19df16358ffb05b4c85aa41db2d677c133f4a37decb265a5050d13ebefa7bf49 + sha256: c2160511f4d81f291503314dccd8ef5c739ec3f57e0e4e570b2e08da77ba36fc requires_dist: - boltons - click ; extra == 'cli' diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index efb553d47a..6454425d2d 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -534,6 +534,7 @@ pub fn verify_package_platform_satisfiability( // If this is path based package we need to check if the source tree hash still matches. // and if it is a directory if let UrlOrPath::Path(path) = &record.0.url_or_path { + let path = project_root.join(path); if path.is_dir() { let hashable = PypiSourceTreeHashable::from_directory(path) .map_err(|e| { diff --git a/src/project/manifest/python.rs b/src/project/manifest/python.rs index 4011c514aa..0dd234f494 100644 --- a/src/project/manifest/python.rs +++ b/src/project/manifest/python.rs @@ -421,7 +421,7 @@ impl PyPiRequirement { let verbatim = VerbatimUrl::from_path(canonicalized.clone()).with_given(given); if *editable == Some(true) { - if !path.is_dir() { + if !canonicalized.is_dir() { return Err(AsPep508Error::EditableIsNotDir { path: path.clone() }); } From 49485264b2a26e36e492155b1a37a66a2f0a1dbe Mon Sep 17 00:00:00 2001 From: Ruben Arts Date: Wed, 27 Mar 2024 16:26:54 +0100 Subject: [PATCH 20/22] docs: update documentation for editable and source dependencies in pypi-dependencies --- docs/configuration.md | 87 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 63558870ca..0fae82c859 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -260,12 +260,9 @@ PyPI packages are not indexed on [prefix.dev](https://prefix.dev/channels) but c !!! warning "Important considerations" - **Stability**: PyPI packages might be less stable than their conda counterparts. Prefer using conda packages in the `dependencies` table where possible. - - **Compatibility limitations**: Currently, pixi doesn't support: - - `git` dependencies (`git+https://github.com/package-org/package.git`) - - Source dependencies - - Private PyPI repositories + - **Compatibility limitations**: Currently, pixi doesn't support: Private PyPI repositories -#### PEP404 Version specification: +#### Version specification: These dependencies don't follow the conda matchspec specification. The `version` is a string specification of the version according to [PEP404/PyPA](https://packaging.python.org/en/latest/specifications/version-specifiers/). Additionally, a list of extra's can be included, which are essentially optional dependencies. @@ -280,10 +277,78 @@ See the example below to see how this is used in practice: python = ">=3.6" [pypi-dependencies] -pytest = "*" # This means any version (the wildcard `*` is a pixi addition, not part of the specification) +fastapi = "*" # This means any version (the wildcard `*` is a pixi addition, not part of the specification) pre-commit = "~=3.5.0" # This is a single version specifier # Using the toml map allows the user to add `extras` -requests = {version = ">= 2.8.1, ==2.8.*", extras=["security", "tests"]} +pandas = { version = ">=1.0.0", extras = ["dataframe", "sql"]} + +# git dependencies +# With ssh +flask = { git = "ssh://git@github.com/pallets/flask" } +# With https and a specific revision +requests = { git = "https://github.com/psf/requests.git", rev = "0106aced5faa299e6ede89d1230bd6784f2c3660" } +# TODO: will support later -> branch = '' or tag = '' to specify a branch or tag + +# You can also directly add a source dependency from a path, tip keep this relative to the root of the project. +minimal-project = { path = "./minimal-project", editable = true} + +# You can also use a direct url, to either a `.tar.gz` or `.zip`, or a `.whl` file +click = { url = "https://github.com/pallets/click/releases/download/8.1.7/click-8.1.7-py3-none-any.whl" } + +# You can also just the default git repo, it will checkout the default branch +pytest = { git = "https://github.com/pytest-dev/pytest.git"} +``` + +#### Full specification +The full specification of a PyPI dependencies that pixi supports can be split into the following fields: +##### `extras` +A list of extras to install with the package. e.g. `["dataframe", "sql"]` +The extras field works with all other version specifiers as it is an addition to the version specifier. +```toml +pandas = { version = ">=1.0.0", extras = ["dataframe", "sql"]} +pytest = { git = "URL", extras = ["dev"]} +black = { url = "URL", extras = ["cli"]} +minimal-project = { path = "./minimal-project", editable = true, extras = ["dev"]} +``` + +##### `version` +The version of the package to install. e.g. `">=1.0.0"` or `*` which stands for any version, this is pixi specific. +Version is our default field so using no inline table (`{}`) will default to this field. +```toml +py-rattler = "*" +ruff = "~=1.0.0" +pytest = {version = "*", extras = ["dev"]} +``` + +##### `git` +A git repository to install from. +This support both https:// and ssh:// urls. + +Use `git` in combination with `rev` or `subdirectory`: +- `rev`: A specific revision to install. e.g. `rev = "0106aced5faa299e6ede89d1230bd6784f2c3660` +- `subdirectory`: A subdirectory to install from. `subdirectory = "src"` or `subdirectory = "src/packagex"` + +```toml +# Note don't forget the `ssh://` or `https://` prefix! +pytest = { git = "https://github.com/pytest-dev/pytest.git"} +requests = { git = "https://github.com/psf/requests.git", rev = "0106aced5faa299e6ede89d1230bd6784f2c3660" } +py-rattler = { git = "ssh://git@github.com:mamba-org/rattler.git", subdirectory = "py-rattler" } +``` + +##### `path` +A local path to install from. e.g. `path = "./path/to/package"` +We would advise to keep your path projects in the project, and to use a relative path. + +Set `editable` to `true` to install in editable mode, this is highly recommended as it is hard to reinstall if you're not using editable mode. e.g. `editable = true` + +```toml +minimal-project = { path = "./minimal-project", editable = true} +``` + +##### `url` +A URL to install a wheel or sdist directly from an url. +```toml +pandas = {url = "https://files.pythonhosted.org/packages/3d/59/2afa81b9fb300c90531803c0fd43ff4548074fa3e8d0f747ef63b3b5e77a/pandas-2.2.1.tar.gz"} ``` @@ -291,15 +356,19 @@ requests = {version = ">= 2.8.1, ==2.8.*", extras=["security", "tests"]} Use the `--pypi` flag with the `add` command to quickly add PyPI packages from the CLI. E.g `pixi add --pypi flask` -#### Source dependencies + _This does not support all the features of the `pypi-dependencies` table yet._ + +#### Source dependencies (`sdist`) The [Source Distribution Format](https://packaging.python.org/en/latest/specifications/source-distribution-format/) is a source based format (sdist for short), that a package can include alongside the binary wheel format. Because these distributions need to be built, the need a python executable to do this. This is why python needs to be present in a conda environment. Sdists usually depend on system packages to be built, especially when compiling C/C++ based python bindings. -Think for example of Python SDL2 bindindings depending on the C library: SDL2. +Think for example of Python SDL2 bindings depending on the C library: SDL2. To help built these dependencies we activate the conda environment that includes these pypi dependencies before resolving. This way when a source distribution depends on `gcc` for example, it's used from the conda environment instead of the system. + + ### `host-dependencies` This table contains dependencies that are needed to build your project but which should not be included when your project is installed as part of another project. From cb18494a3422d54ab2bfd27d6e9f4fc2c0c6ca4a Mon Sep 17 00:00:00 2001 From: Tim de Jager Date: Thu, 28 Mar 2024 10:48:00 +0100 Subject: [PATCH 21/22] feat: tried to fix satifiability for windows --- src/lock_file/satisfiability.rs | 9 +++++++-- ...ling_satisiability@missing-pypi-extra__pixi.toml.snap | 3 +-- ...iling_satisiability@solve-groups-pypi__pixi.toml.snap | 3 +-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index 6454425d2d..6bcb3cb1c8 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -12,7 +12,7 @@ use rattler_conda_types::{ }; use rattler_lock::{ConversionError, Package, PypiPackageData, PypiSourceTreeHashable, UrlOrPath}; use requirements_txt::EditableRequirement; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{ borrow::Cow, @@ -82,6 +82,9 @@ pub enum PlatformUnsat { #[error("source tree hash for {0} does not match the hash in the lock-file")] SourceTreeHashMismatch(PackageName), + + #[error("the path '{0}, cannot be canonicalized")] + FailedToCanonicalizePath(PathBuf, #[source] std::io::Error), } /// Verifies that all the requirements of the specified `environment` can be satisfied with the @@ -534,7 +537,9 @@ pub fn verify_package_platform_satisfiability( // If this is path based package we need to check if the source tree hash still matches. // and if it is a directory if let UrlOrPath::Path(path) = &record.0.url_or_path { - let path = project_root.join(path); + let path = dunce::canonicalize(project_root.join(path)).map_err(|e| { + PlatformUnsat::FailedToCanonicalizePath(path.clone(), e) + })?; if path.is_dir() { let hashable = PypiSourceTreeHashable::from_directory(path) .map_err(|e| { diff --git a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap index 81a4b9fa12..91b3f3b84e 100644 --- a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap +++ b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@missing-pypi-extra__pixi.toml.snap @@ -1,9 +1,8 @@ --- source: src/lock_file/satisfiability.rs -assertion_line: 736 expression: s input_file: tests/non-satisfiability/missing-pypi-extra/pixi.toml --- environment 'default' does not satisfy the requirements of the project for platform 'win-64 Diagnostic severity: error - Caused by: the requirement 'ipython>=7.8.0 ; extra == 'jupyter'' could not be satisfied (required by 'black') + Caused by: the requirement 'ipython >=7.8.0 ; extra == 'jupyter'' could not be satisfied (required by 'black') diff --git a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap index d3b929e3cc..3307572d17 100644 --- a/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap +++ b/src/lock_file/snapshots/pixi__lock_file__satisfiability__tests__failing_satisiability@solve-groups-pypi__pixi.toml.snap @@ -1,9 +1,8 @@ --- source: src/lock_file/satisfiability.rs -assertion_line: 736 expression: s input_file: tests/non-satisfiability/solve-groups-pypi/pixi.toml --- environment 'default' does not satisfy the requirements of the project for platform 'win-64 Diagnostic severity: error - Caused by: the requirement 'packaging>=20.0' could not be satisfied (required by 'matplotlib') + Caused by: the requirement 'packaging >=20.0' could not be satisfied (required by 'matplotlib') From c27515ae30689c6baa4eabaf03245a8af679f13c Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Thu, 28 Mar 2024 14:19:22 +0100 Subject: [PATCH 22/22] fix: normalize file new-lines when computing hashes --- Cargo.lock | 22 +++++++++++----------- Cargo.toml | 18 +++++++++--------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f702ddc69b..7657b77f96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3373,7 +3373,7 @@ dependencies = [ [[package]] name = "rattler" version = "0.19.5" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "anyhow", "async-compression", @@ -3419,7 +3419,7 @@ dependencies = [ [[package]] name = "rattler_conda_types" version = "0.20.3" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "chrono", "fxhash", @@ -3448,7 +3448,7 @@ dependencies = [ [[package]] name = "rattler_digest" version = "0.19.2" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "blake2", "digest", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "rattler_lock" version = "0.21.0" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "chrono", "fxhash", @@ -3486,7 +3486,7 @@ dependencies = [ [[package]] name = "rattler_macros" version = "0.19.2" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "quote", "syn 2.0.53", @@ -3495,7 +3495,7 @@ dependencies = [ [[package]] name = "rattler_networking" version = "0.20.0" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "anyhow", "async-trait", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "rattler_package_streaming" version = "0.20.1" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "bzip2", "chrono", @@ -3551,7 +3551,7 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" version = "0.19.4" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "anyhow", "async-compression", @@ -3590,7 +3590,7 @@ dependencies = [ [[package]] name = "rattler_shell" version = "0.19.4" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "enum_dispatch", "indexmap 2.2.5", @@ -3607,7 +3607,7 @@ dependencies = [ [[package]] name = "rattler_solve" version = "0.20.3" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "anyhow", "chrono", @@ -3627,7 +3627,7 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" version = "0.19.4" -source = "git+https://github.com/baszalmstra/rattler?rev=e5aaed3e2551399985e3c11a87c2c0aedb31b0d3#e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" +source = "git+https://github.com/baszalmstra/rattler?rev=b6ccac0f72df9617d6d02220595ed4595aa34e1c#b6ccac0f72df9617d6d02220595ed4595aa34e1c" dependencies = [ "cfg-if", "libloading", diff --git a/Cargo.toml b/Cargo.toml index c984aca4f7..679fa23f76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -163,15 +163,15 @@ pep440_rs = { git = "https://github.com/astral-sh/uv", tag = "0.1.24" } pep508_rs = { git = "https://github.com/astral-sh/uv", tag = "0.1.24" } # deno_task_shell = { path = "../deno_task_shell" } -rattler = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_digest = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_lock = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_networking = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } -rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "e5aaed3e2551399985e3c11a87c2c0aedb31b0d3" } +rattler = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_digest = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_lock = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_networking = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_shell = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_solve = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } +rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", rev = "b6ccac0f72df9617d6d02220595ed4595aa34e1c" } #rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } #rattler_digest = { path = "../rattler/crates/rattler_digest" } #rattler_networking = { path = "../rattler/crates/rattler_networking" }