Skip to content

Commit

Permalink
fix #8704 check and validate not exist source
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemia committed Dec 5, 2023
1 parent 0578ed8 commit 543268b
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/poetry/console/commands/check.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from __future__ import annotations

from collections import defaultdict
from functools import reduce
from typing import TYPE_CHECKING
from typing import Any

from cleo.helpers import option

Expand Down Expand Up @@ -88,6 +91,44 @@ 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"""
dependency_sources: dict[str, set[str]] = defaultdict(set)
sources = {k["name"] for k in config.get("source", [])}
errors = []

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"])

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

all_referenced_sources: set[str] = reduce(
lambda i, j: i | j, dependency_sources.values(), set()
)
if all_referenced_sources not in sources:
errors.extend([
f'Invalid source "{source}" referenced in dependencies.'
for source in all_referenced_sources - sources
])

errors.sort()
return errors

def handle(self) -> int:
from poetry.factory import Factory
from poetry.pyproject.toml import PyProjectTOML
Expand All @@ -108,6 +149,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" }
invalid_source_multi = [
{ "version" = "*", platform = "linux", source = "exists" },
{ "version" = "*", platform = "win32", source = "not-exists2" },
]

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

0 comments on commit 543268b

Please sign in to comment.