2023-07-15 14:43:08 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2024-05-13 17:17:44 +00:00
|
|
|
import locale
|
2024-05-07 17:01:08 +00:00
|
|
|
from pathlib import Path
|
2023-07-15 14:43:08 +00:00
|
|
|
from random import shuffle
|
|
|
|
from typing import TYPE_CHECKING, Callable, Iterator
|
2024-04-06 14:09:53 +00:00
|
|
|
from unittest.mock import Mock
|
2023-07-15 14:43:08 +00:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from pipdeptree._models import PackageDAG
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from tests.our_types import MockGraph
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
|
|
def mock_pkgs() -> Callable[[MockGraph], Iterator[Mock]]:
|
|
|
|
def func(simple_graph: MockGraph) -> Iterator[Mock]:
|
|
|
|
for node, children in simple_graph.items():
|
|
|
|
nk, nv = node
|
2024-04-02 20:56:00 +00:00
|
|
|
m = Mock(metadata={"Name": nk}, version=nv)
|
2023-07-15 14:43:08 +00:00
|
|
|
reqs = []
|
2023-07-15 16:36:15 +00:00
|
|
|
for ck, cv in children:
|
2024-04-02 20:56:00 +00:00
|
|
|
r = ck
|
|
|
|
for item in cv:
|
|
|
|
if item:
|
|
|
|
rs, rv = item
|
2024-04-06 14:09:53 +00:00
|
|
|
r = r + rs + rv
|
|
|
|
if item != cv[-1]:
|
|
|
|
r += ","
|
2023-07-15 14:43:08 +00:00
|
|
|
reqs.append(r)
|
2024-04-02 20:56:00 +00:00
|
|
|
m.requires = reqs
|
2023-07-15 14:43:08 +00:00
|
|
|
yield m
|
|
|
|
|
|
|
|
return func
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def example_dag(mock_pkgs: Callable[[MockGraph], Iterator[Mock]]) -> PackageDAG:
|
2023-07-15 15:58:56 +00:00
|
|
|
packages: MockGraph = {
|
2023-07-15 14:43:08 +00:00
|
|
|
("a", "3.4.0"): [("b", [(">=", "2.0.0")]), ("c", [(">=", "5.7.1")])],
|
|
|
|
("b", "2.3.1"): [("d", [(">=", "2.30"), ("<", "2.42")])],
|
|
|
|
("c", "5.10.0"): [("d", [(">=", "2.30")]), ("e", [(">=", "0.12.1")])],
|
|
|
|
("d", "2.35"): [("e", [(">=", "0.9.0")])],
|
|
|
|
("e", "0.12.1"): [],
|
|
|
|
("f", "3.1"): [("b", [(">=", "2.1.0")])],
|
|
|
|
("g", "6.8.3rc1"): [("e", [(">=", "0.9.0")]), ("f", [(">=", "3.0.0")])],
|
|
|
|
}
|
|
|
|
return PackageDAG.from_pkgs(list(mock_pkgs(packages)))
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def randomized_example_dag(example_dag: PackageDAG) -> PackageDAG:
|
|
|
|
"""Returns a copy of the package tree fixture with dependencies in randomized order."""
|
|
|
|
# Extract the dependency graph from the package tree and randomize it.
|
|
|
|
randomized_graph = {}
|
|
|
|
randomized_nodes = list(example_dag._obj.keys()) # noqa: SLF001
|
|
|
|
shuffle(randomized_nodes)
|
|
|
|
for node in randomized_nodes:
|
|
|
|
edges = example_dag._obj[node].copy() # noqa: SLF001
|
|
|
|
shuffle(edges)
|
|
|
|
randomized_graph[node] = edges
|
|
|
|
assert set(randomized_graph) == set(example_dag._obj) # noqa: SLF001
|
|
|
|
|
|
|
|
# Create a randomized package tree.
|
|
|
|
randomized_dag = PackageDAG(randomized_graph)
|
|
|
|
assert len(example_dag) == len(randomized_dag)
|
|
|
|
return randomized_dag
|
2024-05-07 17:01:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def fake_dist(tmp_path: Path) -> Path:
|
|
|
|
"""Creates a fake site package (that you get using Path.parent) and a fake dist-info called bar-2.4.5.dist-info."""
|
|
|
|
fake_site_pkgs = tmp_path / "site-packages"
|
|
|
|
fake_dist_path = fake_site_pkgs / "bar-2.4.5.dist-info"
|
|
|
|
fake_dist_path.mkdir(parents=True)
|
|
|
|
fake_metadata = Path(fake_dist_path) / "METADATA"
|
2024-06-03 02:05:35 +00:00
|
|
|
with fake_metadata.open("w", encoding=locale.getpreferredencoding(False)) as f:
|
2024-05-07 17:01:08 +00:00
|
|
|
f.write("Metadata-Version: 2.3\n" "Name: bar\n" "Version: 2.4.5\n")
|
|
|
|
|
|
|
|
return fake_dist_path
|
2024-06-03 02:05:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def fake_dist_with_invalid_metadata(tmp_path: Path) -> Path:
|
|
|
|
"Similar to `fake_dist()`, but creates an invalid METADATA file."
|
|
|
|
fake_site_pkgs = tmp_path / "site-packages"
|
|
|
|
fake_dist_path = fake_site_pkgs / "bar-2.4.5.dist-info"
|
|
|
|
fake_dist_path.mkdir(parents=True)
|
|
|
|
fake_metadata = Path(fake_dist_path) / "METADATA"
|
|
|
|
fake_metadata.touch()
|
|
|
|
return fake_dist_path
|