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.