mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Implement build backend metadata (#7961)
This commit is contained in:
parent
92538ada7c
commit
5d789c6af7
6 changed files with 132 additions and 151 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -4271,7 +4271,6 @@ dependencies = [
|
|||
name = "uv-build-backend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async_zip",
|
||||
"fs-err",
|
||||
"glob",
|
||||
"indoc",
|
||||
|
@ -4281,8 +4280,6 @@ dependencies = [
|
|||
"spdx",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
"tracing",
|
||||
"uv-distribution-filename",
|
||||
|
@ -4294,6 +4291,7 @@ dependencies = [
|
|||
"uv-pypi-types",
|
||||
"uv-version",
|
||||
"uv-warnings",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -20,17 +20,15 @@ uv-pypi-types = { workspace = true }
|
|||
uv-version = { workspace = true }
|
||||
uv-warnings = { workspace = true }
|
||||
|
||||
async_zip = { workspace = true }
|
||||
fs-err = { workspace = true, features = ["tokio"] }
|
||||
fs-err = { workspace = true }
|
||||
glob = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
spdx = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-util = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
zip = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -3,14 +3,13 @@ mod pep639_glob;
|
|||
|
||||
use crate::metadata::{PyProjectToml, ValidationError};
|
||||
use crate::pep639_glob::Pep639GlobError;
|
||||
use async_zip::base::write::ZipFileWriter;
|
||||
use async_zip::error::ZipError;
|
||||
use async_zip::{Compression, ZipEntryBuilder, ZipString};
|
||||
use glob::{GlobError, PatternError};
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use thiserror::Error;
|
||||
use uv_distribution_filename::WheelFilename;
|
||||
use zip::{CompressionMethod, ZipWriter};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
|
@ -28,51 +27,67 @@ pub enum Error {
|
|||
#[error(transparent)]
|
||||
Glob(#[from] GlobError),
|
||||
#[error("Failed to write wheel zip archive")]
|
||||
Zip(#[from] ZipError),
|
||||
Zip(#[from] zip::result::ZipError),
|
||||
}
|
||||
|
||||
/// Allow dispatching between writing to a directory, writing to zip and writing to a `.tar.gz`.
|
||||
trait AsyncDirectoryWrite: Sized {
|
||||
async fn write_bytes(
|
||||
&mut self,
|
||||
directory: &Path,
|
||||
filename: &str,
|
||||
bytes: &[u8],
|
||||
) -> Result<(), Error>;
|
||||
///
|
||||
/// All paths are string types instead of path types since wheel are portable between platforms.
|
||||
trait DirectoryWriter: Sized {
|
||||
/// Add a file with the given content.
|
||||
fn write_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), Error>;
|
||||
|
||||
/// Create a directory.
|
||||
fn write_directory(&mut self, directory: &str) -> Result<(), Error>;
|
||||
|
||||
#[allow(clippy::unused_async)] // https://github.com/rust-lang/rust-clippy/issues/11660
|
||||
async fn close(self) -> Result<(), Error> {
|
||||
fn close(self) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Zip archive (wheel) writer.
|
||||
struct AsyncZipWriter(ZipFileWriter<tokio_util::compat::Compat<fs_err::tokio::File>>);
|
||||
struct ZipDirectoryWriter {
|
||||
writer: ZipWriter<fs_err::File>,
|
||||
compression: CompressionMethod,
|
||||
}
|
||||
|
||||
impl AsyncDirectoryWrite for AsyncZipWriter {
|
||||
async fn write_bytes(
|
||||
&mut self,
|
||||
directory: &Path,
|
||||
filename: &str,
|
||||
bytes: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
self.0
|
||||
.write_entry_whole(
|
||||
ZipEntryBuilder::new(
|
||||
ZipString::from(format!("{}/{}", directory.display(), filename)),
|
||||
// TODO(konsti): Editables use stored.
|
||||
Compression::Deflate,
|
||||
)
|
||||
// https://github.com/Majored/rs-async-zip/issues/150
|
||||
.unix_permissions(0o644),
|
||||
bytes,
|
||||
)
|
||||
.await?;
|
||||
impl ZipDirectoryWriter {
|
||||
/// A wheel writer with deflate compression.
|
||||
fn new_wheel(file: fs_err::File) -> Self {
|
||||
Self {
|
||||
writer: ZipWriter::new(file),
|
||||
compression: CompressionMethod::Deflated,
|
||||
}
|
||||
}
|
||||
|
||||
/// A wheel writer with no (stored) compression.
|
||||
///
|
||||
/// Since editables are temporary, we save time be skipping compression and decompression.
|
||||
#[expect(dead_code)]
|
||||
fn new_editable(file: fs_err::File) -> Self {
|
||||
Self {
|
||||
writer: ZipWriter::new(file),
|
||||
compression: CompressionMethod::Stored,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirectoryWriter for ZipDirectoryWriter {
|
||||
fn write_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), Error> {
|
||||
let options = zip::write::FileOptions::default().compression_method(self.compression);
|
||||
self.writer.start_file(path, options)?;
|
||||
self.writer.write_all(bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn close(self) -> Result<(), Error> {
|
||||
self.0.close().await?;
|
||||
fn write_directory(&mut self, directory: &str) -> Result<(), Error> {
|
||||
let options = zip::write::FileOptions::default().compression_method(self.compression);
|
||||
Ok(self.writer.add_directory(directory, options)?)
|
||||
}
|
||||
|
||||
fn close(mut self) -> Result<(), Error> {
|
||||
self.writer.finish()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -82,22 +97,19 @@ struct AsyncFsWriter {
|
|||
}
|
||||
|
||||
/// File system writer.
|
||||
impl AsyncDirectoryWrite for AsyncFsWriter {
|
||||
async fn write_bytes(
|
||||
&mut self,
|
||||
directory: &Path,
|
||||
filename: &str,
|
||||
bytes: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
fs_err::tokio::create_dir_all(self.root.join(directory)).await?;
|
||||
fs_err::tokio::write(self.root.join(directory).join(filename), bytes).await?;
|
||||
Ok(())
|
||||
impl DirectoryWriter for AsyncFsWriter {
|
||||
fn write_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(fs_err::write(path, bytes)?)
|
||||
}
|
||||
|
||||
fn write_directory(&mut self, directory: &str) -> Result<(), Error> {
|
||||
Ok(fs_err::create_dir(self.root.join(directory))?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a wheel from the source tree and place it in the output directory.
|
||||
pub async fn build(source_tree: &Path, wheel_dir: &Path) -> Result<WheelFilename, Error> {
|
||||
let contents = fs_err::tokio::read_to_string(source_tree.join("pyproject.toml")).await?;
|
||||
pub fn build(source_tree: &Path, wheel_dir: &Path) -> 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();
|
||||
|
||||
|
@ -110,25 +122,24 @@ pub async fn build(source_tree: &Path, wheel_dir: &Path) -> Result<WheelFilename
|
|||
platform_tag: vec!["any".to_string()],
|
||||
};
|
||||
|
||||
// TODO(konsti): async-zip doesn't like a buffered writer
|
||||
let wheel_file = fs_err::tokio::File::create(wheel_dir.join(filename.to_string())).await?;
|
||||
let mut wheel_writer = AsyncZipWriter(ZipFileWriter::with_tokio(wheel_file));
|
||||
write_dist_info(&mut wheel_writer, &pyproject_toml, source_tree).await?;
|
||||
wheel_writer.close().await?;
|
||||
let mut wheel_writer =
|
||||
ZipDirectoryWriter::new_wheel(fs_err::File::create(wheel_dir.join(filename.to_string()))?);
|
||||
write_dist_info(&mut wheel_writer, &pyproject_toml, source_tree)?;
|
||||
wheel_writer.close()?;
|
||||
Ok(filename)
|
||||
}
|
||||
|
||||
/// Write the dist-info directory to the output directory without building the wheel.
|
||||
pub async fn metadata(source_tree: &Path, metadata_directory: &Path) -> Result<String, Error> {
|
||||
let contents = fs_err::tokio::read_to_string(source_tree.join("pyproject.toml")).await?;
|
||||
pub fn metadata(source_tree: &Path, metadata_directory: &Path) -> Result<String, Error> {
|
||||
let contents = fs_err::read_to_string(source_tree.join("pyproject.toml"))?;
|
||||
let pyproject_toml = PyProjectToml::parse(&contents)?;
|
||||
pyproject_toml.check_build_system();
|
||||
|
||||
let mut wheel_writer = AsyncFsWriter {
|
||||
root: metadata_directory.to_path_buf(),
|
||||
};
|
||||
write_dist_info(&mut wheel_writer, &pyproject_toml, source_tree).await?;
|
||||
wheel_writer.close().await?;
|
||||
write_dist_info(&mut wheel_writer, &pyproject_toml, source_tree)?;
|
||||
wheel_writer.close()?;
|
||||
|
||||
Ok(format!(
|
||||
"{}-{}.dist-info",
|
||||
|
@ -138,29 +149,27 @@ pub async fn metadata(source_tree: &Path, metadata_directory: &Path) -> Result<S
|
|||
}
|
||||
|
||||
/// Add `METADATA` and `entry_points.txt` to the dist-info directory.
|
||||
async fn write_dist_info(
|
||||
writer: &mut impl AsyncDirectoryWrite,
|
||||
fn write_dist_info(
|
||||
writer: &mut impl DirectoryWriter,
|
||||
pyproject_toml: &PyProjectToml,
|
||||
root: &Path,
|
||||
) -> Result<(), Error> {
|
||||
let dist_info_dir = PathBuf::from(format!(
|
||||
let dist_info_dir = format!(
|
||||
"{}-{}.dist-info",
|
||||
pyproject_toml.name().as_dist_info_name(),
|
||||
pyproject_toml.version()
|
||||
));
|
||||
);
|
||||
|
||||
let metadata = pyproject_toml
|
||||
.to_metadata(root)
|
||||
.await?
|
||||
.core_metadata_format();
|
||||
writer
|
||||
.write_bytes(&dist_info_dir, "METADATA", metadata.as_bytes())
|
||||
.await?;
|
||||
writer.write_directory(&dist_info_dir)?;
|
||||
|
||||
let metadata = pyproject_toml.to_metadata(root)?.core_metadata_format();
|
||||
writer.write_bytes(&format!("{dist_info_dir}/METADATA"), metadata.as_bytes())?;
|
||||
|
||||
let entrypoint = pyproject_toml.to_entry_points()?;
|
||||
writer
|
||||
.write_bytes(&dist_info_dir, "entry_points.txt", entrypoint.as_bytes())
|
||||
.await?;
|
||||
writer.write_bytes(
|
||||
&format!("{dist_info_dir}/entry_points.txt"),
|
||||
entrypoint.as_bytes(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ impl PyProjectToml {
|
|||
/// <https://packaging.python.org/en/latest/guides/writing-pyproject-toml/>
|
||||
/// <https://packaging.python.org/en/latest/specifications/pyproject-toml/>
|
||||
/// <https://packaging.python.org/en/latest/specifications/core-metadata/>
|
||||
pub(crate) async fn to_metadata(&self, root: &Path) -> Result<Metadata23, Error> {
|
||||
pub(crate) fn to_metadata(&self, root: &Path) -> Result<Metadata23, Error> {
|
||||
let summary = if let Some(description) = &self.project.description {
|
||||
if description.contains('\n') {
|
||||
return Err(ValidationError::DescriptionNewlines.into());
|
||||
|
@ -174,7 +174,7 @@ impl PyProjectToml {
|
|||
let supported_content_types = ["text/plain", "text/x-rst", "text/markdown"];
|
||||
let (description, description_content_type) = match &self.project.readme {
|
||||
Some(Readme::String(path)) => {
|
||||
let content = fs_err::tokio::read_to_string(root.join(path)).await?;
|
||||
let content = fs_err::read_to_string(root.join(path))?;
|
||||
let content_type = match path.extension().and_then(OsStr::to_str) {
|
||||
Some("txt") => "text/plain",
|
||||
Some("rst") => "text/x-rst",
|
||||
|
@ -192,7 +192,7 @@ impl PyProjectToml {
|
|||
content_type,
|
||||
charset,
|
||||
}) => {
|
||||
let content = fs_err::tokio::read_to_string(root.join(file)).await?;
|
||||
let content = fs_err::read_to_string(root.join(file))?;
|
||||
if !supported_content_types.contains(&content_type.as_str()) {
|
||||
return Err(
|
||||
ValidationError::UnsupportedContentType(content_type.clone()).into(),
|
||||
|
@ -346,7 +346,7 @@ impl PyProjectToml {
|
|||
}
|
||||
Some(License::Text { text }) => (Some(text.clone()), None, Vec::new()),
|
||||
Some(License::File { file }) => {
|
||||
let text = fs_err::tokio::read_to_string(root.join(file)).await?;
|
||||
let text = fs_err::read_to_string(root.join(file))?;
|
||||
(Some(text), None, Vec::new())
|
||||
}
|
||||
}
|
||||
|
@ -653,8 +653,8 @@ mod tests {
|
|||
formatted
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn valid() {
|
||||
#[test]
|
||||
fn valid() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
|
||||
fs_err::write(
|
||||
|
@ -728,7 +728,7 @@ mod tests {
|
|||
};
|
||||
|
||||
let pyproject_toml = PyProjectToml::parse(contents).unwrap();
|
||||
let metadata = pyproject_toml.to_metadata(temp_dir.path()).await.unwrap();
|
||||
let metadata = pyproject_toml.to_metadata(temp_dir.path()).unwrap();
|
||||
|
||||
assert_snapshot!(metadata.core_metadata_format(), @r###"
|
||||
Metadata-Version: 2.3
|
||||
|
@ -841,14 +841,13 @@ mod tests {
|
|||
assert!(!pyproject_toml.check_build_system());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn minimal() {
|
||||
#[test]
|
||||
fn minimal() {
|
||||
let contents = extend_project("");
|
||||
|
||||
let metadata = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(metadata.core_metadata_format(), @r###"
|
||||
|
@ -876,8 +875,8 @@ mod tests {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn missing_readme() {
|
||||
#[test]
|
||||
fn missing_readme() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
readme = "Readme.md"
|
||||
"#
|
||||
|
@ -886,16 +885,13 @@ mod tests {
|
|||
let err = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap_err();
|
||||
// Simplified for windows compatibility.
|
||||
assert_snapshot!(err.to_string().replace('\\', "/"), @r###"
|
||||
failed to read from file `/do/not/read/Readme.md`
|
||||
"###);
|
||||
assert_snapshot!(err.to_string().replace('\\', "/"), @"failed to open file `/do/not/read/Readme.md`");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multiline_description() {
|
||||
#[test]
|
||||
fn multiline_description() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
description = "Hi :)\nThis is my project"
|
||||
"#
|
||||
|
@ -904,7 +900,6 @@ mod tests {
|
|||
let err = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_snapshot!(format_err(err), @r###"
|
||||
Invalid pyproject.toml
|
||||
|
@ -912,8 +907,8 @@ mod tests {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn mixed_licenses() {
|
||||
#[test]
|
||||
fn mixed_licenses() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
license-files = ["licenses/*"]
|
||||
license = { text = "MIT" }
|
||||
|
@ -923,7 +918,6 @@ mod tests {
|
|||
let err = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_snapshot!(format_err(err), @r###"
|
||||
Invalid pyproject.toml
|
||||
|
@ -931,8 +925,8 @@ mod tests {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn valid_license() {
|
||||
#[test]
|
||||
fn valid_license() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
license = "MIT OR Apache-2.0"
|
||||
"#
|
||||
|
@ -940,7 +934,6 @@ mod tests {
|
|||
let metadata = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_snapshot!(metadata.core_metadata_format(), @r###"
|
||||
Metadata-Version: 2.4
|
||||
|
@ -950,8 +943,8 @@ mod tests {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_license() {
|
||||
#[test]
|
||||
fn invalid_license() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
license = "MIT XOR Apache-2"
|
||||
"#
|
||||
|
@ -959,7 +952,6 @@ mod tests {
|
|||
let err = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap_err();
|
||||
// TODO(konsti): We mess up the indentation in the error.
|
||||
assert_snapshot!(format_err(err), @r###"
|
||||
|
@ -970,8 +962,8 @@ mod tests {
|
|||
"###);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn dynamic() {
|
||||
#[test]
|
||||
fn dynamic() {
|
||||
let contents = extend_project(indoc! {r#"
|
||||
dynamic = ["dependencies"]
|
||||
"#
|
||||
|
@ -980,7 +972,6 @@ mod tests {
|
|||
let err = PyProjectToml::parse(&contents)
|
||||
.unwrap()
|
||||
.to_metadata(Path::new("/do/not/read"))
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_snapshot!(format_err(err), @r###"
|
||||
Invalid pyproject.toml
|
||||
|
|
|
@ -5,54 +5,42 @@ use anyhow::Result;
|
|||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn build_sdist(_sdist_directory: &Path) -> Result<ExitStatus> {
|
||||
pub(crate) fn build_sdist(_sdist_directory: &Path) -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub(crate) async fn build_wheel(
|
||||
pub(crate) fn build_wheel(
|
||||
wheel_directory: &Path,
|
||||
_metadata_directory: Option<&Path>,
|
||||
) -> Result<ExitStatus> {
|
||||
let filename = uv_build_backend::build(&env::current_dir()?, wheel_directory).await?;
|
||||
let filename = uv_build_backend::build(&env::current_dir()?, wheel_directory)?;
|
||||
println!("{filename}");
|
||||
Ok(ExitStatus::Success)
|
||||
}
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn build_editable(
|
||||
pub(crate) fn build_editable(
|
||||
_wheel_directory: &Path,
|
||||
_metadata_directory: Option<&Path>,
|
||||
) -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn get_requires_for_build_sdist() -> Result<ExitStatus> {
|
||||
pub(crate) fn get_requires_for_build_sdist() -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn get_requires_for_build_wheel() -> Result<ExitStatus> {
|
||||
pub(crate) fn get_requires_for_build_wheel() -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub(crate) async fn prepare_metadata_for_build_wheel(
|
||||
metadata_directory: &Path,
|
||||
) -> Result<ExitStatus> {
|
||||
let filename = uv_build_backend::metadata(&env::current_dir()?, metadata_directory).await?;
|
||||
pub(crate) fn prepare_metadata_for_build_wheel(metadata_directory: &Path) -> Result<ExitStatus> {
|
||||
let filename = uv_build_backend::metadata(&env::current_dir()?, metadata_directory)?;
|
||||
println!("{filename}");
|
||||
Ok(ExitStatus::Success)
|
||||
}
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn get_requires_for_build_editable() -> Result<ExitStatus> {
|
||||
pub(crate) fn get_requires_for_build_editable() -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[expect(clippy::unused_async)]
|
||||
pub(crate) async fn prepare_metadata_for_build_editable(
|
||||
_wheel_directory: &Path,
|
||||
) -> Result<ExitStatus> {
|
||||
pub(crate) fn prepare_metadata_for_build_editable(_wheel_directory: &Path) -> Result<ExitStatus> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use clap::error::{ContextKind, ContextValue};
|
|||
use clap::{CommandFactory, Parser};
|
||||
use owo_colors::OwoColorize;
|
||||
use settings::PipTreeSettings;
|
||||
use tokio::task::spawn_blocking;
|
||||
use tracing::{debug, instrument};
|
||||
use uv_cache::{Cache, Refresh};
|
||||
use uv_cache_info::Timestamp;
|
||||
|
@ -1113,46 +1114,42 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
)
|
||||
.await
|
||||
}
|
||||
Commands::BuildBackend { command } => match command {
|
||||
Commands::BuildBackend { command } => spawn_blocking(move || match command {
|
||||
BuildBackendCommand::BuildSdist { sdist_directory } => {
|
||||
commands::build_backend::build_sdist(&sdist_directory).await
|
||||
commands::build_backend::build_sdist(&sdist_directory)
|
||||
}
|
||||
BuildBackendCommand::BuildWheel {
|
||||
wheel_directory,
|
||||
metadata_directory,
|
||||
} => {
|
||||
commands::build_backend::build_wheel(
|
||||
&wheel_directory,
|
||||
metadata_directory.as_deref(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
} => commands::build_backend::build_wheel(
|
||||
&wheel_directory,
|
||||
metadata_directory.as_deref(),
|
||||
),
|
||||
BuildBackendCommand::BuildEditable {
|
||||
wheel_directory,
|
||||
metadata_directory,
|
||||
} => {
|
||||
commands::build_backend::build_editable(
|
||||
&wheel_directory,
|
||||
metadata_directory.as_deref(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
} => commands::build_backend::build_editable(
|
||||
&wheel_directory,
|
||||
metadata_directory.as_deref(),
|
||||
),
|
||||
BuildBackendCommand::GetRequiresForBuildSdist => {
|
||||
commands::build_backend::get_requires_for_build_sdist().await
|
||||
commands::build_backend::get_requires_for_build_sdist()
|
||||
}
|
||||
BuildBackendCommand::GetRequiresForBuildWheel => {
|
||||
commands::build_backend::get_requires_for_build_wheel().await
|
||||
commands::build_backend::get_requires_for_build_wheel()
|
||||
}
|
||||
BuildBackendCommand::PrepareMetadataForBuildWheel { wheel_directory } => {
|
||||
commands::build_backend::prepare_metadata_for_build_wheel(&wheel_directory).await
|
||||
commands::build_backend::prepare_metadata_for_build_wheel(&wheel_directory)
|
||||
}
|
||||
BuildBackendCommand::GetRequiresForBuildEditable => {
|
||||
commands::build_backend::get_requires_for_build_editable().await
|
||||
commands::build_backend::get_requires_for_build_editable()
|
||||
}
|
||||
BuildBackendCommand::PrepareMetadataForBuildEditable { wheel_directory } => {
|
||||
commands::build_backend::prepare_metadata_for_build_editable(&wheel_directory).await
|
||||
commands::build_backend::prepare_metadata_for_build_editable(&wheel_directory)
|
||||
}
|
||||
},
|
||||
})
|
||||
.await
|
||||
.expect("tokio threadpool exited unexpectedly"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue