From e272527842f70791aa640ec6e9cebbf4be674186 Mon Sep 17 00:00:00 2001
From: "Y.D.X" <73375426+YDX-2147483647@users.noreply.github.com>
Date: Tue, 31 Jan 2023 20:29:36 +0800
Subject: [PATCH 1/5] poetry check command validates readme (files must exist)
Resolves: #6937
---
src/poetry/console/commands/check.py | 28 +++++++++++++++++++
tests/console/commands/test_check.py | 1 +
.../fixtures/invalid_pyproject/pyproject.toml | 1 +
3 files changed, 30 insertions(+)
diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py
index 8a53cd5bc09..b646b20c164 100644
--- a/src/poetry/console/commands/check.py
+++ b/src/poetry/console/commands/check.py
@@ -1,8 +1,14 @@
from __future__ import annotations
+from typing import TYPE_CHECKING
+
from poetry.console.commands.command import Command
+if TYPE_CHECKING:
+ from pathlib import Path
+
+
class CheckCommand(Command):
name = "check"
description = "Checks the validity of the pyproject.toml file."
@@ -57,6 +63,22 @@ def validate_classifiers(
return errors, warnings
+ def validate_readme(
+ self, readme: str | list[str], poetry_file: Path
+ ) -> tuple[list[str], list[str]]:
+ """Check existence of referenced readme files"""
+
+ errors = []
+ warnings: list[str] = []
+
+ readmes = [readme] if isinstance(readme, str) else readme
+
+ for name in readmes:
+ if not (poetry_file.parent / name).exists():
+ errors.append(f"Declared README file must exist: found {name}")
+
+ return errors, warnings
+
def handle(self) -> int:
from poetry.core.pyproject.toml import PyProjectTOML
@@ -73,6 +95,12 @@ def handle(self) -> int:
check_result["errors"].extend(errors)
check_result["warnings"].extend(warnings)
+ # Validate readme (files must exist)
+ if "readme" in config:
+ errors, warnings = self.validate_readme(config["readme"], poetry_file)
+ check_result["errors"].extend(errors)
+ check_result["warnings"].extend(warnings)
+
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 dbf665b6227..49ac23ee34d 100644
--- a/tests/console/commands/test_check.py
+++ b/tests/console/commands/test_check.py
@@ -47,6 +47,7 @@ def test_check_invalid(mocker: MockerFixture, tester: CommandTester):
expected = """\
Error: 'description' is a required property
Error: Unrecognized classifiers: ['Intended Audience :: Clowns'].
+Error: Declared README file must exist: found never/exists.md
Warning: A wildcard Python dependency is ambiguous.\
Consider specifying a more explicit one.
Warning: The "pendulum" dependency specifies the "allows-prereleases" property,\
diff --git a/tests/fixtures/invalid_pyproject/pyproject.toml b/tests/fixtures/invalid_pyproject/pyproject.toml
index dfde9cd449e..3af75578ce6 100644
--- a/tests/fixtures/invalid_pyproject/pyproject.toml
+++ b/tests/fixtures/invalid_pyproject/pyproject.toml
@@ -4,6 +4,7 @@ version = "1.0.0"
authors = [
"Foo "
]
+readme = "never/exists.md"
license = "INVALID"
classifiers = [
"Environment :: Console",
From 98174c682ac3a1b879e76f5cfb9a3a658d0e2283 Mon Sep 17 00:00:00 2001
From: "Y.D.X" <73375426+YDX-2147483647@users.noreply.github.com>
Date: Tue, 31 Jan 2023 21:39:34 +0800
Subject: [PATCH 2/5] docs: case-sensitivity of readme paths
---
docs/pyproject.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/pyproject.md b/docs/pyproject.md
index 955c64d4c6a..6b8bbba8d3e 100644
--- a/docs/pyproject.md
+++ b/docs/pyproject.md
@@ -114,6 +114,12 @@ The file(s) can be of any format, but if you intend to publish to PyPI keep the
https://packaging.python.org/en/latest/guides/making-a-pypi-friendly-readme/) in
mind. README paths are implicitly relative to `pyproject.toml`.
+{{% note %}}
+Whether paths are case-sensitive follows platform defaults, but it is recommended to keep cases.
+
+To be specific, you can set `readme = "rEaDmE.mD"` for `README.md` on macOS and Windows, but Linux users can't `poetry install` after cloning your repo. This is because macOS and Windows are case-insensitive and case-preserving.
+{{% /note %}}
+
The contents of the README file(s) are used to populate the [Description
field](https://packaging.python.org/en/latest/specifications/core-metadata/#description-optional)
of your distribution's metadata (similar to `long_description` in setuptools).
From f9f4e1420c12f67b00e5df2c1e0c69dbd815d18f Mon Sep 17 00:00:00 2001
From: "Y.D.X" <73375426+YDX-2147483647@users.noreply.github.com>
Date: Sun, 11 Jun 2023 23:09:05 +0800
Subject: [PATCH 3/5] Invert the error message
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Randy Döring <30527984+radoering@users.noreply.github.com>
---
src/poetry/console/commands/check.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py
index 98664750098..24b845061c7 100644
--- a/src/poetry/console/commands/check.py
+++ b/src/poetry/console/commands/check.py
@@ -75,7 +75,7 @@ def validate_readme(
for name in readmes:
if not (poetry_file.parent / name).exists():
- errors.append(f"Declared README file must exist: found {name}")
+ errors.append(f"Declared README file does not exist: {name}")
return errors, warnings
From 8ca2c286192d9f79b502d69a025c82c4b1ddc5b9 Mon Sep 17 00:00:00 2001
From: "Y.D.X" <73375426+YDX-2147483647@users.noreply.github.com>
Date: Wed, 14 Jun 2023 22:41:05 +0800
Subject: [PATCH 4/5] fix: Update the error message of the test
---
tests/console/commands/test_check.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/console/commands/test_check.py b/tests/console/commands/test_check.py
index f9825b32d34..2e629436452 100644
--- a/tests/console/commands/test_check.py
+++ b/tests/console/commands/test_check.py
@@ -45,7 +45,7 @@ def test_check_invalid(
Error: 'description' is a required property
Error: Project name (invalid) is same as one of its dependencies
Error: Unrecognized classifiers: ['Intended Audience :: Clowns'].
-Error: Declared README file must exist: found never/exists.md
+Error: Declared README file does not exist: never/exists.md
Warning: A wildcard Python dependency is ambiguous.\
Consider specifying a more explicit one.
Warning: The "pendulum" dependency specifies the "allows-prereleases" property,\
From 6969ded957e754eafdf34912354ba4da3377e081 Mon Sep 17 00:00:00 2001
From: "Y.D.X" <73375426+YDX-2147483647@users.noreply.github.com>
Date: Fri, 16 Jun 2023 13:22:12 +0800
Subject: [PATCH 5/5] refactor: Remove unused `warnings = []`
---
src/poetry/console/commands/check.py | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/src/poetry/console/commands/check.py b/src/poetry/console/commands/check.py
index d2bc141ee90..95bd9912195 100644
--- a/src/poetry/console/commands/check.py
+++ b/src/poetry/console/commands/check.py
@@ -29,7 +29,7 @@ class CheckCommand(Command):
),
]
- def validate_classifiers(
+ def _validate_classifiers(
self, project_classifiers: set[str]
) -> tuple[list[str], list[str]]:
"""Identify unrecognized and deprecated trove classifiers.
@@ -79,21 +79,16 @@ def validate_classifiers(
return errors, warnings
- def validate_readme(
- self, readme: str | list[str], poetry_file: Path
- ) -> tuple[list[str], list[str]]:
+ def _validate_readme(self, readme: str | list[str], poetry_file: Path) -> list[str]:
"""Check existence of referenced readme files"""
- errors = []
- warnings: list[str] = []
-
readmes = [readme] if isinstance(readme, str) else readme
+ errors = []
for name in readmes:
if not (poetry_file.parent / name).exists():
errors.append(f"Declared README file does not exist: {name}")
-
- return errors, warnings
+ return errors
def handle(self) -> int:
from poetry.factory import Factory
@@ -106,15 +101,14 @@ def handle(self) -> int:
# Validate trove classifiers
project_classifiers = set(config.get("classifiers", []))
- errors, warnings = self.validate_classifiers(project_classifiers)
+ errors, warnings = self._validate_classifiers(project_classifiers)
check_result["errors"].extend(errors)
check_result["warnings"].extend(warnings)
# Validate readme (files must exist)
if "readme" in config:
- errors, warnings = self.validate_readme(config["readme"], poetry_file)
+ errors = self._validate_readme(config["readme"], poetry_file)
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():