mirror of https://github.com/astral-sh/uv
Support `pip install --exact` (#8044)
## Summary Resolves #8041 ## Test Plan `cargo test`
This commit is contained in:
parent
1e6c64074d
commit
1764a95d39
|
|
@ -1637,6 +1637,18 @@ pub struct PipInstallArgs {
|
|||
#[arg(long)]
|
||||
pub python_platform: Option<TargetTriple>,
|
||||
|
||||
/// Do not remove extraneous packages present in the environment.
|
||||
#[arg(long, overrides_with("exact"), alias = "no-exact", hide = true)]
|
||||
pub inexact: bool,
|
||||
|
||||
/// Perform an exact sync, removing extraneous packages.
|
||||
///
|
||||
/// By default, installing will make the minimum necessary changes to satisfy the requirements.
|
||||
/// When enabled, uv will update the environment to exactly match the requirements, removing
|
||||
/// packages that are not included in the requirements.
|
||||
#[arg(long, overrides_with("inexact"))]
|
||||
pub exact: bool,
|
||||
|
||||
/// Validate the Python environment after completing the installation, to detect and with
|
||||
/// missing dependencies or other issues.
|
||||
#[arg(long, overrides_with("no_strict"))]
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ pub(crate) async fn pip_install(
|
|||
no_build_isolation: bool,
|
||||
no_build_isolation_package: Vec<PackageName>,
|
||||
build_options: BuildOptions,
|
||||
modifications: Modifications,
|
||||
python_version: Option<PythonVersion>,
|
||||
python_platform: Option<TargetTriple>,
|
||||
strict: bool,
|
||||
|
|
@ -408,7 +409,7 @@ pub(crate) async fn pip_install(
|
|||
operations::install(
|
||||
&resolution,
|
||||
site_packages,
|
||||
Modifications::Sufficient,
|
||||
modifications,
|
||||
&reinstall,
|
||||
&build_options,
|
||||
link_mode,
|
||||
|
|
|
|||
|
|
@ -494,6 +494,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.no_build_isolation,
|
||||
args.settings.no_build_isolation_package,
|
||||
args.settings.build_options,
|
||||
args.modifications,
|
||||
args.settings.python_version,
|
||||
args.settings.python_platform,
|
||||
args.settings.strict,
|
||||
|
|
|
|||
|
|
@ -1307,6 +1307,7 @@ pub(crate) struct PipInstallSettings {
|
|||
pub(crate) dry_run: bool,
|
||||
pub(crate) constraints_from_workspace: Vec<Requirement>,
|
||||
pub(crate) overrides_from_workspace: Vec<Requirement>,
|
||||
pub(crate) modifications: Modifications,
|
||||
pub(crate) refresh: Refresh,
|
||||
pub(crate) settings: PipSettings,
|
||||
}
|
||||
|
|
@ -1320,16 +1321,16 @@ impl PipInstallSettings {
|
|||
editable,
|
||||
constraint,
|
||||
r#override,
|
||||
build_constraint,
|
||||
extra,
|
||||
all_extras,
|
||||
no_all_extras,
|
||||
build_constraint,
|
||||
installer,
|
||||
refresh,
|
||||
no_deps,
|
||||
deps,
|
||||
require_hashes,
|
||||
no_require_hashes,
|
||||
installer,
|
||||
verify_hashes,
|
||||
no_verify_hashes,
|
||||
python,
|
||||
|
|
@ -1345,6 +1346,8 @@ impl PipInstallSettings {
|
|||
only_binary,
|
||||
python_version,
|
||||
python_platform,
|
||||
inexact,
|
||||
exact,
|
||||
strict,
|
||||
no_strict,
|
||||
dry_run,
|
||||
|
|
@ -1398,6 +1401,11 @@ impl PipInstallSettings {
|
|||
dry_run,
|
||||
constraints_from_workspace,
|
||||
overrides_from_workspace,
|
||||
modifications: if flag(exact, inexact).unwrap_or(false) {
|
||||
Modifications::Exact
|
||||
} else {
|
||||
Modifications::Sufficient
|
||||
},
|
||||
refresh: Refresh::from(refresh),
|
||||
settings: PipSettings::combine(
|
||||
PipOptions {
|
||||
|
|
|
|||
|
|
@ -748,6 +748,64 @@ fn reinstall_incomplete() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_install_removes_extraneous_packages() -> Result<()> {
|
||||
let context = TestContext::new("3.12").with_filtered_counts();
|
||||
|
||||
// Install flask
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("flask"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved [N] packages in [TIME]
|
||||
Prepared [N] packages in [TIME]
|
||||
Installed [N] packages in [TIME]
|
||||
+ blinker==1.7.0
|
||||
+ click==8.1.7
|
||||
+ flask==3.0.2
|
||||
+ itsdangerous==2.1.2
|
||||
+ jinja2==3.1.3
|
||||
+ markupsafe==2.1.5
|
||||
+ werkzeug==3.0.1
|
||||
"###
|
||||
);
|
||||
|
||||
// Install anyio with exact flag removes flask and flask dependencies.
|
||||
let requirements_txt = context.temp_dir.child("requirements.txt");
|
||||
requirements_txt.write_str("anyio==3.7.0")?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.pip_install()
|
||||
.arg("--exact")
|
||||
.arg("-r")
|
||||
.arg("requirements.txt"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved [N] packages in [TIME]
|
||||
Prepared [N] packages in [TIME]
|
||||
Uninstalled [N] packages in [TIME]
|
||||
Installed [N] packages in [TIME]
|
||||
+ anyio==3.7.0
|
||||
- blinker==1.7.0
|
||||
- click==8.1.7
|
||||
- flask==3.0.2
|
||||
+ idna==3.6
|
||||
- itsdangerous==2.1.2
|
||||
- jinja2==3.1.3
|
||||
- markupsafe==2.1.5
|
||||
+ sniffio==1.3.1
|
||||
- werkzeug==3.0.1
|
||||
"###
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Like `pip`, we (unfortunately) allow incompatible environments.
|
||||
#[test]
|
||||
fn allow_incompatibilities() -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -5444,6 +5444,10 @@ uv pip install [OPTIONS] <PACKAGE|--requirement <REQUIREMENT>|--editable <EDITAB
|
|||
|
||||
</dd><dt><code>--editable</code>, <code>-e</code> <i>editable</i></dt><dd><p>Install the editable package based on the provided local file path</p>
|
||||
|
||||
</dd><dt><code>--exact</code></dt><dd><p>Perform an exact sync, removing extraneous packages.</p>
|
||||
|
||||
<p>By default, installing will make the minimum necessary changes to satisfy the requirements. When enabled, uv will update the environment to exactly match the requirements, removing packages that are not included in the requirements.</p>
|
||||
|
||||
</dd><dt><code>--exclude-newer</code> <i>exclude-newer</i></dt><dd><p>Limit candidate packages to those that were uploaded prior to the given date.</p>
|
||||
|
||||
<p>Accepts both RFC 3339 timestamps (e.g., <code>2006-12-02T02:07:43Z</code>) and local dates in the same format (e.g., <code>2006-12-02</code>) in your system’s configured time zone.</p>
|
||||
|
|
|
|||
Loading…
Reference in New Issue