mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-27 02:17:08 +00:00
Show a dedicated error for venvs in source trees (#15748)
A user in the support chat had an error message for `uv build` with the `uv_build` backend they didn't understand, which was caused by them having a venv in their build directory. This PR adds a dedicated error message when adding something to a distribution that looks like a venv.
This commit is contained in:
parent
9d3a3843c3
commit
12764df8b2
5 changed files with 79 additions and 3 deletions
|
|
@ -9,6 +9,7 @@ pub use settings::{BuildBackendSettings, WheelDataIncludes};
|
|||
pub use source_dist::{build_source_dist, list_source_dist};
|
||||
pub use wheel::{build_editable, build_wheel, list_wheel, metadata};
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
|
@ -69,6 +70,8 @@ pub enum Error {
|
|||
/// Either an absolute path or a parent path through `..`.
|
||||
#[error("The path for the data directory {} must be inside the project: `{}`", name, path.user_display())]
|
||||
InvalidDataRoot { name: String, path: PathBuf },
|
||||
#[error("Virtual environments must not be added to source distributions or wheels, remove the directory or exclude it from the build: {}", _0.user_display())]
|
||||
VenvInSourceTree(PathBuf),
|
||||
#[error("Inconsistent metadata between prepare and build step: `{0}`")]
|
||||
InconsistentSteps(&'static str),
|
||||
#[error("Failed to write to {}", _0.user_display())]
|
||||
|
|
@ -352,6 +355,27 @@ fn module_path_from_module_name(src_root: &Path, module_name: &str) -> Result<Pa
|
|||
Ok(module_relative)
|
||||
}
|
||||
|
||||
/// Error if we're adding a venv to a distribution.
|
||||
pub(crate) fn error_on_venv(file_name: &OsStr, path: &Path) -> Result<(), Error> {
|
||||
// On 64-bit Unix, `lib64` is a (compatibility) symlink to lib. If we traverse `lib64` before
|
||||
// `pyvenv.cfg`, we show a generic error for symlink directories instead.
|
||||
if !(file_name == "pyvenv.cfg" || file_name == "lib64") {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Some(parent) = path.parent() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if parent.join("bin").join("python").is_symlink()
|
||||
|| parent.join("Scripts").join("python.exe").is_file()
|
||||
{
|
||||
return Err(Error::VenvInSourceTree(parent.to_path_buf()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use uv_pep508::{
|
|||
use uv_pypi_types::{Metadata23, VerbatimParsedUrl};
|
||||
|
||||
use crate::serde_verbatim::SerdeVerbatim;
|
||||
use crate::{BuildBackendSettings, Error};
|
||||
use crate::{BuildBackendSettings, Error, error_on_venv};
|
||||
|
||||
/// By default, we ignore generated python files.
|
||||
pub(crate) const DEFAULT_EXCLUDES: &[&str] = &["__pycache__", "*.pyc", "*.pyo"];
|
||||
|
|
@ -448,6 +448,8 @@ impl PyProjectToml {
|
|||
continue;
|
||||
}
|
||||
|
||||
error_on_venv(entry.file_name(), entry.path())?;
|
||||
|
||||
debug!("License files match: `{}`", relative.user_display());
|
||||
license_files.push(relative.portable_display().to_string());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::metadata::DEFAULT_EXCLUDES;
|
||||
use crate::wheel::build_exclude_matcher;
|
||||
use crate::{
|
||||
BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml, find_roots,
|
||||
BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml,
|
||||
error_on_venv, find_roots,
|
||||
};
|
||||
use flate2::Compression;
|
||||
use flate2::write::GzEncoder;
|
||||
|
|
@ -266,6 +267,8 @@ fn write_source_dist(
|
|||
continue;
|
||||
}
|
||||
|
||||
error_on_venv(entry.file_name(), entry.path())?;
|
||||
|
||||
let entry_path = Path::new(&top_level)
|
||||
.join(relative)
|
||||
.portable_display()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ use uv_warnings::warn_user_once;
|
|||
|
||||
use crate::metadata::DEFAULT_EXCLUDES;
|
||||
use crate::{
|
||||
BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml, find_roots,
|
||||
BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml,
|
||||
error_on_venv, find_roots,
|
||||
};
|
||||
|
||||
/// Build a wheel from the source tree and place it in the output directory.
|
||||
|
|
@ -180,6 +181,8 @@ fn write_wheel(
|
|||
continue;
|
||||
}
|
||||
|
||||
error_on_venv(entry.file_name(), entry.path())?;
|
||||
|
||||
let entry_path = entry_path.portable_display().to_string();
|
||||
debug!("Adding to wheel: {entry_path}");
|
||||
wheel_writer.write_dir_entry(&entry, &entry_path)?;
|
||||
|
|
@ -529,6 +532,8 @@ fn wheel_subdir_from_globs(
|
|||
continue;
|
||||
}
|
||||
|
||||
error_on_venv(entry.file_name(), entry.path())?;
|
||||
|
||||
let license_path = Path::new(target)
|
||||
.join(relative)
|
||||
.portable_display()
|
||||
|
|
|
|||
|
|
@ -987,3 +987,45 @@ fn error_on_relative_data_dir_outside_project_root() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Show an explicit error when there is a venv in source tree.
|
||||
#[test]
|
||||
fn venv_in_source_tree() {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
context
|
||||
.init()
|
||||
.arg("--lib")
|
||||
.arg("--name")
|
||||
.arg("foo")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
context
|
||||
.venv()
|
||||
.arg(context.temp_dir.join("src").join("foo").join(".venv"))
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
uv_snapshot!(context.filters(), context.build(), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building source distribution (uv build backend)...
|
||||
× Failed to build `[TEMP_DIR]/`
|
||||
╰─▶ Virtual environments must not be added to source distributions or wheels, remove the directory or exclude it from the build: src/foo/.venv
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.build().arg("--wheel"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Building wheel (uv build backend)...
|
||||
× Failed to build `[TEMP_DIR]/`
|
||||
╰─▶ Virtual environments must not be added to source distributions or wheels, remove the directory or exclude it from the build: src/foo/.venv
|
||||
");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue