uv-pypi-types: rename "conflicting group" types to more generic "conflicts"

Since this is intended to support _both_ groups and extras, it doesn't
make sense to just name it for groups. And since there isn't really a
word that encapsulates both "extra" and "group," we just fall back to
the super general "conflicts."

We'll rename the variables and other things in the next commit.
This commit is contained in:
Andrew Gallant 2024-11-13 10:08:36 -05:00 committed by Andrew Gallant
parent 84d50ce81a
commit 19a044d4db
17 changed files with 150 additions and 160 deletions

View file

@ -97,7 +97,7 @@ mod resolver {
use uv_pep440::Version;
use uv_pep508::{MarkerEnvironment, MarkerEnvironmentBuilder};
use uv_platform_tags::{Arch, Os, Platform, Tags};
use uv_pypi_types::{ConflictingGroupList, ResolverMarkerEnvironment};
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
use uv_python::Interpreter;
use uv_resolver::{
FlatIndex, InMemoryIndex, Manifest, OptionsBuilder, PythonRequirement, RequiresPython,
@ -163,7 +163,7 @@ mod resolver {
let options = OptionsBuilder::new().exclude_newer(exclude_newer).build();
let sources = SourceStrategy::default();
let dependency_metadata = DependencyMetadata::default();
let conflicting_groups = ConflictingGroupList::empty();
let conflicting_groups = Conflicts::empty();
let python_requirement = if universal {
PythonRequirement::from_requires_python(

View file

@ -26,7 +26,7 @@ use uv_distribution_types::{
};
use uv_git::GitResolver;
use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
use uv_pypi_types::{ConflictingGroupList, Requirement};
use uv_pypi_types::{Conflicts, Requirement};
use uv_python::{Interpreter, PythonEnvironment};
use uv_resolver::{
ExcludeNewer, FlatIndex, Flexibility, InMemoryIndex, Manifest, OptionsBuilder,
@ -188,7 +188,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
ResolverEnvironment::specific(marker_env),
// Conflicting groups only make sense when doing
// universal resolution.
ConflictingGroupList::empty(),
Conflicts::empty(),
Some(tags),
self.flat_index,
self.index,

View file

@ -8,104 +8,104 @@ use uv_normalize::{ExtraName, PackageName};
#[derive(
Debug, Default, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
)]
pub struct ConflictingGroupList(Vec<ConflictingGroups>);
pub struct Conflicts(Vec<ConflictSet>);
impl ConflictingGroupList {
impl Conflicts {
/// Returns no conflicting groups.
///
/// This results in no effect on resolution.
pub fn empty() -> ConflictingGroupList {
ConflictingGroupList::default()
pub fn empty() -> Conflicts {
Conflicts::default()
}
/// Push a set of conflicting groups.
pub fn push(&mut self, groups: ConflictingGroups) {
self.0.push(groups);
/// Push a single set of conflicts.
pub fn push(&mut self, set: ConflictSet) {
self.0.push(set);
}
/// Returns an iterator over all sets of conflicting groups.
pub fn iter(&self) -> impl Iterator<Item = &'_ ConflictingGroups> + '_ {
/// Returns an iterator over all sets of conflicting sets.
pub fn iter(&self) -> impl Iterator<Item = &'_ ConflictSet> + '_ {
self.0.iter()
}
/// Returns true if this conflicting group list contains any conflicting
/// group set that contains the given package and extra name pair.
/// Returns true if these conflicts contain any set that contains the given
/// package and extra name pair.
pub fn contains(&self, package: &PackageName, extra: &ExtraName) -> bool {
self.iter().any(|groups| groups.contains(package, extra))
}
/// Returns true if this set of conflicting groups is empty.
/// Returns true if there are no conflicts.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Appends the given list to this one. This drains all elements
/// from the list given, such that after this call, it is empty.
pub fn append(&mut self, other: &mut ConflictingGroupList) {
/// Appends the given conflicts to this one. This drains all sets from the
/// conflicts given, such that after this call, it is empty.
pub fn append(&mut self, other: &mut Conflicts) {
self.0.append(&mut other.0);
}
}
/// A single set of package-extra pairs that conflict with one another.
///
/// Within each set of conflicting groups, the resolver should isolate
/// the requirements corresponding to each extra from the requirements of
/// other extras in this set. That is, the resolver should put each set of
/// requirements in a different fork.
/// Within each set of conflicts, the resolver should isolate the requirements
/// corresponding to each extra from the requirements of other extras in
/// this set. That is, the resolver should put each set of requirements in a
/// different fork.
///
/// A `TryFrom<Vec<ConflictingGroup>>` impl may be used to build a set
/// from a sequence. Note though that at least 2 groups are required.
/// A `TryFrom<Vec<ConflictItem>>` impl may be used to build a set from a
/// sequence. Note though that at least 2 items are required.
#[derive(Debug, Default, Clone, Eq, PartialEq, serde::Serialize, schemars::JsonSchema)]
pub struct ConflictingGroups(Vec<ConflictingGroup>);
pub struct ConflictSet(Vec<ConflictItem>);
impl ConflictingGroups {
/// Create a pair of groups that conflict with one another.
pub fn pair(group1: ConflictingGroup, group2: ConflictingGroup) -> ConflictingGroups {
ConflictingGroups(vec![group1, group2])
impl ConflictSet {
/// Create a pair of items that conflict with one another.
pub fn pair(item1: ConflictItem, item2: ConflictItem) -> ConflictSet {
ConflictSet(vec![item1, item2])
}
/// Add a new conflicting group to this set.
pub fn push(&mut self, group: ConflictingGroup) {
self.0.push(group);
/// Add a new conflicting item to this set.
pub fn push(&mut self, item: ConflictItem) {
self.0.push(item);
}
/// Returns an iterator over all conflicting groups.
pub fn iter(&self) -> impl Iterator<Item = &'_ ConflictingGroup> + '_ {
/// Returns an iterator over all conflicting items.
pub fn iter(&self) -> impl Iterator<Item = &'_ ConflictItem> + '_ {
self.0.iter()
}
/// Returns true if this conflicting group contains the given
/// package and extra name pair.
/// Returns true if this conflicting item contains the given package and
/// extra name pair.
pub fn contains(&self, package: &PackageName, extra: &ExtraName) -> bool {
self.iter()
.any(|group| group.package() == package && group.extra() == extra)
}
}
impl<'de> serde::Deserialize<'de> for ConflictingGroups {
fn deserialize<D>(deserializer: D) -> Result<ConflictingGroups, D::Error>
impl<'de> serde::Deserialize<'de> for ConflictSet {
fn deserialize<D>(deserializer: D) -> Result<ConflictSet, D::Error>
where
D: serde::Deserializer<'de>,
{
let groups = Vec::<ConflictingGroup>::deserialize(deserializer)?;
let groups = Vec::<ConflictItem>::deserialize(deserializer)?;
Self::try_from(groups).map_err(serde::de::Error::custom)
}
}
impl TryFrom<Vec<ConflictingGroup>> for ConflictingGroups {
type Error = ConflictingGroupError;
impl TryFrom<Vec<ConflictItem>> for ConflictSet {
type Error = ConflictError;
fn try_from(groups: Vec<ConflictingGroup>) -> Result<ConflictingGroups, ConflictingGroupError> {
match groups.len() {
0 => return Err(ConflictingGroupError::ZeroGroups),
1 => return Err(ConflictingGroupError::OneGroup),
fn try_from(items: Vec<ConflictItem>) -> Result<ConflictSet, ConflictError> {
match items.len() {
0 => return Err(ConflictError::ZeroItems),
1 => return Err(ConflictError::OneItem),
_ => {}
}
Ok(ConflictingGroups(groups))
Ok(ConflictSet(items))
}
}
/// A single item in a set conflicting groups.
/// A single item in a conflicting set.
///
/// Each item is a pair of a package and a corresponding extra name for that
/// package.
@ -122,99 +122,99 @@ impl TryFrom<Vec<ConflictingGroup>> for ConflictingGroups {
serde::Serialize,
schemars::JsonSchema,
)]
pub struct ConflictingGroup {
pub struct ConflictItem {
package: PackageName,
extra: ExtraName,
}
impl ConflictingGroup {
/// Returns the package name of this conflicting group.
impl ConflictItem {
/// Returns the package name of this conflicting item.
pub fn package(&self) -> &PackageName {
&self.package
}
/// Returns the extra name of this conflicting group.
/// Returns the extra name of this conflicting item.
pub fn extra(&self) -> &ExtraName {
&self.extra
}
/// Returns this group as a new type with its fields borrowed.
pub fn as_ref(&self) -> ConflictingGroupRef<'_> {
ConflictingGroupRef {
/// Returns this item as a new type with its fields borrowed.
pub fn as_ref(&self) -> ConflictItemRef<'_> {
ConflictItemRef {
package: self.package(),
extra: self.extra(),
}
}
}
impl From<(PackageName, ExtraName)> for ConflictingGroup {
fn from((package, extra): (PackageName, ExtraName)) -> ConflictingGroup {
ConflictingGroup { package, extra }
impl From<(PackageName, ExtraName)> for ConflictItem {
fn from((package, extra): (PackageName, ExtraName)) -> ConflictItem {
ConflictItem { package, extra }
}
}
/// A single item in a set conflicting groups, by reference.
/// A single item in a conflicting set, by reference.
///
/// Each item is a pair of a package and a corresponding extra name for that
/// package.
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ConflictingGroupRef<'a> {
pub struct ConflictItemRef<'a> {
package: &'a PackageName,
extra: &'a ExtraName,
}
impl<'a> ConflictingGroupRef<'a> {
/// Returns the package name of this conflicting group.
impl<'a> ConflictItemRef<'a> {
/// Returns the package name of this conflicting item.
pub fn package(&self) -> &'a PackageName {
self.package
}
/// Returns the extra name of this conflicting group.
/// Returns the extra name of this conflicting item.
pub fn extra(&self) -> &'a ExtraName {
self.extra
}
/// Converts this borrowed conflicting group to its owned variant.
pub fn to_owned(&self) -> ConflictingGroup {
ConflictingGroup {
/// Converts this borrowed conflicting item to its owned variant.
pub fn to_owned(&self) -> ConflictItem {
ConflictItem {
package: self.package().clone(),
extra: self.extra().clone(),
}
}
}
impl<'a> From<(&'a PackageName, &'a ExtraName)> for ConflictingGroupRef<'a> {
fn from((package, extra): (&'a PackageName, &'a ExtraName)) -> ConflictingGroupRef<'a> {
ConflictingGroupRef { package, extra }
impl<'a> From<(&'a PackageName, &'a ExtraName)> for ConflictItemRef<'a> {
fn from((package, extra): (&'a PackageName, &'a ExtraName)) -> ConflictItemRef<'a> {
ConflictItemRef { package, extra }
}
}
/// An error that occurs when the given conflicting groups are invalid somehow.
/// An error that occurs when the given conflicting set is invalid somehow.
#[derive(Debug, thiserror::Error)]
pub enum ConflictingGroupError {
/// An error for when there are zero conflicting groups.
pub enum ConflictError {
/// An error for when there are zero conflicting items.
#[error("Each set of conflicting groups must have at least two entries, but found none")]
ZeroGroups,
/// An error for when there is one conflicting group.
ZeroItems,
/// An error for when there is one conflicting items.
#[error("Each set of conflicting groups must have at least two entries, but found only one")]
OneGroup,
OneItem,
}
/// Like [`ConflictingGroupList`], but for deserialization in `pyproject.toml`.
/// Like [`Conflicts`], but for deserialization in `pyproject.toml`.
///
/// The schema format is different from the in-memory format. Specifically, the
/// schema format does not allow specifying the package name (or will make it
/// optional in the future), where as the in-memory format needs the package
/// name.
///
/// N.B. `ConflictingGroupList` is still used for (de)serialization.
/// Specifically, in the lock file, where the package name is required.
/// N.B. `Conflicts` is still used for (de)serialization. Specifically, in the
/// lock file, where the package name is required.
#[derive(
Debug, Default, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
)]
pub struct SchemaConflictingGroupList(Vec<SchemaConflictingGroups>);
pub struct SchemaConflicts(Vec<SchemaConflictSet>);
impl SchemaConflictingGroupList {
impl SchemaConflicts {
/// Convert the public schema "conflicting" type to our internal fully
/// resolved type. Effectively, this pairs the corresponding package name
/// with each conflict.
@ -222,34 +222,34 @@ impl SchemaConflictingGroupList {
/// If a conflict has an explicit package name (written by the end user),
/// then that takes precedence over the given package name, which is only
/// used when there is no explicit package name written.
pub fn to_conflicting_with_package_name(&self, package: &PackageName) -> ConflictingGroupList {
let mut conflicting = ConflictingGroupList::empty();
pub fn to_conflicting_with_package_name(&self, package: &PackageName) -> Conflicts {
let mut conflicting = Conflicts::empty();
for tool_uv_set in &self.0 {
let mut set = vec![];
for item in &tool_uv_set.0 {
let package = item.package.clone().unwrap_or_else(|| package.clone());
set.push(ConflictingGroup::from((package, item.extra.clone())));
set.push(ConflictItem::from((package, item.extra.clone())));
}
// OK because we guarantee that
// `SchemaConflictingGroupList` is valid and there aren't
// any new errors that can occur here.
let set = ConflictingGroups::try_from(set).unwrap();
let set = ConflictSet::try_from(set).unwrap();
conflicting.push(set);
}
conflicting
}
}
/// Like [`ConflictingGroups`], but for deserialization in `pyproject.toml`.
/// Like [`ConflictSet`], but for deserialization in `pyproject.toml`.
///
/// The schema format is different from the in-memory format. Specifically, the
/// schema format does not allow specifying the package name (or will make it
/// optional in the future), where as the in-memory format needs the package
/// name.
#[derive(Debug, Default, Clone, Eq, PartialEq, serde::Serialize, schemars::JsonSchema)]
pub struct SchemaConflictingGroups(Vec<SchemaConflictingGroup>);
pub struct SchemaConflictSet(Vec<SchemaConflictItem>);
/// Like [`ConflictingGroup`], but for deserialization in `pyproject.toml`.
/// Like [`ConflictItem`], but for deserialization in `pyproject.toml`.
///
/// The schema format is different from the in-memory format. Specifically, the
/// schema format does not allow specifying the package name (or will make it
@ -269,33 +269,31 @@ pub struct SchemaConflictingGroups(Vec<SchemaConflictingGroup>);
schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct SchemaConflictingGroup {
pub struct SchemaConflictItem {
#[serde(default)]
package: Option<PackageName>,
extra: ExtraName,
}
impl<'de> serde::Deserialize<'de> for SchemaConflictingGroups {
fn deserialize<D>(deserializer: D) -> Result<SchemaConflictingGroups, D::Error>
impl<'de> serde::Deserialize<'de> for SchemaConflictSet {
fn deserialize<D>(deserializer: D) -> Result<SchemaConflictSet, D::Error>
where
D: serde::Deserializer<'de>,
{
let items = Vec::<SchemaConflictingGroup>::deserialize(deserializer)?;
let items = Vec::<SchemaConflictItem>::deserialize(deserializer)?;
Self::try_from(items).map_err(serde::de::Error::custom)
}
}
impl TryFrom<Vec<SchemaConflictingGroup>> for SchemaConflictingGroups {
type Error = ConflictingGroupError;
impl TryFrom<Vec<SchemaConflictItem>> for SchemaConflictSet {
type Error = ConflictError;
fn try_from(
items: Vec<SchemaConflictingGroup>,
) -> Result<SchemaConflictingGroups, ConflictingGroupError> {
fn try_from(items: Vec<SchemaConflictItem>) -> Result<SchemaConflictSet, ConflictError> {
match items.len() {
0 => return Err(ConflictingGroupError::ZeroGroups),
1 => return Err(ConflictingGroupError::OneGroup),
0 => return Err(ConflictError::ZeroItems),
1 => return Err(ConflictError::OneItem),
_ => {}
}
Ok(SchemaConflictingGroups(items))
Ok(SchemaConflictSet(items))
}
}

View file

@ -40,8 +40,8 @@ use uv_pep440::Version;
use uv_pep508::{split_scheme, MarkerEnvironment, MarkerTree, VerbatimUrl, VerbatimUrlError};
use uv_platform_tags::{TagCompatibility, TagPriority, Tags};
use uv_pypi_types::{
redact_credentials, ConflictingGroupList, HashDigest, ParsedArchiveUrl, ParsedGitUrl,
Requirement, RequirementSource,
redact_credentials, Conflicts, HashDigest, ParsedArchiveUrl, ParsedGitUrl, Requirement,
RequirementSource,
};
use uv_types::{BuildContext, HashStrategy};
use uv_workspace::dependency_groups::DependencyGroupError;
@ -82,7 +82,7 @@ pub struct Lock {
/// forks in the lockfile so we can recreate them in subsequent resolutions.
fork_markers: Vec<MarkerTree>,
/// The conflicting groups/extras specified by the user.
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
/// The list of supported environments specified by the user.
supported_environments: Vec<MarkerTree>,
/// The range of supported Python versions.
@ -239,7 +239,7 @@ impl Lock {
requires_python,
options,
ResolverManifest::default(),
ConflictingGroupList::empty(),
Conflicts::empty(),
vec![],
graph.fork_markers.clone(),
)?;
@ -315,7 +315,7 @@ impl Lock {
requires_python: RequiresPython,
options: ResolverOptions,
manifest: ResolverManifest,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
supported_environments: Vec<MarkerTree>,
fork_markers: Vec<MarkerTree>,
) -> Result<Self, LockError> {
@ -485,7 +485,7 @@ impl Lock {
/// Record the conflicting groups that were used to generate this lock.
#[must_use]
pub fn with_conflicting_groups(mut self, conflicting_groups: ConflictingGroupList) -> Self {
pub fn with_conflicting_groups(mut self, conflicting_groups: Conflicts) -> Self {
self.conflicting_groups = conflicting_groups;
self
}
@ -550,7 +550,7 @@ impl Lock {
}
/// Returns the conflicting groups that were used to generate this lock.
pub fn conflicting_groups(&self) -> &ConflictingGroupList {
pub fn conflicting_groups(&self) -> &Conflicts {
&self.conflicting_groups
}
@ -1384,7 +1384,7 @@ struct LockWire {
#[serde(rename = "supported-markers", default)]
supported_environments: Vec<SimplifiedMarkerTree>,
#[serde(rename = "conflicting-groups", default)]
conflicting_groups: Option<ConflictingGroupList>,
conflicting_groups: Option<Conflicts>,
/// We discard the lockfile if these options match.
#[serde(default)]
options: ResolverOptions,
@ -1436,8 +1436,7 @@ impl TryFrom<LockWire> for Lock {
wire.requires_python,
wire.options,
wire.manifest,
wire.conflicting_groups
.unwrap_or_else(ConflictingGroupList::empty),
wire.conflicting_groups.unwrap_or_else(Conflicts::empty),
supported_environments,
fork_markers,
)?;

View file

@ -3,7 +3,7 @@ use std::sync::Arc;
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep508::{MarkerTree, MarkerTreeContents};
use uv_pypi_types::ConflictingGroupRef;
use uv_pypi_types::ConflictItemRef;
use crate::python_requirement::PythonRequirement;
@ -190,10 +190,10 @@ impl PubGrubPackage {
///
/// If this package can't possibly be classified as a conflicting group,
/// then this returns `None`.
pub(crate) fn conflicting_group(&self) -> Option<ConflictingGroupRef<'_>> {
pub(crate) fn conflicting_group(&self) -> Option<ConflictItemRef<'_>> {
let package = self.name_no_root()?;
let extra = self.extra()?;
Some(ConflictingGroupRef::from((package, extra)))
Some(ConflictItemRef::from((package, extra)))
}
/// Returns `true` if this PubGrub package is a proxy package.

View file

@ -18,7 +18,7 @@ use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::{Version, VersionSpecifier};
use uv_pep508::{MarkerEnvironment, MarkerTree, MarkerTreeKind};
use uv_pypi_types::{
ConflictingGroupList, HashDigest, ParsedUrlError, Requirement, VerbatimParsedUrl, Yanked,
Conflicts, HashDigest, ParsedUrlError, Requirement, VerbatimParsedUrl, Yanked,
};
use crate::graph_ops::marker_reachability;
@ -103,7 +103,7 @@ impl ResolutionGraph {
index: &InMemoryIndex,
git: &GitResolver,
python: &PythonRequirement,
conflicting_groups: &ConflictingGroupList,
conflicting_groups: &Conflicts,
resolution_strategy: &ResolutionStrategy,
options: Options,
) -> Result<Self, ResolveError> {

View file

@ -3,9 +3,7 @@ use std::sync::Arc;
use rustc_hash::{FxHashMap, FxHashSet};
use uv_normalize::{ExtraName, PackageName};
use uv_pep508::{MarkerEnvironment, MarkerTree};
use uv_pypi_types::{
ConflictingGroup, ConflictingGroupList, ConflictingGroupRef, ResolverMarkerEnvironment,
};
use uv_pypi_types::{ConflictItem, ConflictItemRef, Conflicts, ResolverMarkerEnvironment};
use crate::pubgrub::{PubGrubDependency, PubGrubPackage};
use crate::requires_python::RequiresPythonRange;
@ -165,7 +163,7 @@ impl ResolverEnvironment {
/// Returns true if the dependency represented by this forker may be
/// included in the given resolver environment.
pub(crate) fn included_by_group(&self, group: ConflictingGroupRef<'_>) -> bool {
pub(crate) fn included_by_group(&self, group: ConflictItemRef<'_>) -> bool {
match self.kind {
Kind::Specific { .. } => true,
Kind::Universal { ref exclude, .. } => !exclude
@ -229,7 +227,7 @@ impl ResolverEnvironment {
/// specific marker environment. i.e., "pip"-style resolution.
pub(crate) fn exclude_by_group(
&self,
groups: impl IntoIterator<Item = ConflictingGroup>,
groups: impl IntoIterator<Item = ConflictItem>,
) -> ResolverEnvironment {
match self.kind {
Kind::Specific { .. } => {
@ -427,7 +425,7 @@ impl<'d> Forker<'d> {
pub(crate) fn fork(
&self,
env: &ResolverEnvironment,
_conflicting_groups: &ConflictingGroupList,
_conflicting_groups: &Conflicts,
) -> Option<(Forker<'d>, Vec<ResolverEnvironment>)> {
if !env.included_by_marker(&self.marker) {
return None;

View file

@ -38,8 +38,7 @@ use uv_pep440::{release_specifiers_to_ranges, Version, MIN_VERSION};
use uv_pep508::MarkerTree;
use uv_platform_tags::Tags;
use uv_pypi_types::{
ConflictingGroup, ConflictingGroupList, ConflictingGroupRef, Requirement, ResolutionMetadata,
VerbatimParsedUrl,
ConflictItem, ConflictItemRef, Conflicts, Requirement, ResolutionMetadata, VerbatimParsedUrl,
};
use uv_types::{BuildContext, HashStrategy, InstalledPackagesProvider};
use uv_warnings::warn_user_once;
@ -110,7 +109,7 @@ struct ResolverState<InstalledPackages: InstalledPackagesProvider> {
hasher: HashStrategy,
env: ResolverEnvironment,
python_requirement: PythonRequirement,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
workspace_members: BTreeSet<PackageName>,
selector: CandidateSelector,
index: InMemoryIndex,
@ -151,7 +150,7 @@ impl<'a, Context: BuildContext, InstalledPackages: InstalledPackagesProvider>
options: Options,
python_requirement: &'a PythonRequirement,
env: ResolverEnvironment,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
tags: Option<&'a Tags>,
flat_index: &'a FlatIndex,
index: &'a InMemoryIndex,
@ -199,7 +198,7 @@ impl<Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvider>
hasher: &HashStrategy,
env: ResolverEnvironment,
python_requirement: &PythonRequirement,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
index: &InMemoryIndex,
git: &GitResolver,
capabilities: &IndexCapabilities,
@ -1631,7 +1630,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
return None;
}
if !env.included_by_group(
ConflictingGroupRef::from((&requirement.name, source_extra)),
ConflictItemRef::from((&requirement.name, source_extra)),
) {
return None;
}
@ -1724,7 +1723,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
return None;
}
if !env.included_by_group(
ConflictingGroupRef::from((&requirement.name, source_extra)),
ConflictItemRef::from((&requirement.name, source_extra)),
) {
return None;
}
@ -2695,7 +2694,7 @@ impl Dependencies {
self,
env: &ResolverEnvironment,
python_requirement: &PythonRequirement,
conflicting_groups: &ConflictingGroupList,
conflicting_groups: &Conflicts,
) -> ForkedDependencies {
let deps = match self {
Dependencies::Available(deps) => deps,
@ -2776,7 +2775,7 @@ impl Forks {
name_to_deps: BTreeMap<PackageName, Vec<PubGrubDependency>>,
env: &ResolverEnvironment,
python_requirement: &PythonRequirement,
conflicting_groups: &ConflictingGroupList,
conflicting_groups: &Conflicts,
) -> Forks {
let python_marker = python_requirement.to_marker_tree();
@ -3016,7 +3015,7 @@ impl Fork {
/// Returns true if any of the dependencies in this fork contain a
/// dependency with the given package and extra values.
fn contains_conflicting_group(&self, group: ConflictingGroupRef<'_>) -> bool {
fn contains_conflicting_group(&self, group: ConflictItemRef<'_>) -> bool {
self.conflicting_groups
.get(group.package())
.map(|set| set.contains(group.extra()))
@ -3026,7 +3025,7 @@ impl Fork {
/// Exclude the given groups from this fork.
///
/// This removes all dependencies matching the given conflicting groups.
fn exclude(mut self, groups: impl IntoIterator<Item = ConflictingGroup>) -> Fork {
fn exclude(mut self, groups: impl IntoIterator<Item = ConflictItem>) -> Fork {
self.env = self.env.exclude_by_group(groups);
self.dependencies.retain(|dep| {
let Some(conflicting_group) = dep.package.conflicting_group() else {
@ -3114,10 +3113,7 @@ impl PartialOrd for Fork {
/// depends on `c[x2]`. That's a conflict, but not easily detectable unless
/// you reject either `c[x1]` or `c[x2]` on the grounds that `x1` and `x2` are
/// conflicting and thus cannot be enabled unconditionally.
fn find_conflicting_extra(
conflicting: &ConflictingGroupList,
reqs: &[Requirement],
) -> Option<ResolveError> {
fn find_conflicting_extra(conflicting: &Conflicts, reqs: &[Requirement]) -> Option<ResolveError> {
for req in reqs {
for extra in &req.extras {
if conflicting.contains(&req.name, extra) {

View file

@ -8,7 +8,7 @@ use uv_configuration::{
};
use uv_distribution_types::{Index, IndexUrl, PipExtraIndex, PipFindLinks, PipIndex};
use uv_install_wheel::linker::LinkMode;
use uv_pypi_types::{SchemaConflictingGroupList, SupportedEnvironments};
use uv_pypi_types::{SchemaConflicts, SupportedEnvironments};
use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
use uv_resolver::{AnnotationStyle, ExcludeNewer, PrereleaseMode, ResolutionMode};
@ -90,7 +90,7 @@ impl_combine_or!(PythonVersion);
impl_combine_or!(ResolutionMode);
impl_combine_or!(String);
impl_combine_or!(SupportedEnvironments);
impl_combine_or!(SchemaConflictingGroupList);
impl_combine_or!(SchemaConflicts);
impl_combine_or!(TargetTriple);
impl_combine_or!(TrustedPublishing);
impl_combine_or!(Url);

View file

@ -25,8 +25,7 @@ use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::{Version, VersionSpecifiers};
use uv_pep508::MarkerTree;
use uv_pypi_types::{
ConflictingGroupList, RequirementSource, SchemaConflictingGroupList, SupportedEnvironments,
VerbatimParsedUrl,
Conflicts, RequirementSource, SchemaConflicts, SupportedEnvironments, VerbatimParsedUrl,
};
#[derive(Error, Debug)]
@ -103,8 +102,8 @@ impl PyProjectToml {
}
/// Returns the set of conflicts for the project.
pub fn conflicting_groups(&self) -> ConflictingGroupList {
let empty = ConflictingGroupList::empty();
pub fn conflicting_groups(&self) -> Conflicts {
let empty = Conflicts::empty();
let Some(project) = self.project.as_ref() else {
return empty;
};
@ -504,7 +503,7 @@ pub struct ToolUv {
"#
)]
*/
pub conflicting_groups: Option<SchemaConflictingGroupList>,
pub conflicting_groups: Option<SchemaConflicts>,
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]

View file

@ -11,7 +11,7 @@ use uv_distribution_types::Index;
use uv_fs::{Simplified, CWD};
use uv_normalize::{GroupName, PackageName, DEV_DEPENDENCIES};
use uv_pep508::{MarkerTree, RequirementOrigin, VerbatimUrl};
use uv_pypi_types::{ConflictingGroupList, Requirement, RequirementSource, SupportedEnvironments};
use uv_pypi_types::{Conflicts, Requirement, RequirementSource, SupportedEnvironments};
use uv_static::EnvVars;
use uv_warnings::{warn_user, warn_user_once};
@ -393,8 +393,8 @@ impl Workspace {
}
/// Returns the set of conflicts for the workspace.
pub fn conflicting_groups(&self) -> ConflictingGroupList {
let mut conflicting = ConflictingGroupList::empty();
pub fn conflicting_groups(&self) -> Conflicts {
let mut conflicting = Conflicts::empty();
for member in self.packages.values() {
conflicting.append(&mut member.pyproject_toml.conflicting_groups());
}

View file

@ -23,7 +23,7 @@ use uv_fs::Simplified;
use uv_git::GitResolver;
use uv_install_wheel::linker::LinkMode;
use uv_normalize::PackageName;
use uv_pypi_types::{ConflictingGroupList, Requirement, SupportedEnvironments};
use uv_pypi_types::{Conflicts, Requirement, SupportedEnvironments};
use uv_python::{
EnvironmentPreference, PythonEnvironment, PythonInstallation, PythonPreference, PythonRequest,
PythonVersion, VersionRequest,
@ -54,7 +54,7 @@ pub(crate) async fn pip_compile(
constraints_from_workspace: Vec<Requirement>,
overrides_from_workspace: Vec<Requirement>,
environments: SupportedEnvironments,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
extras: ExtrasSpecification,
output_file: Option<&Path>,
resolution_mode: ResolutionMode,
@ -264,7 +264,7 @@ pub(crate) async fn pip_compile(
(
Some(tags),
ResolverEnvironment::specific(marker_env),
ConflictingGroupList::empty(),
Conflicts::empty(),
)
};

View file

@ -20,7 +20,7 @@ use uv_fs::Simplified;
use uv_install_wheel::linker::LinkMode;
use uv_installer::{SatisfiesResult, SitePackages};
use uv_pep508::PackageName;
use uv_pypi_types::{ConflictingGroupList, Requirement};
use uv_pypi_types::{Conflicts, Requirement};
use uv_python::{
EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target,
};
@ -400,7 +400,7 @@ pub(crate) async fn pip_install(
Some(&tags),
ResolverEnvironment::specific(marker_env.clone()),
python_requirement,
ConflictingGroupList::empty(),
Conflicts::empty(),
&client,
&flat_index,
&state.index,

View file

@ -29,7 +29,7 @@ use uv_install_wheel::linker::LinkMode;
use uv_installer::{Plan, Planner, Preparer, SitePackages};
use uv_normalize::{GroupName, PackageName};
use uv_platform_tags::Tags;
use uv_pypi_types::{ConflictingGroupList, ResolverMarkerEnvironment};
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
use uv_python::PythonEnvironment;
use uv_requirements::{
LookaheadResolver, NamedRequirementsResolver, RequirementsSource, RequirementsSpecification,
@ -104,7 +104,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
tags: Option<&Tags>,
resolver_env: ResolverEnvironment,
python_requirement: PythonRequirement,
conflicting_groups: ConflictingGroupList,
conflicting_groups: Conflicts,
client: &RegistryClient,
flat_index: &FlatIndex,
index: &InMemoryIndex,

View file

@ -17,7 +17,7 @@ use uv_fs::Simplified;
use uv_install_wheel::linker::LinkMode;
use uv_installer::SitePackages;
use uv_pep508::PackageName;
use uv_pypi_types::ConflictingGroupList;
use uv_pypi_types::Conflicts;
use uv_python::{
EnvironmentPreference, Prefix, PythonEnvironment, PythonRequest, PythonVersion, Target,
};
@ -345,7 +345,7 @@ pub(crate) async fn pip_sync(
Some(&tags),
ResolverEnvironment::specific(marker_env.clone()),
python_requirement,
ConflictingGroupList::empty(),
Conflicts::empty(),
&client,
&flat_index,
&state.index,

View file

@ -22,7 +22,7 @@ use uv_installer::{SatisfiesResult, SitePackages};
use uv_normalize::{ExtraName, GroupName, PackageName, DEV_DEPENDENCIES};
use uv_pep440::{Version, VersionSpecifiers};
use uv_pep508::MarkerTreeContents;
use uv_pypi_types::{ConflictingGroupList, ConflictingGroups, Requirement};
use uv_pypi_types::{ConflictSet, Conflicts, Requirement};
use uv_python::{
EnvironmentPreference, Interpreter, InvalidEnvironmentKind, PythonDownloads, PythonEnvironment,
PythonInstallation, PythonPreference, PythonRequest, PythonVariant, PythonVersionFile,
@ -90,7 +90,7 @@ pub(crate) enum ProjectError {
.collect::<Vec<String>>()
.join(", "),
)]
ExtraIncompatibility(ConflictingGroups, Vec<ExtraName>),
ExtraIncompatibility(ConflictSet, Vec<ExtraName>),
#[error("The requested interpreter resolved to Python {0}, which is incompatible with the project's Python requirement: `{1}`")]
RequestedPythonProjectIncompatibility(Version, RequiresPython),
@ -1108,7 +1108,7 @@ pub(crate) async fn resolve_environment<'a>(
Some(tags),
ResolverEnvironment::specific(marker_env),
python_requirement,
ConflictingGroupList::empty(),
Conflicts::empty(),
&client,
&flat_index,
&state.index,
@ -1451,7 +1451,7 @@ pub(crate) async fn update_environment(
Some(tags),
ResolverEnvironment::specific(marker_env.clone()),
python_requirement,
ConflictingGroupList::empty(),
Conflicts::empty(),
&client,
&flat_index,
&state.index,

View file

@ -24,7 +24,7 @@ use uv_cli::{PythonCommand, PythonNamespace, ToolCommand, ToolNamespace, TopLeve
#[cfg(feature = "self-update")]
use uv_cli::{SelfCommand, SelfNamespace, SelfUpdateArgs};
use uv_fs::CWD;
use uv_pypi_types::ConflictingGroupList;
use uv_pypi_types::Conflicts;
use uv_requirements::RequirementsSource;
use uv_scripts::{Pep723Item, Pep723Metadata, Pep723Script};
use uv_settings::{Combine, FilesystemOptions, Options};
@ -333,7 +333,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
args.constraints_from_workspace,
args.overrides_from_workspace,
args.environments,
ConflictingGroupList::empty(),
Conflicts::empty(),
args.settings.extras,
args.settings.output_file.as_deref(),
args.settings.resolution,