diff options
author | Andreas Finkler <3929834+DudeNr33@users.noreply.github.com> | 2023-03-10 21:24:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-10 21:24:37 +0100 |
commit | ceb241047100db4821aaf9bd0edcbe4c4f5d86fc (patch) | |
tree | 163ad6c1ae9e6c7dea1fb0de6a85760e77308c6b | |
parent | ab20812ad0e9ca17cc3bc32dbf34be575dcea502 (diff) | |
download | pylint-git-ceb241047100db4821aaf9bd0edcbe4c4f5d86fc.tar.gz |
pyreverse: drop support for .vcg format (#8426)
-rw-r--r-- | doc/pyreverse.rst | 2 | ||||
-rw-r--r-- | doc/whatsnew/fragments/8416.breaking | 3 | ||||
-rw-r--r-- | pylint/pyreverse/main.py | 1 | ||||
-rw-r--r-- | pylint/pyreverse/printer_factory.py | 2 | ||||
-rw-r--r-- | pylint/pyreverse/vcg_printer.py | 296 | ||||
-rw-r--r-- | pylint/pyreverse/writer.py | 2 | ||||
-rw-r--r-- | tests/pyreverse/conftest.py | 7 | ||||
-rw-r--r-- | tests/pyreverse/data/classes_No_Name.vcg | 50 | ||||
-rw-r--r-- | tests/pyreverse/data/packages_No_Name.vcg | 23 | ||||
-rw-r--r-- | tests/pyreverse/test_printer.py | 5 | ||||
-rw-r--r-- | tests/pyreverse/test_printer_factory.py | 2 | ||||
-rw-r--r-- | tests/pyreverse/test_writer.py | 17 |
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:"\fb09CustomException\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: |