Skip to content

Commit

Permalink
feat: add one safe_compatible version specifiers saving strategy (fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tkzt authored Nov 27, 2024
1 parent 8573f95 commit 2631439
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 3 deletions.
1 change: 1 addition & 0 deletions news/3301.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add one `safe_compatible` version specifiers saving strategy.
7 changes: 7 additions & 0 deletions src/pdm/cli/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,13 @@ def no_isolation_option(
const="compatible",
help="Save compatible version specifiers",
)
_save_sub_group.add_argument(
"--save-safe-compatible",
action="store_const",
dest="save_strategy",
const="safe_compatible",
help="Save safe compatible version specifiers",
)
_save_sub_group.add_argument(
"--save-wildcard",
action="store_const",
Expand Down
9 changes: 6 additions & 3 deletions src/pdm/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def save_version_specifiers(
:param requirements: the requirements to be updated
:param resolved: the resolved mapping
:param save_strategy: compatible/wildcard/exact
:param save_strategy: compatible/safe_compatible/wildcard/exact
"""

def candidate_version(candidates: list[Candidate]) -> Version | None:
Expand All @@ -566,11 +566,14 @@ def candidate_version(candidates: list[Candidate]) -> Version | None:
continue
if save_strategy == "exact":
r.specifier = get_specifier(f"=={version}")
elif save_strategy == "compatible":
elif save_strategy in ["compatible", "safe_compatible"]:
if version.is_prerelease or version.is_devrelease:
r.specifier = get_specifier(f">={version},<{version.major + 1}")
else:
r.specifier = get_specifier(f"~={version.major}.{version.minor}")
if save_strategy == "compatible":
r.specifier = get_specifier(f"~={version.major}.{version.minor}")
else:
r.specifier = get_specifier(f"~={version}")
elif save_strategy == "minimum":
r.specifier = get_specifier(f">={version}")

Expand Down
8 changes: 8 additions & 0 deletions tests/cli/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ def test_update_ignore_constraints(project, repository, pdm):
assert project.pyproject.metadata["dependencies"] == ["pytz~=2020.2"]
assert project.get_locked_repository().candidates["pytz"].version == "2020.2"

pdm(["add", "chardet"], obj=project, strict=True)
assert "chardet~=3.0" in project.pyproject.metadata["dependencies"]
assert project.get_locked_repository().candidates["chardet"].version == "3.0.4"
repository.add_candidate("chardet", "3.0.6")

pdm(["update", "chardet", "--unconstrained", "--save-safe-compatible"], obj=project, strict=True)
assert "chardet~=3.0.6" in project.pyproject.metadata["dependencies"]


@pytest.mark.usefixtures("working_set")
@pytest.mark.parametrize("strategy", ["reuse", "all"])
Expand Down

0 comments on commit 2631439

Please sign in to comment.