Skip to content

Commit 958ff85

Browse files
authored
pyreverse: Add show-stdlib option (#8190)
* pyreverse: Add show-stdlib option * Switch to astroid.modutils.is_standard_module * Add tests * Fix quotes in whatsnew fragment * Update for astroid 2.15.0 * Recategorize news fragment
1 parent ed8b840 commit 958ff85

File tree

7 files changed

+72
-5
lines changed

7 files changed

+72
-5
lines changed

doc/whatsnew/fragments/8181.breaking

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Add new option (``--show-stdlib``, ``-L``) to ``pyreverse``.
2+
This is similar to the behavior of ``--show-builtin`` in that standard library
3+
modules are now not included by default, and this option will include them.
4+
5+
Closes #8181

pylint/pyreverse/diadefslib.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import astroid
1414
from astroid import nodes
15+
from astroid.modutils import is_stdlib_module
1516

1617
from pylint.pyreverse.diagrams import ClassDiagram, PackageDiagram
1718
from pylint.pyreverse.inspector import Linker, Project
@@ -67,10 +68,14 @@ def _get_levels(self) -> tuple[int, int]:
6768
return self.anc_level, self.association_level
6869

6970
def show_node(self, node: nodes.ClassDef) -> bool:
70-
"""True if builtins and not show_builtins."""
71-
if self.config.show_builtin:
72-
return True
73-
return node.root().name != "builtins" # type: ignore[no-any-return]
71+
"""Determine if node should be shown based on config."""
72+
if node.root().name == "builtins":
73+
return self.config.show_builtin # type: ignore[no-any-return]
74+
75+
if is_stdlib_module(node.root().name):
76+
return self.config.show_stdlib # type: ignore[no-any-return]
77+
78+
return True
7479

7580
def add_class(self, node: nodes.ClassDef) -> None:
7681
"""Visit one class and add it to diagram."""

pylint/pyreverse/main.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@
137137
"help": "include builtin objects in representation of classes",
138138
},
139139
),
140+
(
141+
"show-stdlib",
142+
{
143+
"short": "L",
144+
"action": "store_true",
145+
"default": False,
146+
"help": "include standard library objects in representation of classes",
147+
},
148+
),
140149
(
141150
"module-names",
142151
{

pylint/testutils/pyreverse.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(
3838
show_associated: int | None = None,
3939
all_associated: bool | None = None,
4040
show_builtin: bool = False,
41+
show_stdlib: bool = False,
4142
module_names: bool | None = None,
4243
only_classnames: bool = False,
4344
output_format: str = "dot",
@@ -59,6 +60,7 @@ def __init__(
5960
self.show_associated = show_associated
6061
self.all_associated = all_associated
6162
self.show_builtin = show_builtin
63+
self.show_stdlib = show_stdlib
6264
self.module_names = module_names
6365
self.only_classnames = only_classnames
6466
self.output_format = output_format

tests/pyreverse/test_diadefs.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pathlib import Path
1414

1515
import pytest
16-
from astroid import nodes
16+
from astroid import extract_node, nodes
1717

1818
from pylint.pyreverse.diadefslib import (
1919
ClassDiadefGenerator,
@@ -97,6 +97,50 @@ def test_default_values() -> None:
9797
# TODO : should test difference between default values for package or class diagrams
9898

9999

100+
class TestShowOptions:
101+
def test_show_stdlib(self) -> None:
102+
example = extract_node(
103+
'''
104+
import collections
105+
106+
class CustomDict(collections.OrderedDict):
107+
"""docstring"""
108+
'''
109+
)
110+
111+
config = PyreverseConfig()
112+
dd_gen = DiaDefGenerator(Linker(PROJECT), DiadefsHandler(config))
113+
114+
# Default behavior
115+
assert not list(dd_gen.get_ancestors(example, 1))
116+
117+
# Show standard library enabled
118+
config.show_stdlib = True
119+
ancestors = list(dd_gen.get_ancestors(example, 1))
120+
assert len(ancestors) == 1
121+
assert ancestors[0].name == "OrderedDict"
122+
123+
def test_show_builtin(self) -> None:
124+
example = extract_node(
125+
'''
126+
class CustomError(Exception):
127+
"""docstring"""
128+
'''
129+
)
130+
131+
config = PyreverseConfig()
132+
dd_gen = DiaDefGenerator(Linker(PROJECT), DiadefsHandler(config))
133+
134+
# Default behavior
135+
assert not list(dd_gen.get_ancestors(example, 1))
136+
137+
# Show builtin enabled
138+
config.show_builtin = True
139+
ancestors = list(dd_gen.get_ancestors(example, 1))
140+
assert len(ancestors) == 1
141+
assert ancestors[0].name == "Exception"
142+
143+
100144
class TestDefaultDiadefGenerator:
101145
_should_rels = [
102146
("aggregation", "DoNothing2", "Specialization"),

tests/pyreverse/test_main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ def test_graphviz_unsupported_image_format(capsys: CaptureFixture) -> None:
138138
("show_associated", None),
139139
("all_associated", None),
140140
("show_builtin", 0),
141+
("show_stdlib", 0),
141142
("module_names", None),
142143
("output_format", "dot"),
143144
("colorized", 0),

tests/pyreverse/test_writer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"all_associated": None,
3333
"mode": "PUB_ONLY",
3434
"show_builtin": False,
35+
"show_stdlib": False,
3536
"only_classnames": False,
3637
"output_directory": "",
3738
}

0 commit comments

Comments
 (0)