Conflicting groups should handle conflicting inclusions automatically (#12005)

This adds support for inferring dependency group conflict sets from the
directly defined conflicts in configuration. For example, if you declare
a conflict between groups `alpha` and `beta` and `dev` includes `beta`,
then we will infer a conflict between `dev` and `alpha`. We will also
handle a conflict between two groups if they transitively include groups
that conflict with each other. See #11232 for more details.

Closes #11232
This commit is contained in:
John Mumm 2025-03-08 19:21:25 +01:00 committed by GitHub
parent 3739223c96
commit b7968e7789
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 712 additions and 168 deletions

2
Cargo.lock generated
View file

@ -5391,8 +5391,10 @@ dependencies = [
"itertools 0.14.0",
"jiff",
"mailparse",
"petgraph",
"regex",
"rkyv",
"rustc-hash",
"schemars",
"serde",
"serde-untagged",

View file

@ -29,8 +29,10 @@ indexmap = { workspace = true, features = ["serde"] }
itertools = { workspace = true }
jiff = { workspace = true, features = ["serde"] }
mailparse = { workspace = true }
petgraph = { workspace = true }
regex = { workspace = true }
rkyv = { workspace = true }
rustc-hash = { workspace = true }
schemars = { workspace = true, optional = true }
serde = { workspace = true }
serde-untagged = { workspace = true }

View file

@ -1,11 +1,19 @@
use petgraph::{
algo::toposort,
graph::{DiGraph, NodeIndex},
};
use rustc_hash::{FxHashMap, FxHashSet};
use std::{collections::BTreeSet, hash::Hash, rc::Rc};
use uv_normalize::{ExtraName, GroupName, PackageName};
use crate::dependency_groups::{DependencyGroupSpecifier, DependencyGroups};
/// A list of conflicting sets of extras/groups pre-defined by an end user.
///
/// This is useful to force the resolver to fork according to extras that have
/// unavoidable conflicts with each other. (The alternative is that resolution
/// will fail.)
#[derive(Debug, Default, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, Clone, Eq, PartialEq, serde::Deserialize)]
pub struct Conflicts(Vec<ConflictSet>);
impl Conflicts {
@ -47,6 +55,157 @@ impl Conflicts {
pub fn append(&mut self, other: &mut Conflicts) {
self.0.append(&mut other.0);
}
/// Expand [`Conflicts`]s to include all [`ConflictSet`]s that can
/// be transitively inferred from group conflicts directly defined
/// in configuration.
///
/// A directed acyclic graph (DAG) is created representing all
/// transitive group includes, with nodes corresponding to group conflict
/// items. For every conflict item directly mentioned in configuration,
/// its node starts with a set of canonical items with itself as the only
/// member.
///
/// The graph is traversed one node at a time in topological order and
/// canonical items are propagated to each neighbor. We also update our
/// substitutions at each neighbor to reflect that this neighbor transitively
/// includes all canonical items visited so far to reach it.
///
/// Finally, we apply the substitutions to the conflict sets that were
/// directly defined in configuration to generate all transitively inferable
/// [`ConflictSet`]s.
///
/// There is an assumption that inclusion graphs will not be very large
/// or complex. This algorithm creates all combinations of substitutions.
/// Each resulting [`ConflictSet`] would also later correspond to a separate
/// resolver fork during resolution.
pub fn expand_transitive_group_includes(
&mut self,
package: &PackageName,
groups: &DependencyGroups,
) {
let mut graph = DiGraph::new();
let mut group_node_idxs: FxHashMap<&GroupName, NodeIndex> = FxHashMap::default();
let mut node_conflict_items: FxHashMap<NodeIndex, Rc<ConflictItem>> = FxHashMap::default();
// Used for transitively deriving new conflict sets with substitutions.
// The keys are canonical items (mentioned directly in configured conflicts).
// The values correspond to groups that transitively include them.
let mut substitutions: FxHashMap<Rc<ConflictItem>, FxHashSet<Rc<ConflictItem>>> =
FxHashMap::default();
// Conflict sets that were directly defined in configuration.
let mut direct_conflict_sets: FxHashSet<&ConflictSet> = FxHashSet::default();
// Conflict sets that we will transitively infer in this method.
let mut transitive_conflict_sets: FxHashSet<ConflictSet> = FxHashSet::default();
// Add groups in directly defined conflict sets to the graph.
let mut seen: FxHashSet<&GroupName> = FxHashSet::default();
for set in &self.0 {
direct_conflict_sets.insert(set);
for item in set.iter() {
let ConflictPackage::Group(group) = &item.conflict else {
// TODO(john): Do we also want to handle extras here?
continue;
};
if !seen.insert(group) {
continue;
}
let item = Rc::new(item.clone());
let mut canonical_items = FxHashSet::default();
canonical_items.insert(item.clone());
let node_id = graph.add_node(canonical_items);
group_node_idxs.insert(group, node_id);
node_conflict_items.insert(node_id, item.clone());
}
}
// Create conflict items for remaining groups and add them to the graph.
for group in groups.keys() {
if !seen.insert(group) {
continue;
}
let group_conflict_item = ConflictItem {
package: package.clone(),
conflict: ConflictPackage::Group(group.clone()),
};
let node_id = graph.add_node(FxHashSet::default());
group_node_idxs.insert(group, node_id);
node_conflict_items.insert(node_id, Rc::new(group_conflict_item));
}
// Create edges representing group inclusion (with edges reversed so that
// included groups point to including groups).
for (group, specifiers) in groups {
if let Some(includer) = group_node_idxs.get(group) {
for specifier in specifiers {
if let DependencyGroupSpecifier::IncludeGroup { include_group } = specifier {
if let Some(included) = group_node_idxs.get(include_group) {
graph.add_edge(*included, *includer, ());
}
}
}
}
}
let Ok(topo_nodes) = toposort(&graph, None) else {
// FIXME: If we hit a cycle, we are currently bailing and waiting for
// more detailed cycle detection downstream. Is this what we want?
return;
};
// Propagate canonical items through the graph and populate substitutions.
for node in topo_nodes {
for neighbor_idx in graph.neighbors(node).collect::<Vec<_>>() {
let mut neighbor_canonical_items = Vec::new();
if let Some(canonical_items) = graph.node_weight(node) {
let neighbor_item = node_conflict_items
.get(&neighbor_idx)
.expect("ConflictItem should already be in graph")
.clone();
for canonical_item in canonical_items {
neighbor_canonical_items.push(canonical_item.clone());
substitutions
.entry(canonical_item.clone())
.or_default()
.insert(neighbor_item.clone());
}
}
graph
.node_weight_mut(neighbor_idx)
.expect("Graph node should have weight")
.extend(neighbor_canonical_items.into_iter());
}
}
// Create new conflict sets for all possible replacements of canonical
// items by substitution items.
// Note that new sets are (potentially) added to transitive_conflict_sets
// at the end of each iteration.
for (canonical_item, subs) in substitutions {
let mut new_conflict_sets = FxHashSet::default();
for conflict_set in direct_conflict_sets
.iter()
.copied()
.chain(transitive_conflict_sets.iter())
.filter(|set| set.contains_item(&canonical_item))
{
for sub in &subs {
let mut new_set = conflict_set
.replaced_item(&canonical_item, (**sub).clone())
.expect("`ConflictItem` should be in `ConflictSet`");
if !direct_conflict_sets.contains(&new_set) {
new_set = new_set.with_inferred_conflict();
if !transitive_conflict_sets.contains(&new_set) {
new_conflict_sets.insert(new_set);
}
}
}
}
transitive_conflict_sets.extend(new_conflict_sets.into_iter());
}
self.0.extend(transitive_conflict_sets);
}
}
/// A single set of package-extra pairs that conflict with one another.
@ -58,23 +217,24 @@ impl Conflicts {
///
/// 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)]
pub struct ConflictSet(Vec<ConflictItem>);
#[derive(Debug, Default, Clone, Hash, Eq, PartialEq)]
pub struct ConflictSet {
set: BTreeSet<ConflictItem>,
is_inferred_conflict: bool,
}
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 item to this set.
pub fn push(&mut self, item: ConflictItem) {
self.0.push(item);
ConflictSet {
set: BTreeSet::from_iter(vec![item1, item2]),
is_inferred_conflict: false,
}
}
/// Returns an iterator over all conflicting items.
pub fn iter(&self) -> impl Iterator<Item = &'_ ConflictItem> + Clone + '_ {
self.0.iter()
self.set.iter()
}
/// Returns true if this conflicting item contains the given package and
@ -88,6 +248,42 @@ impl ConflictSet {
self.iter()
.any(|set| set.package() == package && *set.conflict() == conflict)
}
/// Returns true if these conflicts contain any set that contains the given
/// [`ConflictItem`].
pub fn contains_item(&self, conflict_item: &ConflictItem) -> bool {
self.set.contains(conflict_item)
}
/// This [`ConflictSet`] was inferred from directly defined conflicts.
pub fn is_inferred_conflict(&self) -> bool {
self.is_inferred_conflict
}
/// Replace an old [`ConflictItem`] with a new one.
pub fn replaced_item(
&self,
old: &ConflictItem,
new: ConflictItem,
) -> Result<Self, ConflictError> {
let mut new_set = self.set.clone();
if !new_set.contains(old) {
return Err(ConflictError::ReplaceMissingConflictItem);
}
new_set.remove(old);
new_set.insert(new);
Ok(Self {
set: new_set,
is_inferred_conflict: false,
})
}
/// Mark this [`ConflictSet`] as being inferred from directly
/// defined conflicts.
fn with_inferred_conflict(mut self) -> Self {
self.is_inferred_conflict = true;
self
}
}
impl<'de> serde::Deserialize<'de> for ConflictSet {
@ -109,14 +305,17 @@ impl TryFrom<Vec<ConflictItem>> for ConflictSet {
1 => return Err(ConflictError::OneItem),
_ => {}
}
Ok(ConflictSet(items))
Ok(ConflictSet {
set: BTreeSet::from_iter(items),
is_inferred_conflict: false,
})
}
}
/// A single item in a conflicting set.
///
/// Each item is a pair of a package and a corresponding extra name for that
/// package.
/// Each item is a pair of a package and a corresponding extra or group name
/// for that package.
#[derive(
Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, serde::Deserialize, serde::Serialize,
)]
@ -364,6 +563,8 @@ pub enum ConflictError {
/// An error that occurs when both `extra` and `group` are present.
#[error("Expected one of `extra` or `group` in conflicting entry, but found both")]
FoundExtraAndGroup,
#[error("Expected `ConflictSet` to contain `ConflictItem` to replace")]
ReplaceMissingConflictItem,
}
/// Like [`Conflicts`], but for deserialization in `pyproject.toml`.

View file

@ -396,7 +396,14 @@ async fn do_lock(
.collect::<Result<BTreeMap<_, _>, ProjectError>>()?;
// Collect the conflicts.
let conflicts = target.conflicts();
let mut conflicts = target.conflicts();
if let LockTarget::Workspace(workspace) = target {
if let Some(groups) = &workspace.pyproject_toml().dependency_groups {
if let Some(project) = &workspace.pyproject_toml().project {
conflicts.expand_transitive_group_includes(&project.name, groups);
}
}
}
// Collect the list of supported environments.
let environments = {
@ -756,7 +763,7 @@ async fn do_lock(
None,
resolver_env,
python_requirement,
conflicts,
conflicts.clone(),
&client,
&flat_index,
state.index(),
@ -787,7 +794,7 @@ async fn do_lock(
let previous = existing_lock.map(ValidatedLock::into_lock);
let lock = Lock::from_resolution(&resolution, target.install_path())?
.with_manifest(manifest)
.with_conflicts(target.conflicts())
.with_conflicts(conflicts)
.with_supported_environments(
environments
.cloned()

View file

@ -300,9 +300,14 @@ impl std::fmt::Display for ConflictError {
.iter()
.all(|conflict| matches!(conflict, ConflictPackage::Group(..)))
{
let conflict_source = if self.set.is_inferred_conflict() {
"transitively inferred"
} else {
"declared"
};
write!(
f,
"Groups {} are incompatible with the declared conflicts: {{{set}}}",
"Groups {} are incompatible with the {conflict_source} conflicts: {{{set}}}",
conjunction(
self.conflicts
.iter()

View file

@ -2090,13 +2090,13 @@ fn mixed() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "project", group = "group1" },
{ package = "project", extra = "extra1" },
{ package = "project", group = "group1" },
]]
[options]
@ -2141,7 +2141,7 @@ fn mixed() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
]
"###
"#
);
});
@ -2189,14 +2189,14 @@ fn mixed() -> Result<()> {
+ sortedcontainers==2.4.0
"###);
// And finally, installing both the group and the extra should fail.
uv_snapshot!(context.filters(), context.sync().arg("--frozen").arg("--group=group1").arg("--extra=extra1"), @r###"
uv_snapshot!(context.filters(), context.sync().arg("--frozen").arg("--group=group1").arg("--extra=extra1"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Group `group1` and extra `extra1` are incompatible with the declared conflicts: {`project:group1`, `project[extra1]`}
"###);
error: Extra `extra1` and group `group1` are incompatible with the declared conflicts: {`project[extra1]`, `project:group1`}
");
Ok(())
}
@ -3054,13 +3054,13 @@ fn shared_optional_dependency_extra1() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "project", extra = "foo" },
{ package = "project", extra = "bar" },
{ package = "project", extra = "foo" },
]]
[options]
@ -3130,7 +3130,7 @@ fn shared_optional_dependency_extra1() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -3194,13 +3194,13 @@ fn shared_optional_dependency_group1() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "project", group = "foo" },
{ package = "project", group = "bar" },
{ package = "project", group = "foo" },
]]
[options]
@ -3269,7 +3269,7 @@ fn shared_optional_dependency_group1() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -3480,13 +3480,13 @@ fn shared_optional_dependency_extra2() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = "==3.11.*"
conflicts = [[
{ package = "project", extra = "foo" },
{ package = "project", extra = "bar" },
{ package = "project", extra = "foo" },
]]
[options]
@ -3556,7 +3556,7 @@ fn shared_optional_dependency_extra2() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -3621,13 +3621,13 @@ fn shared_optional_dependency_group2() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = "==3.11.*"
conflicts = [[
{ package = "project", group = "foo" },
{ package = "project", group = "bar" },
{ package = "project", group = "foo" },
]]
[options]
@ -3700,7 +3700,7 @@ fn shared_optional_dependency_group2() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -3911,13 +3911,13 @@ fn shared_dependency_extra() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "project", extra = "foo" },
{ package = "project", extra = "bar" },
{ package = "project", extra = "foo" },
]]
[options]
@ -3987,7 +3987,7 @@ fn shared_dependency_extra() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -4086,13 +4086,13 @@ fn shared_dependency_group() -> Result<()> {
filters => context.filters(),
}, {
assert_snapshot!(
lock, @r###"
lock, @r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "project", group = "foo" },
{ package = "project", group = "bar" },
{ package = "project", group = "foo" },
]]
[options]
@ -4161,7 +4161,7 @@ fn shared_dependency_group() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
]
"###
"#
);
});
@ -4988,13 +4988,13 @@ fn collision_extra() -> Result<()> {
}, {
assert_snapshot!(
lock,
@r###"
@r#"
version = 1
revision = 1
requires-python = ">=3.12"
conflicts = [[
{ package = "pkg", extra = "foo" },
{ package = "pkg", extra = "bar" },
{ package = "pkg", extra = "foo" },
]]
[options]
@ -5077,7 +5077,7 @@ fn collision_extra() -> Result<()> {
wheels = [
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
]
"###
"#
);
});
@ -10167,14 +10167,14 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"#,
)?;
uv_snapshot!(context.filters(), context.lock(), @r###"
uv_snapshot!(context.filters(), context.lock(), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 133 packages in [TIME]
"###);
Resolved 132 packages in [TIME]
");
let lock = context.read("uv.lock");
insta::with_settings!({
@ -10182,20 +10182,11 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
}, {
assert_snapshot!(
lock,
@r###"
@r#"
version = 1
revision = 1
requires-python = ">=3.10"
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
@ -10208,6 +10199,15 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
@ -10225,14 +10225,14 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
conflicts = [[
{ package = "test", extra = "chgnet" },
{ package = "test", extra = "alignn" },
{ package = "test", extra = "chgnet" },
], [
{ package = "test", extra = "chgnet" },
{ package = "test", extra = "m3gnet" },
], [
{ package = "test", extra = "all" },
{ package = "test", extra = "alignn" },
{ package = "test", extra = "all" },
], [
{ package = "test", extra = "all" },
{ package = "test", extra = "m3gnet" },
@ -10368,7 +10368,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "pydantic" },
{ name = "pydantic-settings" },
{ name = "pydocstyle" },
{ name = "pyparsing" },
{ name = "pyparsing", version = "2.4.7", source = { registry = "https://pypi.org/simple" } },
{ name = "scikit-learn" },
{ name = "scipy" },
{ name = "spglib" },
@ -10629,8 +10629,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "numpy" },
{ name = "opt-einsum" },
{ name = "scipy" },
{ name = "sympy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "sympy", version = "1.13.3", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "sympy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/70/91/c37b2ad1c8534b183eeacb97d2096f50cd2d0a180d1830f235c06aa94bbd/cuequivariance-0.2.0.tar.gz", hash = "sha256:e75999ef436f281e3f5cded9f1353055a599fedae55eea861bdc840cffaf63eb", size = 76738 }
wheels = [
@ -10733,8 +10732,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
dependencies = [
{ name = "opt-einsum-fx" },
{ name = "scipy" },
{ name = "sympy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "sympy", version = "1.13.3", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "sympy" },
{ name = "torch", version = "2.2.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "torch", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
]
@ -11269,7 +11267,8 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "numpy" },
{ name = "packaging" },
{ name = "pillow" },
{ name = "pyparsing" },
{ name = "pyparsing", version = "2.4.7", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or (extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "pyparsing", version = "3.2.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or extra != 'extra-4-test-alignn'" },
{ name = "python-dateutil" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/dd/fa2e1a45fce2d09f4aea3cee169760e672c8262325aa5796c49d543dc7e6/matplotlib-3.10.0.tar.gz", hash = "sha256:b886d02a581b96704c9d1ffe55709e49b4d2d52709ccebc4be42db856e511278", size = 36686418 }
@ -11754,7 +11753,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
dependencies = [
{ name = "nvidia-nvjitlink-cu12", version = "12.4.127", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "nvidia-nvjitlink-cu12", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/7a/8a/0e728f749baca3fbeffad762738276e5df60851958be7783af121a7221e7/nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5dad8008fc7f92f5ddfa2101430917ce2ffacd86824914c82e28990ad7f00399", size = 211422548 },
@ -11824,7 +11823,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
dependencies = [
{ name = "nvidia-cublas-cu12", version = "12.1.3.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "nvidia-cusparse-cu12", version = "12.1.0.106", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "nvidia-nvjitlink-cu12", version = "12.8.61", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "nvidia-nvjitlink-cu12", marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/1d/8de1e5c67099015c834315e333911273a8c6aaba78923dd1d1e25fc5f217/nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl", hash = "sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd", size = 124161928 },
@ -11852,7 +11851,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
dependencies = [
{ name = "nvidia-cublas-cu12", version = "12.4.5.8", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "nvidia-cusparse-cu12", version = "12.3.1.170", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "nvidia-nvjitlink-cu12", version = "12.4.127", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "nvidia-nvjitlink-cu12", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/46/6b/a5c33cf16af09166845345275c34ad2190944bcc6026797a39f8e0a282e0/nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:d338f155f174f90724bbde3758b7ac375a70ce8e706d70b018dd3375545fc84e", size = 127634111 },
@ -11876,7 +11875,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
]
dependencies = [
{ name = "nvidia-nvjitlink-cu12", version = "12.8.61", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "nvidia-nvjitlink-cu12", marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/65/5b/cfaeebf25cd9fdec14338ccb16f6b2c4c7fa9163aefcf057d86b9cc248bb/nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c", size = 195958278 },
@ -11902,7 +11901,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
dependencies = [
{ name = "nvidia-nvjitlink-cu12", version = "12.4.127", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "nvidia-nvjitlink-cu12", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/a9/c0d2f83a53d40a4a41be14cea6a0bf9e668ffcf8b004bd65633f433050c0/nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9d32f62896231ebe0480efd8a7f702e143c98cfaa0e8a76df3386c1ba2b54df3", size = 207381987 },
@ -11961,47 +11960,12 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
name = "nvidia-nvjitlink-cu12"
version = "12.4.127"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/45/239d52c05074898a80a900f49b1615d81c07fceadd5ad6c4f86a987c0bc4/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83", size = 20552510 },
{ url = "https://files.pythonhosted.org/packages/ff/ff/847841bacfbefc97a00036e0fce5a0f086b640756dc38caea5e1bb002655/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57", size = 21066810 },
{ url = "https://files.pythonhosted.org/packages/81/19/0babc919031bee42620257b9a911c528f05fb2688520dcd9ca59159ffea8/nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1", size = 95336325 },
]
[[package]]
name = "nvidia-nvjitlink-cu12"
version = "12.8.61"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/03/f8/9d85593582bd99b8d7c65634d2304780aefade049b2b94d96e44084be90b/nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:45fd79f2ae20bd67e8bc411055939049873bfd8fac70ff13bd4865e0b9bdab17", size = 39243473 },
{ url = "https://files.pythonhosted.org/packages/af/53/698f3758f48c5fcb1112721e40cc6714da3980d3c7e93bae5b29dafa9857/nvidia_nvjitlink_cu12-12.8.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b80ecab31085dda3ce3b41d043be0ec739216c3fc633b8abe212d5a30026df0", size = 38374634 },
{ url = "https://files.pythonhosted.org/packages/7f/c6/0d1b2bfeb2ef42c06db0570c4d081e5cde4450b54c09e43165126cfe6ff6/nvidia_nvjitlink_cu12-12.8.61-py3-none-win_amd64.whl", hash = "sha256:1166a964d25fdc0eae497574d38824305195a5283324a21ccb0ce0c802cbf41c", size = 268514099 },
]
[[package]]
name = "nvidia-nvtx-cu12"
version = "12.1.105"
@ -12480,8 +12444,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "ruamel-yaml" },
{ name = "scipy" },
{ name = "spglib" },
{ name = "sympy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet'" },
{ name = "sympy", version = "1.13.3", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (extra != 'extra-4-test-alignn' and extra == 'extra-4-test-m3gnet') or (extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "sympy" },
{ name = "tabulate" },
{ name = "tqdm" },
{ name = "uncertainties" },
@ -12509,11 +12472,60 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
name = "pyparsing"
version = "2.4.7"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
sdist = { url = "https://files.pythonhosted.org/packages/c1/47/dfc9c342c9842bbe0036c7f763d2d6686bcf5eb1808ba3e170afdb282210/pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", size = 649718 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/bb/488841f56197b13700afd5658fc279a2025a39e22449b7cf29864669b15d/pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b", size = 67842 },
]
[[package]]
name = "pyparsing"
version = "3.2.1"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
sdist = { url = "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716 },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
@ -12858,66 +12870,14 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
name = "sympy"
version = "1.13.1"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra == 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra == 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
]
dependencies = [
{ name = "mpmath", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "mpmath" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ca/99/5a5b6f19ff9f083671ddf7b9632028436167cd3d33e11015754e41b249a4/sympy-1.13.1.tar.gz", hash = "sha256:9cebf7e04ff162015ce31c9c6c9144daa34a93bd082f54fd8f12deca4f47515f", size = 7533040 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b2/fe/81695a1aa331a842b582453b605175f419fe8540355886031328089d840a/sympy-1.13.1-py3-none-any.whl", hash = "sha256:db36cdc64bf61b9b24578b6f7bab1ecdd2452cf008f34faa33776680c26d66f8", size = 6189177 },
]
[[package]]
name = "sympy"
version = "1.13.3"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.12' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and extra == 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra != 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version >= '3.12' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version == '3.11.*' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform == 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
"python_full_version < '3.11' and sys_platform != 'win32' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-all' and extra != 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet'",
]
dependencies = [
{ name = "mpmath", marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/11/8a/5a7fd6284fa8caac23a26c9ddf9c30485a48169344b4bd3b0f02fef1890f/sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9", size = 7533196 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 },
]
[[package]]
name = "tabulate"
version = "0.9.0"
@ -13028,7 +12988,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "nvidia-cusparse-cu12", version = "12.1.0.106", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-alignn') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "nvidia-nccl-cu12", version = "2.19.3", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-alignn') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "nvidia-nvtx-cu12", version = "12.1.105", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-alignn') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "sympy", version = "1.13.3", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "sympy", marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
{ name = "triton", version = "2.2.0", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-alignn') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (platform_machine != 'x86_64' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (sys_platform != 'linux' and extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "typing-extensions", marker = "extra == 'extra-4-test-alignn' or extra == 'extra-4-test-m3gnet'" },
]
@ -13092,10 +13052,10 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "nvidia-cusolver-cu12", version = "11.6.1.9", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "nvidia-cusparse-cu12", version = "12.3.1.170", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "nvidia-nccl-cu12", version = "2.21.5", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "nvidia-nvjitlink-cu12", version = "12.4.127", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "nvidia-nvtx-cu12", version = "12.4.127", source = { registry = "https://pypi.org/simple" }, marker = "(platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "setuptools", marker = "(python_full_version >= '3.12' and extra == 'extra-4-test-all') or (python_full_version >= '3.12' and extra == 'extra-4-test-chgnet') or (python_full_version >= '3.12' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "sympy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "sympy", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
{ name = "triton", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.13' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-all') or (python_full_version < '3.13' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra == 'extra-4-test-chgnet') or (python_full_version < '3.13' and platform_machine == 'x86_64' and sys_platform == 'linux' and extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet') or (python_full_version >= '3.13' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (python_full_version >= '3.13' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (platform_machine != 'x86_64' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (sys_platform != 'linux' and extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-all') or (extra == 'extra-4-test-alignn' and extra == 'extra-4-test-chgnet')" },
{ name = "typing-extensions", marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or (extra != 'extra-4-test-alignn' and extra != 'extra-4-test-m3gnet')" },
]
@ -13138,7 +13098,8 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ name = "jinja2" },
{ name = "numpy" },
{ name = "psutil" },
{ name = "pyparsing" },
{ name = "pyparsing", version = "2.4.7", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-alignn' or (extra == 'extra-4-test-all' and extra == 'extra-4-test-m3gnet') or (extra == 'extra-4-test-chgnet' and extra == 'extra-4-test-m3gnet')" },
{ name = "pyparsing", version = "3.2.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-4-test-all' or extra == 'extra-4-test-chgnet' or extra != 'extra-4-test-alignn'" },
{ name = "requests" },
{ name = "tqdm" },
]
@ -13378,7 +13339,7 @@ fn duplicate_torch_and_sympy_because_of_wrong_inferences() -> Result<()> {
{ url = "https://files.pythonhosted.org/packages/f5/d5/688db678e987c3e0fb17867970700b92603cadf36c56e5fb08f23e822a0c/yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", size = 315723 },
{ url = "https://files.pythonhosted.org/packages/f5/4b/a06e0ec3d155924f77835ed2d167ebd3b211a7b0853da1cf8d8414d784ef/yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", size = 45109 },
]
"###
"#
);
});

View file

@ -8019,15 +8019,381 @@ fn multiple_group_conflicts() -> Result<()> {
+ iniconfig==1.1.1
"###);
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("foo").arg("--group").arg("bar"), @r###"
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("foo").arg("--group").arg("bar"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 3 packages in [TIME]
error: Groups `foo` and `bar` are incompatible with the declared conflicts: {`project:foo`, `project:bar`}
"###);
error: Groups `bar` and `foo` are incompatible with the declared conflicts: {`project:bar`, `project:foo`}
");
Ok(())
}
/// See: <https://github.com/astral-sh/uv/issues/11232>
#[test]
fn transitive_group_conflicts_shallow() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[dependency-groups]
dev = [
{ include-group = "test" },
]
test = ["anyio>4"]
magic = ["anyio<4"]
[tool.uv]
conflicts = [
[
{ group = "test" },
{ group = "magic" },
],
]
"#,
)?;
uv_snapshot!(context.filters(), context.sync(), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Prepared 3 packages in [TIME]
Installed 3 packages in [TIME]
+ anyio==4.3.0
+ idna==3.6
+ sniffio==1.3.1
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Audited 3 packages in [TIME]
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("test"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Audited 3 packages in [TIME]
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("test").arg("--group").arg("magic"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
error: Groups `magic` and `test` are incompatible with the declared conflicts: {`example:magic`, `example:test`}
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("magic"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
error: Groups `dev` and `magic` are incompatible with the transitively inferred conflicts: {`example:dev`, `example:magic`}
");
Ok(())
}
/// See: <https://github.com/astral-sh/uv/issues/11232>
#[test]
fn transitive_group_conflicts_deep() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[dependency-groups]
dev = [
{ include-group = "intermediate" },
]
intermediate = [
{ include-group = "test" },
{ include-group = "other" },
]
test = ["iniconfig>=2"]
magic = ["iniconfig<2", "anyio<4"]
other = ["anyio>4"]
[tool.uv]
conflicts = [
[
{ group = "test" },
{ group = "magic" },
],
[
{ group = "other" },
{ group = "magic" },
],
]"#,
)?;
uv_snapshot!(context.filters(), context.sync(), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
Prepared 4 packages in [TIME]
Installed 4 packages in [TIME]
+ anyio==4.3.0
+ idna==3.6
+ iniconfig==2.0.0
+ sniffio==1.3.1
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
Audited 4 packages in [TIME]
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("test"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
Audited 4 packages in [TIME]
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("magic"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
error: Groups `dev` and `magic` are incompatible with the transitively inferred conflicts: {`example:dev`, `example:magic`}
");
uv_snapshot!(context.filters(), context.sync().arg("--no-dev").arg("--group").arg("intermediate").arg("--group").arg("magic"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 7 packages in [TIME]
error: Groups `intermediate` and `magic` are incompatible with the transitively inferred conflicts: {`example:intermediate`, `example:magic`}
");
Ok(())
}
/// See: <https://github.com/astral-sh/uv/issues/11232>
#[test]
fn transitive_group_conflicts_siblings() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[dependency-groups]
dev = [
{ include-group = "test" },
]
dev2 = [
{ include-group = "magic" },
]
test = ["anyio>4"]
magic = ["anyio<4"]
[tool.uv]
conflicts = [
[
{ group = "test" },
{ group = "magic" },
],
]"#,
)?;
uv_snapshot!(context.filters(), context.sync(), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Prepared 3 packages in [TIME]
Installed 3 packages in [TIME]
+ anyio==4.3.0
+ idna==3.6
+ sniffio==1.3.1
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Audited 3 packages in [TIME]
");
uv_snapshot!(context.filters(), context.sync().arg("--no-dev").arg("--group").arg("dev2"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
Prepared 1 package in [TIME]
Uninstalled 1 package in [TIME]
Installed 1 package in [TIME]
- anyio==4.3.0
+ anyio==3.7.1
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev2"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
error: Groups `dev` (enabled by default) and `dev2` are incompatible with the transitively inferred conflicts: {`example:dev`, `example:dev2`}
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("dev2"), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Resolved 5 packages in [TIME]
error: Groups `dev` and `dev2` are incompatible with the transitively inferred conflicts: {`example:dev`, `example:dev2`}
");
Ok(())
}
/// See: <https://github.com/astral-sh/uv/issues/11232>
#[test]
fn transitive_group_conflicts_cycle() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
[dependency-groups]
dev = [
{ include-group = "test" },
]
test = [
"anyio>4",
{ include-group = "dev" },
]
magic = ["anyio<4"]
[tool.uv]
conflicts = [
[
{ group = "test" },
{ group = "magic" },
],
]
"#,
)?;
uv_snapshot!(context.filters(), context.sync(), @r"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to build `example @ file://[TEMP_DIR]/`
Detected a cycle in `dependency-groups`: `dev` -> `test` -> `dev`
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev"), @r"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to build `example @ file://[TEMP_DIR]/`
Detected a cycle in `dependency-groups`: `dev` -> `test` -> `dev`
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("test"), @r"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to build `example @ file://[TEMP_DIR]/`
Detected a cycle in `dependency-groups`: `dev` -> `test` -> `dev`
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("test").arg("--group").arg("magic"), @r"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to build `example @ file://[TEMP_DIR]/`
Detected a cycle in `dependency-groups`: `dev` -> `test` -> `dev`
");
uv_snapshot!(context.filters(), context.sync().arg("--group").arg("dev").arg("--group").arg("magic"), @r"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to build `example @ file://[TEMP_DIR]/`
Detected a cycle in `dependency-groups`: `dev` -> `test` -> `dev`
");
Ok(())
}