diff --git a/news/225.feature b/news/225.feature new file mode 100644 index 0000000000000000000000000000000000000000..820e5edf4a44362f130df04add526a7faa3d2667 --- /dev/null +++ b/news/225.feature @@ -0,0 +1 @@ +Change the behavior of `--save-compatible` slightly. Now the version specifier saved is using the REAL compatible operator `~=` as described in PEP 440. Before: `requests<3.0.0,>=2.19.1`, After: `requests~=2.19`. The new specifier accepts `requests==2.19.0` as compatible version. diff --git a/news/226.feature.rst b/news/226.feature similarity index 100% rename from news/226.feature.rst rename to news/226.feature diff --git a/news/227.doc.rst b/news/227.doc similarity index 100% rename from news/227.doc.rst rename to news/227.doc diff --git a/pdm/cli/utils.py b/pdm/cli/utils.py index d1526e81cc8650819a156f135f58558a8f2ed45a..bc05ebfde4a8e00626720f8c03b45dbeca749823 100644 --- a/pdm/cli/utils.py +++ b/pdm/cli/utils.py @@ -19,7 +19,7 @@ from pdm.formats.base import make_inline_table from pdm.iostream import stream from pdm.models.environment import WorkingSet from pdm.models.requirements import Requirement, strip_extras -from pdm.models.specifiers import bump_version, get_specifier +from pdm.models.specifiers import get_specifier from pdm.project import Project if TYPE_CHECKING: @@ -376,10 +376,8 @@ def save_version_specifiers( r.specifier = get_specifier(f"=={resolved[name].version}") elif save_strategy == "compatible": version = str(resolved[name].version) - next_major_version = ".".join( - map(str, bump_version(tuple(version.split(".")), 0)) - ) - r.specifier = get_specifier(f">={version},<{next_major_version}") + compatible_version = ".".join((version.split(".") + ["0"])[:2]) + r.specifier = get_specifier(f"~={compatible_version}") def check_project_file(project: Project) -> None: diff --git a/tests/cli/test_actions.py b/tests/cli/test_actions.py index f6f463415849aab14f3b4eb3eebd186bc914ed95..eedb7650e761ca17b6b59bfc2aefaedb5798d16b 100644 --- a/tests/cli/test_actions.py +++ b/tests/cli/test_actions.py @@ -76,7 +76,7 @@ def test_add_package(project, repository, working_set, is_dev): actions.do_add(project, is_dev, packages=["requests"]) section = "dev-dependencies" if is_dev else "dependencies" - assert project.meta[section][0] == "requests<3.0.0,>=2.19.1" + assert project.meta[section][0] == "requests~=2.19" locked_candidates = project.get_locked_candidates("dev" if is_dev else "default") assert locked_candidates["idna"].version == "2.7" for package in ("requests", "idna", "chardet", "urllib3", "certifi"): @@ -435,15 +435,15 @@ def test_update_unconstrained_without_packages(project, repository, working_set) def test_update_ignore_constraints(project, repository, working_set): actions.do_add(project, packages=("pytz",)) - assert project.meta.dependencies == ["pytz<2020.0.0,>=2019.3"] + assert project.meta.dependencies == ["pytz~=2019.3"] repository.add_candidate("pytz", "2020.2") actions.do_update(project, unconstrained=False, packages=("pytz",)) - assert project.meta.dependencies == ["pytz<2020.0.0,>=2019.3"] + assert project.meta.dependencies == ["pytz~=2019.3"] assert project.get_locked_candidates()["pytz"].version == "2019.3" actions.do_update(project, unconstrained=True, packages=("pytz",)) - assert project.meta.dependencies == ["pytz<2021.0.0,>=2020.2"] + assert project.meta.dependencies == ["pytz~=2020.2"] assert project.get_locked_candidates()["pytz"].version == "2020.2"