mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-02 18:12:17 +00:00

This PR adds a notion of "conflict markers" to the lock file as an attempt to address #9289. The idea is to encode a new kind of boolean expression indicating how to choose dependencies based on which extras are activated. As an example of what conflict markers look like, consider one of the cases brought up in #9289, where `anyio` had unconditional dependencies on two different versions of `idna`. Now, those are gated by markers, like this: ```toml [[package]] name = "anyio" version = "4.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-foo'" }, { name = "idna", version = "3.6", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-7-project-bar' or extra != 'extra-7-project-foo'" }, { name = "sniffio" }, ] ``` The odd extra values like `extra-7-project-foo` are an encoding of not just the conflicting extra (`foo`) but also the package it's declared for (`project`). We need both bits of information because different packages may have the same extra name, even if they are completely unrelated. The `extra-` part is a prefix to distinguish it from groups (which, in this case, would be encoded as `group-7-project-foo` if `foo` were a dependency group). And the `7` part indicates the length of the package name which makes it possible to parse out the package and extra name from this encoding. (We don't actually utilize that property, but it seems like good sense to do it in case we do need to extra information from these markers.) While this preserves PEP 508 compatibility at a surface level, it does require utilizing this encoding scheme in order to evaluate them when they're present (which only occurs when conflicting extras/groups are declared). My sense is that the most complex part of this change is not just adding conflict markers, but their simplification. I tried to address this in the code comments and commit messages. Reviewers should look at this commit-by-commit. Fixes #9289, Fixes #9546, Fixes #9640, Fixes #9622, Fixes #9498, Fixes #9701, Fixes #9734
62 lines
2 KiB
Rust
62 lines
2 KiB
Rust
pub use dependency_mode::DependencyMode;
|
|
pub use error::{NoSolutionError, NoSolutionHeader, ResolveError, SentinelRange};
|
|
pub use exclude_newer::ExcludeNewer;
|
|
pub use exclusions::Exclusions;
|
|
pub use flat_index::{FlatDistributions, FlatIndex};
|
|
pub use lock::{
|
|
InstallTarget, Lock, LockError, LockVersion, PackageMap, RequirementsTxtExport,
|
|
ResolverManifest, SatisfiesResult, TreeDisplay, VERSION,
|
|
};
|
|
pub use manifest::Manifest;
|
|
pub use options::{Flexibility, Options, OptionsBuilder};
|
|
pub use preferences::{Preference, PreferenceError, Preferences};
|
|
pub use prerelease::PrereleaseMode;
|
|
pub use python_requirement::PythonRequirement;
|
|
pub use requires_python::{RequiresPython, RequiresPythonRange};
|
|
pub use resolution::{
|
|
AnnotationStyle, ConflictingDistributionError, DisplayResolutionGraph, ResolverOutput,
|
|
};
|
|
pub use resolution_mode::ResolutionMode;
|
|
pub use resolver::{
|
|
BuildId, DefaultResolverProvider, DerivationChainBuilder, InMemoryIndex, MetadataResponse,
|
|
PackageVersionsResult, Reporter as ResolverReporter, Resolver, ResolverEnvironment,
|
|
ResolverProvider, VersionsResponse, WheelMetadataResult,
|
|
};
|
|
pub use universal_marker::{ConflictMarker, UniversalMarker};
|
|
pub use version_map::VersionMap;
|
|
pub use yanks::AllowedYanks;
|
|
|
|
/// A custom `HashSet` using `hashbrown`.
|
|
///
|
|
/// We use `hashbrown` instead of `std` to get access to its `Equivalent`
|
|
/// trait. This lets use store things like `ConflictItem`, but refer to it via
|
|
/// `ConflictItemRef`. i.e., We can avoid allocs on lookups.
|
|
type FxHashbrownSet<T> = hashbrown::HashSet<T, rustc_hash::FxBuildHasher>;
|
|
|
|
mod candidate_selector;
|
|
mod dependency_mode;
|
|
mod dependency_provider;
|
|
mod error;
|
|
mod exclude_newer;
|
|
mod exclusions;
|
|
mod flat_index;
|
|
mod fork_indexes;
|
|
mod fork_urls;
|
|
mod graph_ops;
|
|
mod lock;
|
|
mod manifest;
|
|
mod marker;
|
|
mod options;
|
|
mod pins;
|
|
mod preferences;
|
|
mod prerelease;
|
|
mod pubgrub;
|
|
mod python_requirement;
|
|
mod redirect;
|
|
mod requires_python;
|
|
mod resolution;
|
|
mod resolution_mode;
|
|
mod resolver;
|
|
mod universal_marker;
|
|
mod version_map;
|
|
mod yanks;
|