Skip to content

Commit 5672fb0

Browse files
authored
Have render functions call print() themselves rather than the caller (#506)
It makes more sense to call print() inside the render functions because that’s their purpose. Some were already doing this anyways. This change also adds a coverage test for the --json render.
1 parent a1832d8 commit 5672fb0

File tree

8 files changed

+95
-22
lines changed

8 files changed

+95
-22
lines changed

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ lint.select = [
7878
]
7979
lint.ignore = [
8080
"A005", # Don't care about shadowing builtin modules
81-
"ANN101", # No type annotation for self
82-
"ANN102", # Missing type annotation for `cls` in classmethod
8381
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in
8482
"COM812", # Conflict with formatter
8583
"CPY", # No copyright statements

src/pipdeptree/_render/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
def render(options: Options, tree: PackageDAG) -> None:
1818
if options.json:
19-
print(render_json(tree)) # noqa: T201
19+
render_json(tree)
2020
elif options.json_tree:
21-
print(render_json_tree(tree)) # noqa: T201
21+
render_json_tree(tree)
2222
elif options.mermaid:
23-
print(render_mermaid(tree)) # noqa: T201
23+
render_mermaid(tree)
2424
elif options.output_format:
2525
render_graphviz(tree, output_format=options.output_format, reverse=options.reverse)
2626
elif options.freeze:

src/pipdeptree/_render/json.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pipdeptree._models import PackageDAG
88

99

10-
def render_json(tree: PackageDAG) -> str:
10+
def render_json(tree: PackageDAG) -> None:
1111
"""
1212
Convert the tree into a flat json representation.
1313
@@ -20,10 +20,11 @@ def render_json(tree: PackageDAG) -> str:
2020
2121
"""
2222
tree = tree.sort()
23-
return json.dumps(
23+
output = json.dumps(
2424
[{"package": k.as_dict(), "dependencies": [v.as_dict() for v in vs]} for k, vs in tree.items()],
2525
indent=4,
2626
)
27+
print(output) # noqa: T201
2728

2829

2930
__all__ = [

src/pipdeptree/_render/json_tree.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from pipdeptree._models import DistPackage, PackageDAG
1111

1212

13-
def render_json_tree(tree: PackageDAG) -> str:
13+
def render_json_tree(tree: PackageDAG) -> None:
1414
"""
1515
Convert the tree into a nested json representation.
1616
@@ -52,7 +52,7 @@ def aux(
5252

5353
return d
5454

55-
return json.dumps([aux(p) for p in nodes], indent=4)
55+
print(json.dumps([aux(p) for p in nodes], indent=4)) # noqa: T201
5656

5757

5858
__all__ = [

src/pipdeptree/_render/mermaid.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
)
3535

3636

37-
def render_mermaid(tree: PackageDAG) -> str: # noqa: C901
37+
def render_mermaid(tree: PackageDAG) -> None: # noqa: C901
3838
"""
3939
Produce a Mermaid flowchart from the dependency graph.
4040
@@ -105,7 +105,7 @@ def mermaid_id(key: str) -> str:
105105
*sorted(nodes),
106106
*sorted(edges),
107107
]
108-
return "".join(f"{' ' if i else ''}{line}\n" for i, line in enumerate(lines))
108+
print("".join(f"{' ' if i else ''}{line}\n" for i, line in enumerate(lines))) # noqa: T201
109109

110110

111111
__all__ = [

tests/render/test_json.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from __future__ import annotations
2+
3+
from textwrap import dedent
4+
from typing import TYPE_CHECKING, Callable
5+
6+
from pipdeptree._models.dag import PackageDAG
7+
from pipdeptree._render.json import render_json
8+
9+
if TYPE_CHECKING:
10+
from collections.abc import Iterator
11+
from unittest.mock import Mock
12+
13+
import pytest
14+
15+
from tests.our_types import MockGraph
16+
17+
18+
def test_render_json(mock_pkgs: Callable[[MockGraph], Iterator[Mock]], capsys: pytest.CaptureFixture[str]) -> None:
19+
graph: MockGraph = {
20+
("a", "1.2.3"): [("b", [(">=", "4.0.0")])],
21+
("b", "4.5.6"): [],
22+
}
23+
expected_output = dedent("""\
24+
[
25+
{
26+
"package": {
27+
"key": "a",
28+
"package_name": "a",
29+
"installed_version": "1.2.3"
30+
},
31+
"dependencies": [
32+
{
33+
"key": "b",
34+
"package_name": "b",
35+
"installed_version": "4.5.6",
36+
"required_version": ">=4.0.0"
37+
}
38+
]
39+
},
40+
{
41+
"package": {
42+
"key": "b",
43+
"package_name": "b",
44+
"installed_version": "4.5.6"
45+
},
46+
"dependencies": []
47+
}
48+
]
49+
""")
50+
package_dag = PackageDAG.from_pkgs(list(mock_pkgs(graph)))
51+
52+
render_json(package_dag)
53+
54+
output = capsys.readouterr()
55+
assert output.out == expected_output

tests/render/test_json_tree.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ def test_json_tree_given_req_package_with_version_spec(
2525
mock_pkgs: Callable[[MockGraph], Iterator[Mock]],
2626
version_spec_tuple: tuple[str, str],
2727
expected_version_spec: str,
28+
capsys: pytest.CaptureFixture[str],
2829
) -> None:
2930
graph: MockGraph = {
3031
("a", "1.2.3"): [("b", [version_spec_tuple])],
3132
("b", "2.2.0"): [],
3233
}
3334
package_dag = PackageDAG.from_pkgs(list(mock_pkgs(graph)))
34-
json_tree_str = render_json_tree(package_dag)
35-
assert json_tree_str.find(expected_version_spec) != -1
35+
36+
render_json_tree(package_dag)
37+
38+
captured = capsys.readouterr()
39+
assert captured.out.find(expected_version_spec) != -1

tests/render/test_mermaid.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
from collections.abc import Iterator
1111
from unittest.mock import Mock
1212

13+
import pytest
14+
1315
from tests.our_types import MockGraph
1416

1517

16-
def test_render_mermaid(example_dag: PackageDAG, randomized_example_dag: PackageDAG) -> None:
18+
def test_render_mermaid(
19+
example_dag: PackageDAG, randomized_example_dag: PackageDAG, capsys: pytest.CaptureFixture[str]
20+
) -> None:
1721
"""Check both the sorted and randomized package tree produces the same sorted Mermaid output.
1822
1923
Rendering a reverse dependency tree should produce the same set of nodes. Edges should have the same version spec
@@ -70,22 +74,33 @@ def test_render_mermaid(example_dag: PackageDAG, randomized_example_dag: Package
7074
).rstrip()
7175

7276
for package_tree in (example_dag, randomized_example_dag):
73-
output = render_mermaid(package_tree)
74-
assert output.rstrip() == nodes + dependency_edges
75-
reversed_output = render_mermaid(package_tree.reverse())
76-
assert reversed_output.rstrip() == nodes + reverse_dependency_edges
77+
render_mermaid(package_tree)
78+
output = capsys.readouterr()
79+
assert output.out.rstrip() == nodes + dependency_edges
80+
81+
render_mermaid(package_tree.reverse())
82+
output = capsys.readouterr()
83+
assert output.out.rstrip() == nodes + reverse_dependency_edges
7784

7885

79-
def test_mermaid_reserved_ids(mock_pkgs: Callable[[MockGraph], Iterator[Mock]]) -> None:
86+
def test_mermaid_reserved_ids(
87+
mock_pkgs: Callable[[MockGraph], Iterator[Mock]], capsys: pytest.CaptureFixture[str]
88+
) -> None:
8089
graph = {("click", "3.4.0"): [("click-extra", [(">=", "2.0.0")])]}
8190
package_tree = PackageDAG.from_pkgs(list(mock_pkgs(graph)))
82-
output = render_mermaid(package_tree)
83-
assert output == dedent(
84-
"""\
91+
92+
render_mermaid(package_tree)
93+
94+
output = capsys.readouterr()
95+
assert (
96+
output.out.rstrip()
97+
== dedent(
98+
"""\
8599
flowchart TD
86100
classDef missing stroke-dasharray: 5
87101
click-extra["click-extra\\n(missing)"]:::missing
88102
click_0["click\\n3.4.0"]
89103
click_0 -.-> click-extra
90104
""",
105+
).rstrip()
91106
)

0 commit comments

Comments
 (0)