mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Build backend: Add reference docs and schema (#12803)
Add reference documentation and schema integration for the uv build backend. The reference documentation comes with a preview note upfront.
This commit is contained in:
parent
2b96dbdd49
commit
da09ece8a9
18 changed files with 559 additions and 171 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -4743,6 +4743,7 @@ dependencies = [
|
|||
"indoc",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
"schemars",
|
||||
"serde",
|
||||
"sha2",
|
||||
"spdx",
|
||||
|
@ -4754,7 +4755,9 @@ dependencies = [
|
|||
"uv-distribution-filename",
|
||||
"uv-fs",
|
||||
"uv-globfilter",
|
||||
"uv-macros",
|
||||
"uv-normalize",
|
||||
"uv-options-metadata",
|
||||
"uv-pep440",
|
||||
"uv-pep508",
|
||||
"uv-platform-tags",
|
||||
|
@ -5916,6 +5919,7 @@ dependencies = [
|
|||
"toml_edit",
|
||||
"tracing",
|
||||
"url",
|
||||
"uv-build-backend",
|
||||
"uv-cache-key",
|
||||
"uv-distribution-types",
|
||||
"uv-fs",
|
||||
|
|
|
@ -16,7 +16,9 @@ doctest = false
|
|||
uv-distribution-filename = { workspace = true }
|
||||
uv-fs = { workspace = true }
|
||||
uv-globfilter = { workspace = true }
|
||||
uv-macros = { workspace = true }
|
||||
uv-normalize = { workspace = true }
|
||||
uv-options-metadata = { workspace = true }
|
||||
uv-pep440 = { workspace = true }
|
||||
uv-pep508 = { workspace = true }
|
||||
uv-platform-tags = { workspace = true }
|
||||
|
@ -29,6 +31,7 @@ flate2 = { workspace = true, default-features = false }
|
|||
fs-err = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
sha2 = { workspace = true }
|
||||
spdx = { workspace = true }
|
||||
|
@ -43,6 +46,13 @@ zip = { workspace = true }
|
|||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.cargo-shear]
|
||||
# Imported by the `OptionsMetadata` derive macro
|
||||
ignored = ["uv-options-metadata"]
|
||||
|
||||
[features]
|
||||
schemars = ["dep:schemars", "uv-pypi-types/schemars"]
|
||||
|
||||
[dev-dependencies]
|
||||
indoc = { workspace = true }
|
||||
insta = { version = "1.40.0", features = ["filters"] }
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
mod metadata;
|
||||
mod serde_verbatim;
|
||||
mod settings;
|
||||
mod source_dist;
|
||||
mod wheel;
|
||||
|
||||
pub use metadata::{check_direct_build, PyProjectToml};
|
||||
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};
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ use uv_pep440::{Version, VersionSpecifiers};
|
|||
use uv_pep508::{
|
||||
ExtraOperator, MarkerExpression, MarkerTree, MarkerValueExtra, Requirement, VersionOrUrl,
|
||||
};
|
||||
use uv_pypi_types::{Identifier, Metadata23, VerbatimParsedUrl};
|
||||
use uv_pypi_types::{Metadata23, VerbatimParsedUrl};
|
||||
|
||||
use crate::serde_verbatim::SerdeVerbatim;
|
||||
use crate::Error;
|
||||
use crate::{BuildBackendSettings, Error};
|
||||
|
||||
/// By default, we ignore generated python files.
|
||||
pub(crate) const DEFAULT_EXCLUDES: &[&str] = &["__pycache__", "*.pyc", "*.pyo"];
|
||||
|
@ -796,149 +796,6 @@ pub(crate) struct ToolUv {
|
|||
build_backend: Option<BuildBackendSettings>,
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// `src/<module-name or project_name_with_underscores>/**`.
|
||||
/// * `project.license-files` and `project.readme`.
|
||||
/// * All directories under `tool.uv.build-backend.data`.
|
||||
/// * All patterns from `tool.uv.build-backend.source-include`.
|
||||
///
|
||||
/// From these, we remove the `tool.uv.build-backend.source-exclude` matches.
|
||||
///
|
||||
/// When building the wheel, the following files and directories are included:
|
||||
/// * The module under `tool.uv.build-backend.module-root`, by default
|
||||
/// `src/<module-name or project_name_with_underscores>/**`.
|
||||
/// * `project.license-files` and `project.readme`, as part of the project metadata.
|
||||
/// * Each directory under `tool.uv.build-backend.data`, as data directories.
|
||||
///
|
||||
/// From these, we remove the `tool.uv.build-backend.source-exclude` and
|
||||
/// `tool.uv.build-backend.wheel-exclude` matches. The source dist excludes are applied to avoid
|
||||
/// source tree -> wheel source including more files than
|
||||
/// source tree -> source distribution -> wheel.
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// 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 {
|
||||
/// The directory that contains the module directory, usually `src`, or an empty path when
|
||||
/// using the flat layout over the src layout.
|
||||
pub(crate) module_root: PathBuf,
|
||||
|
||||
/// The name of the module directory inside `module-root`.
|
||||
///
|
||||
/// The default module name is the package name with dots and dashes replaced by underscores.
|
||||
///
|
||||
/// Note that using this option runs the risk of creating two packages with different names but
|
||||
/// the same module names. Installing such packages together leads to unspecified behavior,
|
||||
/// often with corrupted files or directory trees.
|
||||
pub(crate) module_name: Option<Identifier>,
|
||||
|
||||
/// Glob expressions which files and directories to additionally include in the source
|
||||
/// distribution.
|
||||
///
|
||||
/// `pyproject.toml` and the contents of the module directory are always included.
|
||||
///
|
||||
/// 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>,
|
||||
|
||||
/// If set to `false`, the default excludes aren't applied.
|
||||
///
|
||||
/// 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.
|
||||
pub(crate) wheel_exclude: Vec<String>,
|
||||
|
||||
/// Data includes for wheels.
|
||||
///
|
||||
/// The directories included here are also included in the source distribution. They are copied
|
||||
/// to the right wheel subdirectory on build.
|
||||
pub(crate) data: WheelDataIncludes,
|
||||
}
|
||||
|
||||
impl Default for BuildBackendSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
module_root: PathBuf::from("src"),
|
||||
module_name: None,
|
||||
source_include: Vec::new(),
|
||||
default_excludes: true,
|
||||
source_exclude: Vec::new(),
|
||||
wheel_exclude: Vec::new(),
|
||||
data: WheelDataIncludes::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data includes for wheels.
|
||||
///
|
||||
/// Each entry is a directory, whose contents are copied to the matching directory in the wheel in
|
||||
/// `<name>-<version>.data/(purelib|platlib|headers|scripts|data)`. Upon installation, this data
|
||||
/// is moved to its target location, as defined by
|
||||
/// <https://docs.python.org/3.12/library/sysconfig.html#installation-paths>:
|
||||
/// - `data`: Installed over the virtualenv environment root. Warning: This may override existing
|
||||
/// files!
|
||||
/// - `scripts`: Installed to the directory for executables, `<venv>/bin` on Unix or
|
||||
/// `<venv>\Scripts` on Windows. This directory is added to PATH when the virtual environment is
|
||||
/// activated or when using `uv run`, so this data type can be used to install additional
|
||||
/// binaries. Consider using `project.scripts` instead for starting Python code.
|
||||
/// - `headers`: Installed to the include directory, where compilers building Python packages with
|
||||
/// this package as built requirement will search for header files.
|
||||
/// - `purelib` and `platlib`: Installed to the `site-packages` directory. It is not recommended to
|
||||
/// uses these two options.
|
||||
#[derive(Default, Deserialize, Debug, Clone)]
|
||||
// `deny_unknown_fields` to catch typos such as `header` vs `headers`.
|
||||
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
|
||||
pub(crate) struct WheelDataIncludes {
|
||||
purelib: Option<String>,
|
||||
platlib: Option<String>,
|
||||
headers: Option<String>,
|
||||
scripts: Option<String>,
|
||||
data: Option<String>,
|
||||
}
|
||||
|
||||
impl WheelDataIncludes {
|
||||
/// Yield all data directories name and corresponding paths.
|
||||
pub(crate) fn iter(&self) -> impl Iterator<Item = (&'static str, &str)> {
|
||||
[
|
||||
("purelib", self.purelib.as_deref()),
|
||||
("platlib", self.platlib.as_deref()),
|
||||
("headers", self.headers.as_deref()),
|
||||
("scripts", self.scripts.as_deref()),
|
||||
("data", self.data.as_deref()),
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|(name, value)| Some((name, value?)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
159
crates/uv-build-backend/src/settings.rs
Normal file
159
crates/uv-build-backend/src/settings.rs
Normal file
|
@ -0,0 +1,159 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use uv_macros::OptionsMetadata;
|
||||
use uv_pypi_types::Identifier;
|
||||
|
||||
/// Settings for the uv build backend (`uv_build`).
|
||||
///
|
||||
/// !!! note
|
||||
///
|
||||
/// The uv build backend is currently in preview and may change in any future release.
|
||||
///
|
||||
/// Note that those settings only apply when using the `uv_build` backend, other build backends
|
||||
/// (such as hatchling) have their own configuration.
|
||||
///
|
||||
/// All options that accept globs use the portable glob patterns from
|
||||
/// [PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/).
|
||||
#[derive(Deserialize, Serialize, OptionsMetadata, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(default, rename_all = "kebab-case")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct BuildBackendSettings {
|
||||
/// The directory that contains the module directory.
|
||||
///
|
||||
/// Common values are `src` (src layout, the default) or an empty path (flat layout).
|
||||
#[option(
|
||||
default = r#""src""#,
|
||||
value_type = "str",
|
||||
example = r#"module-root = """#
|
||||
)]
|
||||
pub module_root: PathBuf,
|
||||
|
||||
/// The name of the module directory inside `module-root`.
|
||||
///
|
||||
/// The default module name is the package name with dots and dashes replaced by underscores.
|
||||
///
|
||||
/// Note that using this option runs the risk of creating two packages with different names but
|
||||
/// the same module names. Installing such packages together leads to unspecified behavior,
|
||||
/// often with corrupted files or directory trees.
|
||||
#[option(
|
||||
default = r#"None"#,
|
||||
value_type = "str",
|
||||
example = r#"module-name = "sklearn""#
|
||||
)]
|
||||
pub module_name: Option<Identifier>,
|
||||
|
||||
/// Glob expressions which files and directories to additionally include in the source
|
||||
/// distribution.
|
||||
///
|
||||
/// `pyproject.toml` and the contents of the module directory are always included.
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "list[str]",
|
||||
example = r#"source-include = ["tests/**"]"#
|
||||
)]
|
||||
pub source_include: Vec<String>,
|
||||
|
||||
/// If set to `false`, the default excludes aren't applied.
|
||||
///
|
||||
/// Default excludes: `__pycache__`, `*.pyc`, and `*.pyo`.
|
||||
#[option(
|
||||
default = r#"true"#,
|
||||
value_type = "bool",
|
||||
example = r#"default-excludes = false"#
|
||||
)]
|
||||
pub default_excludes: bool,
|
||||
|
||||
/// Glob expressions which files and directories to exclude from the source distribution.
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "list[str]",
|
||||
example = r#"source-exclude = ["*.bin"]"#
|
||||
)]
|
||||
pub source_exclude: Vec<String>,
|
||||
|
||||
/// Glob expressions which files and directories to exclude from the wheel.
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "list[str]",
|
||||
example = r#"wheel-exclude = ["*.bin"]"#
|
||||
)]
|
||||
pub wheel_exclude: Vec<String>,
|
||||
|
||||
/// Data includes for wheels.
|
||||
///
|
||||
/// Each entry is a directory, whose contents are copied to the matching directory in the wheel
|
||||
/// in `<name>-<version>.data/(purelib|platlib|headers|scripts|data)`. Upon installation, this
|
||||
/// data is moved to its target location, as defined by
|
||||
/// <https://docs.python.org/3.12/library/sysconfig.html#installation-paths>. Usually, small
|
||||
/// data files are included by placing them in the Python module instead of using data includes.
|
||||
///
|
||||
/// - `scripts`: Installed to the directory for executables, `<venv>/bin` on Unix or
|
||||
/// `<venv>\Scripts` on Windows. This directory is added to `PATH` when the virtual
|
||||
/// environment is activated or when using `uv run`, so this data type can be used to install
|
||||
/// additional binaries. Consider using `project.scripts` instead for Python entrypoints.
|
||||
/// - `data`: Installed over the virtualenv environment root.
|
||||
///
|
||||
/// Warning: This may override existing files!
|
||||
///
|
||||
/// - `headers`: Installed to the include directory. Compilers building Python packages
|
||||
/// with this package as build requirement use the include directory to find additional header
|
||||
/// files.
|
||||
/// - `purelib` and `platlib`: Installed to the `site-packages` directory. It is not recommended
|
||||
/// to uses these two options.
|
||||
// TODO(konsti): We should show a flat example instead.
|
||||
// ```toml
|
||||
// [tool.uv.build-backend.data]
|
||||
// headers = "include/headers",
|
||||
// scripts = "bin"
|
||||
// ```
|
||||
#[option(
|
||||
default = r#"{}"#,
|
||||
value_type = "dict[str, str]",
|
||||
example = r#"data = { "headers": "include/headers", "scripts": "bin" }"#
|
||||
)]
|
||||
pub data: WheelDataIncludes,
|
||||
}
|
||||
|
||||
impl Default for BuildBackendSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
module_root: PathBuf::from("src"),
|
||||
module_name: None,
|
||||
source_include: Vec::new(),
|
||||
default_excludes: true,
|
||||
source_exclude: Vec::new(),
|
||||
wheel_exclude: Vec::new(),
|
||||
data: WheelDataIncludes::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data includes for wheels.
|
||||
///
|
||||
/// See `BuildBackendSettings::data`.
|
||||
#[derive(Default, Deserialize, Serialize, OptionsMetadata, Debug, Clone, PartialEq, Eq)]
|
||||
// `deny_unknown_fields` to catch typos such as `header` vs `headers`.
|
||||
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct WheelDataIncludes {
|
||||
purelib: Option<String>,
|
||||
platlib: Option<String>,
|
||||
headers: Option<String>,
|
||||
scripts: Option<String>,
|
||||
data: Option<String>,
|
||||
}
|
||||
|
||||
impl WheelDataIncludes {
|
||||
/// Yield all data directories name and corresponding paths.
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&'static str, &str)> {
|
||||
[
|
||||
("purelib", self.purelib.as_deref()),
|
||||
("platlib", self.platlib.as_deref()),
|
||||
("headers", self.headers.as_deref()),
|
||||
("scripts", self.scripts.as_deref()),
|
||||
("data", self.data.as_deref()),
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|(name, value)| Some((name, value?)))
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
use crate::metadata::{BuildBackendSettings, DEFAULT_EXCLUDES};
|
||||
use crate::metadata::DEFAULT_EXCLUDES;
|
||||
use crate::wheel::build_exclude_matcher;
|
||||
use crate::{find_roots, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml};
|
||||
use crate::{
|
||||
find_roots, BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml,
|
||||
};
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::Compression;
|
||||
use fs_err::File;
|
||||
|
|
|
@ -17,8 +17,10 @@ use uv_platform_tags::{AbiTag, LanguageTag, PlatformTag};
|
|||
use uv_pypi_types::Identifier;
|
||||
use uv_warnings::warn_user_once;
|
||||
|
||||
use crate::metadata::{BuildBackendSettings, DEFAULT_EXCLUDES};
|
||||
use crate::{find_roots, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml};
|
||||
use crate::metadata::DEFAULT_EXCLUDES;
|
||||
use crate::{
|
||||
find_roots, BuildBackendSettings, DirectoryWriter, Error, FileList, ListWriter, PyProjectToml,
|
||||
};
|
||||
|
||||
/// Build a wheel from the source tree and place it in the output directory.
|
||||
pub fn build_wheel(
|
||||
|
|
|
@ -16,7 +16,7 @@ When traversing the directory, you can use
|
|||
## Syntax
|
||||
|
||||
This crate supports the cross-language, restricted glob syntax from
|
||||
[PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key):
|
||||
[PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/):
|
||||
|
||||
- Alphanumeric characters, underscores (`_`), hyphens (`-`) and dots (`.`) are matched verbatim.
|
||||
- The special glob characters are:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Cross-language glob syntax from [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key).
|
||||
//! Cross-language glob syntax from [PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/).
|
||||
|
||||
use globset::{Glob, GlobBuilder};
|
||||
use thiserror::Error;
|
||||
|
@ -28,7 +28,7 @@ pub enum PortableGlobError {
|
|||
TooManyStars { glob: String, pos: usize },
|
||||
}
|
||||
|
||||
/// Parse cross-language glob syntax from [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key):
|
||||
/// Parse cross-language glob syntax from [PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/):
|
||||
///
|
||||
/// - Alphanumeric characters, underscores (`_`), hyphens (`-`) and dots (`.`) are matched verbatim.
|
||||
/// - The special glob characters are:
|
||||
|
|
|
@ -291,7 +291,7 @@ fn parse_field_attributes(attribute: &Attribute) -> syn::Result<FieldAttributes>
|
|||
return Err(syn::Error::new(
|
||||
meta.path.span(),
|
||||
format!(
|
||||
"Deprecated meta {:?} is not supported by ruff's option macro.",
|
||||
"Deprecated meta {:?} is not supported by uv's option macro.",
|
||||
meta.path.get_ident()
|
||||
),
|
||||
));
|
||||
|
@ -332,7 +332,7 @@ fn parse_deprecated_attribute(attribute: &Attribute) -> syn::Result<DeprecatedAt
|
|||
return Err(syn::Error::new(
|
||||
meta.path.span(),
|
||||
format!(
|
||||
"Deprecated meta {:?} is not supported by ruff's option macro.",
|
||||
"Deprecated meta {:?} is not supported by uv's option macro.",
|
||||
meta.path.get_ident()
|
||||
),
|
||||
));
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use serde::{Serialize, Serializer};
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
|
@ -87,6 +88,39 @@ impl<'de> serde::de::Deserialize<'de> for Identifier {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serialize for Identifier {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
Serialize::serialize(&self.0, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
impl schemars::JsonSchema for Identifier {
|
||||
fn schema_name() -> String {
|
||||
"Identifier".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
schemars::schema::SchemaObject {
|
||||
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
||||
string: Some(Box::new(schemars::schema::StringValidation {
|
||||
// Best-effort Unicode support (https://stackoverflow.com/a/68844380/3549270)
|
||||
pattern: Some(r"^[_\p{Alphabetic}][_0-9\p{Alphabetic}]*$".to_string()),
|
||||
..schemars::schema::StringValidation::default()
|
||||
})),
|
||||
metadata: Some(Box::new(schemars::schema::Metadata {
|
||||
description: Some("An identifier in Python".to_string()),
|
||||
..schemars::schema::Metadata::default()
|
||||
})),
|
||||
..schemars::schema::SchemaObject::default()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -141,6 +141,9 @@ pub struct Options {
|
|||
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
pub r#package: Option<serde::de::IgnoredAny>,
|
||||
|
||||
#[cfg_attr(feature = "schemars", schemars(skip))]
|
||||
pub build_backend: Option<serde::de::IgnoredAny>,
|
||||
}
|
||||
|
||||
impl Options {
|
||||
|
@ -1842,7 +1845,6 @@ pub struct OptionsWire {
|
|||
dev_dependencies: Option<serde::de::IgnoredAny>,
|
||||
|
||||
// Build backend
|
||||
#[allow(dead_code)]
|
||||
build_backend: Option<serde::de::IgnoredAny>,
|
||||
}
|
||||
|
||||
|
@ -1907,7 +1909,7 @@ impl From<OptionsWire> for Options {
|
|||
managed,
|
||||
package,
|
||||
// Used by the build backend
|
||||
build_backend: _,
|
||||
build_backend,
|
||||
} = value;
|
||||
|
||||
Self {
|
||||
|
@ -1956,6 +1958,7 @@ impl From<OptionsWire> for Options {
|
|||
},
|
||||
pip,
|
||||
cache_keys,
|
||||
build_backend,
|
||||
override_dependencies,
|
||||
constraint_dependencies,
|
||||
build_constraint_dependencies,
|
||||
|
|
|
@ -16,6 +16,7 @@ doctest = false
|
|||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
uv-build-backend = { workspace = true, features = ["schemars"] }
|
||||
uv-cache-key = { workspace = true }
|
||||
uv-distribution-types = { workspace = true }
|
||||
uv-fs = { workspace = true, features = ["tokio", "schemars"] }
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_hash::{FxBuildHasher, FxHashSet};
|
|||
use serde::{de::IntoDeserializer, de::SeqAccess, Deserialize, Deserializer, Serialize};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
use uv_build_backend::BuildBackendSettings;
|
||||
use uv_distribution_types::{Index, IndexName, RequirementSource};
|
||||
use uv_fs::{relative_to, PortablePathBuf};
|
||||
use uv_git_types::GitReference;
|
||||
|
@ -583,6 +583,15 @@ pub struct ToolUv {
|
|||
"#
|
||||
)]
|
||||
pub conflicts: Option<SchemaConflicts>,
|
||||
|
||||
// Only exists on this type for schema and docs generation, the build backend settings are
|
||||
// never merged in a workspace and read separately by the backend code.
|
||||
/// Configuration for the uv build backend.
|
||||
///
|
||||
/// Note that those settings only apply when using the `uv_build` backend, other build backends
|
||||
/// (such as hatchling) have their own configuration.
|
||||
#[option_group]
|
||||
pub build_backend: Option<BuildBackendSettings>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
|
|
|
@ -1824,7 +1824,8 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
|
@ -1918,7 +1919,8 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
|
@ -2060,7 +2062,7 @@ mod tests {
|
|||
{
|
||||
".workspace.packages.*.pyproject_toml" => "[PYPROJECT_TOML]"
|
||||
},
|
||||
@r###"
|
||||
@r#"
|
||||
{
|
||||
"project_root": "[ROOT]",
|
||||
"project_name": "albatross",
|
||||
|
@ -2127,14 +2129,15 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
// Rewrite the members to both include and exclude `bird-feeder` by name.
|
||||
|
@ -2165,7 +2168,7 @@ mod tests {
|
|||
{
|
||||
".workspace.packages.*.pyproject_toml" => "[PYPROJECT_TOML]"
|
||||
},
|
||||
@r###"
|
||||
@r#"
|
||||
{
|
||||
"project_root": "[ROOT]",
|
||||
"project_name": "albatross",
|
||||
|
@ -2233,14 +2236,15 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
// Rewrite the exclusion to use the top-level directory (`packages`).
|
||||
|
@ -2271,7 +2275,7 @@ mod tests {
|
|||
{
|
||||
".workspace.packages.*.pyproject_toml" => "[PYPROJECT_TOML]"
|
||||
},
|
||||
@r###"
|
||||
@r#"
|
||||
{
|
||||
"project_root": "[ROOT]",
|
||||
"project_name": "albatross",
|
||||
|
@ -2352,14 +2356,15 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
// Rewrite the exclusion to use the top-level directory with a glob (`packages/*`).
|
||||
|
@ -2390,7 +2395,7 @@ mod tests {
|
|||
{
|
||||
".workspace.packages.*.pyproject_toml" => "[PYPROJECT_TOML]"
|
||||
},
|
||||
@r###"
|
||||
@r#"
|
||||
{
|
||||
"project_root": "[ROOT]",
|
||||
"project_name": "albatross",
|
||||
|
@ -2445,14 +2450,15 @@ mod tests {
|
|||
"build-constraint-dependencies": null,
|
||||
"environments": null,
|
||||
"required-environments": null,
|
||||
"conflicts": null
|
||||
"conflicts": null,
|
||||
"build-backend": null
|
||||
}
|
||||
},
|
||||
"dependency-groups": null
|
||||
}
|
||||
}
|
||||
}
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -367,6 +367,179 @@ pydantic = { path = "/path/to/pydantic", editable = true }
|
|||
|
||||
---
|
||||
|
||||
### `build-backend`
|
||||
|
||||
Settings for the uv build backend (`uv_build`).
|
||||
|
||||
!!! note
|
||||
|
||||
The uv build backend is currently in preview and may change in any future release.
|
||||
|
||||
Note that those settings only apply when using the `uv_build` backend, other build backends
|
||||
(such as hatchling) have their own configuration.
|
||||
|
||||
All options that accept globs use the portable glob patterns from
|
||||
[PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/).
|
||||
|
||||
#### [`data`](#build-backend_data) {: #build-backend_data }
|
||||
<span id="data"></span>
|
||||
|
||||
Data includes for wheels.
|
||||
|
||||
Each entry is a directory, whose contents are copied to the matching directory in the wheel
|
||||
in `<name>-<version>.data/(purelib|platlib|headers|scripts|data)`. Upon installation, this
|
||||
data is moved to its target location, as defined by
|
||||
<https://docs.python.org/3.12/library/sysconfig.html#installation-paths>. Usually, small
|
||||
data files are included by placing them in the Python module instead of using data includes.
|
||||
|
||||
- `scripts`: Installed to the directory for executables, `<venv>/bin` on Unix or
|
||||
`<venv>\Scripts` on Windows. This directory is added to `PATH` when the virtual
|
||||
environment is activated or when using `uv run`, so this data type can be used to install
|
||||
additional binaries. Consider using `project.scripts` instead for Python entrypoints.
|
||||
- `data`: Installed over the virtualenv environment root.
|
||||
|
||||
Warning: This may override existing files!
|
||||
|
||||
- `headers`: Installed to the include directory. Compilers building Python packages
|
||||
with this package as build requirement use the include directory to find additional header
|
||||
files.
|
||||
- `purelib` and `platlib`: Installed to the `site-packages` directory. It is not recommended
|
||||
to uses these two options.
|
||||
|
||||
**Default value**: `{}`
|
||||
|
||||
**Type**: `dict[str, str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
data = { "headers": "include/headers", "scripts": "bin" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`default-excludes`](#build-backend_default-excludes) {: #build-backend_default-excludes }
|
||||
<span id="default-excludes"></span>
|
||||
|
||||
If set to `false`, the default excludes aren't applied.
|
||||
|
||||
Default excludes: `__pycache__`, `*.pyc`, and `*.pyo`.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
default-excludes = false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`module-name`](#build-backend_module-name) {: #build-backend_module-name }
|
||||
<span id="module-name"></span>
|
||||
|
||||
The name of the module directory inside `module-root`.
|
||||
|
||||
The default module name is the package name with dots and dashes replaced by underscores.
|
||||
|
||||
Note that using this option runs the risk of creating two packages with different names but
|
||||
the same module names. Installing such packages together leads to unspecified behavior,
|
||||
often with corrupted files or directory trees.
|
||||
|
||||
**Default value**: `None`
|
||||
|
||||
**Type**: `str`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
module-name = "sklearn"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`module-root`](#build-backend_module-root) {: #build-backend_module-root }
|
||||
<span id="module-root"></span>
|
||||
|
||||
The directory that contains the module directory.
|
||||
|
||||
Common values are `src` (src layout, the default) or an empty path (flat layout).
|
||||
|
||||
**Default value**: `"src"`
|
||||
|
||||
**Type**: `str`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
module-root = ""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`source-exclude`](#build-backend_source-exclude) {: #build-backend_source-exclude }
|
||||
<span id="source-exclude"></span>
|
||||
|
||||
Glob expressions which files and directories to exclude from the source distribution.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
source-exclude = ["*.bin"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`source-include`](#build-backend_source-include) {: #build-backend_source-include }
|
||||
<span id="source-include"></span>
|
||||
|
||||
Glob expressions which files and directories to additionally include in the source
|
||||
distribution.
|
||||
|
||||
`pyproject.toml` and the contents of the module directory are always included.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
source-include = ["tests/**"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`wheel-exclude`](#build-backend_wheel-exclude) {: #build-backend_wheel-exclude }
|
||||
<span id="wheel-exclude"></span>
|
||||
|
||||
Glob expressions which files and directories to exclude from the wheel.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml title="pyproject.toml"
|
||||
[tool.uv.build-backend]
|
||||
wheel-exclude = ["*.bin"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `workspace`
|
||||
|
||||
#### [`exclude`](#workspace_exclude) {: #workspace_exclude }
|
||||
|
|
|
@ -81,6 +81,7 @@ version_files = [
|
|||
"crates/uv-version/Cargo.toml",
|
||||
"crates/uv-build/Cargo.toml",
|
||||
"crates/uv-build/pyproject.toml",
|
||||
"docs/configuration/build_backend.md",
|
||||
"docs/getting-started/installation.md",
|
||||
"docs/guides/integration/docker.md",
|
||||
"docs/guides/integration/pre-commit.md",
|
||||
|
|
125
uv.schema.json
generated
125
uv.schema.json
generated
|
@ -14,6 +14,17 @@
|
|||
"$ref": "#/definitions/TrustedHost"
|
||||
}
|
||||
},
|
||||
"build-backend": {
|
||||
"description": "Configuration for the uv build backend.\n\nNote that those settings only apply when using the `uv_build` backend, other build backends (such as hatchling) have their own configuration.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/BuildBackendSettings"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"build-constraint-dependencies": {
|
||||
"description": "PEP 508-style requirements, e.g., `ruff==0.5.0`, or `ruff @ https://...`.",
|
||||
"type": [
|
||||
|
@ -584,6 +595,73 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"BuildBackendSettings": {
|
||||
"description": "Settings for the uv build backend (`uv_build`).\n\n!!! note\n\nThe uv build backend is currently in preview and may change in any future release.\n\nNote that those settings only apply when using the `uv_build` backend, other build backends (such as hatchling) have their own configuration.\n\nAll options that accept globs use the portable glob patterns from [PEP 639](https://packaging.python.org/en/latest/specifications/glob-patterns/).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"description": "Data includes for wheels.\n\nEach entry is a directory, whose contents are copied to the matching directory in the wheel in `<name>-<version>.data/(purelib|platlib|headers|scripts|data)`. Upon installation, this data is moved to its target location, as defined by <https://docs.python.org/3.12/library/sysconfig.html#installation-paths>. Usually, small data files are included by placing them in the Python module instead of using data includes.\n\n- `scripts`: Installed to the directory for executables, `<venv>/bin` on Unix or `<venv>\\Scripts` on Windows. This directory is added to `PATH` when the virtual environment is activated or when using `uv run`, so this data type can be used to install additional binaries. Consider using `project.scripts` instead for Python entrypoints. - `data`: Installed over the virtualenv environment root.\n\nWarning: This may override existing files!\n\n- `headers`: Installed to the include directory. Compilers building Python packages with this package as build requirement use the include directory to find additional header files. - `purelib` and `platlib`: Installed to the `site-packages` directory. It is not recommended to uses these two options.",
|
||||
"default": {
|
||||
"data": null,
|
||||
"headers": null,
|
||||
"platlib": null,
|
||||
"purelib": null,
|
||||
"scripts": null
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WheelDataIncludes"
|
||||
}
|
||||
]
|
||||
},
|
||||
"default-excludes": {
|
||||
"description": "If set to `false`, the default excludes aren't applied.\n\nDefault excludes: `__pycache__`, `*.pyc`, and `*.pyo`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"module-name": {
|
||||
"description": "The name of the module directory inside `module-root`.\n\nThe default module name is the package name with dots and dashes replaced by underscores.\n\nNote that using this option runs the risk of creating two packages with different names but the same module names. Installing such packages together leads to unspecified behavior, often with corrupted files or directory trees.",
|
||||
"default": null,
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"module-root": {
|
||||
"description": "The directory that contains the module directory.\n\nCommon values are `src` (src layout, the default) or an empty path (flat layout).",
|
||||
"default": "src",
|
||||
"type": "string"
|
||||
},
|
||||
"source-exclude": {
|
||||
"description": "Glob expressions which files and directories to exclude from the source distribution.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"source-include": {
|
||||
"description": "Glob expressions which files and directories to additionally include in the source distribution.\n\n`pyproject.toml` and the contents of the module directory are always included.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"wheel-exclude": {
|
||||
"description": "Glob expressions which files and directories to exclude from the wheel.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CacheKey": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
@ -753,6 +831,11 @@
|
|||
"description": "The normalized name of a dependency group.\n\nSee: - <https://peps.python.org/pep-0735/> - <https://packaging.python.org/en/latest/specifications/name-normalization/>",
|
||||
"type": "string"
|
||||
},
|
||||
"Identifier": {
|
||||
"description": "An identifier in Python",
|
||||
"type": "string",
|
||||
"pattern": "^[_\\p{Alphabetic}][_0-9\\p{Alphabetic}]*$"
|
||||
},
|
||||
"Index": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -2422,6 +2505,48 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"WheelDataIncludes": {
|
||||
"description": "Data includes for wheels.\n\nSee `BuildBackendSettings::data`.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"headers": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"platlib": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"purelib": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue