From 475e8c64a9c802506bcb1ec2866d3daf8c174822 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Thu, 25 May 2023 18:40:48 -0400 Subject: [PATCH 01/12] Moving "poetry lock --check" to "poetry check --lock" --- src/poetry/console/commands/check.py | 25 +++++++++ src/poetry/console/commands/lock.py | 7 ++- tests/console/commands/test_check.py | 84 ++++++++++++++++++++++++++++ tests/console/commands/test_lock.py | 10 +++- 4 files changed, 123 insertions(+), 3 deletions(-) diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py index 3ca831e7213..54a89d44969 100644 --- a/src/poetry/console/commands/check.py +++ b/src/poetry/console/commands/check.py @@ -1,5 +1,7 @@ from __future__ import annotations +from cleo.helpers import option + from poetry.console.commands.command import Command @@ -7,6 +9,17 @@ class CheckCommand(Command): name = "check" description = "Checks the validity of the pyproject.toml file." + options = [ + option( + "lock", + None, + ( + "Check that the poetry.lock file corresponds to the current" + " version of pyproject.toml." + ), + ), + ] + def validate_classifiers( self, project_classifiers: set[str] ) -> tuple[list[str], list[str]]: @@ -58,6 +71,18 @@ def validate_classifiers( return errors, warnings def handle(self) -> int: + if self.option("lock"): + if self.poetry.locker.is_locked() and self.poetry.locker.is_fresh(): + self.line("poetry.lock is consistent with pyproject.toml.") + return 0 + self.line_error( + "" + "Error: poetry.lock is not consistent with pyproject.toml. " + "Run `poetry lock [--no-update]` to fix it." + "" + ) + return 1 + from poetry.factory import Factory from poetry.pyproject.toml import PyProjectTOML diff --git a/src/poetry/console/commands/lock.py b/src/poetry/console/commands/lock.py index c87f1359dc7..87273a66776 100644 --- a/src/poetry/console/commands/lock.py +++ b/src/poetry/console/commands/lock.py @@ -18,7 +18,8 @@ class LockCommand(InstallerCommand): None, ( "Check that the poetry.lock file corresponds to the current" - " version of pyproject.toml." + " version of pyproject.toml. (Deprecated) Use" + " poetry check --lock instead." ), ), ] @@ -36,6 +37,10 @@ class LockCommand(InstallerCommand): def handle(self) -> int: if self.option("check"): + self.line_error( + "poetry lock --check is deprecated, use `poetry" + " check --lock` instead." + ) if self.poetry.locker.is_locked() and self.poetry.locker.is_fresh(): self.line("poetry.lock is consistent with pyproject.toml.") return 0 diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py index 323364c8def..890a631edac 100644 --- a/tests/console/commands/test_check.py +++ b/tests/console/commands/test_check.py @@ -4,13 +4,19 @@ import pytest +from poetry.packages import Locker + if TYPE_CHECKING: + import httpretty + from cleo.testers.command_tester import CommandTester from pytest_mock import MockerFixture + from poetry.poetry import Poetry from tests.types import CommandTesterFactory from tests.types import FixtureDirGetter + from tests.types import ProjectFactory @pytest.fixture() @@ -18,6 +24,36 @@ def tester(command_tester_factory: CommandTesterFactory) -> CommandTester: return command_tester_factory("check") +def _project_factory( + fixture_name: str, + project_factory: ProjectFactory, + fixture_dir: FixtureDirGetter, +) -> Poetry: + source = fixture_dir(fixture_name) + pyproject_content = (source / "pyproject.toml").read_text(encoding="utf-8") + poetry_lock_content = (source / "poetry.lock").read_text(encoding="utf-8") + return project_factory( + name="foobar", + pyproject_content=pyproject_content, + poetry_lock_content=poetry_lock_content, + source=source, + ) + + +@pytest.fixture +def poetry_with_outdated_lockfile( + project_factory: ProjectFactory, fixture_dir: FixtureDirGetter +) -> Poetry: + return _project_factory("outdated_lock", project_factory, fixture_dir) + + +@pytest.fixture +def poetry_with_up_to_date_lockfile( + project_factory: ProjectFactory, fixture_dir: FixtureDirGetter +) -> Poetry: + return _project_factory("up_to_date_lock", project_factory, fixture_dir) + + def test_check_valid(tester: CommandTester) -> None: tester.execute() @@ -74,3 +110,51 @@ def test_check_private( """ assert tester.io.fetch_output() == expected + + +def test_lock_check_outdated( + command_tester_factory: CommandTesterFactory, + poetry_with_outdated_lockfile: Poetry, + http: type[httpretty.httpretty], +) -> None: + http.disable() + + locker = Locker( + lock=poetry_with_outdated_lockfile.pyproject.file.path.parent / "poetry.lock", + local_config=poetry_with_outdated_lockfile.locker._local_config, + ) + poetry_with_outdated_lockfile.set_locker(locker) + + tester = command_tester_factory("check", poetry=poetry_with_outdated_lockfile) + status_code = tester.execute("--lock") + expected = ( + "Error: poetry.lock is not consistent with pyproject.toml. " + "Run `poetry lock [--no-update]` to fix it.\n" + ) + + assert tester.io.fetch_error() == expected + + # exit with an error + assert status_code == 1 + + +def test_lock_check_up_to_date( + command_tester_factory: CommandTesterFactory, + poetry_with_up_to_date_lockfile: Poetry, + http: type[httpretty.httpretty], +) -> None: + http.disable() + + locker = Locker( + lock=poetry_with_up_to_date_lockfile.pyproject.file.path.parent / "poetry.lock", + local_config=poetry_with_up_to_date_lockfile.locker._local_config, + ) + poetry_with_up_to_date_lockfile.set_locker(locker) + + tester = command_tester_factory("check", poetry=poetry_with_up_to_date_lockfile) + status_code = tester.execute("--lock") + expected = "poetry.lock is consistent with pyproject.toml.\n" + assert tester.io.fetch_output() == expected + + # exit with an error + assert status_code == 0 diff --git a/tests/console/commands/test_lock.py b/tests/console/commands/test_lock.py index 7a910caccf7..26e0b98277c 100644 --- a/tests/console/commands/test_lock.py +++ b/tests/console/commands/test_lock.py @@ -89,7 +89,7 @@ def poetry_with_invalid_lockfile( return _project_factory("invalid_lock", project_factory, fixture_dir) -def test_lock_check_outdated( +def test_lock_check_outdated_legacy( command_tester_factory: CommandTesterFactory, poetry_with_outdated_lockfile: Poetry, http: type[httpretty.httpretty], @@ -105,6 +105,7 @@ def test_lock_check_outdated( tester = command_tester_factory("lock", poetry=poetry_with_outdated_lockfile) status_code = tester.execute("--check") expected = ( + "poetry lock --check is deprecated, use `poetry check --lock` instead.\n" "Error: poetry.lock is not consistent with pyproject.toml. " "Run `poetry lock [--no-update]` to fix it.\n" ) @@ -115,7 +116,7 @@ def test_lock_check_outdated( assert status_code == 1 -def test_lock_check_up_to_date( +def test_lock_check_up_to_date_legacy( command_tester_factory: CommandTesterFactory, poetry_with_up_to_date_lockfile: Poetry, http: type[httpretty.httpretty], @@ -133,6 +134,11 @@ def test_lock_check_up_to_date( expected = "poetry.lock is consistent with pyproject.toml.\n" assert tester.io.fetch_output() == expected + expected_error = ( + "poetry lock --check is deprecated, use `poetry check --lock` instead.\n" + ) + assert tester.io.fetch_error() == expected_error + # exit with an error assert status_code == 0 From bc7f2b8937d126ed680dac88f1b68686470d840c Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Thu, 25 May 2023 18:48:47 -0400 Subject: [PATCH 02/12] Updating Docs to use poetry lock --check --- docs/cli.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index b5913b69040..93ab4986eb1 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -636,6 +636,10 @@ This command is also available as a pre-commit hook. See [pre-commit hooks]({{< poetry check ``` +### Options + +* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. + ## search This command searches for packages on a remote index. @@ -659,7 +663,7 @@ poetry lock ### Options -* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml` +* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. (**Deprecated**) Use `poetry check --lock` instead. * `--no-update`: Do not update locked versions, only refresh lock file. ## version @@ -944,7 +948,7 @@ poetry self lock #### Options -* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml` +* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. (**Deprecated**) Use `poetry check --lock` instead. * `--no-update`: Do not update locked versions, only refresh lock file. ### self show From b3b5270b0fbd25b955f59d8a3786c70a0234e17d Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Thu, 25 May 2023 18:49:15 -0400 Subject: [PATCH 03/12] Updating GH Action Workflow to use poetry lock --check --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 23508592e2c..d6487b91713 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,7 +90,7 @@ jobs: timeout 10s poetry run pip --version || rm -rf .venv - name: Check lock file - run: poetry lock --check + run: poetry check --lock - name: Install dependencies run: poetry install --with github-actions From b708f9d4066e3a150a14c58c9611b75027b28eb1 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Thu, 25 May 2023 19:10:13 -0400 Subject: [PATCH 04/12] Reverting b3b5270b0fbd25b955f59d8a3786c70a0234e17d to make CI pass --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d6487b91713..23508592e2c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,7 +90,7 @@ jobs: timeout 10s poetry run pip --version || rm -rf .venv - name: Check lock file - run: poetry check --lock + run: poetry lock --check - name: Install dependencies run: poetry install --with github-actions From ed67a838965d83f749c059c05bf44329448159aa Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Fri, 26 May 2023 08:32:12 -0400 Subject: [PATCH 05/12] fix: typo in docs --- docs/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli.md b/docs/cli.md index 93ab4986eb1..cb339609656 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -638,7 +638,7 @@ poetry check ### Options -* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. +* `--lock`: Verify that `poetry.lock` is consistent with `pyproject.toml`. ## search From e0fab00d9dad3e7f82979b47c475d48814c4c127 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:54:17 -0400 Subject: [PATCH 06/12] Update check command description to match docs --- src/poetry/console/commands/check.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py index 54a89d44969..84179362a70 100644 --- a/src/poetry/console/commands/check.py +++ b/src/poetry/console/commands/check.py @@ -7,7 +7,10 @@ class CheckCommand(Command): name = "check" - description = "Checks the validity of the pyproject.toml file." + description = ( + "Validates the structure of the pyproject.toml file and returns a" + " detailed report if there are any errors." + ) options = [ option( From 6125b6a18cdbb7aa1ef8386fcbbe461f3ac81d52 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:56:15 -0400 Subject: [PATCH 07/12] Incorporating suggestions --- docs/cli.md | 2 +- src/poetry/console/commands/check.py | 23 ++++++++++------------- tests/console/commands/test_check.py | 9 +++++---- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index cb339609656..463cce458a7 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -638,7 +638,7 @@ poetry check ### Options -* `--lock`: Verify that `poetry.lock` is consistent with `pyproject.toml`. +* `--lock`: Verifies that `poetry.lock` exists for the current `pyproject.toml`. ## search diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py index 84179362a70..12664d1a411 100644 --- a/src/poetry/console/commands/check.py +++ b/src/poetry/console/commands/check.py @@ -17,7 +17,7 @@ class CheckCommand(Command): "lock", None, ( - "Check that the poetry.lock file corresponds to the current" + "Checks that poetry.lock exists for the current" " version of pyproject.toml." ), ), @@ -74,18 +74,6 @@ def validate_classifiers( return errors, warnings def handle(self) -> int: - if self.option("lock"): - if self.poetry.locker.is_locked() and self.poetry.locker.is_fresh(): - self.line("poetry.lock is consistent with pyproject.toml.") - return 0 - self.line_error( - "" - "Error: poetry.lock is not consistent with pyproject.toml. " - "Run `poetry lock [--no-update]` to fix it." - "" - ) - return 1 - from poetry.factory import Factory from poetry.pyproject.toml import PyProjectTOML @@ -100,6 +88,15 @@ def handle(self) -> int: check_result["errors"].extend(errors) check_result["warnings"].extend(warnings) + # Verify that lock file is consistent + if self.option("lock") and not self.poetry.locker.is_locked(): + check_result["errors"] += ["poetry.lock was not found."] + if self.poetry.locker.is_locked() and not self.poetry.locker.is_fresh(): + check_result["errors"] += [ + "poetry.lock is not consistent with pyproject.toml. Run `poetry" + " lock [--no-update]` to fix it." + ] + if not check_result["errors"] and not check_result["warnings"]: self.info("All set!") diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py index 890a631edac..d4e5eecc96b 100644 --- a/tests/console/commands/test_check.py +++ b/tests/console/commands/test_check.py @@ -75,12 +75,13 @@ def test_check_invalid( new_callable=mocker.PropertyMock, ) - tester.execute() + tester.execute("--lock") expected = """\ Error: 'description' is a required property Error: Project name (invalid) is same as one of its dependencies Error: Unrecognized classifiers: ['Intended Audience :: Clowns']. +Error: poetry.lock was not found. Warning: A wildcard Python dependency is ambiguous.\ Consider specifying a more explicit one. Warning: The "pendulum" dependency specifies the "allows-prereleases" property,\ @@ -112,7 +113,7 @@ def test_check_private( assert tester.io.fetch_output() == expected -def test_lock_check_outdated( +def test_check_lock_outdated( command_tester_factory: CommandTesterFactory, poetry_with_outdated_lockfile: Poetry, http: type[httpretty.httpretty], @@ -138,7 +139,7 @@ def test_lock_check_outdated( assert status_code == 1 -def test_lock_check_up_to_date( +def test_check_lock_up_to_date( command_tester_factory: CommandTesterFactory, poetry_with_up_to_date_lockfile: Poetry, http: type[httpretty.httpretty], @@ -153,7 +154,7 @@ def test_lock_check_up_to_date( tester = command_tester_factory("check", poetry=poetry_with_up_to_date_lockfile) status_code = tester.execute("--lock") - expected = "poetry.lock is consistent with pyproject.toml.\n" + expected = "All set!\n" assert tester.io.fetch_output() == expected # exit with an error From 8aab9f41a7076f94e6737db2a64f6f8472752e33 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Sun, 11 Jun 2023 16:53:53 -0400 Subject: [PATCH 08/12] docs: improve description in check command --- src/poetry/console/commands/check.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py index 12664d1a411..733f0a7c5d5 100644 --- a/src/poetry/console/commands/check.py +++ b/src/poetry/console/commands/check.py @@ -8,8 +8,8 @@ class CheckCommand(Command): name = "check" description = ( - "Validates the structure of the pyproject.toml file and returns a" - " detailed report if there are any errors." + "Validates the content of the pyproject.toml file and its" + " consistency with the poetry.lock file." ) options = [ From dc4e667f94dc702c9210fd2d9a387890bf9a6a74 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Sun, 11 Jun 2023 17:00:38 -0400 Subject: [PATCH 09/12] docs: improve description in self lock command --- docs/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli.md b/docs/cli.md index 463cce458a7..3fafb4b76c8 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -948,7 +948,7 @@ poetry self lock #### Options -* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. (**Deprecated**) Use `poetry check --lock` instead. +* `--check`: Verify that `poetry.lock` is consistent with `pyproject.toml`. (**Deprecated**) * `--no-update`: Do not update locked versions, only refresh lock file. ### self show From 275ff17fc269c79d21805b6f5e3c1a1850f8c808 Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:41:07 -0400 Subject: [PATCH 10/12] parametrize check tests --- tests/console/commands/test_check.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py index d4e5eecc96b..13323ee28be 100644 --- a/tests/console/commands/test_check.py +++ b/tests/console/commands/test_check.py @@ -113,10 +113,12 @@ def test_check_private( assert tester.io.fetch_output() == expected +@pytest.mark.parametrize("options", ["", "--lock"]) def test_check_lock_outdated( command_tester_factory: CommandTesterFactory, poetry_with_outdated_lockfile: Poetry, http: type[httpretty.httpretty], + options: str, ) -> None: http.disable() @@ -127,7 +129,7 @@ def test_check_lock_outdated( poetry_with_outdated_lockfile.set_locker(locker) tester = command_tester_factory("check", poetry=poetry_with_outdated_lockfile) - status_code = tester.execute("--lock") + status_code = tester.execute(options) expected = ( "Error: poetry.lock is not consistent with pyproject.toml. " "Run `poetry lock [--no-update]` to fix it.\n" @@ -139,10 +141,12 @@ def test_check_lock_outdated( assert status_code == 1 +@pytest.mark.parametrize("options", ["", "--lock"]) def test_check_lock_up_to_date( command_tester_factory: CommandTesterFactory, poetry_with_up_to_date_lockfile: Poetry, http: type[httpretty.httpretty], + options: str, ) -> None: http.disable() @@ -153,7 +157,7 @@ def test_check_lock_up_to_date( poetry_with_up_to_date_lockfile.set_locker(locker) tester = command_tester_factory("check", poetry=poetry_with_up_to_date_lockfile) - status_code = tester.execute("--lock") + status_code = tester.execute(options) expected = "All set!\n" assert tester.io.fetch_output() == expected From a801b7453faccf3bda1e2010e1934c315aeecc5e Mon Sep 17 00:00:00 2001 From: samypr100 <3933065+samypr100@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:01:17 -0400 Subject: [PATCH 11/12] adding additional tests --- tests/console/commands/test_check.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py index 13323ee28be..6347d4585fb 100644 --- a/tests/console/commands/test_check.py +++ b/tests/console/commands/test_check.py @@ -113,6 +113,39 @@ def test_check_private( assert tester.io.fetch_output() == expected +@pytest.mark.parametrize( + ("options", "expected", "expected_status"), + [ + ("", "All set!\n", 0), + ("--lock", "Error: poetry.lock was not found.\n", 1), + ], +) +def test_check_lock_missing( + mocker: MockerFixture, + tester: CommandTester, + fixture_dir: FixtureDirGetter, + options: str, + expected: str, + expected_status: int, +) -> None: + from poetry.toml import TOMLFile + + mocker.patch( + "poetry.poetry.Poetry.file", + return_value=TOMLFile(fixture_dir("private_pyproject") / "pyproject.toml"), + new_callable=mocker.PropertyMock, + ) + + status_code = tester.execute(options) + + assert status_code == expected_status + + if status_code == 0: + assert tester.io.fetch_output() == expected + else: + assert tester.io.fetch_error() == expected + + @pytest.mark.parametrize("options", ["", "--lock"]) def test_check_lock_outdated( command_tester_factory: CommandTesterFactory, From e7e0b0858187432cb2a782d3d82a5fbd25537b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:33:54 +0200 Subject: [PATCH 12/12] update description analogous to cli help --- docs/cli.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index 3fafb4b76c8..5a5fd878f7e 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -625,8 +625,9 @@ As such, `exit` should be used to properly exit the shell and the virtual enviro ## check -The `check` command validates the structure of the `pyproject.toml` file -and returns a detailed report if there are any errors. +The `check` command validates the content of the `pyproject.toml` file +and its consistency with the `poetry.lock` file. +It returns a detailed report if there are any errors. {{% note %}} This command is also available as a pre-commit hook. See [pre-commit hooks]({{< relref "pre-commit-hooks#poetry-check">}}) for more information.