Support editable in pip-sync and pip-compile (#587)

Support `-e path/do/dir` in pip-sync and and pip-compile.
This commit is contained in:
konsti 2023-12-16 23:37:34 +01:00 committed by GitHub
parent f62458f600
commit f059c6e6a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 1016 additions and 250 deletions

View file

@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::io;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
@ -13,9 +14,9 @@ use url::Url;
use distribution_filename::{WheelFilename, WheelFilenameError};
use distribution_types::direct_url::DirectGitUrl;
use distribution_types::{BuiltDist, Dist, Metadata, SourceDist};
use distribution_types::{BuiltDist, Dist, LocalEditable, Metadata, SourceDist};
use platform_tags::Tags;
use puffin_cache::{Cache, CacheBucket, WheelCache};
use puffin_cache::{digest, Cache, CacheBucket, WheelCache};
use puffin_client::RegistryClient;
use puffin_git::GitSource;
use puffin_traits::BuildContext;
@ -273,6 +274,26 @@ impl<'a, Context: BuildContext + Send + Sync> DistributionDatabase<'a, Context>
}
}
/// Build a directory into an editable wheel.
pub async fn build_wheel_editable(
&self,
editable: &LocalEditable,
editable_wheel_dir: &Path,
) -> Result<(LocalWheel, Metadata21), DistributionDatabaseError> {
let (dist, disk_filename, filename, metadata) = self
.builder
.build_editable(editable, editable_wheel_dir)
.await?;
let built_wheel = BuiltWheel {
dist,
filename,
path: editable_wheel_dir.join(disk_filename),
target: editable_wheel_dir.join(digest(&editable.path)),
};
Ok((LocalWheel::Built(built_wheel), metadata))
}
/// Given a remote source distribution, return a precise variant, if possible.
///
/// For example, given a Git dependency with a reference to a branch or tag, return a URL

View file

@ -1,5 +1,5 @@
pub use distribution_database::{DistributionDatabase, DistributionDatabaseError};
pub use download::{DiskWheel, InMemoryWheel, LocalWheel};
pub use download::{BuiltWheel, DiskWheel, InMemoryWheel, LocalWheel};
pub use index::{BuiltWheelIndex, RegistryWheelIndex};
pub use reporter::Reporter;
pub use source_dist::{SourceDistCachedBuilder, SourceDistError};

View file

@ -2,14 +2,14 @@ use std::sync::Arc;
use url::Url;
use distribution_types::SourceDist;
use distribution_types::Metadata;
pub trait Reporter: Send + Sync {
/// Callback to invoke when a source distribution build is kicked off.
fn on_build_start(&self, dist: &SourceDist) -> usize;
fn on_build_start(&self, dist: &dyn Metadata) -> usize;
/// Callback to invoke when a source distribution build is complete.
fn on_build_complete(&self, dist: &SourceDist, id: usize);
fn on_build_complete(&self, dist: &dyn Metadata, id: usize);
/// Callback to invoke when a repository checkout begins.
fn on_checkout_start(&self, url: &Url, rev: &str) -> usize;

View file

@ -21,7 +21,9 @@ use zip::ZipArchive;
use distribution_filename::{WheelFilename, WheelFilenameError};
use distribution_types::direct_url::{DirectArchiveUrl, DirectGitUrl};
use distribution_types::{GitSourceDist, Metadata, PathSourceDist, RemoteSource, SourceDist};
use distribution_types::{
Dist, GitSourceDist, LocalEditable, Metadata, PathSourceDist, RemoteSource, SourceDist,
};
use install_wheel_rs::read_dist_info;
use platform_tags::Tags;
use puffin_cache::{
@ -31,7 +33,7 @@ use puffin_client::{CachedClient, CachedClientError, DataWithCachePolicy};
use puffin_fs::write_atomic;
use puffin_git::{Fetch, GitSource};
use puffin_normalize::PackageName;
use puffin_traits::{BuildContext, SourceBuildTrait};
use puffin_traits::{BuildContext, BuildKind, SourceBuildTrait};
use pypi_types::Metadata21;
use crate::locks::LockedFile;
@ -63,7 +65,7 @@ pub enum SourceDistError {
// Build error
#[error("Failed to build: {0}")]
Build(Box<SourceDist>, #[source] anyhow::Error),
Build(String, #[source] anyhow::Error),
#[error("Built wheel has an invalid filename")]
WheelFilename(#[from] WheelFilenameError),
#[error("Package metadata name `{metadata}` does not match given name `{given}`")]
@ -688,12 +690,17 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
fs::create_dir_all(&cache_entry.dir).await?;
let disk_filename = self
.build_context
.setup_build(source_dist, subdirectory, &dist.to_string())
.setup_build(
source_dist,
subdirectory,
&dist.to_string(),
BuildKind::Wheel,
)
.await
.map_err(|err| SourceDistError::Build(Box::new(dist.clone()), err))?
.map_err(|err| SourceDistError::Build(dist.to_string(), err))?
.wheel(&cache_entry.dir)
.await
.map_err(|err| SourceDistError::Build(Box::new(dist.clone()), err))?;
.map_err(|err| SourceDistError::Build(dist.to_string(), err))?;
// Read the metadata from the wheel.
let filename = WheelFilename::from_str(&disk_filename)?;
@ -703,6 +710,40 @@ impl<'a, T: BuildContext> SourceDistCachedBuilder<'a, T> {
Ok((disk_filename, filename, metadata))
}
/// Build a single directory into an editable wheel
pub async fn build_editable(
&self,
editable: &LocalEditable,
editable_wheel_dir: &Path,
) -> Result<(Dist, String, WheelFilename, Metadata21), SourceDistError> {
debug!("Building (editable) {editable}");
let disk_filename = self
.build_context
.setup_build(
&editable.path,
None,
&editable.to_string(),
BuildKind::Editable,
)
.await
.map_err(|err| SourceDistError::Build(editable.to_string(), err))?
.wheel(editable_wheel_dir)
.await
.map_err(|err| SourceDistError::Build(editable.to_string(), err))?;
let filename = WheelFilename::from_str(&disk_filename)?;
// We finally have the name of the package and can construct the dist
let dist = Dist::Source(SourceDist::Path(PathSourceDist {
name: filename.name.clone(),
url: editable.url().clone(),
path: editable.path.clone(),
editable: true,
}));
let metadata = read_metadata(&filename, editable_wheel_dir.join(&disk_filename))?;
debug!("Finished building (editable): {dist}");
Ok((dist, disk_filename, filename, metadata))
}
/// Read an existing cache entry, if it exists and is up-to-date.
async fn read_fresh_metadata(
cache_entry: &CacheEntry,