summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Finkler <3929834+DudeNr33@users.noreply.github.com>2023-03-10 21:24:37 +0100
committerGitHub <noreply@github.com>2023-03-10 21:24:37 +0100
commitceb241047100db4821aaf9bd0edcbe4c4f5d86fc (patch)
tree163ad6c1ae9e6c7dea1fb0de6a85760e77308c6b
parentab20812ad0e9ca17cc3bc32dbf34be575dcea502 (diff)
downloadpylint-git-ceb241047100db4821aaf9bd0edcbe4c4f5d86fc.tar.gz
pyreverse: drop support for .vcg format (#8426)
-rw-r--r--doc/pyreverse.rst2
-rw-r--r--doc/whatsnew/fragments/8416.breaking3
-rw-r--r--pylint/pyreverse/main.py1
-rw-r--r--pylint/pyreverse/printer_factory.py2
-rw-r--r--pylint/pyreverse/vcg_printer.py296
-rw-r--r--pylint/pyreverse/writer.py2
-rw-r--r--tests/pyreverse/conftest.py7
-rw-r--r--tests/pyreverse/data/classes_No_Name.vcg50
-rw-r--r--tests/pyreverse/data/packages_No_Name.vcg23
-rw-r--r--tests/pyreverse/test_printer.py5
-rw-r--r--tests/pyreverse/test_printer_factory.py2
-rw-r--r--tests/pyreverse/test_writer.py17
12 files changed, 5 insertions, 405 deletions
diff --git a/doc/pyreverse.rst b/doc/pyreverse.rst
index fecbbaf5a..7595683d7 100644
--- a/doc/pyreverse.rst
+++ b/doc/pyreverse.rst
@@ -5,7 +5,7 @@ Pyreverse
``pyreverse`` analyzes your source code and generates package and class diagrams.
-It supports output to ``.dot``/``.gv``, ``.vcg``, ``.puml``/``.plantuml`` (PlantUML) and ``.mmd``/``.html`` (MermaidJS) file formats.
+It supports output to ``.dot``/``.gv``, ``.puml``/``.plantuml`` (PlantUML) and ``.mmd``/``.html`` (MermaidJS) file formats.
If Graphviz (or the ``dot`` command) is installed, all `output formats supported by Graphviz <https://graphviz.org/docs/outputs/>`_
can be used as well. In this case, ``pyreverse`` first generates a temporary ``.gv`` file, which is then
fed to Graphviz to generate the final image.
diff --git a/doc/whatsnew/fragments/8416.breaking b/doc/whatsnew/fragments/8416.breaking
new file mode 100644
index 000000000..7984da1b1
--- /dev/null
+++ b/doc/whatsnew/fragments/8416.breaking
@@ -0,0 +1,3 @@
+``pyreverse``: Support for the ``.vcg`` output format (Visualaization of Compiler Graphs) has been dropped.
+
+Closes #8416
diff --git a/pylint/pyreverse/main.py b/pylint/pyreverse/main.py
index bdd1eb4a9..c2eaf699b 100644
--- a/pylint/pyreverse/main.py
+++ b/pylint/pyreverse/main.py
@@ -27,7 +27,6 @@ from pylint.typing import Options
DIRECTLY_SUPPORTED_FORMATS = (
"dot",
- "vcg",
"puml",
"plantuml",
"mmd",
diff --git a/pylint/pyreverse/printer_factory.py b/pylint/pyreverse/printer_factory.py
index 41e8b46c8..e981b5ba4 100644
--- a/pylint/pyreverse/printer_factory.py
+++ b/pylint/pyreverse/printer_factory.py
@@ -8,10 +8,8 @@ from pylint.pyreverse.dot_printer import DotPrinter
from pylint.pyreverse.mermaidjs_printer import HTMLMermaidJSPrinter, MermaidJSPrinter
from pylint.pyreverse.plantuml_printer import PlantUmlPrinter
from pylint.pyreverse.printer import Printer
-from pylint.pyreverse.vcg_printer import VCGPrinter
filetype_to_printer: dict[str, type[Printer]] = {
- "vcg": VCGPrinter,
"plantuml": PlantUmlPrinter,
"puml": PlantUmlPrinter,
"mmd": MermaidJSPrinter,
diff --git a/pylint/pyreverse/vcg_printer.py b/pylint/pyreverse/vcg_printer.py
deleted file mode 100644
index 2a2591265..000000000
--- a/pylint/pyreverse/vcg_printer.py
+++ /dev/null
@@ -1,296 +0,0 @@
-# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
-# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
-
-"""Functions to generate files readable with George Sander's vcg
-(Visualization of Compiler Graphs).
-
-You can download vcg at https://rw4.cs.uni-sb.de/~sander/html/gshome.html
-Note that vcg exists as a debian package.
-See vcg's documentation for explanation about the different values that
-maybe used for the functions parameters.
-"""
-
-from __future__ import annotations
-
-from collections.abc import Mapping
-from typing import Any
-
-from pylint.pyreverse.printer import EdgeType, Layout, NodeProperties, NodeType, Printer
-
-ATTRS_VAL = {
- "algos": (
- "dfs",
- "tree",
- "minbackward",
- "left_to_right",
- "right_to_left",
- "top_to_bottom",
- "bottom_to_top",
- "maxdepth",
- "maxdepthslow",
- "mindepth",
- "mindepthslow",
- "mindegree",
- "minindegree",
- "minoutdegree",
- "maxdegree",
- "maxindegree",
- "maxoutdegree",
- ),
- "booleans": ("yes", "no"),
- "colors": (
- "black",
- "white",
- "blue",
- "red",
- "green",
- "yellow",
- "magenta",
- "lightgrey",
- "cyan",
- "darkgrey",
- "darkblue",
- "darkred",
- "darkgreen",
- "darkyellow",
- "darkmagenta",
- "darkcyan",
- "gold",
- "lightblue",
- "lightred",
- "lightgreen",
- "lightyellow",
- "lightmagenta",
- "lightcyan",
- "lilac",
- "turquoise",
- "aquamarine",
- "khaki",
- "purple",
- "yellowgreen",
- "pink",
- "orange",
- "orchid",
- ),
- "shapes": ("box", "ellipse", "rhomb", "triangle"),
- "textmodes": ("center", "left_justify", "right_justify"),
- "arrowstyles": ("solid", "line", "none"),
- "linestyles": ("continuous", "dashed", "dotted", "invisible"),
-}
-
-# meaning of possible values:
-# O -> string
-# 1 -> int
-# list -> value in list
-GRAPH_ATTRS = {
- "title": 0,
- "label": 0,
- "color": ATTRS_VAL["colors"],
- "textcolor": ATTRS_VAL["colors"],
- "bordercolor": ATTRS_VAL["colors"],
- "width": 1,
- "height": 1,
- "borderwidth": 1,
- "textmode": ATTRS_VAL["textmodes"],
- "shape": ATTRS_VAL["shapes"],
- "shrink": 1,
- "stretch": 1,
- "orientation": ATTRS_VAL["algos"],
- "vertical_order": 1,
- "horizontal_order": 1,
- "xspace": 1,
- "yspace": 1,
- "layoutalgorithm": ATTRS_VAL["algos"],
- "late_edge_labels": ATTRS_VAL["booleans"],
- "display_edge_labels": ATTRS_VAL["booleans"],
- "dirty_edge_labels": ATTRS_VAL["booleans"],
- "finetuning": ATTRS_VAL["booleans"],
- "manhattan_edges": ATTRS_VAL["booleans"],
- "smanhattan_edges": ATTRS_VAL["booleans"],
- "port_sharing": ATTRS_VAL["booleans"],
- "edges": ATTRS_VAL["booleans"],
- "nodes": ATTRS_VAL["booleans"],
- "splines": ATTRS_VAL["booleans"],
-}
-NODE_ATTRS = {
- "title": 0,
- "label": 0,
- "color": ATTRS_VAL["colors"],
- "textcolor": ATTRS_VAL["colors"],
- "bordercolor": ATTRS_VAL["colors"],
- "width": 1,
- "height": 1,
- "borderwidth": 1,
- "textmode": ATTRS_VAL["textmodes"],
- "shape": ATTRS_VAL["shapes"],
- "shrink": 1,
- "stretch": 1,
- "vertical_order": 1,
- "horizontal_order": 1,
-}
-EDGE_ATTRS = {
- "sourcename": 0,
- "targetname": 0,
- "label": 0,
- "linestyle": ATTRS_VAL["linestyles"],
- "class": 1,
- "thickness": 0,
- "color": ATTRS_VAL["colors"],
- "textcolor": ATTRS_VAL["colors"],
- "arrowcolor": ATTRS_VAL["colors"],
- "backarrowcolor": ATTRS_VAL["colors"],
- "arrowsize": 1,
- "backarrowsize": 1,
- "arrowstyle": ATTRS_VAL["arrowstyles"],
- "backarrowstyle": ATTRS_VAL["arrowstyles"],
- "textmode": ATTRS_VAL["textmodes"],
- "priority": 1,
- "anchor": 1,
- "horizontal_order": 1,
-}
-SHAPES: dict[NodeType, str] = {
- NodeType.PACKAGE: "box",
- NodeType.CLASS: "box",
-}
-# pylint: disable-next=consider-using-namedtuple-or-dataclass
-ARROWS: dict[EdgeType, dict[str, str | int]] = {
- EdgeType.USES: {
- "arrowstyle": "solid",
- "backarrowstyle": "none",
- "backarrowsize": 0,
- },
- EdgeType.INHERITS: {
- "arrowstyle": "solid",
- "backarrowstyle": "none",
- "backarrowsize": 10,
- },
- EdgeType.ASSOCIATION: {
- "arrowstyle": "solid",
- "backarrowstyle": "none",
- "textcolor": "green",
- },
- EdgeType.AGGREGATION: {
- "arrowstyle": "solid",
- "backarrowstyle": "none",
- "textcolor": "green",
- },
-}
-ORIENTATION: dict[Layout, str] = {
- Layout.LEFT_TO_RIGHT: "left_to_right",
- Layout.RIGHT_TO_LEFT: "right_to_left",
- Layout.TOP_TO_BOTTOM: "top_to_bottom",
- Layout.BOTTOM_TO_TOP: "bottom_to_top",
-}
-
-# Misc utilities ###############################################################
-
-
-class VCGPrinter(Printer):
- def _open_graph(self) -> None:
- """Emit the header lines."""
- self.emit("graph:{\n")
- self._inc_indent()
- self._write_attributes(
- GRAPH_ATTRS,
- title=self.title,
- layoutalgorithm="dfs",
- late_edge_labels="yes",
- port_sharing="no",
- manhattan_edges="yes",
- )
- if self.layout:
- self._write_attributes(GRAPH_ATTRS, orientation=ORIENTATION[self.layout])
-
- def _close_graph(self) -> None:
- """Emit the lines needed to properly close the graph."""
- self._dec_indent()
- self.emit("}")
-
- def emit_node(
- self,
- name: str,
- type_: NodeType,
- properties: NodeProperties | None = None,
- ) -> None:
- """Create a new node.
-
- Nodes can be classes, packages, participants etc.
- """
- if properties is None:
- properties = NodeProperties(label=name)
- elif properties.label is None:
- properties.label = name
- self.emit(f'node: {{title:"{name}"', force_newline=False)
- self._write_attributes(
- NODE_ATTRS,
- label=self._build_label_for_node(properties),
- shape=SHAPES[type_],
- )
- self.emit("}")
-
- @staticmethod
- def _build_label_for_node(properties: NodeProperties) -> str:
- fontcolor = "\f09" if properties.fontcolor == "red" else ""
- label = rf"\fb{fontcolor}{properties.label}\fn"
- if properties.attrs is None and properties.methods is None:
- # return a compact form which only displays the classname in a box
- return label
- attrs = properties.attrs or []
- methods = properties.methods or []
- method_names = [func.name for func in methods]
- # box width for UML like diagram
- maxlen = max(len(name) for name in [properties.label] + method_names + attrs)
- line = "_" * (maxlen + 2)
- label = rf"{label}\n\f{line}"
- for attr in attrs:
- label = rf"{label}\n\f08{attr}"
- if attrs:
- label = rf"{label}\n\f{line}"
- for func in method_names:
- label = rf"{label}\n\f10{func}()"
- return label
-
- def emit_edge(
- self,
- from_node: str,
- to_node: str,
- type_: EdgeType,
- label: str | None = None,
- ) -> None:
- """Create an edge from one node to another to display relationships."""
- self.emit(
- f'edge: {{sourcename:"{from_node}" targetname:"{to_node}"',
- force_newline=False,
- )
- attributes = ARROWS[type_]
- if label:
- attributes["label"] = label
- self._write_attributes(
- EDGE_ATTRS,
- **attributes,
- )
- self.emit("}")
-
- def _write_attributes(
- self, attributes_dict: Mapping[str, Any], **args: Any
- ) -> None:
- """Write graph, node or edge attributes."""
- for key, value in args.items():
- try:
- _type = attributes_dict[key]
- except KeyError as e:
- raise AttributeError(
- f"no such attribute {key}\npossible attributes are {attributes_dict.keys()}"
- ) from e
-
- if not _type:
- self.emit(f'{key}:"{value}"\n')
- elif _type == 1:
- self.emit(f"{key}:{int(value)}\n")
- elif value in _type:
- self.emit(f"{key}:{value}\n")
- else:
- raise ValueError(
- f"value {value} isn't correct for attribute {key} correct values are {type}"
- )
diff --git a/pylint/pyreverse/writer.py b/pylint/pyreverse/writer.py
index a8b1143fd..c1831feaa 100644
--- a/pylint/pyreverse/writer.py
+++ b/pylint/pyreverse/writer.py
@@ -2,7 +2,7 @@
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
-"""Utilities for creating VCG and Dot diagrams."""
+"""Utilities for creating diagrams."""
from __future__ import annotations
diff --git a/tests/pyreverse/conftest.py b/tests/pyreverse/conftest.py
index 02a19e613..000e31967 100644
--- a/tests/pyreverse/conftest.py
+++ b/tests/pyreverse/conftest.py
@@ -29,13 +29,6 @@ def colorized_dot_config() -> PyreverseConfig:
@pytest.fixture()
-def vcg_config() -> PyreverseConfig:
- return PyreverseConfig(
- output_format="vcg",
- )
-
-
-@pytest.fixture()
def puml_config() -> PyreverseConfig:
return PyreverseConfig(
output_format="puml",
diff --git a/tests/pyreverse/data/classes_No_Name.vcg b/tests/pyreverse/data/classes_No_Name.vcg
deleted file mode 100644
index 2df09a2dc..000000000
--- a/tests/pyreverse/data/classes_No_Name.vcg
+++ /dev/null
@@ -1,50 +0,0 @@
-graph:{
- title:"classes_No_Name"
- layoutalgorithm:dfs
- late_edge_labels:yes
- port_sharing:no
- manhattan_edges:yes
- node: {title:"data.clientmodule_test.Ancestor" label:"\fbAncestor\fn\n\f____________\n\f08attr : str\n\f08cls_member\n\f____________\n\f10get_value()\n\f10set_value()"
- shape:box
-}
- node: {title:"data.suppliermodule_test.CustomException" label:"\fb 09CustomException\fn\n\f_________________"
- shape:box
-}
- node: {title:"data.suppliermodule_test.DoNothing" label:"\fbDoNothing\fn\n\f___________"
- shape:box
-}
- node: {title:"data.suppliermodule_test.DoNothing2" label:"\fbDoNothing2\fn\n\f____________"
- shape:box
-}
- node: {title:"data.suppliermodule_test.DoSomething" label:"\fbDoSomething\fn\n\f__________________________\n\f08my_int : Optional[int]\n\f08my_int_2 : Optional[int]\n\f08my_string : str\n\f__________________________\n\f10do_it()"
- shape:box
-}
- node: {title:"data.suppliermodule_test.Interface" label:"\fbInterface\fn\n\f___________\n\f10get_value()\n\f10set_value()"
- shape:box
-}
- node: {title:"data.property_pattern.PropertyPatterns" label:"\fbPropertyPatterns\fn\n\f__________________\n\f08prop1\n\f08prop2\n\f__________________"
- shape:box
-}
- node: {title:"data.clientmodule_test.Specialization" label:"\fbSpecialization\fn\n\f_________________\n\f08TYPE : str\n\f08relation\n\f08relation2\n\f08top : str\n\f_________________\n\f10from_value()\n\f10increment_value()\n\f10transform_value()"
- shape:box
-}
- edge: {sourcename:"data.clientmodule_test.Specialization" targetname:"data.clientmodule_test.Ancestor" arrowstyle:solid
- backarrowstyle:none
- backarrowsize:10
-}
- edge: {sourcename:"data.suppliermodule_test.DoNothing" targetname:"data.clientmodule_test.Ancestor" arrowstyle:solid
- backarrowstyle:none
- textcolor:green
- label:"cls_member"
-}
- edge: {sourcename:"data.suppliermodule_test.DoNothing" targetname:"data.clientmodule_test.Specialization" arrowstyle:solid
- backarrowstyle:none
- textcolor:green
- label:"relation"
-}
- edge: {sourcename:"data.suppliermodule_test.DoNothing2" targetname:"data.clientmodule_test.Specialization" arrowstyle:solid
- backarrowstyle:none
- textcolor:green
- label:"relation2"
-}
-}
diff --git a/tests/pyreverse/data/packages_No_Name.vcg b/tests/pyreverse/data/packages_No_Name.vcg
deleted file mode 100644
index f9f4e4cec..000000000
--- a/tests/pyreverse/data/packages_No_Name.vcg
+++ /dev/null
@@ -1,23 +0,0 @@
-graph:{
- title:"packages_No_Name"
- layoutalgorithm:dfs
- late_edge_labels:yes
- port_sharing:no
- manhattan_edges:yes
- node: {title:"data" label:"\fbdata\fn"
- shape:box
-}
- node: {title:"data.clientmodule_test" label:"\fbdata.clientmodule_test\fn"
- shape:box
-}
- node: {title:"data.property_pattern" label:"\fbdata.property_pattern\fn"
- shape:box
-}
- node: {title:"data.suppliermodule_test" label:"\fbdata.suppliermodule_test\fn"
- shape:box
-}
- edge: {sourcename:"data.clientmodule_test" targetname:"data.suppliermodule_test" arrowstyle:solid
- backarrowstyle:none
- backarrowsize:0
-}
-}
diff --git a/tests/pyreverse/test_printer.py b/tests/pyreverse/test_printer.py
index 4248e8bae..df8bc6367 100644
--- a/tests/pyreverse/test_printer.py
+++ b/tests/pyreverse/test_printer.py
@@ -10,7 +10,6 @@ from astroid import nodes
from pylint.pyreverse.dot_printer import DotPrinter
from pylint.pyreverse.plantuml_printer import PlantUmlPrinter
from pylint.pyreverse.printer import Layout, NodeType, Printer
-from pylint.pyreverse.vcg_printer import VCGPrinter
@pytest.mark.parametrize(
@@ -20,10 +19,6 @@ from pylint.pyreverse.vcg_printer import VCGPrinter
(Layout.BOTTOM_TO_TOP, DotPrinter, "rankdir=BT", -2),
(Layout.LEFT_TO_RIGHT, DotPrinter, "rankdir=LR", -2),
(Layout.RIGHT_TO_LEFT, DotPrinter, "rankdir=RL", -2),
- (Layout.TOP_TO_BOTTOM, VCGPrinter, "orientation:top_to_bottom", -1),
- (Layout.BOTTOM_TO_TOP, VCGPrinter, "orientation:bottom_to_top", -1),
- (Layout.LEFT_TO_RIGHT, VCGPrinter, "orientation:left_to_right", -1),
- (Layout.RIGHT_TO_LEFT, VCGPrinter, "orientation:right_to_left", -1),
(Layout.TOP_TO_BOTTOM, PlantUmlPrinter, "top to bottom direction", -1),
(Layout.LEFT_TO_RIGHT, PlantUmlPrinter, "left to right direction", -1),
],
diff --git a/tests/pyreverse/test_printer_factory.py b/tests/pyreverse/test_printer_factory.py
index 76406f0a8..6b1135a84 100644
--- a/tests/pyreverse/test_printer_factory.py
+++ b/tests/pyreverse/test_printer_factory.py
@@ -12,13 +12,11 @@ from pylint.pyreverse import printer_factory
from pylint.pyreverse.dot_printer import DotPrinter
from pylint.pyreverse.plantuml_printer import PlantUmlPrinter
from pylint.pyreverse.printer import Printer
-from pylint.pyreverse.vcg_printer import VCGPrinter
@pytest.mark.parametrize(
"filetype, expected_printer_class",
[
- ("vcg", VCGPrinter),
("dot", DotPrinter),
("puml", PlantUmlPrinter),
("plantuml", PlantUmlPrinter),
diff --git a/tests/pyreverse/test_writer.py b/tests/pyreverse/test_writer.py
index c5a78d383..c68eb1adf 100644
--- a/tests/pyreverse/test_writer.py
+++ b/tests/pyreverse/test_writer.py
@@ -41,7 +41,6 @@ TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data")
DOT_FILES = ["packages_No_Name.dot", "classes_No_Name.dot"]
COLORIZED_DOT_FILES = ["packages_colorized.dot", "classes_colorized.dot"]
-VCG_FILES = ["packages_No_Name.vcg", "classes_No_Name.vcg"]
PUML_FILES = ["packages_No_Name.puml", "classes_No_Name.puml"]
COLORIZED_PUML_FILES = ["packages_colorized.puml", "classes_colorized.puml"]
MMD_FILES = ["packages_No_Name.mmd", "classes_No_Name.mmd"]
@@ -89,15 +88,6 @@ def setup_colorized_dot(
@pytest.fixture()
-def setup_vcg(
- vcg_config: PyreverseConfig, get_project: GetProjectCallable
-) -> Iterator[None]:
- writer = DiagramWriter(vcg_config)
- project = get_project(TEST_DATA_DIR)
- yield from _setup(project, vcg_config, writer)
-
-
-@pytest.fixture()
def setup_puml(
puml_config: PyreverseConfig, get_project: GetProjectCallable
) -> Iterator[None]:
@@ -148,7 +138,6 @@ def _setup(
for fname in (
DOT_FILES
+ COLORIZED_DOT_FILES
- + VCG_FILES
+ PUML_FILES
+ COLORIZED_PUML_FILES
+ MMD_FILES
@@ -172,12 +161,6 @@ def test_colorized_dot_files(generated_file: str) -> None:
_assert_files_are_equal(generated_file)
-@pytest.mark.usefixtures("setup_vcg")
-@pytest.mark.parametrize("generated_file", VCG_FILES)
-def test_vcg_files(generated_file: str) -> None:
- _assert_files_are_equal(generated_file)
-
-
@pytest.mark.usefixtures("setup_puml")
@pytest.mark.parametrize("generated_file", PUML_FILES)
def test_puml_files(generated_file: str) -> None: