Respect tool.uv.environments in pip compile --universal (#6663)

## Summary

We now respect the `environments` field in `uv pip compile --universal`,
e.g.:

```toml
[tool.uv]
environments = ["platform_system == 'Emscripten'"]
```

Closes https://github.com/astral-sh/uv/issues/6641.
This commit is contained in:
Charlie Marsh 2024-08-26 19:58:17 -04:00 committed by GitHub
parent 154ea243d0
commit 1ae2c3f142
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 179 additions and 45 deletions

View file

@ -1,78 +0,0 @@
use std::str::FromStr;
use serde::ser::SerializeSeq;
use pep508_rs::MarkerTree;
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct SupportedEnvironments(Vec<MarkerTree>);
impl SupportedEnvironments {
/// Return the list of marker trees.
pub fn as_markers(&self) -> &[MarkerTree] {
&self.0
}
/// Convert the [`SupportedEnvironments`] struct into a list of marker trees.
pub fn into_markers(self) -> Vec<MarkerTree> {
self.0
}
}
/// Serialize a [`SupportedEnvironments`] struct into a list of marker strings.
impl serde::Serialize for SupportedEnvironments {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for element in &self.0 {
if let Some(contents) = element.contents() {
seq.serialize_element(&contents)?;
}
}
seq.end()
}
}
/// Deserialize a marker string or list of marker strings into a [`SupportedEnvironments`] struct.
impl<'de> serde::Deserialize<'de> for SupportedEnvironments {
fn deserialize<D>(deserializer: D) -> Result<SupportedEnvironments, D::Error>
where
D: serde::Deserializer<'de>,
{
struct StringOrVecVisitor;
impl<'de> serde::de::Visitor<'de> for StringOrVecVisitor {
type Value = SupportedEnvironments;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string or a list of strings")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let marker = MarkerTree::from_str(value).map_err(serde::de::Error::custom)?;
Ok(SupportedEnvironments(vec![marker]))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut markers = Vec::new();
while let Some(elem) = seq.next_element::<String>()? {
let marker = MarkerTree::from_str(&elem).map_err(serde::de::Error::custom)?;
markers.push(marker);
}
Ok(SupportedEnvironments(markers))
}
}
deserializer.deserialize_any(StringOrVecVisitor)
}
}

View file

@ -1,10 +1,8 @@
pub use environments::SupportedEnvironments;
pub use workspace::{
check_nested_workspaces, DiscoveryOptions, ProjectWorkspace, VirtualProject, Workspace,
WorkspaceError, WorkspaceMember,
};
mod environments;
pub mod pyproject;
pub mod pyproject_mut;
mod workspace;

View file

@ -14,9 +14,8 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use url::Url;
use crate::environments::SupportedEnvironments;
use pep440_rs::VersionSpecifiers;
use pypi_types::{RequirementSource, VerbatimParsedUrl};
use pypi_types::{RequirementSource, SupportedEnvironments, VerbatimParsedUrl};
use uv_git::GitReference;
use uv_macros::OptionsMetadata;
use uv_normalize::{ExtraName, PackageName};
@ -121,11 +120,14 @@ pub struct ToolUv {
/// By default, uv will resolve for all possible environments during a `uv lock` operation.
/// However, you can restrict the set of supported environments to improve performance and avoid
/// unsatisfiable branches in the solution space.
///
/// These environments will also respected when `uv pip compile` is invoked with the
/// `--universal` flag.
#[cfg_attr(
feature = "schemars",
schemars(
with = "Option<Vec<String>>",
description = "A list of environment markers, e.g. `python_version >= '3.6'`."
description = "A list of environment markers, e.g., `python_version >= '3.6'`."
)
)]
#[option(

View file

@ -9,12 +9,11 @@ use rustc_hash::FxHashSet;
use tracing::{debug, trace, warn};
use pep508_rs::{MarkerTree, RequirementOrigin, VerbatimUrl};
use pypi_types::{Requirement, RequirementSource, VerbatimParsedUrl};
use pypi_types::{Requirement, RequirementSource, SupportedEnvironments, VerbatimParsedUrl};
use uv_fs::Simplified;
use uv_normalize::{GroupName, PackageName, DEV_DEPENDENCIES};
use uv_warnings::warn_user;
use crate::environments::SupportedEnvironments;
use crate::pyproject::{Project, PyProjectToml, Source, ToolUvWorkspace};
#[derive(thiserror::Error, Debug)]