Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pyreverse: PlantUML support + coloring (from PR #4521) #4615

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
53e99b4
WIP: automatically color package diagrams in pyreverse
DudeNr33 May 24, 2021
832202b
Add command line options ``--colorized`` and ``-max-color-depth``.
DudeNr33 May 24, 2021
7010985
Dummy implementation of new methods for VCG writer; ignore style attr…
DudeNr33 May 25, 2021
72e2d01
Add simple unit test for colored output
DudeNr33 May 25, 2021
71d6d29
Add test files for colorized output
DudeNr33 May 25, 2021
bc0febf
Apply consistent definition of dictionaries
DudeNr33 May 26, 2021
128ea44
Fix unittest that also relied on the Config class of another test module
DudeNr33 May 26, 2021
d2763be
Enable coloring of class diagrams without relying on the module-names…
DudeNr33 May 26, 2021
738e7b9
Modify test data and config so that colorization of standard library …
DudeNr33 May 26, 2021
36c3688
Add regression tests for vcg output
DudeNr33 May 28, 2021
a32ca13
Merge branch 'master' into pyreverse-autocolor
DudeNr33 May 28, 2021
225ef45
Delete class inheriting from standard library in test data, since the…
DudeNr33 May 28, 2021
e8e898f
Refactoring: extract logic what attributes to set for packages in met…
DudeNr33 May 29, 2021
e70c135
Add ChangeLog and whatsnew entrAdd ChangeLog and whatsnew entryy
DudeNr33 May 29, 2021
2dcfdb0
Merge branch 'master' into pyreverse-autocolor
DudeNr33 May 29, 2021
ca0e3ec
First implementation of PlantUML backend for pyreverse.
DudeNr33 May 30, 2021
f8deba0
Implement automatic coloring for PlantUML diagrams.
DudeNr33 May 30, 2021
7b54169
Stereotypes can now be optionally specified for classes in ``PlantUml…
DudeNr33 May 30, 2021
ec7265b
Delete ``classes.dot`` file in cleanup fixture that was generated dur…
DudeNr33 May 30, 2021
ce98e5f
Use the qualified name of objects as unique ID for diagrams to make t…
DudeNr33 May 31, 2021
9e7c36d
Refactoring: create ``Printer`` base class and move logic for differe…
DudeNr33 Jun 6, 2021
9ae5c49
Refactoring of pyreverse tests - extract common fixtures and function…
DudeNr33 Jun 20, 2021
168faeb
Exclude all 'data' subdirectories under 'tests' for pre-commit hooks
DudeNr33 Jun 20, 2021
a933c2c
Move test file back to where it belongs
DudeNr33 Jun 20, 2021
eb917e3
Exclude 'data' subdirectories under test, as they may contain deliber…
DudeNr33 Jun 22, 2021
7e0cba8
Improve typing by replacing dictionaries with NamedTuple, add type hi…
DudeNr33 Jun 26, 2021
f46a41e
Merge branch 'master' into pyreverse-plantuml
DudeNr33 Jun 26, 2021
db5f507
Use factory functions to obtain a ``Printer`` or ``DiagramWriter`` cl…
DudeNr33 Jun 26, 2021
bb227a1
Emitting the "URL" attribute breaks output for VCG and PlantUML, but …
DudeNr33 Jun 26, 2021
7eeaa50
Add changelog and whatsnew entries
DudeNr33 Jun 26, 2021
7375104
Fix unit test after removing the URL attribute from import-graph
DudeNr33 Jun 26, 2021
36847b8
Remove dead code
DudeNr33 Jun 27, 2021
7938bf1
Refactor tests and add new ones to increase coverage for new code
DudeNr33 Jun 27, 2021
14cd177
Use factory function to get the corresponding writer for the desired …
DudeNr33 Jun 27, 2021
49ba34e
Fix expected output message
DudeNr33 Jun 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Expand Up @@ -13,7 +13,7 @@ repos:
rev: v1.4
hooks:
- id: autoflake
exclude: &fixtures tests/functional/|tests/input|tests/extensions/data|tests/regrtest_data/|tests/data/
exclude: &fixtures tests/functional/|tests/input|tests(/.*)*/data|tests/regrtest_data/
args:
- --in-place
- --remove-all-unused-imports
Expand Down Expand Up @@ -60,7 +60,7 @@ repos:
"--load-plugins=pylint.extensions.docparams",
]
# disabled plugins: pylint.extensions.mccabe
exclude: tests/functional/|tests/input|tests/extensions/data|tests/regrtest_data/|tests/data/|doc/
exclude: tests/functional/|tests/input|tests/regrtest_data/|tests(/.*)*/data/|doc/
- id: fix-documentation
name: Fix documentation
entry: python3 -m script.fix_documentation
Expand All @@ -78,7 +78,7 @@ repos:
args: []
require_serial: true
additional_dependencies: ["types-pkg_resources==0.1.3", "types-toml==0.1.3"]
exclude: tests/functional/|tests/input|tests/extensions/data|tests/regrtest_data/|tests/data/|doc/|bin/
exclude: tests/functional/|tests/input|tests(/.*)*/data|tests/regrtest_data/|tests/data/|tests(/.*)+/conftest.py|doc/|bin/
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.3.1
hooks:
Expand Down
8 changes: 8 additions & 0 deletions ChangeLog
Expand Up @@ -9,6 +9,14 @@ Release date: TBA
..
Put new features and bugfixes here and also in 'doc/whatsnew/2.9.rst'

* Add PlantUML as possible output format for ``pyreverse`` and the ``--import-graph`` option

Closes #4498

* Added ``--colorized`` option to ``pyreverse`` to visualize modules/packages of the same parent package.

Closes #4488

* Add type annotations to pyreverse dot files

Closes #1548
Expand Down
6 changes: 6 additions & 0 deletions doc/whatsnew/2.9.rst
Expand Up @@ -49,6 +49,10 @@ New checkers
Other Changes
=============

* Add support for PlantUML output to pyreverse

* Add colorized output for pyreverse

* Add type annotations to pyreverse dot files

* Pylint's tags are now the standard form ``vX.Y.Z`` and not ``pylint-X.Y.Z`` anymore.
Expand All @@ -73,6 +77,8 @@ Other Changes

* ``ignore-paths`` configuration directive has been added. Defined regex patterns are matched against file path.

* ``pyreverse`` now supports automatic coloring of package and class diagrams for .dot files by passing the ``--colorized`` option.

* Added handling of floating point values when parsing configuration from pyproject.toml

* Fix false positive ``useless-type-doc`` on ignored argument using ``pylint.extensions.docparams`` when a function
Expand Down
70 changes: 60 additions & 10 deletions pylint/checkers/imports.py
Expand Up @@ -37,6 +37,7 @@
# Copyright (c) 2021 yushao2 <36848472+yushao2@users.noreply.github.com>
# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
# Copyright (c) 2021 Matus Valo <matusvalo@users.noreply.github.com>
# Copyright (c) 2021 Andreas Finkler <andi.finkler@gmail.com>
# Copyright (c) 2021 Andrew Howe <howeaj@users.noreply.github.com>

# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Expand All @@ -60,8 +61,13 @@
node_ignores_exception,
)
from pylint.exceptions import EmptyReportError
from pylint.graph import DotBackend, get_cycles
from pylint.interfaces import IAstroidChecker
from pylint.pyreverse.printer import (
EdgeType,
Layout,
NodeType,
get_printer_for_filetype,
)
from pylint.reporters.ureports.nodes import Paragraph, VerbatimText, VNode
from pylint.utils import IsortDriver, get_global_option

Expand Down Expand Up @@ -191,30 +197,74 @@ def _repr_tree_defs(data, indent_str=None):
return "\n".join(lines)


def _dependencies_graph(filename: str, dep_info: Dict[str, List[str]]) -> str:
def _dependencies_graph(filename: str, dep_info: Dict[str, List[str]]) -> None:
"""write dependencies as a dot (graphviz) file"""
done = {}
printer = DotBackend(os.path.splitext(os.path.basename(filename))[0], rankdir="LR")
printer.emit('URL="." node[shape="box"]')
printer = get_printer_for_filetype(filename)(
os.path.splitext(os.path.basename(filename))[0], layout=Layout.LEFT_TO_RIGHT
)
for modname, dependencies in sorted(dep_info.items()):
done[modname] = 1
printer.emit_node(modname)
printer.emit_node(modname, type_=NodeType.PACKAGE)
for depmodname in dependencies:
if depmodname not in done:
done[depmodname] = 1
printer.emit_node(depmodname)
printer.emit_node(depmodname, type_=NodeType.PACKAGE)
for depmodname, dependencies in sorted(dep_info.items()):
for modname in dependencies:
printer.emit_edge(modname, depmodname)
return printer.generate(filename)
printer.emit_edge(modname, depmodname, type_=EdgeType.USES)
printer.generate(filename)


def _make_graph(filename: str, dep_info: Dict[str, List[str]], sect: VNode, gtype: str):
"""generate a dependencies graph and add some information about it in the
report's section
"""
outputfile = _dependencies_graph(filename, dep_info)
sect.append(Paragraph(f"{gtype}imports graph has been written to {outputfile}"))
_dependencies_graph(filename, dep_info)
sect.append(Paragraph(f"{gtype}imports graph has been written to {filename}"))


def get_cycles(graph_dict, vertices=None):
"""given a dictionary representing an ordered graph (i.e. key are vertices
and values is a list of destination vertices representing edges), return a
list of detected cycles
"""
if not graph_dict:
return ()
result = []
if vertices is None:
vertices = graph_dict.keys()
for vertice in vertices:
_get_cycles(graph_dict, [], set(), result, vertice)
return result


def _get_cycles(graph_dict, path, visited, result, vertice):
"""recursive function doing the real work for get_cycles"""
if vertice in path:
cycle = [vertice]
for node in path[::-1]:
if node == vertice:
break
cycle.insert(0, node)
# make a canonical representation
start_from = min(cycle)
index = cycle.index(start_from)
cycle = cycle[index:] + cycle[0:index]
# append it to result if not already in
if cycle not in result:
result.append(cycle)
return
path.append(vertice)
try:
for node in graph_dict[vertice]:
# don't check already visited nodes again
if node not in visited:
_get_cycles(graph_dict, path, visited, result, node)
visited.add(node)
except KeyError:
pass
path.pop()


# the import checker itself ###################################################
Expand Down
207 changes: 0 additions & 207 deletions pylint/graph.py

This file was deleted.