diff --git a/pylint/testutils/pyreverse.py b/pylint/testutils/pyreverse.py index c621f9e7a9..9e66471831 100644 --- a/pylint/testutils/pyreverse.py +++ b/pylint/testutils/pyreverse.py @@ -110,6 +110,34 @@ def get_functional_test_files( return test_files +def get_functional_test_packages( + root_directory: Path, +) -> list[FunctionalPyreverseTestfile]: + """Treat every subdirectory as a package and get all functional test files.""" + test_files = [] + for package_directory in root_directory.iterdir(): + package_name = package_directory.name + config_file = package_directory / f"{package_name}.rc" + if config_file.exists(): + test_files.append( + FunctionalPyreverseTestfile( + source=package_directory, options=_read_config(config_file) + ) + ) + else: + test_files.append( + FunctionalPyreverseTestfile( + source=package_directory, + options={ + "source_roots": [], + "output_formats": ["mmd"], + "command_line_args": [], + }, + ) + ) + return test_files + + def _read_config(config_file: Path) -> TestFileOptions: config = configparser.ConfigParser() config.read(str(config_file)) diff --git a/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.mmd b/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.mmd new file mode 100644 index 0000000000..9b48a3d31f --- /dev/null +++ b/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.mmd @@ -0,0 +1,11 @@ +classDiagram + class AbstractParent { + } + class Child { + } + class ConcreteChild { + } + class GenericParent { + } + Child --|> AbstractParent + ConcreteChild --|> GenericParent diff --git a/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.py b/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.py new file mode 100644 index 0000000000..94fab0fd33 --- /dev/null +++ b/tests/pyreverse/functional/class_diagrams/inheritance/complex_inheritance.py @@ -0,0 +1,24 @@ +from abc import ABC +from dataclasses import dataclass +from typing import Generic, TypeVar + + +@dataclass +class AbstractParent(ABC): + """parent class""" + + +@dataclass +class Child(AbstractParent): + """child class""" + + +GenericType = TypeVar("GenericType") + + +class GenericParent(Generic[GenericType]): + """parent class""" + + +class ConcreteChild(GenericParent[int]): + """child class""" diff --git a/tests/pyreverse/functional/packages/complex_inheritance/__init__.py b/tests/pyreverse/functional/packages/complex_inheritance/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/pyreverse/functional/packages/complex_inheritance/child.py b/tests/pyreverse/functional/packages/complex_inheritance/child.py new file mode 100644 index 0000000000..7a676afda7 --- /dev/null +++ b/tests/pyreverse/functional/packages/complex_inheritance/child.py @@ -0,0 +1,9 @@ +from dataclasses import dataclass + +from parent import AbstractParent + + +@dataclass +class Child(AbstractParent): + """child class""" + pass diff --git a/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.mmd b/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.mmd new file mode 100644 index 0000000000..bc505a79ba --- /dev/null +++ b/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.mmd @@ -0,0 +1,6 @@ +classDiagram + class Child { + } + class AbstractParent { + } + Child --|> AbstractParent diff --git a/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.rc b/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.rc new file mode 100644 index 0000000000..3af8d24084 --- /dev/null +++ b/tests/pyreverse/functional/packages/complex_inheritance/complex_inheritance.rc @@ -0,0 +1,2 @@ +[testoptions] +command_line_args=-ASmy diff --git a/tests/pyreverse/functional/packages/complex_inheritance/parent.py b/tests/pyreverse/functional/packages/complex_inheritance/parent.py new file mode 100644 index 0000000000..301fbd2030 --- /dev/null +++ b/tests/pyreverse/functional/packages/complex_inheritance/parent.py @@ -0,0 +1,7 @@ +from abc import ABC +from dataclasses import dataclass + + +@dataclass +class AbstractParent(ABC): + """parent class""" diff --git a/tests/pyreverse/test_pyreverse_functional.py b/tests/pyreverse/test_pyreverse_functional.py index 715ad3dada..beeb0330be 100644 --- a/tests/pyreverse/test_pyreverse_functional.py +++ b/tests/pyreverse/test_pyreverse_functional.py @@ -10,12 +10,18 @@ from pylint.testutils.pyreverse import ( FunctionalPyreverseTestfile, get_functional_test_files, + get_functional_test_packages, ) FUNCTIONAL_DIR = Path(__file__).parent / "functional" CLASS_DIAGRAMS_DIR = FUNCTIONAL_DIR / "class_diagrams" CLASS_DIAGRAM_TESTS = get_functional_test_files(CLASS_DIAGRAMS_DIR) CLASS_DIAGRAM_TEST_IDS = [testfile.source.stem for testfile in CLASS_DIAGRAM_TESTS] +PACKAGE_DIAGRAMS_DIR = FUNCTIONAL_DIR / "packages" +PACKAGE_DIAGRAM_TESTS = get_functional_test_packages(PACKAGE_DIAGRAMS_DIR) +PACKAGE_DIAGRAM_TEST_IDS = [ + test_package.source.name for test_package in PACKAGE_DIAGRAM_TESTS +] @pytest.mark.parametrize( @@ -49,3 +55,36 @@ def test_class_diagrams(testfile: FunctionalPyreverseTestfile, tmp_path: Path) - assert testfile.source.with_suffix(f".{output_format}").read_text( encoding="utf8" ) == (tmp_path / f"classes.{output_format}").read_text(encoding="utf8") + + +@pytest.mark.parametrize( + "test_package", + PACKAGE_DIAGRAM_TESTS, + ids=PACKAGE_DIAGRAM_TEST_IDS, +) +def test_packages(test_package: FunctionalPyreverseTestfile, tmp_path: Path) -> None: + input_path = test_package.source + if test_package.options["source_roots"]: + source_roots = ",".join( + [ + os.path.realpath( + os.path.expanduser(os.path.join(input_path, source_root)) + ) + for source_root in test_package.options["source_roots"] + ] + ) + else: + source_roots = "" + for output_format in test_package.options["output_formats"]: + output_file = input_path / f"{input_path.name}.{output_format}" + with pytest.raises(SystemExit) as sys_exit: + args = ["-o", f"{output_format}", "-d", str(tmp_path)] + if source_roots: + args += ["--source-roots", source_roots] + args.extend(test_package.options["command_line_args"]) + args += [str(input_path)] + Run(args) + assert sys_exit.value.code == 0 + assert output_file.read_text(encoding="utf8") == ( + tmp_path / f"classes.{output_format}" + ).read_text(encoding="utf8")