mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Add --package
argument to uv add
and uv remove
(#4556)
## Summary Closes https://github.com/astral-sh/uv/issues/4550.
This commit is contained in:
parent
1ee201da5a
commit
963a7b2ab5
6 changed files with 53 additions and 20 deletions
|
@ -1639,6 +1639,10 @@ pub struct RunArgs {
|
|||
#[command(flatten)]
|
||||
pub refresh: RefreshArgs,
|
||||
|
||||
/// Run the command in a specific package in the workspace.
|
||||
#[arg(long, conflicts_with = "isolated")]
|
||||
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
|
||||
|
@ -1652,10 +1656,6 @@ pub struct RunArgs {
|
|||
/// - `/home/ferris/.local/bin/python3.10` uses the exact Python at the given path.
|
||||
#[arg(long, short, env = "UV_PYTHON", verbatim_doc_comment)]
|
||||
pub python: Option<String>,
|
||||
|
||||
/// Run the command in a different package in the workspace.
|
||||
#[arg(long, conflicts_with = "isolated")]
|
||||
pub package: Option<PackageName>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
@ -1784,6 +1784,10 @@ pub struct AddArgs {
|
|||
#[command(flatten)]
|
||||
pub refresh: RefreshArgs,
|
||||
|
||||
/// Add the dependency to a specific package in the workspace.
|
||||
#[arg(long, conflicts_with = "isolated")]
|
||||
pub package: Option<PackageName>,
|
||||
|
||||
/// The Python interpreter into which packages should be installed.
|
||||
///
|
||||
/// By default, `uv` installs into the virtual environment in the current working directory or
|
||||
|
@ -1811,6 +1815,10 @@ pub struct RemoveArgs {
|
|||
#[arg(long)]
|
||||
pub dev: bool,
|
||||
|
||||
/// Remove the dependency from a specific package in the workspace.
|
||||
#[arg(long, conflicts_with = "isolated")]
|
||||
pub package: Option<PackageName>,
|
||||
|
||||
/// The Python interpreter into which packages should be installed.
|
||||
///
|
||||
/// By default, `uv` installs into the virtual environment in the current working directory or
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
use uv_distribution::pyproject::{Source, SourceError};
|
||||
|
@ -11,7 +11,8 @@ use uv_types::{BuildIsolation, HashStrategy, InFlight};
|
|||
|
||||
use uv_cache::Cache;
|
||||
use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, SetupPyStrategy};
|
||||
use uv_distribution::{DistributionDatabase, ProjectWorkspace};
|
||||
use uv_distribution::{DistributionDatabase, ProjectWorkspace, Workspace};
|
||||
use uv_normalize::PackageName;
|
||||
use uv_warnings::warn_user;
|
||||
|
||||
use crate::commands::pip::operations::Modifications;
|
||||
|
@ -32,6 +33,7 @@ pub(crate) async fn add(
|
|||
rev: Option<String>,
|
||||
tag: Option<String>,
|
||||
branch: Option<String>,
|
||||
package: Option<PackageName>,
|
||||
python: Option<String>,
|
||||
settings: ResolverInstallerSettings,
|
||||
toolchain_preference: ToolchainPreference,
|
||||
|
@ -46,8 +48,15 @@ pub(crate) async fn add(
|
|||
warn_user!("`uv add` is experimental and may change without warning.");
|
||||
}
|
||||
|
||||
// Find the project requirements.
|
||||
let project = ProjectWorkspace::discover(&std::env::current_dir()?, None).await?;
|
||||
// Find the project in the workspace.
|
||||
let project = if let Some(package) = package {
|
||||
Workspace::discover(&std::env::current_dir()?, None)
|
||||
.await?
|
||||
.with_current_project(package.clone())
|
||||
.with_context(|| format!("Package `{package}` not found in workspace"))?
|
||||
} else {
|
||||
ProjectWorkspace::discover(&std::env::current_dir()?, None).await?
|
||||
};
|
||||
|
||||
// Discover or create the virtual environment.
|
||||
let venv = project::init_environment(
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use pep508_rs::PackageName;
|
||||
use uv_cache::Cache;
|
||||
use uv_client::Connectivity;
|
||||
use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode};
|
||||
use uv_distribution::pyproject_mut::PyProjectTomlMut;
|
||||
use uv_distribution::ProjectWorkspace;
|
||||
use uv_distribution::{ProjectWorkspace, Workspace};
|
||||
use uv_toolchain::{ToolchainPreference, ToolchainRequest};
|
||||
use uv_warnings::warn_user;
|
||||
|
||||
|
@ -19,6 +19,7 @@ use crate::settings::{InstallerSettings, ResolverSettings};
|
|||
pub(crate) async fn remove(
|
||||
requirements: Vec<PackageName>,
|
||||
dev: bool,
|
||||
package: Option<PackageName>,
|
||||
python: Option<String>,
|
||||
toolchain_preference: ToolchainPreference,
|
||||
preview: PreviewMode,
|
||||
|
@ -32,8 +33,15 @@ pub(crate) async fn remove(
|
|||
warn_user!("`uv remove` is experimental and may change without warning.");
|
||||
}
|
||||
|
||||
// Find the project requirements.
|
||||
let project = ProjectWorkspace::discover(&std::env::current_dir()?, None).await?;
|
||||
// Find the project in the workspace.
|
||||
let project = if let Some(package) = package {
|
||||
Workspace::discover(&std::env::current_dir()?, None)
|
||||
.await?
|
||||
.with_current_project(package.clone())
|
||||
.with_context(|| format!("Package `{package}` not found in workspace"))?
|
||||
} else {
|
||||
ProjectWorkspace::discover(&std::env::current_dir()?, None).await?
|
||||
};
|
||||
|
||||
let mut pyproject = PyProjectTomlMut::from_toml(project.current_project().pyproject_toml())?;
|
||||
for req in requirements {
|
||||
|
@ -47,7 +55,7 @@ pub(crate) async fn remove(
|
|||
.filter(|deps| !deps.is_empty())
|
||||
.is_some()
|
||||
{
|
||||
uv_warnings::warn_user!("`{req}` is not a development dependency; try calling `uv remove` without the `--dev` flag");
|
||||
warn_user!("`{req}` is not a development dependency; try calling `uv remove` without the `--dev` flag");
|
||||
}
|
||||
|
||||
anyhow::bail!("The dependency `{req}` could not be found in `dev-dependencies`");
|
||||
|
@ -65,9 +73,7 @@ pub(crate) async fn remove(
|
|||
.filter(|deps| !deps.is_empty())
|
||||
.is_some()
|
||||
{
|
||||
uv_warnings::warn_user!(
|
||||
"`{req}` is a development dependency; try calling `uv remove --dev`"
|
||||
);
|
||||
warn_user!("`{req}` is a development dependency; try calling `uv remove --dev`");
|
||||
}
|
||||
|
||||
anyhow::bail!("The dependency `{req}` could not be found in `dependencies`");
|
||||
|
|
|
@ -726,6 +726,7 @@ async fn run() -> Result<ExitStatus> {
|
|||
args.rev,
|
||||
args.tag,
|
||||
args.branch,
|
||||
args.package,
|
||||
args.python,
|
||||
args.settings,
|
||||
globals.toolchain_preference,
|
||||
|
@ -749,6 +750,7 @@ async fn run() -> Result<ExitStatus> {
|
|||
commands::remove(
|
||||
args.requirements,
|
||||
args.dev,
|
||||
args.package,
|
||||
args.python,
|
||||
globals.toolchain_preference,
|
||||
globals.preview,
|
||||
|
|
|
@ -147,8 +147,8 @@ pub(crate) struct RunSettings {
|
|||
pub(crate) dev: bool,
|
||||
pub(crate) command: ExternalCommand,
|
||||
pub(crate) with: Vec<String>,
|
||||
pub(crate) python: Option<String>,
|
||||
pub(crate) package: Option<PackageName>,
|
||||
pub(crate) python: Option<String>,
|
||||
pub(crate) refresh: Refresh,
|
||||
pub(crate) settings: ResolverInstallerSettings,
|
||||
}
|
||||
|
@ -168,8 +168,8 @@ impl RunSettings {
|
|||
installer,
|
||||
build,
|
||||
refresh,
|
||||
python,
|
||||
package,
|
||||
python,
|
||||
} = args;
|
||||
|
||||
Self {
|
||||
|
@ -180,8 +180,8 @@ impl RunSettings {
|
|||
dev: flag(dev, no_dev).unwrap_or(true),
|
||||
command,
|
||||
with,
|
||||
python,
|
||||
package,
|
||||
python,
|
||||
refresh: Refresh::from(refresh),
|
||||
settings: ResolverInstallerSettings::combine(
|
||||
resolver_installer_options(installer, build),
|
||||
|
@ -438,6 +438,7 @@ pub(crate) struct AddSettings {
|
|||
pub(crate) rev: Option<String>,
|
||||
pub(crate) tag: Option<String>,
|
||||
pub(crate) branch: Option<String>,
|
||||
pub(crate) package: Option<PackageName>,
|
||||
pub(crate) python: Option<String>,
|
||||
pub(crate) refresh: Refresh,
|
||||
pub(crate) settings: ResolverInstallerSettings,
|
||||
|
@ -459,6 +460,7 @@ impl AddSettings {
|
|||
installer,
|
||||
build,
|
||||
refresh,
|
||||
package,
|
||||
python,
|
||||
} = args;
|
||||
|
||||
|
@ -476,6 +478,7 @@ impl AddSettings {
|
|||
rev,
|
||||
tag,
|
||||
branch,
|
||||
package,
|
||||
python,
|
||||
refresh: Refresh::from(refresh),
|
||||
settings: ResolverInstallerSettings::combine(
|
||||
|
@ -492,6 +495,7 @@ impl AddSettings {
|
|||
pub(crate) struct RemoveSettings {
|
||||
pub(crate) requirements: Vec<PackageName>,
|
||||
pub(crate) dev: bool,
|
||||
pub(crate) package: Option<PackageName>,
|
||||
pub(crate) python: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -502,12 +506,14 @@ impl RemoveSettings {
|
|||
let RemoveArgs {
|
||||
dev,
|
||||
requirements,
|
||||
package,
|
||||
python,
|
||||
} = args;
|
||||
|
||||
Self {
|
||||
requirements,
|
||||
dev,
|
||||
package,
|
||||
python,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -740,7 +740,9 @@ fn add_remove_workspace() -> Result<()> {
|
|||
add_cmd
|
||||
.arg("--preview")
|
||||
.arg("--workspace")
|
||||
.current_dir(&child1);
|
||||
.arg("--package")
|
||||
.arg("child1")
|
||||
.current_dir(&context.temp_dir);
|
||||
|
||||
uv_snapshot!(context.filters(), add_cmd, @r###"
|
||||
success: true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue