Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/poetry/console/commands/check.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import Any

from cleo.helpers import option

Expand Down Expand Up @@ -88,6 +89,37 @@ def _validate_readme(self, readme: str | list[str], poetry_file: Path) -> list[s
errors.append(f"Declared README file does not exist: {name}")
return errors

def _validate_dependencies_source(self, config: dict[str, Any]) -> list[str]:
"""Check dependencies's source are valid"""
sources = {k["name"] for k in config.get("source", [])}

dependency_declarations: list[
dict[str, str | dict[str, str] | list[dict[str, str]]]
] = []
# scan dependencies and group dependencies settings in pyproject.toml
if "dependencies" in config:
dependency_declarations.append(config["dependencies"])

for group in config.get("group", {}).values():
if "dependencies" in group:
dependency_declarations.append(group["dependencies"])

all_referenced_sources: set[str] = set()

for dependency_declaration in dependency_declarations:
for declaration in dependency_declaration.values():
if isinstance(declaration, list):
for item in declaration:
if "source" in item:
all_referenced_sources.add(item["source"])
elif isinstance(declaration, dict) and "source" in declaration:
all_referenced_sources.add(declaration["source"])

return [
f'Invalid source "{source}" referenced in dependencies.'
for source in sorted(all_referenced_sources - sources)
]

def handle(self) -> int:
from poetry.factory import Factory
from poetry.pyproject.toml import PyProjectTOML
Expand All @@ -108,6 +140,8 @@ def handle(self) -> int:
errors = self._validate_readme(config["readme"], poetry_file)
check_result["errors"].extend(errors)

check_result["errors"] += self._validate_dependencies_source(config)

# 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."]
Expand Down
2 changes: 2 additions & 0 deletions tests/console/commands/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ def test_check_invalid(
Error: Project name (invalid) is same as one of its dependencies
Error: Unrecognized classifiers: ['Intended Audience :: Clowns'].
Error: Declared README file does not exist: never/exists.md
Error: Invalid source "not-exists" referenced in dependencies.
Error: Invalid source "not-exists2" referenced in dependencies.
Error: poetry.lock was not found.
Warning: A wildcard Python dependency is ambiguous.\
Consider specifying a more explicit one.
Expand Down
9 changes: 9 additions & 0 deletions tests/fixtures/invalid_pyproject/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ classifiers = [
python = "*"
pendulum = {"version" = "^2.0.5", allows-prereleases = true}
invalid = "1.0"
invalid_source = { "version" = "*", source = "not-exists" }
Comment thread
lucemia marked this conversation as resolved.
invalid_source_multi = [
{ "version" = "*", platform = "linux", source = "exists" },
{ "version" = "*", platform = "win32", source = "not-exists2" },
]

[[tool.poetry.source]]
name = "exists"
priority = "explicit"