mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-01 09:32:18 +00:00
Add --package
to uv sync
(#5656)
## Summary Closes https://github.com/astral-sh/uv/issues/5008.
This commit is contained in:
parent
37a60a57e8
commit
176e9c4deb
5 changed files with 89 additions and 4 deletions
|
@ -2008,6 +2008,10 @@ pub struct SyncArgs {
|
|||
#[command(flatten)]
|
||||
pub refresh: RefreshArgs,
|
||||
|
||||
/// Sync a specific package in the workspace.
|
||||
#[arg(long)]
|
||||
pub package: Option<PackageName>,
|
||||
|
||||
/// The Python interpreter to use to build the run environment.
|
||||
///
|
||||
/// By default, uv uses the virtual environment in the current working directory or any parent
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use uv_auth::store_credentials_from_url;
|
||||
use uv_cache::Cache;
|
||||
|
@ -10,11 +10,12 @@ use uv_dispatch::BuildDispatch;
|
|||
use uv_distribution::DEV_DEPENDENCIES;
|
||||
use uv_fs::CWD;
|
||||
use uv_installer::SitePackages;
|
||||
use uv_normalize::PackageName;
|
||||
use uv_python::{PythonEnvironment, PythonFetch, PythonPreference, PythonRequest};
|
||||
use uv_resolver::{FlatIndex, Lock};
|
||||
use uv_types::{BuildIsolation, HashStrategy};
|
||||
use uv_warnings::warn_user_once;
|
||||
use uv_workspace::{DiscoveryOptions, VirtualProject};
|
||||
use uv_workspace::{DiscoveryOptions, VirtualProject, Workspace};
|
||||
|
||||
use crate::commands::pip::operations::Modifications;
|
||||
use crate::commands::project::lock::do_safe_lock;
|
||||
|
@ -28,6 +29,7 @@ use crate::settings::{InstallerSettingsRef, ResolverInstallerSettings};
|
|||
pub(crate) async fn sync(
|
||||
locked: bool,
|
||||
frozen: bool,
|
||||
package: Option<PackageName>,
|
||||
extras: ExtrasSpecification,
|
||||
dev: bool,
|
||||
modifications: Modifications,
|
||||
|
@ -46,8 +48,17 @@ pub(crate) async fn sync(
|
|||
warn_user_once!("`uv sync` is experimental and may change without warning");
|
||||
}
|
||||
|
||||
// Identify the project
|
||||
let project = VirtualProject::discover(&CWD, &DiscoveryOptions::default()).await?;
|
||||
// Identify the project.
|
||||
let project = if let Some(package) = package {
|
||||
VirtualProject::Project(
|
||||
Workspace::discover(&CWD, &DiscoveryOptions::default())
|
||||
.await?
|
||||
.with_current_project(package.clone())
|
||||
.with_context(|| format!("Package `{package}` not found in workspace"))?,
|
||||
)
|
||||
} else {
|
||||
VirtualProject::discover(&CWD, &DiscoveryOptions::default()).await?
|
||||
};
|
||||
|
||||
// Discover or create the virtual environment.
|
||||
let venv = project::get_or_init_environment(
|
||||
|
|
|
@ -979,6 +979,7 @@ async fn run_project(
|
|||
commands::sync(
|
||||
args.locked,
|
||||
args.frozen,
|
||||
args.package,
|
||||
args.extras,
|
||||
args.dev,
|
||||
args.modifications,
|
||||
|
|
|
@ -543,6 +543,7 @@ pub(crate) struct SyncSettings {
|
|||
pub(crate) extras: ExtrasSpecification,
|
||||
pub(crate) dev: bool,
|
||||
pub(crate) modifications: Modifications,
|
||||
pub(crate) package: Option<PackageName>,
|
||||
pub(crate) python: Option<String>,
|
||||
pub(crate) refresh: Refresh,
|
||||
pub(crate) settings: ResolverInstallerSettings,
|
||||
|
@ -564,6 +565,7 @@ impl SyncSettings {
|
|||
installer,
|
||||
build,
|
||||
refresh,
|
||||
package,
|
||||
python,
|
||||
} = args;
|
||||
|
||||
|
@ -582,6 +584,7 @@ impl SyncSettings {
|
|||
),
|
||||
dev: flag(dev, no_dev).unwrap_or(true),
|
||||
modifications,
|
||||
package,
|
||||
python,
|
||||
refresh: Refresh::from(refresh),
|
||||
settings: ResolverInstallerSettings::combine(
|
||||
|
|
|
@ -205,3 +205,69 @@ fn empty() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sync an individual package within a workspace.
|
||||
#[test]
|
||||
fn package() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "root"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["child", "anyio>3"]
|
||||
|
||||
[tool.uv.sources]
|
||||
child = { workspace = true }
|
||||
|
||||
[tool.uv.workspace]
|
||||
members = ["child"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let src = context.temp_dir.child("src").child("albatross");
|
||||
src.create_dir_all()?;
|
||||
|
||||
let init = src.child("__init__.py");
|
||||
init.touch()?;
|
||||
|
||||
let child = context.temp_dir.child("child");
|
||||
fs_err::create_dir_all(&child)?;
|
||||
|
||||
let pyproject_toml = child.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "child"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["iniconfig>1"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let src = child.child("src").child("albatross");
|
||||
src.create_dir_all()?;
|
||||
|
||||
let init = src.child("__init__.py");
|
||||
init.touch()?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.sync().arg("--package").arg("child"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: `uv sync` is experimental and may change without warning
|
||||
warning: `uv.sources` is experimental and may change without warning
|
||||
Resolved 6 packages in [TIME]
|
||||
Prepared 2 packages in [TIME]
|
||||
Installed 2 packages in [TIME]
|
||||
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||
+ iniconfig==2.0.0
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue