mirror of https://github.com/astral-sh/uv
Avoid overwriting dependencies with different markers in `uv add` (#6010)
## Summary Splitting out https://github.com/astral-sh/uv/pull/6005 ## Test Plan `cargo test` --------- Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
parent
92ff120983
commit
3a46e48f93
|
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
|
|
||||||
use pep440_rs::{Version, VersionSpecifier, VersionSpecifiers};
|
use pep440_rs::{Version, VersionSpecifier, VersionSpecifiers};
|
||||||
use pep508_rs::{ExtraName, PackageName, Requirement, VersionOrUrl};
|
use pep508_rs::{ExtraName, MarkerTree, PackageName, Requirement, VersionOrUrl};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use toml_edit::{Array, DocumentMut, Item, RawString, Table, TomlError, Value};
|
use toml_edit::{Array, DocumentMut, Item, RawString, Table, TomlError, Value};
|
||||||
use uv_fs::PortablePath;
|
use uv_fs::PortablePath;
|
||||||
|
|
@ -343,7 +343,7 @@ impl PyProjectTomlMut {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all occurrences of dependencies with the given name.
|
/// Removes all occurrences of dependencies with the given name.
|
||||||
pub fn remove_dependency(&mut self, req: &PackageName) -> Result<Vec<Requirement>, Error> {
|
pub fn remove_dependency(&mut self, name: &PackageName) -> Result<Vec<Requirement>, Error> {
|
||||||
// Try to get `project.dependencies`.
|
// Try to get `project.dependencies`.
|
||||||
let Some(dependencies) = self
|
let Some(dependencies) = self
|
||||||
.doc_mut()?
|
.doc_mut()?
|
||||||
|
|
@ -354,14 +354,14 @@ impl PyProjectTomlMut {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
};
|
};
|
||||||
|
|
||||||
let requirements = remove_dependency(req, dependencies);
|
let requirements = remove_dependency(name, dependencies);
|
||||||
self.remove_source(req)?;
|
self.remove_source(name)?;
|
||||||
|
|
||||||
Ok(requirements)
|
Ok(requirements)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all occurrences of development dependencies with the given name.
|
/// Removes all occurrences of development dependencies with the given name.
|
||||||
pub fn remove_dev_dependency(&mut self, req: &PackageName) -> Result<Vec<Requirement>, Error> {
|
pub fn remove_dev_dependency(&mut self, name: &PackageName) -> Result<Vec<Requirement>, Error> {
|
||||||
// Try to get `tool.uv.dev-dependencies`.
|
// Try to get `tool.uv.dev-dependencies`.
|
||||||
let Some(dev_dependencies) = self
|
let Some(dev_dependencies) = self
|
||||||
.doc
|
.doc
|
||||||
|
|
@ -378,8 +378,8 @@ impl PyProjectTomlMut {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
};
|
};
|
||||||
|
|
||||||
let requirements = remove_dependency(req, dev_dependencies);
|
let requirements = remove_dependency(name, dev_dependencies);
|
||||||
self.remove_source(req)?;
|
self.remove_source(name)?;
|
||||||
|
|
||||||
Ok(requirements)
|
Ok(requirements)
|
||||||
}
|
}
|
||||||
|
|
@ -387,7 +387,7 @@ impl PyProjectTomlMut {
|
||||||
/// Removes all occurrences of optional dependencies in the group with the given name.
|
/// Removes all occurrences of optional dependencies in the group with the given name.
|
||||||
pub fn remove_optional_dependency(
|
pub fn remove_optional_dependency(
|
||||||
&mut self,
|
&mut self,
|
||||||
req: &PackageName,
|
name: &PackageName,
|
||||||
group: &ExtraName,
|
group: &ExtraName,
|
||||||
) -> Result<Vec<Requirement>, Error> {
|
) -> Result<Vec<Requirement>, Error> {
|
||||||
// Try to get `project.optional-dependencies.<group>`.
|
// Try to get `project.optional-dependencies.<group>`.
|
||||||
|
|
@ -403,8 +403,8 @@ impl PyProjectTomlMut {
|
||||||
return Ok(Vec::new());
|
return Ok(Vec::new());
|
||||||
};
|
};
|
||||||
|
|
||||||
let requirements = remove_dependency(req, optional_dependencies);
|
let requirements = remove_dependency(name, optional_dependencies);
|
||||||
self.remove_source(req)?;
|
self.remove_source(name)?;
|
||||||
|
|
||||||
Ok(requirements)
|
Ok(requirements)
|
||||||
}
|
}
|
||||||
|
|
@ -434,13 +434,17 @@ impl PyProjectTomlMut {
|
||||||
///
|
///
|
||||||
/// This method searches `project.dependencies`, `tool.uv.dev-dependencies`, and
|
/// This method searches `project.dependencies`, `tool.uv.dev-dependencies`, and
|
||||||
/// `tool.uv.optional-dependencies`.
|
/// `tool.uv.optional-dependencies`.
|
||||||
pub fn find_dependency(&self, name: &PackageName) -> Vec<DependencyType> {
|
pub fn find_dependency(
|
||||||
|
&self,
|
||||||
|
name: &PackageName,
|
||||||
|
marker: Option<&MarkerTree>,
|
||||||
|
) -> Vec<DependencyType> {
|
||||||
let mut types = Vec::new();
|
let mut types = Vec::new();
|
||||||
|
|
||||||
if let Some(project) = self.doc.get("project").and_then(Item::as_table) {
|
if let Some(project) = self.doc.get("project").and_then(Item::as_table) {
|
||||||
// Check `project.dependencies`.
|
// Check `project.dependencies`.
|
||||||
if let Some(dependencies) = project.get("dependencies").and_then(Item::as_array) {
|
if let Some(dependencies) = project.get("dependencies").and_then(Item::as_array) {
|
||||||
if !find_dependencies(name, dependencies).is_empty() {
|
if !find_dependencies(name, marker, dependencies).is_empty() {
|
||||||
types.push(DependencyType::Production);
|
types.push(DependencyType::Production);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +462,7 @@ impl PyProjectTomlMut {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !find_dependencies(name, dependencies).is_empty() {
|
if !find_dependencies(name, marker, dependencies).is_empty() {
|
||||||
types.push(DependencyType::Optional(extra));
|
types.push(DependencyType::Optional(extra));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +479,7 @@ impl PyProjectTomlMut {
|
||||||
.and_then(|tool| tool.get("dev-dependencies"))
|
.and_then(|tool| tool.get("dev-dependencies"))
|
||||||
.and_then(Item::as_array)
|
.and_then(Item::as_array)
|
||||||
{
|
{
|
||||||
if !find_dependencies(name, dev_dependencies).is_empty() {
|
if !find_dependencies(name, marker, dev_dependencies).is_empty() {
|
||||||
types.push(DependencyType::Dev);
|
types.push(DependencyType::Dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -500,7 +504,7 @@ pub fn add_dependency(
|
||||||
has_source: bool,
|
has_source: bool,
|
||||||
) -> Result<ArrayEdit, Error> {
|
) -> Result<ArrayEdit, Error> {
|
||||||
// Find matching dependencies.
|
// Find matching dependencies.
|
||||||
let mut to_replace = find_dependencies(&req.name, deps);
|
let mut to_replace = find_dependencies(&req.name, Some(&req.marker), deps);
|
||||||
match to_replace.as_slice() {
|
match to_replace.as_slice() {
|
||||||
[] => {
|
[] => {
|
||||||
deps.push(req.to_string());
|
deps.push(req.to_string());
|
||||||
|
|
@ -545,9 +549,9 @@ fn update_requirement(old: &mut Requirement, new: &Requirement, has_source: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all occurrences of dependencies with the given name from the given `deps` array.
|
/// Removes all occurrences of dependencies with the given name from the given `deps` array.
|
||||||
fn remove_dependency(req: &PackageName, deps: &mut Array) -> Vec<Requirement> {
|
fn remove_dependency(name: &PackageName, deps: &mut Array) -> Vec<Requirement> {
|
||||||
// Remove matching dependencies.
|
// Remove matching dependencies.
|
||||||
let removed = find_dependencies(req, deps)
|
let removed = find_dependencies(name, None, deps)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.rev() // Reverse to preserve indices as we remove them.
|
.rev() // Reverse to preserve indices as we remove them.
|
||||||
.filter_map(|(i, _)| {
|
.filter_map(|(i, _)| {
|
||||||
|
|
@ -566,11 +570,15 @@ fn remove_dependency(req: &PackageName, deps: &mut Array) -> Vec<Requirement> {
|
||||||
|
|
||||||
/// Returns a `Vec` containing the all dependencies with the given name, along with their positions
|
/// Returns a `Vec` containing the all dependencies with the given name, along with their positions
|
||||||
/// in the array.
|
/// in the array.
|
||||||
fn find_dependencies(name: &PackageName, deps: &Array) -> Vec<(usize, Requirement)> {
|
fn find_dependencies(
|
||||||
|
name: &PackageName,
|
||||||
|
marker: Option<&MarkerTree>,
|
||||||
|
deps: &Array,
|
||||||
|
) -> Vec<(usize, Requirement)> {
|
||||||
let mut to_replace = Vec::new();
|
let mut to_replace = Vec::new();
|
||||||
for (i, dep) in deps.iter().enumerate() {
|
for (i, dep) in deps.iter().enumerate() {
|
||||||
if let Some(req) = dep.as_str().and_then(try_parse_requirement) {
|
if let Some(req) = dep.as_str().and_then(try_parse_requirement) {
|
||||||
if req.name == *name {
|
if marker.map_or(true, |m| *m == req.marker) && *name == req.name {
|
||||||
to_replace.push((i, req));
|
to_replace.push((i, req));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ enum Target {
|
||||||
/// This is useful when a dependency of the user-specified type was not found, but it may be present
|
/// This is useful when a dependency of the user-specified type was not found, but it may be present
|
||||||
/// elsewhere.
|
/// elsewhere.
|
||||||
fn warn_if_present(name: &PackageName, pyproject: &PyProjectTomlMut) {
|
fn warn_if_present(name: &PackageName, pyproject: &PyProjectTomlMut) {
|
||||||
for dep_ty in pyproject.find_dependency(name) {
|
for dep_ty in pyproject.find_dependency(name, None) {
|
||||||
match dep_ty {
|
match dep_ty {
|
||||||
DependencyType::Production => {
|
DependencyType::Production => {
|
||||||
warn_user!("`{name}` is a production dependency");
|
warn_user!("`{name}` is a production dependency");
|
||||||
|
|
@ -235,7 +235,7 @@ fn warn_if_present(name: &PackageName, pyproject: &PyProjectTomlMut) {
|
||||||
}
|
}
|
||||||
DependencyType::Optional(group) => {
|
DependencyType::Optional(group) => {
|
||||||
warn_user!(
|
warn_user!(
|
||||||
"`{name}` is an optional dependency; try calling `uv remove --optional {group}`"
|
"`{name}` is an optional dependency; try calling `uv remove --optional {group}`",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1770,7 +1770,8 @@ fn update() -> Result<()> {
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_full_version >= '3.8'",
|
"requests[security]==2.31.0",
|
||||||
|
"requests[socks,use-chardet-on-py3]>=2.31.0 ; python_full_version >= '3.8'",
|
||||||
]
|
]
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
@ -1808,7 +1809,8 @@ fn update() -> Result<()> {
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"requests[security,socks,use-chardet-on-py3]==2.31.0 ; python_full_version >= '3.8'",
|
"requests[security]==2.31.0",
|
||||||
|
"requests[socks,use-chardet-on-py3]>=2.31.0 ; python_full_version >= '3.8'",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.uv.sources]
|
[tool.uv.sources]
|
||||||
|
|
@ -1890,7 +1892,10 @@ fn update() -> Result<()> {
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [{ name = "requests", extras = ["security", "socks", "use-chardet-on-py3"], marker = "python_full_version >= '3.8'", git = "https://github.com/psf/requests?tag=v2.32.3" }]
|
requires-dist = [
|
||||||
|
{ name = "requests", extras = ["security"], git = "https://github.com/psf/requests?tag=v2.32.3" },
|
||||||
|
{ name = "requests", extras = ["socks", "use-chardet-on-py3"], marker = "python_full_version >= '3.8'", git = "https://github.com/psf/requests?tag=v2.32.3" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pysocks"
|
name = "pysocks"
|
||||||
|
|
@ -1946,6 +1951,241 @@ fn update() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add and update a requirement, with different markers
|
||||||
|
#[test]
|
||||||
|
fn add_update_marker() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.30; python_version >= '3.11'"
|
||||||
|
]
|
||||||
|
"#})?;
|
||||||
|
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv lock` is experimental and may change without warning
|
||||||
|
Resolved 6 packages in [TIME]
|
||||||
|
"###);
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.sync().arg("--frozen"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv sync` is experimental and may change without warning
|
||||||
|
Prepared 6 packages in [TIME]
|
||||||
|
Installed 6 packages in [TIME]
|
||||||
|
+ certifi==2024.2.2
|
||||||
|
+ charset-normalizer==3.3.2
|
||||||
|
+ idna==3.6
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ requests==2.31.0
|
||||||
|
+ urllib3==2.2.1
|
||||||
|
"###);
|
||||||
|
|
||||||
|
// Restrict the `requests` version for Python <3.11
|
||||||
|
uv_snapshot!(context.filters(), context.add(&["requests>=2.0,<2.29; python_version < '3.11'"]), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv add` is experimental and may change without warning
|
||||||
|
Resolved 8 packages in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Uninstalled 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
- project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
|
||||||
|
// Should add a new line for the dependency since the marker does not match an existing one
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject_toml, @r###"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.30; python_version >= '3.11'",
|
||||||
|
"requests>=2.0,<2.29 ; python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change the restricted `requests` version for Python <3.11
|
||||||
|
uv_snapshot!(context.filters(), context.add(&["requests>=2.0,<2.20; python_version < '3.11'"]), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv add` is experimental and may change without warning
|
||||||
|
Resolved 10 packages in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Uninstalled 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
- project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
|
||||||
|
// Should mutate the existing dependency since the marker matches
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject_toml, @r###"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.30; python_version >= '3.11'",
|
||||||
|
"requests>=2.0,<2.20 ; python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restrict the `requests` version on Windows and Python >3.11
|
||||||
|
uv_snapshot!(context.filters(), context.add(&["requests>=2.31 ; sys_platform == 'win32' and python_version > '3.11'"]), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv add` is experimental and may change without warning
|
||||||
|
Resolved 8 packages in [TIME]
|
||||||
|
Prepared 3 packages in [TIME]
|
||||||
|
Uninstalled 3 packages in [TIME]
|
||||||
|
Installed 3 packages in [TIME]
|
||||||
|
- idna==3.6
|
||||||
|
+ idna==2.7
|
||||||
|
- project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
- urllib3==2.2.1
|
||||||
|
+ urllib3==1.23
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
|
||||||
|
// Should add a new line for the dependency since the marker does not match an existing one
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject_toml, @r###"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.30; python_version >= '3.11'",
|
||||||
|
"requests>=2.0,<2.20 ; python_full_version < '3.11'",
|
||||||
|
"requests>=2.31 ; python_full_version >= '3.12' and sys_platform == 'win32'",
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restrict the `requests` version on Windows
|
||||||
|
uv_snapshot!(context.filters(), context.add(&["requests>=2.10 ; sys_platform == 'win32'"]), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv add` is experimental and may change without warning
|
||||||
|
Resolved 8 packages in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Uninstalled 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
- project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
|
||||||
|
// Should add a new line for the dependency since the marker does not exactly match an existing
|
||||||
|
// one — although it is a subset of the existing marker.
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject_toml, @r###"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.30; python_version >= '3.11'",
|
||||||
|
"requests>=2.0,<2.20 ; python_full_version < '3.11'",
|
||||||
|
"requests>=2.31 ; python_full_version >= '3.12' and sys_platform == 'win32'",
|
||||||
|
"requests>=2.10 ; sys_platform == 'win32'",
|
||||||
|
]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove `requests`
|
||||||
|
uv_snapshot!(context.filters(), context.remove(&["requests"]), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv remove` is experimental and may change without warning
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Uninstalled 6 packages in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
- certifi==2024.2.2
|
||||||
|
- charset-normalizer==3.3.2
|
||||||
|
- idna==2.7
|
||||||
|
- project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
+ project==0.1.0 (from file://[TEMP_DIR]/)
|
||||||
|
- requests==2.31.0
|
||||||
|
- urllib3==1.23
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let pyproject_toml = fs_err::read_to_string(context.temp_dir.join("pyproject.toml"))?;
|
||||||
|
|
||||||
|
// Should remove all variants of `requests`
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => context.filters(),
|
||||||
|
}, {
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject_toml, @r###"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
dependencies = []
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
fn update_source_replace_url() -> Result<()> {
|
fn update_source_replace_url() -> Result<()> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue