mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-03 05:03:46 +00:00
Show build output by default in uv build (#6912)
## Summary This is a big improvement IMO: 
This commit is contained in:
parent
5d8e99045a
commit
05ed4bc11d
9 changed files with 719 additions and 44 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -4561,6 +4561,7 @@ dependencies = [
|
|||
name = "uv-build"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anyhow",
|
||||
"distribution-types",
|
||||
"fs-err",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ uv-python = { workspace = true }
|
|||
uv-types = { workspace = true }
|
||||
uv-virtualenv = { workspace = true }
|
||||
|
||||
anstream = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
fs-err = { workspace = true }
|
||||
indoc = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_hash::FxHashMap;
|
|||
use serde::de::{value, SeqAccess, Visitor};
|
||||
use serde::{de, Deserialize, Deserializer};
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::Write;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -29,7 +30,7 @@ use distribution_types::Resolution;
|
|||
use pep440_rs::Version;
|
||||
use pep508_rs::PackageName;
|
||||
use pypi_types::{Requirement, VerbatimParsedUrl};
|
||||
use uv_configuration::{BuildKind, ConfigSettings};
|
||||
use uv_configuration::{BuildKind, BuildOutput, ConfigSettings};
|
||||
use uv_fs::{rename_with_retry, PythonExt, Simplified};
|
||||
use uv_python::{Interpreter, PythonEnvironment};
|
||||
use uv_types::{BuildContext, BuildIsolation, SourceBuildTrait};
|
||||
|
|
@ -93,7 +94,7 @@ pub enum Error {
|
|||
#[error("Failed to run `{0}`")]
|
||||
CommandFailed(PathBuf, #[source] io::Error),
|
||||
#[error("{message} with {exit_code}\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")]
|
||||
BuildBackend {
|
||||
BuildBackendOutput {
|
||||
message: String,
|
||||
exit_code: ExitStatus,
|
||||
stdout: String,
|
||||
|
|
@ -101,7 +102,7 @@ pub enum Error {
|
|||
},
|
||||
/// Nudge the user towards installing the missing dev library
|
||||
#[error("{message} with {exit_code}\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")]
|
||||
MissingHeader {
|
||||
MissingHeaderOutput {
|
||||
message: String,
|
||||
exit_code: ExitStatus,
|
||||
stdout: String,
|
||||
|
|
@ -109,6 +110,18 @@ pub enum Error {
|
|||
#[source]
|
||||
missing_header_cause: MissingHeaderCause,
|
||||
},
|
||||
#[error("{message} with {exit_code}")]
|
||||
BuildBackend {
|
||||
message: String,
|
||||
exit_code: ExitStatus,
|
||||
},
|
||||
#[error("{message} with {exit_code}")]
|
||||
MissingHeader {
|
||||
message: String,
|
||||
exit_code: ExitStatus,
|
||||
#[source]
|
||||
missing_header_cause: MissingHeaderCause,
|
||||
},
|
||||
#[error("Failed to build PATH for build script")]
|
||||
BuildScriptPath(#[source] env::JoinPathsError),
|
||||
}
|
||||
|
|
@ -161,6 +174,7 @@ impl Error {
|
|||
fn from_command_output(
|
||||
message: String,
|
||||
output: &PythonRunnerOutput,
|
||||
level: BuildOutput,
|
||||
version_id: impl Into<String>,
|
||||
) -> Self {
|
||||
// In the cases I've seen it was the 5th and 3rd last line (see test case), 10 seems like a reasonable cutoff.
|
||||
|
|
@ -186,27 +200,74 @@ impl Error {
|
|||
});
|
||||
|
||||
if let Some(missing_library) = missing_library {
|
||||
return Self::MissingHeader {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
stdout: output.stdout.iter().join("\n"),
|
||||
stderr: output.stderr.iter().join("\n"),
|
||||
missing_header_cause: MissingHeaderCause {
|
||||
missing_library,
|
||||
version_id: version_id.into(),
|
||||
return match level {
|
||||
BuildOutput::Stderr => Self::MissingHeader {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
missing_header_cause: MissingHeaderCause {
|
||||
missing_library,
|
||||
version_id: version_id.into(),
|
||||
},
|
||||
},
|
||||
BuildOutput::Debug => Self::MissingHeaderOutput {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
stdout: output.stdout.iter().join("\n"),
|
||||
stderr: output.stderr.iter().join("\n"),
|
||||
missing_header_cause: MissingHeaderCause {
|
||||
missing_library,
|
||||
version_id: version_id.into(),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Self::BuildBackend {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
stdout: output.stdout.iter().join("\n"),
|
||||
stderr: output.stderr.iter().join("\n"),
|
||||
match level {
|
||||
BuildOutput::Stderr => Self::BuildBackend {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
},
|
||||
BuildOutput::Debug => Self::BuildBackendOutput {
|
||||
message,
|
||||
exit_code: output.status,
|
||||
stdout: output.stdout.iter().join("\n"),
|
||||
stderr: output.stderr.iter().join("\n"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Printer {
|
||||
/// Send the build backend output to `stderr`.
|
||||
Stderr,
|
||||
/// Send the build backend output to `tracing`.
|
||||
Debug,
|
||||
}
|
||||
|
||||
impl From<BuildOutput> for Printer {
|
||||
fn from(output: BuildOutput) -> Self {
|
||||
match output {
|
||||
BuildOutput::Stderr => Self::Stderr,
|
||||
BuildOutput::Debug => Self::Debug,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Printer {
|
||||
fn write_str(&mut self, s: &str) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Stderr => {
|
||||
anstream::eprint!("{s}");
|
||||
}
|
||||
Self::Debug => {
|
||||
debug!("{}", s);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A `pyproject.toml` as specified in PEP 517.
|
||||
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
|
@ -380,6 +441,8 @@ pub struct SourceBuild {
|
|||
version_id: String,
|
||||
/// Whether we do a regular PEP 517 build or an PEP 660 editable build
|
||||
build_kind: BuildKind,
|
||||
/// Whether to send build output to `stderr` or `tracing`, etc.
|
||||
level: BuildOutput,
|
||||
/// Modified PATH that contains the `venv_bin`, `user_path` and `system_path` variables in that order
|
||||
modified_path: OsString,
|
||||
/// Environment variables to be passed in during metadata or wheel building
|
||||
|
|
@ -405,6 +468,7 @@ impl SourceBuild {
|
|||
build_isolation: BuildIsolation<'_>,
|
||||
build_kind: BuildKind,
|
||||
mut environment_variables: FxHashMap<OsString, OsString>,
|
||||
level: BuildOutput,
|
||||
concurrent_builds: usize,
|
||||
) -> Result<Self, Error> {
|
||||
let temp_dir = build_context.cache().environment()?;
|
||||
|
|
@ -488,7 +552,7 @@ impl SourceBuild {
|
|||
|
||||
// Create the PEP 517 build environment. If build isolation is disabled, we assume the build
|
||||
// environment is already setup.
|
||||
let runner = PythonRunner::new(concurrent_builds);
|
||||
let runner = PythonRunner::new(concurrent_builds, level);
|
||||
if build_isolation.is_isolated(package_name) {
|
||||
create_pep517_build_environment(
|
||||
&runner,
|
||||
|
|
@ -498,6 +562,7 @@ impl SourceBuild {
|
|||
build_context,
|
||||
&version_id,
|
||||
build_kind,
|
||||
level,
|
||||
&config_settings,
|
||||
&environment_variables,
|
||||
&modified_path,
|
||||
|
|
@ -513,6 +578,7 @@ impl SourceBuild {
|
|||
project,
|
||||
venv,
|
||||
build_kind,
|
||||
level,
|
||||
config_settings,
|
||||
metadata_directory: None,
|
||||
version_id,
|
||||
|
|
@ -698,6 +764,7 @@ impl SourceBuild {
|
|||
return Err(Error::from_command_output(
|
||||
format!("Build backend failed to determine metadata through `prepare_metadata_for_build_{}`", self.build_kind),
|
||||
&output,
|
||||
self.level,
|
||||
&self.version_id,
|
||||
));
|
||||
}
|
||||
|
|
@ -827,6 +894,7 @@ impl SourceBuild {
|
|||
self.build_kind, self.build_kind,
|
||||
),
|
||||
&output,
|
||||
self.level,
|
||||
&self.version_id,
|
||||
));
|
||||
}
|
||||
|
|
@ -839,6 +907,7 @@ impl SourceBuild {
|
|||
self.build_kind, self.build_kind,
|
||||
),
|
||||
&output,
|
||||
self.level,
|
||||
&self.version_id,
|
||||
));
|
||||
}
|
||||
|
|
@ -871,6 +940,7 @@ async fn create_pep517_build_environment(
|
|||
build_context: &impl BuildContext,
|
||||
version_id: &str,
|
||||
build_kind: BuildKind,
|
||||
level: BuildOutput,
|
||||
config_settings: &ConfigSettings,
|
||||
environment_variables: &FxHashMap<OsString, OsString>,
|
||||
modified_path: &OsString,
|
||||
|
|
@ -924,6 +994,7 @@ async fn create_pep517_build_environment(
|
|||
return Err(Error::from_command_output(
|
||||
format!("Build backend failed to determine extra requires with `build_{build_kind}()`"),
|
||||
&output,
|
||||
level,
|
||||
version_id,
|
||||
));
|
||||
}
|
||||
|
|
@ -935,6 +1006,7 @@ async fn create_pep517_build_environment(
|
|||
"Build backend failed to read extra requires from `get_requires_for_build_{build_kind}`: {err}"
|
||||
),
|
||||
&output,
|
||||
level,
|
||||
version_id,
|
||||
)
|
||||
})?;
|
||||
|
|
@ -946,6 +1018,7 @@ async fn create_pep517_build_environment(
|
|||
"Build backend failed to return extra requires with `get_requires_for_build_{build_kind}`: {err}"
|
||||
),
|
||||
&output,
|
||||
level,
|
||||
version_id,
|
||||
)
|
||||
})?;
|
||||
|
|
@ -985,6 +1058,7 @@ async fn create_pep517_build_environment(
|
|||
#[derive(Debug)]
|
||||
struct PythonRunner {
|
||||
control: Semaphore,
|
||||
level: BuildOutput,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -995,10 +1069,11 @@ struct PythonRunnerOutput {
|
|||
}
|
||||
|
||||
impl PythonRunner {
|
||||
/// Create a `PythonRunner` with the provided concurrency limit.
|
||||
fn new(concurrency: usize) -> PythonRunner {
|
||||
PythonRunner {
|
||||
/// Create a `PythonRunner` with the provided concurrency limit and output level.
|
||||
fn new(concurrency: usize, level: BuildOutput) -> Self {
|
||||
Self {
|
||||
control: Semaphore::new(concurrency),
|
||||
level,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1019,12 +1094,13 @@ impl PythonRunner {
|
|||
/// Read lines from a reader and store them in a buffer.
|
||||
async fn read_from(
|
||||
mut reader: tokio::io::Lines<tokio::io::BufReader<impl tokio::io::AsyncRead + Unpin>>,
|
||||
mut printer: Printer,
|
||||
buffer: &mut Vec<String>,
|
||||
) -> io::Result<()> {
|
||||
loop {
|
||||
match reader.next_line().await? {
|
||||
Some(line) => {
|
||||
debug!("{line}");
|
||||
let _ = writeln!(printer, "{line}");
|
||||
buffer.push(line);
|
||||
}
|
||||
None => return Ok(()),
|
||||
|
|
@ -1055,9 +1131,10 @@ impl PythonRunner {
|
|||
let stderr_reader = tokio::io::BufReader::new(child.stderr.take().unwrap()).lines();
|
||||
|
||||
// Asynchronously read from the in-memory pipes.
|
||||
let printer = Printer::from(self.level);
|
||||
let result = tokio::join!(
|
||||
read_from(stdout_reader, &mut stdout_buf),
|
||||
read_from(stderr_reader, &mut stderr_buf),
|
||||
read_from(stdout_reader, printer, &mut stdout_buf),
|
||||
read_from(stderr_reader, printer, &mut stderr_buf),
|
||||
);
|
||||
match result {
|
||||
(Ok(()), Ok(())) => {}
|
||||
|
|
@ -1087,9 +1164,9 @@ impl PythonRunner {
|
|||
mod test {
|
||||
use std::process::ExitStatus;
|
||||
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::{Error, PythonRunnerOutput};
|
||||
use indoc::indoc;
|
||||
use uv_configuration::BuildOutput;
|
||||
|
||||
#[test]
|
||||
fn missing_header() {
|
||||
|
|
@ -1120,9 +1197,10 @@ mod test {
|
|||
let err = Error::from_command_output(
|
||||
"Failed building wheel through setup.py".to_string(),
|
||||
&output,
|
||||
BuildOutput::Debug,
|
||||
"pygraphviz-1.11",
|
||||
);
|
||||
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
||||
// Unix uses exit status, Windows uses exit code.
|
||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||
insta::assert_snapshot!(formatted, @r###"
|
||||
|
|
@ -1172,9 +1250,10 @@ mod test {
|
|||
let err = Error::from_command_output(
|
||||
"Failed building wheel through setup.py".to_string(),
|
||||
&output,
|
||||
BuildOutput::Debug,
|
||||
"pygraphviz-1.11",
|
||||
);
|
||||
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
||||
// Unix uses exit status, Windows uses exit code.
|
||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||
insta::assert_snapshot!(formatted, @r###"
|
||||
|
|
@ -1217,9 +1296,10 @@ mod test {
|
|||
let err = Error::from_command_output(
|
||||
"Failed building wheel through setup.py".to_string(),
|
||||
&output,
|
||||
BuildOutput::Debug,
|
||||
"pygraphviz-1.11",
|
||||
);
|
||||
assert!(matches!(err, Error::MissingHeader { .. }));
|
||||
assert!(matches!(err, Error::MissingHeaderOutput { .. }));
|
||||
// Unix uses exit status, Windows uses exit code.
|
||||
let formatted = err.to_string().replace("exit status: ", "exit code: ");
|
||||
insta::assert_snapshot!(formatted, @r###"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ impl Display for BuildKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum BuildOutput {
|
||||
/// Send the build backend output to `stderr`.
|
||||
Stderr,
|
||||
/// Send the build backend output to `tracing`.
|
||||
Debug,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||
pub struct BuildOptions {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ use pypi_types::Requirement;
|
|||
use uv_build::{SourceBuild, SourceBuildContext};
|
||||
use uv_cache::Cache;
|
||||
use uv_client::RegistryClient;
|
||||
use uv_configuration::Concurrency;
|
||||
use uv_configuration::{
|
||||
BuildKind, BuildOptions, ConfigSettings, Constraints, IndexStrategy, Reinstall, SourceStrategy,
|
||||
};
|
||||
use uv_configuration::{BuildOutput, Concurrency};
|
||||
use uv_distribution::DistributionDatabase;
|
||||
use uv_git::GitResolver;
|
||||
use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
|
||||
|
|
@ -299,6 +299,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
|
|||
version_id: &'data str,
|
||||
dist: Option<&'data SourceDist>,
|
||||
build_kind: BuildKind,
|
||||
build_output: BuildOutput,
|
||||
) -> Result<SourceBuild> {
|
||||
let dist_name = dist.map(distribution_types::Name::name);
|
||||
// Note we can only prevent builds by name for packages with names
|
||||
|
|
@ -330,6 +331,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
|
|||
self.build_isolation,
|
||||
build_kind,
|
||||
self.build_extra_env_vars.clone(),
|
||||
build_output,
|
||||
self.concurrency.builds,
|
||||
)
|
||||
.boxed_local()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use uv_cache::{
|
|||
use uv_client::{
|
||||
CacheControl, CachedClientError, Connectivity, DataWithCachePolicy, RegistryClient,
|
||||
};
|
||||
use uv_configuration::BuildKind;
|
||||
use uv_configuration::{BuildKind, BuildOutput};
|
||||
use uv_extract::hash::Hasher;
|
||||
use uv_fs::{rename_with_retry, write_atomic, LockedFile};
|
||||
use uv_types::{BuildContext, SourceBuildTrait};
|
||||
|
|
@ -1436,6 +1436,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
} else {
|
||||
BuildKind::Wheel
|
||||
},
|
||||
BuildOutput::Debug,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::Build)?
|
||||
|
|
@ -1477,6 +1478,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
} else {
|
||||
BuildKind::Wheel
|
||||
},
|
||||
BuildOutput::Debug,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::Build)?;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use distribution_types::{CachedDist, IndexLocations, InstalledDist, Resolution,
|
|||
use pep508_rs::PackageName;
|
||||
use pypi_types::Requirement;
|
||||
use uv_cache::Cache;
|
||||
use uv_configuration::{BuildKind, BuildOptions, SourceStrategy};
|
||||
use uv_configuration::{BuildKind, BuildOptions, BuildOutput, SourceStrategy};
|
||||
use uv_git::GitResolver;
|
||||
use uv_python::PythonEnvironment;
|
||||
|
||||
|
|
@ -97,6 +97,7 @@ pub trait BuildContext {
|
|||
version_id: &'a str,
|
||||
dist: Option<&'a SourceDist>,
|
||||
build_kind: BuildKind,
|
||||
build_output: BuildOutput,
|
||||
) -> impl Future<Output = Result<Self::SourceDistBuilder>> + 'a;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use std::path::{Path, PathBuf};
|
|||
use uv_auth::store_credentials_from_url;
|
||||
use uv_cache::Cache;
|
||||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{BuildKind, Concurrency};
|
||||
use uv_configuration::{BuildKind, BuildOutput, Concurrency};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
use uv_fs::{Simplified, CWD};
|
||||
use uv_python::{
|
||||
|
|
@ -303,6 +303,8 @@ async fn build_impl(
|
|||
|
||||
let assets = match plan {
|
||||
BuildPlan::SdistToWheel => {
|
||||
anstream::eprintln!("{}", "Building source distribution...".bold());
|
||||
|
||||
// Build the sdist.
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
|
|
@ -311,6 +313,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Sdist,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let sdist = builder.build(&output_dir).await?;
|
||||
|
|
@ -331,6 +334,8 @@ async fn build_impl(
|
|||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
||||
anstream::eprintln!("{}", "Building wheel from source distribution...".bold());
|
||||
|
||||
// Build a wheel from the source distribution.
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
|
|
@ -339,6 +344,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Wheel,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let wheel = builder.build(&output_dir).await?;
|
||||
|
|
@ -346,6 +352,8 @@ async fn build_impl(
|
|||
BuiltDistributions::Both(output_dir.join(sdist), output_dir.join(wheel))
|
||||
}
|
||||
BuildPlan::Sdist => {
|
||||
anstream::eprintln!("{}", "Building source distribution...".bold());
|
||||
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
src.path(),
|
||||
|
|
@ -353,6 +361,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Sdist,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let sdist = builder.build(&output_dir).await?;
|
||||
|
|
@ -360,6 +369,8 @@ async fn build_impl(
|
|||
BuiltDistributions::Sdist(output_dir.join(sdist))
|
||||
}
|
||||
BuildPlan::Wheel => {
|
||||
anstream::eprintln!("{}", "Building wheel...".bold());
|
||||
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
src.path(),
|
||||
|
|
@ -367,6 +378,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Wheel,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let wheel = builder.build(&output_dir).await?;
|
||||
|
|
@ -374,6 +386,7 @@ async fn build_impl(
|
|||
BuiltDistributions::Wheel(output_dir.join(wheel))
|
||||
}
|
||||
BuildPlan::SdistAndWheel => {
|
||||
anstream::eprintln!("{}", "Building source distribution...".bold());
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
src.path(),
|
||||
|
|
@ -381,10 +394,12 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Sdist,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let sdist = builder.build(&output_dir).await?;
|
||||
|
||||
anstream::eprintln!("{}", "Building wheel...".bold());
|
||||
let builder = build_dispatch
|
||||
.setup_build(
|
||||
src.path(),
|
||||
|
|
@ -392,6 +407,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Wheel,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let wheel = builder.build(&output_dir).await?;
|
||||
|
|
@ -399,6 +415,8 @@ async fn build_impl(
|
|||
BuiltDistributions::Both(output_dir.join(&sdist), output_dir.join(&wheel))
|
||||
}
|
||||
BuildPlan::WheelFromSdist => {
|
||||
anstream::eprintln!("{}", "Building source distribution from wheel...".bold());
|
||||
|
||||
// Extract the source distribution into a temporary directory.
|
||||
let reader = fs_err::tokio::File::open(src.path()).await?;
|
||||
let ext = SourceDistExtension::from_path(src.path()).map_err(|err| {
|
||||
|
|
@ -422,6 +440,7 @@ async fn build_impl(
|
|||
&version_id,
|
||||
dist,
|
||||
BuildKind::Wheel,
|
||||
BuildOutput::Stderr,
|
||||
)
|
||||
.await?;
|
||||
let wheel = builder.build(&output_dir).await?;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,15 @@ mod common;
|
|||
#[test]
|
||||
fn build() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
|
|
@ -29,14 +38,88 @@ fn build() -> Result<()> {
|
|||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
// Build the specified path.
|
||||
uv_snapshot!(context.filters(), context.build().arg("project"), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("project"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
creating src/project.egg-info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Building wheel from source distribution...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/dist/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built project/dist/project-0.1.0.tar.gz and project/dist/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -52,12 +135,83 @@ fn build() -> Result<()> {
|
|||
fs_err::remove_dir_all(project.child("dist"))?;
|
||||
|
||||
// Build the current working directory.
|
||||
uv_snapshot!(context.filters(), context.build().current_dir(project.path()), @r###"
|
||||
uv_snapshot!(&filters, context.build().current_dir(project.path()), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Building wheel from source distribution...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/dist/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built dist/project-0.1.0.tar.gz and dist/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -73,22 +227,95 @@ fn build() -> Result<()> {
|
|||
fs_err::remove_dir_all(project.child("dist"))?;
|
||||
|
||||
// Error if there's nothing to build.
|
||||
uv_snapshot!(context.filters(), context.build(), @r###"
|
||||
uv_snapshot!(&filters, context.build(), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
error: [TEMP_DIR]/ does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in the directory
|
||||
|
||||
"###);
|
||||
|
||||
// Build to a specified path.
|
||||
uv_snapshot!(context.filters(), context.build().arg("--out-dir").arg("out").current_dir(project.path()), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("--out-dir").arg("out").current_dir(project.path()), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Building wheel from source distribution...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/out/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built out/project-0.1.0.tar.gz and out/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -107,6 +334,15 @@ fn build() -> Result<()> {
|
|||
#[test]
|
||||
fn sdist() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
|
|
@ -126,14 +362,50 @@ fn sdist() -> Result<()> {
|
|||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
// Build the specified path.
|
||||
uv_snapshot!(context.filters(), context.build().arg("--sdist").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("--sdist").current_dir(&project), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
creating src/project.egg-info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Successfully built dist/project-0.1.0.tar.gz
|
||||
"###);
|
||||
|
||||
|
|
@ -152,6 +424,15 @@ fn sdist() -> Result<()> {
|
|||
#[test]
|
||||
fn wheel() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
|
|
@ -171,14 +452,55 @@ fn wheel() -> Result<()> {
|
|||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
// Build the specified path.
|
||||
uv_snapshot!(context.filters(), context.build().arg("--wheel").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("--wheel").current_dir(&project), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building wheel...
|
||||
running egg_info
|
||||
creating src/project.egg-info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/dist/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built dist/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -197,6 +519,15 @@ fn wheel() -> Result<()> {
|
|||
#[test]
|
||||
fn sdist_wheel() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
|
|
@ -216,14 +547,88 @@ fn sdist_wheel() -> Result<()> {
|
|||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
// Build the specified path.
|
||||
uv_snapshot!(context.filters(), context.build().arg("--sdist").arg("--wheel").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("--sdist").arg("--wheel").current_dir(&project), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
creating src/project.egg-info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Building wheel...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/dist/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built dist/project-0.1.0.tar.gz and dist/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -242,6 +647,15 @@ fn sdist_wheel() -> Result<()> {
|
|||
#[test]
|
||||
fn wheel_from_sdist() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
|
|
@ -261,14 +675,50 @@ fn wheel_from_sdist() -> Result<()> {
|
|||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
// Build the sdist.
|
||||
uv_snapshot!(context.filters(), context.build().arg("--sdist").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("--sdist").current_dir(&project), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
running egg_info
|
||||
creating src/project.egg-info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running sdist
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running check
|
||||
creating project-0.1.0
|
||||
creating project-0.1.0/src
|
||||
creating project-0.1.0/src/project.egg-info
|
||||
copying files to project-0.1.0...
|
||||
copying README -> project-0.1.0
|
||||
copying pyproject.toml -> project-0.1.0
|
||||
copying src/__init__.py -> project-0.1.0/src
|
||||
copying src/project.egg-info/PKG-INFO -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/dependency_links.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/requires.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/top_level.txt -> project-0.1.0/src/project.egg-info
|
||||
copying src/project.egg-info/SOURCES.txt -> project-0.1.0/src/project.egg-info
|
||||
Writing project-0.1.0/setup.cfg
|
||||
Creating tar archive
|
||||
removing 'project-0.1.0' (and everything under it)
|
||||
Successfully built dist/project-0.1.0.tar.gz
|
||||
"###);
|
||||
|
||||
|
|
@ -282,7 +732,7 @@ fn wheel_from_sdist() -> Result<()> {
|
|||
.assert(predicate::path::missing());
|
||||
|
||||
// Error if `--wheel` is not specified.
|
||||
uv_snapshot!(context.filters(), context.build().arg("./dist/project-0.1.0.tar.gz").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("./dist/project-0.1.0.tar.gz").current_dir(&project), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
|
@ -292,7 +742,7 @@ fn wheel_from_sdist() -> Result<()> {
|
|||
"###);
|
||||
|
||||
// Error if `--sdist` is specified.
|
||||
uv_snapshot!(context.filters(), context.build().arg("./dist/project-0.1.0.tar.gz").arg("--sdist").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("./dist/project-0.1.0.tar.gz").arg("--sdist").current_dir(&project), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
|
@ -302,12 +752,50 @@ fn wheel_from_sdist() -> Result<()> {
|
|||
"###);
|
||||
|
||||
// Build the wheel from the sdist.
|
||||
uv_snapshot!(context.filters(), context.build().arg("./dist/project-0.1.0.tar.gz").arg("--wheel").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("./dist/project-0.1.0.tar.gz").arg("--wheel").current_dir(&project), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution from wheel...
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
running bdist_wheel
|
||||
running build
|
||||
running build_py
|
||||
creating build
|
||||
creating build/lib
|
||||
copying src/__init__.py -> build/lib
|
||||
running egg_info
|
||||
writing src/project.egg-info/PKG-INFO
|
||||
writing dependency_links to src/project.egg-info/dependency_links.txt
|
||||
writing requirements to src/project.egg-info/requires.txt
|
||||
writing top-level names to src/project.egg-info/top_level.txt
|
||||
reading manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
writing manifest file 'src/project.egg-info/SOURCES.txt'
|
||||
installing to build/bdist.linux-x86_64/wheel
|
||||
running install
|
||||
running install_lib
|
||||
creating build/bdist.linux-x86_64
|
||||
creating build/bdist.linux-x86_64/wheel
|
||||
copying build/lib/__init__.py -> build/bdist.linux-x86_64/wheel
|
||||
running install_egg_info
|
||||
Copying src/project.egg-info to build/bdist.linux-x86_64/wheel/project-0.1.0-py3.12.egg-info
|
||||
running install_scripts
|
||||
creating build/bdist.linux-x86_64/wheel/project-0.1.0.dist-info/WHEEL
|
||||
creating '[TEMP_DIR]/project/dist/[TMP]/wheel' to it
|
||||
adding '__init__.py'
|
||||
adding 'project-0.1.0.dist-info/METADATA'
|
||||
adding 'project-0.1.0.dist-info/WHEEL'
|
||||
adding 'project-0.1.0.dist-info/top_level.txt'
|
||||
adding 'project-0.1.0.dist-info/RECORD'
|
||||
removing build/bdist.linux-x86_64/wheel
|
||||
Successfully built dist/project-0.1.0-py3-none-any.whl
|
||||
"###);
|
||||
|
||||
|
|
@ -321,14 +809,87 @@ fn wheel_from_sdist() -> Result<()> {
|
|||
.assert(predicate::path::is_file());
|
||||
|
||||
// Passing a wheel is an error.
|
||||
uv_snapshot!(context.filters(), context.build().arg("./dist/project-0.1.0-py3-none-any.whl").arg("--wheel").current_dir(&project), @r###"
|
||||
uv_snapshot!(&filters, context.build().arg("./dist/project-0.1.0-py3-none-any.whl").arg("--wheel").current_dir(&project), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution from wheel...
|
||||
error: `dist/project-0.1.0-py3-none-any.whl` is not a valid build source. Expected to receive a source directory, or a source distribution ending in one of: `.zip`, `.tar.gz`, `.tar.bz2`, `.tar.xz`, or `.tar.zst`.
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fail() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain([
|
||||
(r"exit code: 1", "exit status: 1"),
|
||||
(r"bdist\.[^/\\\s]+-[^/\\\s]+", "bdist.linux-x86_64"),
|
||||
(r"\\\.", ""),
|
||||
])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let project = context.temp_dir.child("project");
|
||||
|
||||
let pyproject_toml = project.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["anyio==3.7.0"]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=42"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
project.child("src").child("__init__.py").touch()?;
|
||||
project.child("README").touch()?;
|
||||
|
||||
project.child("setup.py").write_str(
|
||||
r#"
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name="project",
|
||||
version="0.1.0",
|
||||
packages=["project"],
|
||||
install_requires=["foo==3.7.0"],
|
||||
)
|
||||
"#,
|
||||
)?;
|
||||
|
||||
// Build the specified path.
|
||||
uv_snapshot!(&filters, context.build().arg("project"), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution...
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 14, in <module>
|
||||
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 328, in get_requires_for_build_sdist
|
||||
return self._get_build_requires(config_settings, requirements=[])
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 295, in _get_build_requires
|
||||
self.run_setup()
|
||||
File "[CACHE_DIR]/builds-v0/[TMP]/build_meta.py", line 311, in run_setup
|
||||
exec(code, locals())
|
||||
File "<string>", line 2
|
||||
from setuptools import setup
|
||||
IndentationError: unexpected indent
|
||||
error: Build backend failed to determine extra requires with `build_sdist()` with exit status: 1
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue