Skip to content

Commit

Permalink
Build source distributions in the resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
konstin committed Oct 19, 2023
1 parent 7ef6c03 commit 3700120
Show file tree
Hide file tree
Showing 23 changed files with 392 additions and 111 deletions.
47 changes: 41 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/install-wheel-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
use std::io;

use platform_host::{Arch, Os};
use platform_info::PlatformInfoError;
use thiserror::Error;
use zip::result::ZipError;

pub use install_location::{normalize_name, InstallLocation, LockedDir};
use platform_host::{Arch, Os};
pub use record::RecordEntry;
pub use script::Script;
pub use uninstall::{uninstall_wheel, Uninstall};
pub use wheel::{
get_script_launcher, install_wheel, parse_key_value_file, read_record_file, relative_to,
SHEBANG_PYTHON,
find_dist_info, get_script_launcher, install_wheel, parse_key_value_file, read_record_file,
relative_to, SHEBANG_PYTHON,
};

mod install_location;
Expand Down
2 changes: 1 addition & 1 deletion crates/install-wheel-rs/src/wheel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ pub fn install_wheel(
/// Either way, we just search the wheel for the name
///
/// <https://github.com/PyO3/python-pkginfo-rs>
fn find_dist_info(
pub fn find_dist_info(
filename: &WheelFilename,
archive: &mut ZipArchive<impl Read + Seek + Sized>,
) -> Result<String, Error> {
Expand Down
2 changes: 2 additions & 0 deletions crates/puffin-build-cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
downloads
wheels
37 changes: 37 additions & 0 deletions crates/puffin-build-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[package]
name = "puffin-build-cli"
version = "0.0.1"
description = "Build wheels from source distributions"
edition = { workspace = true }
rust-version = { workspace = true }
homepage = { workspace = true }
documentation = { workspace = true }
repository = { workspace = true }
authors = { workspace = true }
license = { workspace = true }

[dependencies]
gourgeist = { path = "../gourgeist" }
pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" }
puffin-build = { path = "../puffin-build" }
puffin-client = { path = "../puffin-client" }
puffin-installer = { path = "../puffin-installer" }
puffin-interpreter = { path = "../puffin-interpreter" }
puffin-package = { path = "../puffin-package" }
puffin-resolver = { path = "../puffin-resolver" }
puffin-workspace = { path = "../puffin-workspace" }

anyhow = { workspace = true }
clap = { workspace = true, features = ["derive"] }
directories = { workspace = true }
fs-err = { workspace = true }
futures = { workspace = true }
itertools = { workspace = true }
owo-colors = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
which = { workspace = true }
3 changes: 3 additions & 0 deletions crates/puffin-build-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod sdist;

pub use sdist::resolve_and_install;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(clippy::print_stdout, clippy::print_stderr)]

use crate::sdist::resolve_and_install;
use anyhow::Context;
use clap::Parser;
use directories::ProjectDirs;
Expand All @@ -16,6 +17,8 @@ use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter};

pub mod sdist;

#[derive(Parser)]
struct Args {
/// Base python in a way that can be found with `which`
Expand Down Expand Up @@ -49,9 +52,14 @@ async fn run() -> anyhow::Result<()> {
})?;
let interpreter_info = gourgeist::get_interpreter_info(&base_python)?;

let builder =
SourceDistributionBuilder::setup(&args.sdist, &base_python, &interpreter_info, cache)
.await?;
let builder = SourceDistributionBuilder::setup(
&args.sdist,
&base_python,
&interpreter_info,
cache,
resolve_and_install,
)
.await?;
let wheel = builder.build(&wheel_dir)?;
println!("Wheel built to {}", wheel.display());
Ok(())
Expand Down
74 changes: 74 additions & 0 deletions crates/puffin-build-cli/src/sdist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use anyhow::Context;
use futures::FutureExt;
use itertools::{Either, Itertools};
use pep508_rs::Requirement;
use platform_host::Platform;
use platform_tags::Tags;
use puffin_client::PypiClientBuilder;
use puffin_installer::{CachedDistribution, Downloader, LocalIndex, RemoteDistribution, Unzipper};
use puffin_interpreter::PythonExecutable;
use puffin_package::package_name::PackageName;
use puffin_resolver::WheelFinder;
use std::future::Future;
use std::path::Path;
use std::pin::Pin;
use tempfile::tempdir;
use tracing::{debug, instrument};

#[instrument(skip_all)]
pub async fn resolve_and_install_impl(
venv: &Path,
requirements: &[Requirement],
cache: Option<&Path>,
) -> anyhow::Result<()> {
debug!("Installing {} build requirements", requirements.len());

let local_index = if let Some(cache) = cache {
LocalIndex::from_directory(cache).await?
} else {
LocalIndex::default()
};
let (cached, uncached): (Vec<CachedDistribution>, Vec<Requirement>) =
requirements.iter().partition_map(|requirement| {
let package = PackageName::normalize(&requirement.name);
if let Some(distribution) = local_index
.get(&package)
.filter(|dist| requirement.is_satisfied_by(dist.version()))
{
Either::Left(distribution.clone())
} else {
Either::Right(requirement.clone())
}
});

let client = PypiClientBuilder::default().cache(cache).build();

let platform = Platform::current()?;
let python = PythonExecutable::from_venv(platform, venv, cache)?;
let tags = Tags::from_env(python.platform(), python.simple_version())?;
let resolution = WheelFinder::new(&tags, &client).resolve(&uncached).await?;
let uncached = resolution
.into_files()
.map(RemoteDistribution::from_file)
.collect::<anyhow::Result<Vec<_>>>()?;
let staging = tempdir()?;
let downloads = Downloader::new(&client, cache)
.download(&uncached, cache.unwrap_or(staging.path()))
.await?;
let unzips = Unzipper::default()
.download(downloads, cache.unwrap_or(staging.path()))
.await
.context("Failed to download and unpack wheels")?;
let wheels = unzips.into_iter().chain(cached).collect::<Vec<_>>();
puffin_installer::Installer::new(&python).install(&wheels)?;

Ok(())
}

pub fn resolve_and_install<'a>(
venv: &'a Path,
requirements: &'a [Requirement],
cache: Option<&'a Path>,
) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send + 'a>> {
resolve_and_install_impl(venv, requirements, cache).boxed()
}
File renamed without changes.
6 changes: 0 additions & 6 deletions crates/puffin-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ gourgeist = { path = "../gourgeist" }
pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" }
puffin-client = { path = "../puffin-client" }
puffin-installer = { path = "../puffin-installer" }
puffin-interpreter = { path = "../puffin-interpreter" }
puffin-package = { path = "../puffin-package" }
puffin-resolver = { path = "../puffin-resolver" }
puffin-workspace = { path = "../puffin-workspace" }

anyhow = { workspace = true }
clap = { workspace = true, features = ["derive"] }
Expand Down
Loading

0 comments on commit 3700120

Please sign in to comment.