PEP 751 uv export supports --no-editable (#13852)

## Summary

When trying out `uv export --no-editable --format pylock.toml` the
exported contents would still retain `editable = true` regardless.

## Test Plan

Added additional test. Tested locally on few projects where I was
previously using `uv export --no-editable --format requirements.txt` to
ensure the output aligns.
This commit is contained in:
samypr100 2025-06-06 07:52:14 -04:00 committed by GitHub
parent 7dd564d3d0
commit a68fb53c4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 71 additions and 2 deletions

View file

@ -13,7 +13,8 @@ use url::Url;
use uv_cache_key::RepositoryUrl;
use uv_configuration::{
BuildOptions, DependencyGroupsWithDefaults, ExtrasSpecificationWithDefaults, InstallOptions,
BuildOptions, DependencyGroupsWithDefaults, EditableMode, ExtrasSpecificationWithDefaults,
InstallOptions,
};
use uv_distribution_filename::{
BuildTag, DistExtension, ExtensionError, SourceDistExtension, SourceDistFilename,
@ -619,6 +620,7 @@ impl<'lock> PylockToml {
extras: &ExtrasSpecificationWithDefaults,
dev: &DependencyGroupsWithDefaults,
annotate: bool,
editable: EditableMode,
install_options: &'lock InstallOptions,
) -> Result<Self, PylockTomlErrorKind> {
// Extract the packages from the lock file.
@ -733,7 +735,10 @@ impl<'lock> PylockToml {
.unwrap_or_else(|_| sdist.install_path.to_path_buf())
.into_boxed_path(),
),
editable: Some(sdist.editable),
editable: match editable {
EditableMode::NonEditable => None,
EditableMode::Editable => Some(sdist.editable),
},
subdirectory: None,
}),
_ => None,

View file

@ -330,6 +330,7 @@ pub(crate) async fn export(
&extras,
&dev,
include_annotations,
editable,
&install_options,
)?;

View file

@ -3550,6 +3550,69 @@ fn pep_751_export_no_header() -> Result<()> {
Ok(())
}
#[test]
fn pep_751_export_no_editable() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
"#,
)?;
context.lock().assert().success();
uv_snapshot!(context.filters(), context.export().arg("--format").arg("pylock.toml").arg("--no-editable"), @r#"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv export --cache-dir [CACHE_DIR] --format pylock.toml --no-editable
lock-version = "1.0"
created-by = "uv"
requires-python = ">=3.12"
[[packages]]
name = "anyio"
version = "3.7.0"
index = "https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/c6/b3/fefbf7e78ab3b805dec67d698dc18dd505af7a18a8dd08868c9b4fa736b5/anyio-3.7.0.tar.gz", upload-time = 2023-05-27T11:12:46Z, size = 142737, hashes = { sha256 = "275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce" } }
wheels = [{ url = "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl", upload-time = 2023-05-27T11:12:44Z, size = 80873, hashes = { sha256 = "eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0" } }]
[[packages]]
name = "idna"
version = "3.6"
index = "https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", upload-time = 2023-11-25T15:40:54Z, size = 175426, hashes = { sha256 = "9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca" } }
wheels = [{ url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", upload-time = 2023-11-25T15:40:52Z, size = 61567, hashes = { sha256 = "c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" } }]
[[packages]]
name = "project"
directory = { path = "." }
[[packages]]
name = "sniffio"
version = "1.3.1"
index = "https://pypi.org/simple"
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", upload-time = 2024-02-25T23:20:04Z, size = 20372, hashes = { sha256 = "f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" } }
wheels = [{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", upload-time = 2024-02-25T23:20:01Z, size = 10235, hashes = { sha256 = "2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2" } }]
----- stderr -----
Resolved 4 packages in [TIME]
"#);
Ok(())
}
#[test]
fn pep_751_dependency_extra() -> Result<()> {
let context = TestContext::new("3.12");