Skip to content

Commit 1634c65

Browse files
committed
Reject --editable flag on non-directory requirements
1 parent ad60f8d commit 1634c65

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

crates/uv-workspace/src/pyproject.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,8 @@ pub enum SourceError {
13121312
UnusedTag(String, String),
13131313
#[error("`{0}` did not resolve to a Git repository, but a Git reference (`--branch {1}`) was provided.")]
13141314
UnusedBranch(String, String),
1315+
#[error("`{0}` did not resolve to a local directory, but the `--editable` flag was provided.")]
1316+
UnusedEditable(String),
13151317
#[error("Failed to resolve absolute path")]
13161318
Absolute(#[from] std::io::Error),
13171319
#[error("Path contains invalid characters: `{}`", _0.display())]
@@ -1349,6 +1351,13 @@ impl Source {
13491351
}
13501352
}
13511353

1354+
// If we resolved a non-path source, and user specified an editable flag, error.
1355+
if !matches!(source, RequirementSource::Directory { .. }) {
1356+
if editable.unwrap_or(false) {
1357+
return Err(SourceError::UnusedEditable(name.to_string()));
1358+
}
1359+
}
1360+
13521361
// If the source is a workspace package, error if the user tried to specify a source.
13531362
if workspace {
13541363
return match source {

crates/uv/tests/it/edit.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,37 @@ fn add_raw_error() -> Result<()> {
875875
Ok(())
876876
}
877877

878+
#[test]
879+
#[cfg(feature = "git")]
880+
fn add_editable_error() -> Result<()> {
881+
let context = TestContext::new("3.12");
882+
883+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
884+
pyproject_toml.write_str(indoc! {r#"
885+
[project]
886+
name = "project"
887+
version = "0.1.0"
888+
requires-python = ">=3.12"
889+
dependencies = []
890+
891+
[build-system]
892+
requires = ["setuptools>=42"]
893+
build-backend = "setuptools.build_meta"
894+
"#})?;
895+
896+
// Provide `--editable` with a non-source tree.
897+
uv_snapshot!(context.filters(), context.add().arg("flask @ https://files.pythonhosted.org/packages/61/80/ffe1da13ad9300f87c93af113edd0638c75138c42a0994becfacac078c06/flask-3.0.3-py3-none-any.whl").arg("--editable"), @r###"
898+
success: false
899+
exit_code: 2
900+
----- stdout -----
901+
902+
----- stderr -----
903+
error: `flask` did not resolve to a local directory, but the `--editable` flag was provided.
904+
"###);
905+
906+
Ok(())
907+
}
908+
878909
/// Add an unnamed requirement.
879910
#[test]
880911
#[cfg(feature = "git")]
@@ -2187,7 +2218,7 @@ fn add_workspace_editable() -> Result<()> {
21872218

21882219
let child1 = context.temp_dir.join("child1");
21892220
let mut add_cmd = context.add();
2190-
add_cmd.arg("child2").arg("--editable").current_dir(&child1);
2221+
add_cmd.arg("child2").current_dir(&child1);
21912222

21922223
uv_snapshot!(context.filters(), add_cmd, @r###"
21932224
success: true

0 commit comments

Comments
 (0)