Add a builder for resolution options (#1192)

This commit is contained in:
Charlie Marsh 2024-01-30 11:50:16 -08:00 committed by GitHub
parent aa3b79ec63
commit 8305acc584
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 150 additions and 138 deletions

View file

@ -17,7 +17,7 @@ use puffin_client::{FlatIndex, FlatIndexClient, RegistryClientBuilder};
use puffin_dispatch::BuildDispatch;
use puffin_installer::NoBinary;
use puffin_interpreter::Virtualenv;
use puffin_resolver::{InMemoryIndex, Manifest, ResolutionOptions, Resolver};
use puffin_resolver::{InMemoryIndex, Manifest, Options, Resolver};
use puffin_traits::{InFlight, SetupPyStrategy};
#[derive(ValueEnum, Default, Clone)]
@ -87,7 +87,7 @@ pub(crate) async fn resolve_cli(args: ResolveCliArgs) -> Result<()> {
let tags = venv.interpreter().tags()?;
let resolver = Resolver::new(
Manifest::simple(args.requirements.clone()),
ResolutionOptions::default(),
Options::default(),
venv.interpreter().markers(),
venv.interpreter(),
tags,

View file

@ -16,7 +16,7 @@ use puffin_cache::Cache;
use puffin_client::{FlatIndex, RegistryClient};
use puffin_installer::{Downloader, Installer, NoBinary, Plan, Planner, Reinstall, SitePackages};
use puffin_interpreter::{Interpreter, Virtualenv};
use puffin_resolver::{InMemoryIndex, Manifest, ResolutionOptions, Resolver};
use puffin_resolver::{InMemoryIndex, Manifest, Options, Resolver};
use puffin_traits::{BuildContext, BuildKind, InFlight, SetupPyStrategy};
/// The main implementation of [`BuildContext`], used by the CLI, see [`BuildContext`]
@ -34,7 +34,7 @@ pub struct BuildDispatch<'a> {
no_build: bool,
no_binary: &'a NoBinary,
source_build_context: SourceBuildContext,
options: ResolutionOptions,
options: Options,
}
impl<'a> BuildDispatch<'a> {
@ -65,12 +65,12 @@ impl<'a> BuildDispatch<'a> {
no_build,
no_binary,
source_build_context: SourceBuildContext::default(),
options: ResolutionOptions::default(),
options: Options::default(),
}
}
#[must_use]
pub fn with_options(mut self, options: ResolutionOptions) -> Self {
pub fn with_options(mut self, options: Options) -> Self {
self.options = options;
self
}

View file

@ -11,7 +11,7 @@ use crate::prerelease_mode::PreReleaseStrategy;
use crate::python_requirement::PythonRequirement;
use crate::resolution_mode::ResolutionStrategy;
use crate::version_map::VersionMap;
use crate::{Manifest, ResolutionOptions};
use crate::{Manifest, Options};
#[derive(Debug, Clone)]
pub(crate) struct CandidateSelector {
@ -22,7 +22,7 @@ pub(crate) struct CandidateSelector {
impl CandidateSelector {
/// Return a [`CandidateSelector`] for the given [`Manifest`].
pub(crate) fn for_resolution(manifest: &Manifest, options: ResolutionOptions) -> Self {
pub(crate) fn for_resolution(manifest: &Manifest, options: Options) -> Self {
Self {
resolution_strategy: ResolutionStrategy::from_mode(
options.resolution_mode,

View file

@ -1,10 +1,10 @@
pub use error::ResolveError;
pub use finder::{DistFinder, Reporter as FinderReporter};
pub use manifest::Manifest;
pub use options::{Options, OptionsBuilder};
pub use prerelease_mode::PreReleaseMode;
pub use resolution::{Diagnostic, DisplayResolutionGraph, ResolutionGraph};
pub use resolution_mode::ResolutionMode;
pub use resolution_options::ResolutionOptions;
pub use resolver::{
BuildId, InMemoryIndex, Reporter as ResolverReporter, Resolver, ResolverProvider,
};
@ -13,6 +13,7 @@ mod candidate_selector;
mod error;
mod finder;
mod manifest;
mod options;
mod overrides;
mod pins;
mod prerelease_mode;
@ -20,7 +21,6 @@ mod pubgrub;
mod python_requirement;
mod resolution;
mod resolution_mode;
mod resolution_options;
mod resolver;
mod version_map;
mod yanks;

View file

@ -0,0 +1,56 @@
use chrono::{DateTime, Utc};
use crate::{PreReleaseMode, ResolutionMode};
/// Options for resolving a manifest.
#[derive(Debug, Default, Copy, Clone)]
pub struct Options {
pub resolution_mode: ResolutionMode,
pub prerelease_mode: PreReleaseMode,
pub exclude_newer: Option<DateTime<Utc>>,
}
/// Builder for [`Options`].
#[derive(Debug, Default, Clone)]
pub struct OptionsBuilder {
resolution_mode: ResolutionMode,
prerelease_mode: PreReleaseMode,
exclude_newer: Option<DateTime<Utc>>,
}
impl OptionsBuilder {
/// Creates a new builder.
pub fn new() -> Self {
Self::default()
}
/// Sets the [`ResolutionMode`].
#[must_use]
pub fn resolution_mode(mut self, resolution_mode: ResolutionMode) -> Self {
self.resolution_mode = resolution_mode;
self
}
/// Sets the [`PreReleaseMode`].
#[must_use]
pub fn prerelease_mode(mut self, prerelease_mode: PreReleaseMode) -> Self {
self.prerelease_mode = prerelease_mode;
self
}
/// Sets the exclusion date.
#[must_use]
pub fn exclude_newer(mut self, exclude_newer: Option<DateTime<Utc>>) -> Self {
self.exclude_newer = exclude_newer;
self
}
/// Builds the options.
pub fn build(self) -> Options {
Options {
resolution_mode: self.resolution_mode,
prerelease_mode: self.prerelease_mode,
exclude_newer: self.exclude_newer,
}
}
}

View file

@ -1,25 +0,0 @@
use chrono::{DateTime, Utc};
use crate::{PreReleaseMode, ResolutionMode};
/// Options for resolving a manifest.
#[derive(Debug, Default, Copy, Clone)]
pub struct ResolutionOptions {
pub resolution_mode: ResolutionMode,
pub prerelease_mode: PreReleaseMode,
pub exclude_newer: Option<DateTime<Utc>>,
}
impl ResolutionOptions {
pub fn new(
resolution_mode: ResolutionMode,
prerelease_mode: PreReleaseMode,
exclude_newer: Option<DateTime<Utc>>,
) -> Self {
Self {
resolution_mode,
prerelease_mode,
exclude_newer,
}
}
}

View file

@ -50,7 +50,7 @@ pub use crate::resolver::provider::ResolverProvider;
use crate::resolver::reporter::Facade;
pub use crate::resolver::reporter::{BuildId, Reporter};
use crate::version_map::VersionMap;
use crate::ResolutionOptions;
use crate::Options;
mod allowed_urls;
mod index;
@ -83,7 +83,7 @@ impl<'a, Context: BuildContext + Send + Sync> Resolver<'a, DefaultResolverProvid
#[allow(clippy::too_many_arguments)]
pub fn new(
manifest: Manifest,
options: ResolutionOptions,
options: Options,
markers: &'a MarkerEnvironment,
interpreter: &'a Interpreter,
tags: &'a Tags,
@ -121,7 +121,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
/// Initialize a new resolver using a user provided backend.
pub fn new_custom_io(
manifest: Manifest,
options: ResolutionOptions,
options: Options,
markers: &'a MarkerEnvironment,
python_requirement: PythonRequirement,
index: &'a InMemoryIndex,

View file

@ -18,8 +18,8 @@ use puffin_cache::Cache;
use puffin_client::{FlatIndex, RegistryClientBuilder};
use puffin_interpreter::{Interpreter, Virtualenv};
use puffin_resolver::{
DisplayResolutionGraph, InMemoryIndex, Manifest, PreReleaseMode, ResolutionGraph,
ResolutionMode, ResolutionOptions, Resolver,
DisplayResolutionGraph, InMemoryIndex, Manifest, Options, OptionsBuilder, PreReleaseMode,
ResolutionGraph, ResolutionMode, Resolver,
};
use puffin_traits::{BuildContext, BuildKind, NoBinary, SetupPyStrategy, SourceBuildTrait};
@ -99,7 +99,7 @@ impl SourceBuildTrait for DummyBuilder {
async fn resolve(
manifest: Manifest,
options: ResolutionOptions,
options: Options,
markers: &'static MarkerEnvironment,
tags: &Tags,
) -> Result<ResolutionGraph> {
@ -142,11 +142,9 @@ macro_rules! assert_snapshot {
#[tokio::test]
async fn black() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black<=23.9.1").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -172,11 +170,9 @@ async fn black_colorama() -> Result<()> {
let manifest = Manifest::simple(vec![
Requirement::from_str("black[colorama]<=23.9.1").unwrap()
]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -205,11 +201,9 @@ async fn black_tensorboard() -> Result<()> {
let manifest = Manifest::simple(vec![
Requirement::from_str("black[tensorboard]<=23.9.1").unwrap()
]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -233,11 +227,9 @@ async fn black_tensorboard() -> Result<()> {
#[tokio::test]
async fn black_python_310() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black<=23.9.1").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_310, &TAGS_310).await?;
@ -274,11 +266,9 @@ async fn black_mypy_extensions() -> Result<()> {
None,
vec![],
);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -311,11 +301,9 @@ async fn black_mypy_extensions_extra() -> Result<()> {
None,
vec![],
);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -348,11 +336,9 @@ async fn black_flake8() -> Result<()> {
None,
vec![],
);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -376,11 +362,10 @@ async fn black_flake8() -> Result<()> {
#[tokio::test]
async fn black_lowest() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black>21").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::Lowest,
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.resolution_mode(ResolutionMode::Lowest)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -404,11 +389,10 @@ async fn black_lowest() -> Result<()> {
#[tokio::test]
async fn black_lowest_direct() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black>21").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::LowestDirect,
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.resolution_mode(ResolutionMode::LowestDirect)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -439,11 +423,9 @@ async fn black_respect_preference() -> Result<()> {
None,
vec![],
);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -474,11 +456,9 @@ async fn black_ignore_preference() -> Result<()> {
None,
vec![],
);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -502,11 +482,10 @@ async fn black_ignore_preference() -> Result<()> {
#[tokio::test]
async fn black_disallow_prerelease() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black<=20.0").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::Disallow,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::Disallow)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let err = resolve(manifest, options, &MARKERS_311, &TAGS_311)
.await
@ -524,11 +503,10 @@ async fn black_disallow_prerelease() -> Result<()> {
#[tokio::test]
async fn black_allow_prerelease_if_necessary() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("black<=20.0").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::IfNecessary,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::IfNecessary)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let err = resolve(manifest, options, &MARKERS_311, &TAGS_311)
.await
@ -546,11 +524,10 @@ async fn black_allow_prerelease_if_necessary() -> Result<()> {
#[tokio::test]
async fn pylint_disallow_prerelease() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("pylint==2.3.0").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::Disallow,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::Disallow)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -570,11 +547,10 @@ async fn pylint_disallow_prerelease() -> Result<()> {
#[tokio::test]
async fn pylint_allow_prerelease() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("pylint==2.3.0").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::Allow,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::Allow)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -597,11 +573,10 @@ async fn pylint_allow_explicit_prerelease_without_marker() -> Result<()> {
Requirement::from_str("pylint==2.3.0").unwrap(),
Requirement::from_str("isort>=5.0.0").unwrap(),
]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::Explicit,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::Explicit)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -624,11 +599,10 @@ async fn pylint_allow_explicit_prerelease_with_marker() -> Result<()> {
Requirement::from_str("pylint==2.3.0").unwrap(),
Requirement::from_str("isort>=5.0.0b").unwrap(),
]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::Explicit,
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.prerelease_mode(PreReleaseMode::Explicit)
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let resolution = resolve(manifest, options, &MARKERS_311, &TAGS_311).await?;
@ -650,11 +624,9 @@ async fn pylint_allow_explicit_prerelease_with_marker() -> Result<()> {
#[tokio::test]
async fn msgraph_sdk() -> Result<()> {
let manifest = Manifest::simple(vec![Requirement::from_str("msgraph-sdk==1.0.0").unwrap()]);
let options = ResolutionOptions::new(
ResolutionMode::default(),
PreReleaseMode::default(),
Some(*EXCLUDE_NEWER),
);
let options = OptionsBuilder::new()
.exclude_newer(Some(*EXCLUDE_NEWER))
.build();
let err = resolve(manifest, options, &MARKERS_311, &TAGS_311)
.await

View file

@ -27,8 +27,8 @@ use puffin_installer::{Downloader, NoBinary};
use puffin_interpreter::{Interpreter, PythonVersion};
use puffin_normalize::{ExtraName, PackageName};
use puffin_resolver::{
DisplayResolutionGraph, InMemoryIndex, Manifest, PreReleaseMode, ResolutionMode,
ResolutionOptions, Resolver,
DisplayResolutionGraph, InMemoryIndex, Manifest, OptionsBuilder, PreReleaseMode,
ResolutionMode, Resolver,
};
use puffin_traits::{InFlight, SetupPyStrategy};
use puffin_warnings::warn_user;
@ -207,7 +207,12 @@ pub(crate) async fn pip_compile(
// Track in-flight downloads, builds, etc., across resolutions.
let in_flight = InFlight::default();
let options = ResolutionOptions::new(resolution_mode, prerelease_mode, exclude_newer);
let options = OptionsBuilder::new()
.resolution_mode(resolution_mode)
.prerelease_mode(prerelease_mode)
.exclude_newer(exclude_newer)
.build();
let build_dispatch = BuildDispatch::new(
&client,
&cache,

View file

@ -26,8 +26,8 @@ use puffin_installer::{
use puffin_interpreter::{Interpreter, Virtualenv};
use puffin_normalize::PackageName;
use puffin_resolver::{
InMemoryIndex, Manifest, PreReleaseMode, ResolutionGraph, ResolutionMode, ResolutionOptions,
Resolver,
InMemoryIndex, Manifest, Options, OptionsBuilder, PreReleaseMode, ResolutionGraph,
ResolutionMode, Resolver,
};
use puffin_traits::{InFlight, SetupPyStrategy};
use requirements_txt::EditableRequirement;
@ -151,7 +151,11 @@ pub(crate) async fn pip_install(
// Track in-flight downloads, builds, etc., across resolutions.
let in_flight = InFlight::default();
let options = ResolutionOptions::new(resolution_mode, prerelease_mode, exclude_newer);
let options = OptionsBuilder::new()
.resolution_mode(resolution_mode)
.prerelease_mode(prerelease_mode)
.exclude_newer(exclude_newer)
.build();
let resolve_dispatch = BuildDispatch::new(
&client,
@ -379,7 +383,7 @@ async fn resolve(
flat_index: &FlatIndex,
index: &InMemoryIndex,
build_dispatch: &BuildDispatch<'_>,
options: ResolutionOptions,
options: Options,
mut printer: Printer,
) -> Result<ResolutionGraph, Error> {
let start = std::time::Instant::now();