Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build backend: Default excludes #9552

Merged
merged 2 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions crates/uv-build-backend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod metadata;

use crate::metadata::{BuildBackendSettings, PyProjectToml, ValidationError};
use crate::metadata::{BuildBackendSettings, PyProjectToml, ValidationError, DEFAULT_EXCLUDES};
use flate2::write::GzEncoder;
use flate2::Compression;
use fs_err::File;
Expand Down Expand Up @@ -304,7 +304,7 @@ pub fn build_wheel(
) -> Result<WheelFilename, Error> {
let contents = fs_err::read_to_string(source_tree.join("pyproject.toml"))?;
let pyproject_toml = PyProjectToml::parse(&contents)?;
pyproject_toml.check_build_system("1.0.0+test");
pyproject_toml.check_build_system(uv_version);
let settings = pyproject_toml
.settings()
.cloned()
Expand All @@ -326,7 +326,16 @@ pub fn build_wheel(
let mut wheel_writer = ZipDirectoryWriter::new_wheel(File::create(&wheel_path)?);

// Wheel excludes
let mut excludes: Vec<String> = settings.wheel_exclude;
let mut excludes: Vec<String> = Vec::new();
if settings.default_excludes {
excludes.extend(DEFAULT_EXCLUDES.iter().map(ToString::to_string));
}
for exclude in settings.wheel_exclude {
// Avoid duplicate entries.
if !excludes.contains(&exclude) {
excludes.push(exclude);
}
}
// The wheel must not include any files excluded by the source distribution (at least until we
// have files generated in the source dist -> wheel build step).
for exclude in settings.source_exclude {
Expand Down Expand Up @@ -456,7 +465,7 @@ pub fn build_editable(
) -> Result<WheelFilename, Error> {
let contents = fs_err::read_to_string(source_tree.join("pyproject.toml"))?;
let pyproject_toml = PyProjectToml::parse(&contents)?;
pyproject_toml.check_build_system("1.0.0+test");
pyproject_toml.check_build_system(uv_version);
let settings = pyproject_toml
.settings()
.cloned()
Expand Down Expand Up @@ -693,7 +702,15 @@ pub fn build_source_dist(
})?;

let mut excludes: Vec<String> = Vec::new();
excludes.extend(settings.source_exclude);
if settings.default_excludes {
excludes.extend(DEFAULT_EXCLUDES.iter().map(ToString::to_string));
}
for exclude in settings.source_exclude {
// Avoid duplicate entries.
if !excludes.contains(&exclude) {
excludes.push(exclude);
}
}
debug!("Source dist excludes: {:?}", excludes);
let exclude_matcher = build_exclude_matcher(excludes)?;
if exclude_matcher.is_match("pyproject.toml") {
Expand Down
53 changes: 26 additions & 27 deletions crates/uv-build-backend/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use version_ranges::Ranges;
use walkdir::WalkDir;

/// By default, we ignore generated python files.
const DEFAULT_EXCLUDES: &[&str] = &["__pycache__", "*.pyc", "*.pyo"];
pub(crate) const DEFAULT_EXCLUDES: &[&str] = &["__pycache__", "*.pyc", "*.pyo"];

#[derive(Debug, Error)]
pub enum ValidationError {
Expand Down Expand Up @@ -708,6 +708,8 @@ pub(crate) struct ToolUv {
/// To select which files to include in the source distribution, we first add the includes, then
/// remove the excludes from that.
///
/// ## Include and exclude configuration
///
/// When building the source distribution, the following files and directories are included:
/// * `pyproject.toml`
/// * The module under `tool.uv.build-backend.module-root`, by default
Expand All @@ -732,6 +734,21 @@ pub(crate) struct ToolUv {
/// There are no specific wheel includes. There must only be one top level module, and all data
/// files must either be under the module root or in a data directory. Most packages store small
/// data in the module root alongside the source code.
///
/// ## Include and exclude syntax
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm staging the real docs here

///
/// Includes are anchored, which means that `pyproject.toml` includes only
/// `<project root>/pyproject.toml`. Use for example `assets/**/sample.csv` to include for all
/// `sample.csv` files in `<project root>/assets` or any child directory. To recursively include
/// all files under a directory, use a `/**` suffix, e.g. `src/**`. For performance and
/// reproducibility, avoid unanchored matches such as `**/sample.csv`.
///
/// Excludes are not anchored, which means that `__pycache__` excludes all directories named
/// `__pycache__` and it's children anywhere. To anchor a directory, use a `/` prefix, e.g.,
/// `/dist` will exclude only `<project root>/dist`.
///
/// The glob syntax is the reduced portable glob from
/// [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key).
#[derive(Deserialize, Debug, Clone)]
#[serde(default, rename_all = "kebab-case")]
pub(crate) struct BuildBackendSettings {
Expand All @@ -744,38 +761,19 @@ pub(crate) struct BuildBackendSettings {
///
/// `pyproject.toml` and the contents of the module directory are always included.
///
/// Includes are anchored, which means that `pyproject.toml` includes only
/// `<project root>/pyproject.toml`. Use for example `assets/**/sample.csv` to include for all
/// `sample.csv` files in `<project root>/assets` or any child directory. To recursively include
/// all files under a directory, use a `/**` suffix, e.g. `src/**`. For performance and
/// reproducibility, avoid unanchored matches such as `**/sample.csv`.
///
/// The glob syntax is the reduced portable glob from
/// [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key).
pub(crate) source_include: Vec<String>,

/// Glob expressions which files and directories to exclude from the source distribution.
///
/// Default: `__pycache__`, `*.pyc`, and `*.pyo`.
///
/// Excludes are not anchored, which means that `__pycache__` excludes all directories named
/// `__pycache__` and it's children anywhere. To anchor a directory, use a `/` prefix, e.g.,
/// `/dist` will exclude only `<project root>/dist`.
/// If set to `false`, the default excludes aren't applied.
///
/// The glob syntax is the reduced portable glob from
/// [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key).
/// Default excludes: `__pycache__`, `*.pyc`, and `*.pyo`.
pub(crate) default_excludes: bool,

/// Glob expressions which files and directories to exclude from the source distribution.
pub(crate) source_exclude: Vec<String>,

/// Glob expressions which files and directories to exclude from the wheel.
///
/// Default: `__pycache__`, `*.pyc`, and `*.pyo`.
///
/// Excludes are not anchored, which means that `__pycache__` excludes all directories named
/// `__pycache__` and it's children anywhere. To anchor a directory, use a `/` prefix, e.g.,
/// `/dist` will exclude only `<project root>/dist`.
///
/// The glob syntax is the reduced portable glob from
/// [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key).
pub(crate) wheel_exclude: Vec<String>,

/// Data includes for wheels.
Expand All @@ -790,8 +788,9 @@ impl Default for BuildBackendSettings {
Self {
module_root: PathBuf::from("src"),
source_include: Vec::new(),
source_exclude: DEFAULT_EXCLUDES.iter().map(ToString::to_string).collect(),
wheel_exclude: DEFAULT_EXCLUDES.iter().map(ToString::to_string).collect(),
default_excludes: true,
source_exclude: Vec::new(),
wheel_exclude: Vec::new(),
data: WheelDataIncludes::default(),
}
}
Expand Down
4 changes: 2 additions & 2 deletions scripts/packages/built-by-uv/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license-files = ["LICENSE*", "third-party-licenses/*"]
# A file we need for the source dist -> wheel step, but not in the wheel itself (currently unused)
source-include = ["data/build-script.py"]
# A temporary or generated file we want to ignore
source-exclude = ["/src/built_by_uv/not-packaged.txt", "__pycache__", "*.pyc", "*.pyo"]
source-exclude = ["/src/built_by_uv/not-packaged.txt"]
# Headers are build-only
wheel-exclude = ["build-*.h"]

Expand All @@ -21,5 +21,5 @@ data = "assets"
headers = "header"

[build-system]
requires = ["uv>=0.4.15,<5"]
requires = ["uv>=0.5,<0.6"]
build-backend = "uv"
Loading