Change install to sync (with sync semantics) (#24)

For better separate at this stage (and following `pip-tools`), it's now
`puffin sync`, and it assumes `--no-deps`.
This commit is contained in:
Charlie Marsh 2023-10-06 15:42:58 -04:00 committed by GitHub
parent ff8e24a621
commit dab70a661a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 39 deletions

View file

@ -13,7 +13,7 @@ cargo run -p puffin-cli -- compile requirements.in
To install from a resolved `requirements.txt` file:
```shell
cargo run -p puffin-cli -- install requirements.txt
cargo run -p puffin-cli -- sync requirements.txt
```
## Benchmarks

View file

@ -43,7 +43,14 @@ pub(crate) async fn compile(src: &Path, cache: Option<&Path>) -> Result<ExitStat
};
// Resolve the dependencies.
let resolution = puffin_resolver::resolve(&requirements, markers, &tags, &client).await?;
let resolution = puffin_resolver::resolve(
&requirements,
markers,
&tags,
&client,
puffin_resolver::Flags::default(),
)
.await?;
for (name, package) in resolution.iter() {
#[allow(clippy::print_stdout)]

View file

@ -1,10 +1,10 @@
use std::process::ExitCode;
pub(crate) use compile::compile;
pub(crate) use install::install;
pub(crate) use sync::sync;
mod compile;
mod install;
mod sync;
#[derive(Copy, Clone)]
pub(crate) enum ExitStatus {

View file

@ -11,8 +11,8 @@ use puffin_platform::Platform;
use crate::commands::ExitStatus;
/// Install a set of requirements into the current Python environment.
pub(crate) async fn install(src: &Path, cache: Option<&Path>) -> Result<ExitStatus> {
/// Install a set of locked requirements into the current Python environment.
pub(crate) async fn sync(src: &Path, cache: Option<&Path>) -> Result<ExitStatus> {
// Read the `requirements.txt` from disk.
let requirements_txt = std::fs::read_to_string(src)?;
@ -43,12 +43,23 @@ pub(crate) async fn install(src: &Path, cache: Option<&Path>) -> Result<ExitStat
};
// Resolve the dependencies.
// TODO(charlie): When installing, assume `--no-deps`.
let resolution = puffin_resolver::resolve(&requirements, markers, &tags, &client).await?;
let resolution = puffin_resolver::resolve(
&requirements,
markers,
&tags,
&client,
puffin_resolver::Flags::NO_DEPS,
)
.await?;
// Install into the current environment.
let wheels = resolution.into_files().collect::<Vec<_>>();
puffin_installer::install(&wheels, &python, &client).await?;
#[allow(clippy::print_stdout)]
{
println!("Installed {} wheels", wheels.len());
}
Ok(ExitStatus::Success)
}

View file

@ -22,8 +22,8 @@ struct Cli {
enum Commands {
/// Compile a `requirements.in` file to a `requirements.txt` file.
Compile(CompileArgs),
/// Install dependencies from a `requirements.txt` file.
Install(InstallArgs),
/// Sync dependencies from a `requirements.txt` file.
Sync(SyncArgs),
}
#[derive(Args)]
@ -37,7 +37,7 @@ struct CompileArgs {
}
#[derive(Args)]
struct InstallArgs {
struct SyncArgs {
/// Path to the `requirements.txt` file to install.
src: PathBuf,
@ -59,16 +59,16 @@ async fn main() -> ExitCode {
commands::compile(
&args.src,
dirs.as_ref()
.map(directories::ProjectDirs::cache_dir)
.map(ProjectDirs::cache_dir)
.filter(|_| !args.no_cache),
)
.await
}
Commands::Install(args) => {
commands::install(
Commands::Sync(args) => {
commands::sync(
&args.src,
dirs.as_ref()
.map(directories::ProjectDirs::cache_dir)
.map(ProjectDirs::cache_dir)
.filter(|_| !args.no_cache),
)
.await

View file

@ -19,3 +19,4 @@ futures = "0.3.28"
anyhow = "1.0.75"
tracing = "0.1.37"
pep508_rs = "0.2.3"
bitflags = "2.4.0"

View file

@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
use std::str::FromStr;
use anyhow::Result;
use bitflags::bitflags;
use futures::future::Either;
use futures::{StreamExt, TryFutureExt};
use pep440_rs::Version;
@ -42,12 +43,21 @@ impl PinnedPackage {
}
}
bitflags! {
#[derive(Debug, Copy, Clone, Default)]
pub struct Flags: u8 {
/// Don't install package dependencies.
const NO_DEPS = 1 << 0;
}
}
/// Resolve a set of requirements into a set of pinned versions.
pub async fn resolve(
requirements: &Requirements,
markers: &MarkerEnvironment,
tags: &Tags,
client: &PypiClient,
flags: Flags,
) -> Result<Resolution> {
// A channel to fetch package metadata (e.g., given `flask`, fetch all versions) and version
// metadata (e.g., given `flask==1.0.0`, fetch the metadata for that version).
@ -141,6 +151,7 @@ pub async fn resolve(
},
);
if !flags.intersects(Flags::NO_DEPS) {
// Enqueue its dependencies.
for dependency in metadata.requires_dist {
if !dependency.evaluate_markers(
@ -166,6 +177,7 @@ pub async fn resolve(
package_sink.unbounded_send(Request::Package(dependency))?;
}
};
}
}
}