Skip to content

Commit 292148d

Browse files
committed
Allow virtual packages with --no-build
1 parent e40c551 commit 292148d

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

crates/uv-distribution-types/src/lib.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -637,22 +637,31 @@ impl SourceDist {
637637
}
638638
}
639639

640+
/// Returns the [`Version`] of the distribution, if it is known.
640641
pub fn version(&self) -> Option<&Version> {
641642
match self {
642643
Self::Registry(source_dist) => Some(&source_dist.version),
643644
Self::DirectUrl(_) | Self::Git(_) | Self::Path(_) | Self::Directory(_) => None,
644645
}
645646
}
646647

647-
/// Return true if the distribution is editable.
648+
/// Returns `true` if the distribution is editable.
648649
pub fn is_editable(&self) -> bool {
649650
match self {
650651
Self::Directory(DirectorySourceDist { editable, .. }) => *editable,
651652
_ => false,
652653
}
653654
}
654655

655-
/// Return true if the distribution refers to a local file or directory.
656+
/// Returns `true` if the distribution is virtual.
657+
pub fn is_virtual(&self) -> bool {
658+
match self {
659+
Self::Directory(DirectorySourceDist { r#virtual, .. }) => *r#virtual,
660+
_ => false,
661+
}
662+
}
663+
664+
/// Returns `true` if the distribution refers to a local file or directory.
656665
pub fn is_local(&self) -> bool {
657666
matches!(self, Self::Directory(_) | Self::Path(_))
658667
}
@@ -666,7 +675,7 @@ impl SourceDist {
666675
}
667676
}
668677

669-
/// Return the source tree of the distribution, if available.
678+
/// Returns the source tree of the distribution, if available.
670679
pub fn source_tree(&self) -> Option<&Path> {
671680
match self {
672681
Self::Directory(dist) => Some(&dist.install_path),

crates/uv-resolver/src/lock/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2196,8 +2196,11 @@ impl Package {
21962196
};
21972197
}
21982198

2199-
if !no_build {
2200-
if let Some(sdist) = self.to_source_dist(workspace_root)? {
2199+
if let Some(sdist) = self.to_source_dist(workspace_root)? {
2200+
// Even with `--no-build`, allow virtual packages. (In the future, we may want to allow
2201+
// any local source tree, or at least editable source trees, which we allow in
2202+
// `uv pip`.)
2203+
if !no_build || sdist.is_virtual() {
22012204
return Ok(Dist::Source(sdist));
22022205
}
22032206
}

crates/uv/tests/it/sync.rs

+83
Original file line numberDiff line numberDiff line change
@@ -3482,6 +3482,89 @@ fn no_install_project_no_build() -> Result<()> {
34823482
Ok(())
34833483
}
34843484

3485+
/// Ensure that `--no-build` isn't enforced for projects that aren't installed in the first place.
3486+
#[test]
3487+
fn virtual_no_build() -> Result<()> {
3488+
let context = TestContext::new("3.12");
3489+
3490+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
3491+
pyproject_toml.write_str(
3492+
r#"
3493+
[project]
3494+
name = "project"
3495+
version = "0.1.0"
3496+
requires-python = ">=3.12"
3497+
dependencies = ["anyio==3.7.0"]
3498+
"#,
3499+
)?;
3500+
3501+
// Generate a lockfile.
3502+
context.lock().assert().success();
3503+
3504+
// `--no-build` should not raise an error, since we don't install virtual projects.
3505+
uv_snapshot!(context.filters(), context.sync().arg("--no-build"), @r"
3506+
success: true
3507+
exit_code: 0
3508+
----- stdout -----
3509+
3510+
----- stderr -----
3511+
Resolved 4 packages in [TIME]
3512+
Prepared 3 packages in [TIME]
3513+
Installed 3 packages in [TIME]
3514+
+ anyio==3.7.0
3515+
+ idna==3.6
3516+
+ sniffio==1.3.1
3517+
");
3518+
3519+
Ok(())
3520+
}
3521+
3522+
/// Ensure that `--no-build` isn't enforced for projects that aren't installed in the first place.
3523+
#[test]
3524+
fn virtual_no_build_dynamic() -> Result<()> {
3525+
let context = TestContext::new("3.12");
3526+
3527+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
3528+
pyproject_toml.write_str(
3529+
r#"
3530+
[project]
3531+
name = "project"
3532+
version = "0.1.0"
3533+
requires-python = ">=3.12"
3534+
dynamic = ["dependencies"]
3535+
3536+
[tool.setuptools.dynamic]
3537+
dependencies = {file = ["requirements.txt"]}
3538+
"#,
3539+
)?;
3540+
3541+
context
3542+
.temp_dir
3543+
.child("requirements.txt")
3544+
.write_str("anyio==3.7.0")?;
3545+
3546+
// Generate a lockfile.
3547+
context.lock().assert().success();
3548+
3549+
// `--no-build` should not raise an error, since we don't install virtual projects (and we even
3550+
// allow building dynamic metadata under `--no-build`).
3551+
uv_snapshot!(context.filters(), context.sync().arg("--no-build"), @r"
3552+
success: true
3553+
exit_code: 0
3554+
----- stdout -----
3555+
3556+
----- stderr -----
3557+
Resolved 4 packages in [TIME]
3558+
Prepared 3 packages in [TIME]
3559+
Installed 3 packages in [TIME]
3560+
+ anyio==3.7.0
3561+
+ idna==3.6
3562+
+ sniffio==1.3.1
3563+
");
3564+
3565+
Ok(())
3566+
}
3567+
34853568
/// Convert from a package to a virtual project.
34863569
#[test]
34873570
fn convert_to_virtual() -> Result<()> {

0 commit comments

Comments
 (0)