Skip to content

Commit 0442431

Browse files
committedMar 19, 2025·
Allow virtual packages with --no-build
1 parent e40c551 commit 0442431

File tree

3 files changed

+144
-5
lines changed

3 files changed

+144
-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

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

3485+
#[test]
3486+
fn virtual_no_build() -> Result<()> {
3487+
let context = TestContext::new("3.12");
3488+
3489+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
3490+
pyproject_toml.write_str(
3491+
r#"
3492+
[project]
3493+
name = "project"
3494+
version = "0.1.0"
3495+
requires-python = ">=3.12"
3496+
dependencies = ["anyio==3.7.0"]
3497+
"#,
3498+
)?;
3499+
3500+
// Generate a lockfile.
3501+
context.lock().assert().success();
3502+
3503+
// Clear the cache.
3504+
fs_err::remove_dir_all(&context.cache_dir)?;
3505+
3506+
// `--no-build` should not raise an error, since we don't install virtual projects.
3507+
uv_snapshot!(context.filters(), context.sync().arg("--no-build"), @r"
3508+
success: true
3509+
exit_code: 0
3510+
----- stdout -----
3511+
3512+
----- stderr -----
3513+
Resolved 4 packages in [TIME]
3514+
Prepared 3 packages in [TIME]
3515+
Installed 3 packages in [TIME]
3516+
+ anyio==3.7.0
3517+
+ idna==3.6
3518+
+ sniffio==1.3.1
3519+
");
3520+
3521+
Ok(())
3522+
}
3523+
3524+
#[test]
3525+
fn virtual_no_build_dynamic_cached() -> Result<()> {
3526+
let context = TestContext::new("3.12");
3527+
3528+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
3529+
pyproject_toml.write_str(
3530+
r#"
3531+
[project]
3532+
name = "project"
3533+
version = "0.1.0"
3534+
requires-python = ">=3.12"
3535+
dynamic = ["dependencies"]
3536+
3537+
[tool.setuptools.dynamic]
3538+
dependencies = {file = ["requirements.txt"]}
3539+
"#,
3540+
)?;
3541+
3542+
context
3543+
.temp_dir
3544+
.child("requirements.txt")
3545+
.write_str("anyio==3.7.0")?;
3546+
3547+
// Generate a lockfile.
3548+
context.lock().assert().success();
3549+
3550+
// `--no-build` should not raise an error, since we don't build or install the project (given
3551+
// that it's virtual and the metadata is cached).
3552+
uv_snapshot!(context.filters(), context.sync().arg("--no-build"), @r"
3553+
success: true
3554+
exit_code: 0
3555+
----- stdout -----
3556+
3557+
----- stderr -----
3558+
Resolved 4 packages in [TIME]
3559+
Prepared 3 packages in [TIME]
3560+
Installed 3 packages in [TIME]
3561+
+ anyio==3.7.0
3562+
+ idna==3.6
3563+
+ sniffio==1.3.1
3564+
");
3565+
3566+
Ok(())
3567+
}
3568+
3569+
#[test]
3570+
fn virtual_no_build_dynamic_no_cache() -> Result<()> {
3571+
let context = TestContext::new("3.12");
3572+
3573+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
3574+
pyproject_toml.write_str(
3575+
r#"
3576+
[project]
3577+
name = "project"
3578+
version = "0.1.0"
3579+
requires-python = ">=3.12"
3580+
dynamic = ["dependencies"]
3581+
3582+
[tool.setuptools.dynamic]
3583+
dependencies = {file = ["requirements.txt"]}
3584+
"#,
3585+
)?;
3586+
3587+
context
3588+
.temp_dir
3589+
.child("requirements.txt")
3590+
.write_str("anyio==3.7.0")?;
3591+
3592+
// Generate a lockfile.
3593+
context.lock().assert().success();
3594+
3595+
// Clear the cache.
3596+
fs_err::remove_dir_all(&context.cache_dir)?;
3597+
3598+
// `--no-build` should raise an error, since we need to build the project.
3599+
uv_snapshot!(context.filters(), context.sync().arg("--no-build"), @r"
3600+
success: false
3601+
exit_code: 2
3602+
----- stdout -----
3603+
3604+
----- stderr -----
3605+
error: Failed to generate package metadata for `project==0.1.0 @ virtual+.`
3606+
Caused by: Building source distributions for `project` is disabled
3607+
");
3608+
3609+
Ok(())
3610+
}
3611+
34853612
/// Convert from a package to a virtual project.
34863613
#[test]
34873614
fn convert_to_virtual() -> Result<()> {

0 commit comments

Comments
 (0)