# Copyright (c) 2008, 2010, 2013 LOGILAB S.A. (Paris, FRANCE) # Copyright (c) 2014-2018, 2020 Claudiu Popa # Copyright (c) 2014 Google, Inc. # Copyright (c) 2014 Arun Persaud # Copyright (c) 2015 Ionel Cristian Maries # Copyright (c) 2016 Derek Gustafson # Copyright (c) 2018 Ville Skyttä # Copyright (c) 2019-2021 Pierre Sassoulas # Copyright (c) 2019 Ashley Whetter # Copyright (c) 2020 hippo91 # Copyright (c) 2020 Anthony Sottile # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/COPYING """ unit test for visitors.diadefs and extensions.diadefslib modules """ import codecs import os from difflib import unified_diff import pytest from pylint.pyreverse.diadefslib import DefaultDiadefGenerator, DiadefsHandler from pylint.pyreverse.inspector import Linker, project_from_files from pylint.pyreverse.utils import get_visibility from pylint.pyreverse.writer import DotWriter _DEFAULTS = { "all_ancestors": None, "show_associated": None, "module_names": None, "output_format": "dot", "diadefs_file": None, "quiet": 0, "show_ancestors": None, "classes": (), "all_associated": None, "mode": "PUB_ONLY", "show_builtin": False, "only_classnames": False, "output_directory": "", } class Config: """config object for tests""" def __init__(self): for attr, value in _DEFAULTS.items(): setattr(self, attr, value) def _file_lines(path): # we don't care about the actual encoding, but python3 forces us to pick one with codecs.open(path, encoding="latin1") as stream: lines = [ line.strip() for line in stream.readlines() if ( line.find("squeleton generated by ") == -1 and not line.startswith('__revision__ = "$Id:') ) ] return [line for line in lines if line] def get_project(module, name="No Name"): """return an astroid project representation""" def _astroid_wrapper(func, modname): return func(modname) return project_from_files([module], _astroid_wrapper, project_name=name) DOT_FILES = ["packages_No_Name.dot", "classes_No_Name.dot"] @pytest.fixture(scope="module") def setup(): project = get_project(os.path.join(os.path.dirname(__file__), "data")) linker = Linker(project) CONFIG = Config() handler = DiadefsHandler(CONFIG) dd = DefaultDiadefGenerator(linker, handler).visit(project) for diagram in dd: diagram.extract_relationships() writer = DotWriter(CONFIG) writer.write(dd) yield for fname in DOT_FILES: try: os.remove(fname) except FileNotFoundError: continue @pytest.mark.usefixtures("setup") @pytest.mark.parametrize("generated_file", DOT_FILES) def test_dot_files(generated_file): expected_file = os.path.join(os.path.dirname(__file__), "data", generated_file) generated = _file_lines(generated_file) expected = _file_lines(expected_file) generated = "\n".join(generated) expected = "\n".join(expected) files = f"\n *** expected : {expected_file}, generated : {generated_file} \n" diff = "\n".join( line for line in unified_diff(expected.splitlines(), generated.splitlines()) ) assert expected == generated, f"{files}{diff}" os.remove(generated_file) @pytest.mark.parametrize( "names, expected", [ (["__reduce_ex__", "__setattr__"], "special"), (["__g_", "____dsf", "__23_9"], "private"), (["simple"], "public"), ( ["_", "__", "___", "____", "_____", "___e__", "_nextsimple", "_filter_it_"], "protected", ), ], ) def test_get_visibility(names, expected): for name in names: got = get_visibility(name) assert got == expected, f"got {got} instead of {expected} for value {name}"