mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Enable constraints in uv tool upgrade
CLI (#9375)
## Summary Closes https://github.com/astral-sh/uv/issues/9321.
This commit is contained in:
parent
0158717ae6
commit
5759cb9891
8 changed files with 76 additions and 23 deletions
|
@ -3849,9 +3849,9 @@ pub struct ToolUninstallArgs {
|
|||
#[derive(Args)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct ToolUpgradeArgs {
|
||||
/// The name of the tool to upgrade.
|
||||
/// The name of the tool to upgrade, along with an optional version specifier.
|
||||
#[arg(required = true)]
|
||||
pub name: Vec<PackageName>,
|
||||
pub name: Vec<String>,
|
||||
|
||||
/// Upgrade all tools.
|
||||
#[arg(long, conflicts_with("name"))]
|
||||
|
|
|
@ -351,9 +351,25 @@ impl RequirementsSpecification {
|
|||
}
|
||||
}
|
||||
|
||||
/// Initialize a [`RequirementsSpecification`] from a list of [`Requirement`], including
|
||||
/// constraints.
|
||||
pub fn from_constraints(requirements: Vec<Requirement>, constraints: Vec<Requirement>) -> Self {
|
||||
Self {
|
||||
requirements: requirements
|
||||
.into_iter()
|
||||
.map(UnresolvedRequirementSpecification::from)
|
||||
.collect(),
|
||||
constraints: constraints
|
||||
.into_iter()
|
||||
.map(NameRequirementSpecification::from)
|
||||
.collect(),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize a [`RequirementsSpecification`] from a list of [`Requirement`], including
|
||||
/// constraints and overrides.
|
||||
pub fn from_constraints(
|
||||
pub fn from_overrides(
|
||||
requirements: Vec<Requirement>,
|
||||
constraints: Vec<Requirement>,
|
||||
overrides: Vec<Requirement>,
|
||||
|
|
|
@ -316,7 +316,7 @@ pub(crate) async fn run(
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let spec =
|
||||
RequirementsSpecification::from_constraints(requirements, constraints, overrides);
|
||||
RequirementsSpecification::from_overrides(requirements, constraints, overrides);
|
||||
let result = CachedEnvironment::get_or_create(
|
||||
EnvironmentSpecification::from(spec),
|
||||
interpreter,
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
use std::{collections::BTreeSet, fmt::Write};
|
||||
|
||||
use anyhow::Result;
|
||||
use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Write;
|
||||
use tracing::debug;
|
||||
|
||||
use uv_cache::Cache;
|
||||
use uv_client::{BaseClientBuilder, Connectivity};
|
||||
use uv_configuration::{Concurrency, TrustedHost};
|
||||
use uv_fs::CWD;
|
||||
use uv_normalize::PackageName;
|
||||
use uv_pypi_types::Requirement;
|
||||
use uv_python::{
|
||||
EnvironmentPreference, Interpreter, PythonDownloads, PythonInstallation, PythonPreference,
|
||||
PythonRequest,
|
||||
|
@ -31,7 +33,7 @@ use crate::settings::ResolverInstallerSettings;
|
|||
|
||||
/// Upgrade a tool.
|
||||
pub(crate) async fn upgrade(
|
||||
name: Vec<PackageName>,
|
||||
names: Vec<String>,
|
||||
python: Option<String>,
|
||||
install_mirrors: PythonInstallMirrors,
|
||||
connectivity: Connectivity,
|
||||
|
@ -48,17 +50,24 @@ pub(crate) async fn upgrade(
|
|||
let installed_tools = InstalledTools::from_settings()?.init()?;
|
||||
let _lock = installed_tools.lock().await?;
|
||||
|
||||
// Collect the tools to upgrade.
|
||||
let names: BTreeSet<PackageName> = {
|
||||
if name.is_empty() {
|
||||
// Collect the tools to upgrade, along with any constraints.
|
||||
let names: BTreeMap<PackageName, Vec<Requirement>> = {
|
||||
if names.is_empty() {
|
||||
installed_tools
|
||||
.tools()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(name, _)| name)
|
||||
.map(|(name, _)| (name, Vec::new()))
|
||||
.collect()
|
||||
} else {
|
||||
name.into_iter().collect()
|
||||
let mut map = BTreeMap::new();
|
||||
for name in names {
|
||||
let requirement = Requirement::from(uv_pep508::Requirement::parse(&name, &*CWD)?);
|
||||
map.entry(requirement.name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(requirement);
|
||||
}
|
||||
map
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -102,10 +111,11 @@ pub(crate) async fn upgrade(
|
|||
let mut did_upgrade_environment = vec![];
|
||||
|
||||
let mut errors = Vec::new();
|
||||
for name in &names {
|
||||
for (name, constraints) in &names {
|
||||
debug!("Upgrading tool: `{name}`");
|
||||
let result = upgrade_tool(
|
||||
name,
|
||||
constraints,
|
||||
interpreter.as_ref(),
|
||||
printer,
|
||||
&installed_tools,
|
||||
|
@ -194,6 +204,7 @@ enum UpgradeOutcome {
|
|||
/// Upgrade a specific tool.
|
||||
async fn upgrade_tool(
|
||||
name: &PackageName,
|
||||
constraints: &[Requirement],
|
||||
interpreter: Option<&Interpreter>,
|
||||
printer: Printer,
|
||||
installed_tools: &InstalledTools,
|
||||
|
@ -255,7 +266,8 @@ async fn upgrade_tool(
|
|||
|
||||
// Resolve the requirements.
|
||||
let requirements = existing_tool_receipt.requirements();
|
||||
let spec = RequirementsSpecification::from_requirements(requirements.to_vec());
|
||||
let spec =
|
||||
RequirementsSpecification::from_constraints(requirements.to_vec(), constraints.to_vec());
|
||||
|
||||
// Initialize any shared state.
|
||||
let state = SharedState::default();
|
||||
|
@ -267,7 +279,7 @@ async fn upgrade_tool(
|
|||
{
|
||||
// If we're using a new interpreter, re-create the environment for each tool.
|
||||
let resolution = resolve_environment(
|
||||
RequirementsSpecification::from_requirements(requirements.to_vec()).into(),
|
||||
spec.into(),
|
||||
interpreter,
|
||||
settings.as_ref().into(),
|
||||
&state,
|
||||
|
|
|
@ -1002,7 +1002,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
|||
let cache = cache.init()?.with_refresh(Refresh::All(Timestamp::now()));
|
||||
|
||||
Box::pin(commands::tool_upgrade(
|
||||
args.name,
|
||||
args.names,
|
||||
args.python,
|
||||
args.install_mirrors,
|
||||
globals.connectivity,
|
||||
|
|
|
@ -534,7 +534,7 @@ impl ToolInstallSettings {
|
|||
#[allow(clippy::struct_excessive_bools)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ToolUpgradeSettings {
|
||||
pub(crate) name: Vec<PackageName>,
|
||||
pub(crate) names: Vec<String>,
|
||||
pub(crate) python: Option<String>,
|
||||
pub(crate) install_mirrors: PythonInstallMirrors,
|
||||
pub(crate) args: ResolverInstallerOptions,
|
||||
|
@ -574,6 +574,9 @@ impl ToolUpgradeSettings {
|
|||
if upgrade {
|
||||
warn_user_once!("`--upgrade` is enabled by default on `uv tool upgrade`");
|
||||
}
|
||||
if !upgrade_package.is_empty() {
|
||||
warn_user_once!("`--upgrade-package` is enabled by default on `uv tool upgrade`");
|
||||
}
|
||||
|
||||
// Enable `--upgrade` by default.
|
||||
let installer = ResolverInstallerArgs {
|
||||
|
@ -611,7 +614,7 @@ impl ToolUpgradeSettings {
|
|||
.unwrap_or_default();
|
||||
|
||||
Self {
|
||||
name: if all { vec![] } else { name },
|
||||
names: if all { vec![] } else { name },
|
||||
python: python.and_then(Maybe::into_option),
|
||||
args,
|
||||
filesystem: top_level,
|
||||
|
|
|
@ -467,7 +467,28 @@ fn tool_upgrade_constraint() {
|
|||
Installed 1 executable: pybabel
|
||||
"###);
|
||||
|
||||
// Upgrade `babel`, but apply a constraint.
|
||||
// Upgrade `babel`, but apply a constraint inline.
|
||||
uv_snapshot!(context.filters(), context.tool_upgrade()
|
||||
.arg("babel<2.12.0")
|
||||
.arg("--index-url")
|
||||
.arg("https://pypi.org/simple/")
|
||||
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
|
||||
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
|
||||
.env(EnvVars::PATH, bin_dir.as_os_str()), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Updated babel v2.6.0 -> v2.11.0
|
||||
- babel==2.6.0
|
||||
+ babel==2.11.0
|
||||
- pytz==2018.5
|
||||
+ pytz==2024.1
|
||||
Installed 1 executable: pybabel
|
||||
"###);
|
||||
|
||||
// Upgrade `babel`, but apply a constraint via `--upgrade-package`.
|
||||
uv_snapshot!(context.filters(), context.tool_upgrade()
|
||||
.arg("babel")
|
||||
.arg("--index-url")
|
||||
|
@ -482,10 +503,11 @@ fn tool_upgrade_constraint() {
|
|||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Updated babel v2.6.0 -> v2.13.1
|
||||
- babel==2.6.0
|
||||
warning: `--upgrade-package` is enabled by default on `uv tool upgrade`
|
||||
Updated babel v2.11.0 -> v2.13.1
|
||||
- babel==2.11.0
|
||||
+ babel==2.13.1
|
||||
- pytz==2018.5
|
||||
- pytz==2024.1
|
||||
+ setuptools==69.2.0
|
||||
Installed 1 executable: pybabel
|
||||
"###);
|
||||
|
|
|
@ -3495,7 +3495,7 @@ uv tool upgrade [OPTIONS] <NAME>...
|
|||
|
||||
<h3 class="cli-reference">Arguments</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>NAME</code></dt><dd><p>The name of the tool to upgrade</p>
|
||||
<dl class="cli-reference"><dt><code>NAME</code></dt><dd><p>The name of the tool to upgrade, along with an optional version specifier</p>
|
||||
|
||||
</dd></dl>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue