Skip to content
Draft
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
47 changes: 0 additions & 47 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 0 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,14 @@ arrayvec = { version = "0.7.6" }
astral-tokio-tar = { version = "0.6.3" }
async-channel = { version = "2.3.1" }
async-compression = { version = "0.4.12", features = [
"bzip2",
"gzip",
"xz",
"zstd",
] }
async-trait = { version = "0.1.82" }
async_http_range_reader = { version = "0.11.0", package = "astral_async_http_range_reader" }
async_zip = { version = "0.0.20", package = "astral_async_zip", features = [
"bzip2",
"deflate",
"lzma",
"tokio",
"xz",
"zstd",
] }
axoupdater = { version = "0.10.0", default-features = false }
Expand Down Expand Up @@ -278,7 +273,6 @@ tokio = { version = "1.40.0", features = [
tokio-stream = { version = "0.1.16" }
tokio-util = { version = "0.7.12", features = ["compat", "io"] }
toml = { version = "1.1.0", features = ["fast_hash"] }
toml_datetime = { version = "1.1.0" }
toml_edit = { version = "0.25.8", features = ["serde"] }
toml_parser = { version = "1.1.0", features = ["simd"] }
toml_writer = { version = "1.1.0" }
Expand Down Expand Up @@ -317,7 +311,6 @@ windows = { version = "0.61.0", features = [
windows-registry = { version = "0.5.0" }
windows-version = { version = "0.1.6" }
wiremock = { version = "0.6.4" }
xz2 = { version = "0.1.7", features = ["static"] }
zeroize = { version = "1.8.1" }

# dev-dependencies
Expand Down
3 changes: 0 additions & 3 deletions crates/uv-bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,3 @@ tempfile = { workspace = true }
tokio = { workspace = true }
tokio-util = { workspace = true }
toml = { workspace = true }

[features]
static = ["uv-extract/static"]
2 changes: 0 additions & 2 deletions crates/uv-bench/benches/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use uv_resolver::Manifest;

const MANY_FILES_WHEEL_FILENAME: &str = "manyfiles-0.0.0-py3-none-any.whl";
const MANY_FILES_WHEEL_FILE_COUNT: usize = 10_000;
const MANY_FILES_SDIST_FILENAME: &str = "manyfiles-0.0.0.tar.gz";
const MANY_FILES_SDIST_TOP_LEVEL: &str = "manyfiles-0.0.0";
const MANY_FILES_SDIST_FILE_COUNT: usize = 10_000;

Expand Down Expand Up @@ -126,7 +125,6 @@ fn unpack_sdist_many_files(c: &mut Criterion<WallTime>) {
|(archive, extracted_sdist)| {
let files = runtime
.block_on(uv_extract::stream::archive(
MANY_FILES_SDIST_FILENAME,
archive,
SourceDistExtension::TarGz,
extracted_sdist.path(),
Expand Down
14 changes: 5 additions & 9 deletions crates/uv-bin-install/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use tokio::io::{AsyncRead, ReadBuf};
use tokio_util::compat::FuturesAsyncReadCompatExt;
use url::Url;
use uv_client::retryable_on_request_failure;
use uv_distribution_filename::LegacySourceDistExtension;
use uv_distribution_filename::SourceDistExtension;
use uv_static::{astral_mirror_base_url, astral_mirror_url_from_env, custom_astral_mirror_url};

Expand Down Expand Up @@ -230,7 +231,7 @@ impl ArchiveFormat {
impl From<ArchiveFormat> for SourceDistExtension {
fn from(val: ArchiveFormat) -> Self {
match val {
ArchiveFormat::Zip => Self::Zip,
ArchiveFormat::Zip => Self::Legacy(LegacySourceDistExtension::Zip),
ArchiveFormat::TarGz => Self::TarGz,
}
}
Expand Down Expand Up @@ -841,14 +842,9 @@ async fn download_and_unpack(

let id = reporter.on_download_start(binary.name(), version, size);
let mut progress_reader = ProgressReader::new(reader, id, reporter);
stream::archive(
&download_url,
&mut progress_reader,
format.into(),
temp_dir.path(),
)
.await
.map_err(|e| Error::Extract { source: e })?;
stream::archive(&mut progress_reader, format.into(), temp_dir.path())
.await
.map_err(|e| Error::Extract { source: e })?;
reporter.on_download_complete(id);

// Find the binary in the extracted files
Expand Down
19 changes: 11 additions & 8 deletions crates/uv-build-backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -788,17 +788,18 @@ mod tests {
// Check that the source dist is reproducible across platforms.
assert_snapshot!(
format!("{:x}", sha2::Sha256::digest(fs_err::read(&source_dist_path).unwrap())),
@"8bed1f7a8059064bcbeedb61a867cca7f63a474306011d0114280de631ac705e"
@"1d9ce1ce63195fbee07314c0b595ba9e063670da8d10c252c351b21e94e3f508"
);
// Check both the files we report and the actual files
assert_snapshot!(format_file_list(build.source_dist_list_files, src.path()), @"
built_by_uv-0.1.0/PKG-INFO (generated)
built_by_uv-0.1.0/pyproject.toml (generated)
built_by_uv-0.1.0/pyproject.toml.orig (pyproject.toml)
built_by_uv-0.1.0/LICENSE-APACHE (LICENSE-APACHE)
built_by_uv-0.1.0/LICENSE-MIT (LICENSE-MIT)
built_by_uv-0.1.0/README.md (README.md)
built_by_uv-0.1.0/assets/data.csv (assets/data.csv)
built_by_uv-0.1.0/header/built_by_uv.h (header/built_by_uv.h)
built_by_uv-0.1.0/pyproject.toml (pyproject.toml)
built_by_uv-0.1.0/scripts/whoami.sh (scripts/whoami.sh)
built_by_uv-0.1.0/src/built_by_uv/__init__.py (src/built_by_uv/__init__.py)
built_by_uv-0.1.0/src/built_by_uv/arithmetic/__init__.py (src/built_by_uv/arithmetic/__init__.py)
Expand All @@ -819,6 +820,7 @@ mod tests {
built_by_uv-0.1.0/header
built_by_uv-0.1.0/header/built_by_uv.h
built_by_uv-0.1.0/pyproject.toml
built_by_uv-0.1.0/pyproject.toml.orig
built_by_uv-0.1.0/scripts
built_by_uv-0.1.0/scripts/whoami.sh
built_by_uv-0.1.0/src
Expand Down Expand Up @@ -1060,6 +1062,7 @@ mod tests {
two_step_build-1.0.0/
two_step_build-1.0.0/PKG-INFO
two_step_build-1.0.0/pyproject.toml
two_step_build-1.0.0/pyproject.toml.orig
two_step_build-1.0.0/two_step_build
two_step_build-1.0.0/two_step_build/__init__.py
");
Expand Down Expand Up @@ -1462,6 +1465,7 @@ mod tests {
simple_namespace_part-1.0.0/
simple_namespace_part-1.0.0/PKG-INFO
simple_namespace_part-1.0.0/pyproject.toml
simple_namespace_part-1.0.0/pyproject.toml.orig
simple_namespace_part-1.0.0/src
simple_namespace_part-1.0.0/src/simple_namespace
simple_namespace_part-1.0.0/src/simple_namespace/part
Expand Down Expand Up @@ -1724,6 +1728,7 @@ mod tests {
simple_namespace_part-1.0.0/
simple_namespace_part-1.0.0/PKG-INFO
simple_namespace_part-1.0.0/pyproject.toml
simple_namespace_part-1.0.0/pyproject.toml.orig
simple_namespace_part-1.0.0/src
simple_namespace_part-1.0.0/src/foo
simple_namespace_part-1.0.0/src/foo/__init__.py
Expand Down Expand Up @@ -1839,6 +1844,7 @@ mod tests {
duplicate-1.0.0/
duplicate-1.0.0/PKG-INFO
duplicate-1.0.0/pyproject.toml
duplicate-1.0.0/pyproject.toml.orig
duplicate-1.0.0/src
duplicate-1.0.0/src/bar
duplicate-1.0.0/src/bar/baz
Expand Down Expand Up @@ -1906,8 +1912,7 @@ mod tests {
/// not accidentally skipped by the root-level TOML rewriting logic.
#[test]
fn nested_pyproject_toml_preserved() {
let _preview =
uv_preview::test::with_features(&[PreviewFeature::TomlBackwardsCompatibility]);
let _preview = uv_preview::test::with_features(&[]);
let tmp_dir = TempDir::new().unwrap();

fs_err::write(
Expand Down Expand Up @@ -1966,8 +1971,7 @@ mod tests {
/// compatibility with older tools. The original file is preserved as pyproject.toml.orig.
#[test]
fn toml_1_1_backward_compatibility() {
let _preview =
uv_preview::test::with_features(&[PreviewFeature::TomlBackwardsCompatibility]);
let _preview = uv_preview::test::with_features(&[]);
let src = TempDir::new().unwrap();

// A `pyproject.toml` with a TOML 1.1 feature, trailing commas in inline tables.
Expand Down Expand Up @@ -2054,8 +2058,7 @@ mod tests {
"#);
}

/// Test that TOML 1.1 features in pyproject.toml trigger auto-detection and rewrite to TOML
/// 1.0, even without explicitly enabling `PreviewFeature::TomlBackwardsCompatibility`.
/// Test that TOML 1.1 features in pyproject.toml are rewritten by default.
#[test]
fn toml_1_1_backward_compatibility_auto_detection() {
let _preview = uv_preview::test::with_features(&[]);
Expand Down
77 changes: 27 additions & 50 deletions crates/uv-build-backend/src/source_dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ use tracing::{debug, trace};
use uv_distribution_filename::{SourceDistExtension, SourceDistFilename};
use uv_fs::{Simplified, normalize_path};
use uv_globfilter::{GlobDirFilter, PortableGlobParser};
use uv_preview::PreviewFeature;
use uv_toml::has_toml11_features;
use uv_warnings::warn_user_once;
use walkdir::WalkDir;

Expand Down Expand Up @@ -242,47 +240,28 @@ fn write_source_dist(
//
// To work around this, we do a best-effort rewrite of `pyproject.toml` to TOML 1.0. We also
// add the original `pyproject.toml` as `pyproject.toml.orig` for reference.
//
// The feature is enabled either explicitly via the preview flag, or automatically when the
// `pyproject.toml` is detected to contain TOML 1.1-only syntax.
let pyproject_path = source_tree.join("pyproject.toml");
let pyproject_contents = fs_err::read_to_string(&pyproject_path)?;
let toml_backwards_compatibility =
if uv_preview::is_enabled(PreviewFeature::TomlBackwardsCompatibility) {
true
} else if has_toml11_features(&pyproject_contents) {
warn_user_once!(
"`pyproject.toml` uses TOML 1.1 features; rewriting to TOML 1.0 for \
compatibility with older build tools. Use `--preview-feature \
{feature}` to suppress this warning.",
feature = PreviewFeature::TomlBackwardsCompatibility
);
true
} else {
false
};
if toml_backwards_compatibility {
let mut pyproject_value: toml::Value = toml::from_str(&pyproject_contents)
.map_err(|err| Error::Toml(pyproject_path.clone(), err))?;
// See https://github.com/toml-rs/toml/issues/1088 for `to_string_pretty`.
normalize_toml10_datetimes(&mut pyproject_value);
let pyproject_rewritten =
toml::to_string_pretty(&pyproject_value).map_err(Error::TomlSerialize)?;
writer.write_bytes(
&Path::new(&top_level)
.join("pyproject.toml")
.portable_display()
.to_string(),
pyproject_rewritten.as_bytes(),
)?;
writer.write_file(
&Path::new(&top_level)
.join("pyproject.toml.orig")
.portable_display()
.to_string(),
&pyproject_path,
)?;
}
let mut pyproject_value: toml::Value = toml::from_str(&pyproject_contents)
.map_err(|err| Error::Toml(pyproject_path.clone(), err))?;
// See https://github.com/toml-rs/toml/issues/1088 for `to_string_pretty`.
normalize_toml10_datetimes(&mut pyproject_value);
let pyproject_rewritten =
toml::to_string_pretty(&pyproject_value).map_err(Error::TomlSerialize)?;
writer.write_bytes(
&Path::new(&top_level)
.join("pyproject.toml")
.portable_display()
.to_string(),
pyproject_rewritten.as_bytes(),
)?;
writer.write_file(
&Path::new(&top_level)
.join("pyproject.toml.orig")
.portable_display()
.to_string(),
&pyproject_path,
)?;

let (include_matcher, exclude_matcher) =
source_dist_matcher(source_tree, &pyproject_toml, settings, show_warnings)?;
Expand Down Expand Up @@ -333,15 +312,13 @@ fn write_source_dist(
continue;
}

if toml_backwards_compatibility {
// `pyproject.toml` is handled separately.
if relative == "pyproject.toml" {
continue;
}
if relative == "pyproject.toml.orig" {
debug!("Ignoring existing `pyproject.toml.orig`");
continue;
}
// `pyproject.toml` is handled separately.
if relative == "pyproject.toml" {
continue;
}
if relative == "pyproject.toml.orig" {
debug!("Ignoring existing `pyproject.toml.orig`");
continue;
}

error_on_venv(entry.file_name(), entry.path())?;
Expand Down
Loading