From 89cd646ea8c9cdee041c12fa543ef0cad2128b12 Mon Sep 17 00:00:00 2001 From: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> Date: Sun, 17 Oct 2021 10:33:57 +0200 Subject: pyreverse - Add project modules to sys.path (#4856) * pyreverse - Add project modules to sys.path - Use the fix_import_path context manager in the existing pyreverse tests - Style refactor: - Use a constant for the path - Move the constants closer to the top of the module - Add a test for the fix_import_path context manager to ensure the project root directory is in sys.path - Prevent re-defining from outer scope - Add a type-hint & docstrings Closes #2479 --- ChangeLog | 4 ++++ pylint/pyreverse/main.py | 15 +++++---------- tests/pyreverse/conftest.py | 5 ++++- tests/pyreverse/test_main.py | 31 +++++++++++++++++++++++++++++++ tests/pyreverse/test_writer.py | 29 +++++++++++++---------------- 5 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 tests/pyreverse/test_main.py diff --git a/ChangeLog b/ChangeLog index 6fc6d0f6c..99f40212d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -69,6 +69,10 @@ Release date: TBA .. Put bug fixes that should not wait for a new minor version here +* Pyreverse - Add the project root directory to sys.path + + Closes #2479 + * Don't emit ``consider-using-f-string`` if ``py-version`` is set to Python < ``3.6``. ``f-strings`` were added in Python ``3.6`` diff --git a/pylint/pyreverse/main.py b/pylint/pyreverse/main.py index 0fe8f5f21..55e416e3b 100644 --- a/pylint/pyreverse/main.py +++ b/pylint/pyreverse/main.py @@ -22,11 +22,11 @@ create UML diagrams for classes and modules in """ -import os import sys from typing import Iterable from pylint.config import ConfigurationMixIn +from pylint.lint.utils import fix_import_path from pylint.pyreverse import writer from pylint.pyreverse.diadefslib import DiadefsHandler from pylint.pyreverse.inspector import Linker, project_from_files @@ -213,20 +213,15 @@ class Run(ConfigurationMixIn): if not args: print(self.help()) return 1 - # insert current working directory to the python path to recognize - # dependencies to local modules even if cwd is not in the PYTHONPATH - sys.path.insert(0, os.getcwd()) - try: + with fix_import_path(args): project = project_from_files( args, project_name=self.config.project, black_list=self.config.ignore_list, ) - linker = Linker(project, tag=True) - handler = DiadefsHandler(self.config) - diadefs = handler.get_diadefs(project, linker) - finally: - sys.path.pop(0) + linker = Linker(project, tag=True) + handler = DiadefsHandler(self.config) + diadefs = handler.get_diadefs(project, linker) writer.DiagramWriter(self.config).write(diadefs) return 0 diff --git a/tests/pyreverse/conftest.py b/tests/pyreverse/conftest.py index cb9e0780a..9536fbcb0 100644 --- a/tests/pyreverse/conftest.py +++ b/tests/pyreverse/conftest.py @@ -3,6 +3,7 @@ from typing import Callable, Optional import pytest from astroid.nodes.scoped_nodes import Module +from pylint.lint import fix_import_path from pylint.pyreverse.inspector import Project, project_from_files from pylint.testutils.pyreverse import PyreverseConfig @@ -50,6 +51,8 @@ def get_project() -> Callable: def _astroid_wrapper(func: Callable, modname: str) -> Module: return func(modname) - return project_from_files([module], _astroid_wrapper, project_name=name) + with fix_import_path([module]): + project = project_from_files([module], _astroid_wrapper, project_name=name) + return project return _get_project diff --git a/tests/pyreverse/test_main.py b/tests/pyreverse/test_main.py new file mode 100644 index 000000000..792bcbb8b --- /dev/null +++ b/tests/pyreverse/test_main.py @@ -0,0 +1,31 @@ +"""Unittest for the main module""" +import os +import sys +from typing import Iterator + +import pytest + +from pylint.lint import fix_import_path + +TEST_DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "data")) +PROJECT_ROOT_DIR = os.path.abspath(os.path.join(TEST_DATA_DIR, "..")) + + +@pytest.fixture(params=[PROJECT_ROOT_DIR, TEST_DATA_DIR]) +def setup_path(request) -> Iterator: + current_sys_path = list(sys.path) + sys.path[:] = [] + current_dir = os.getcwd() + os.chdir(request.param) + yield + os.chdir(current_dir) + sys.path[:] = current_sys_path + + +@pytest.mark.usefixtures("setup_path") +def test_project_root_in_sys_path(): + """Test the context manager adds the project root directory to sys.path. + This should happen when pyreverse is run from any directory + """ + with fix_import_path([TEST_DATA_DIR]): + assert sys.path == [PROJECT_ROOT_DIR] diff --git a/tests/pyreverse/test_writer.py b/tests/pyreverse/test_writer.py index 9826dfa39..dc6394262 100644 --- a/tests/pyreverse/test_writer.py +++ b/tests/pyreverse/test_writer.py @@ -51,6 +51,14 @@ _DEFAULTS = { "output_directory": "", } +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"] + class Config: """config object for tests""" @@ -74,17 +82,10 @@ def _file_lines(path: str) -> List[str]: return [line for line in lines if line] -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"] - - @pytest.fixture() def setup_dot(default_config: PyreverseConfig, get_project: Callable) -> Iterator: writer = DiagramWriter(default_config) - project = get_project(os.path.join(os.path.dirname(__file__), "..", "data")) + project = get_project(TEST_DATA_DIR) yield from _setup(project, default_config, writer) @@ -93,23 +94,21 @@ def setup_colorized_dot( colorized_dot_config: PyreverseConfig, get_project: Callable ) -> Iterator: writer = DiagramWriter(colorized_dot_config) - project = get_project( - os.path.join(os.path.dirname(__file__), "..", "data"), name="colorized" - ) + project = get_project(TEST_DATA_DIR, name="colorized") yield from _setup(project, colorized_dot_config, writer) @pytest.fixture() def setup_vcg(vcg_config: PyreverseConfig, get_project: Callable) -> Iterator: writer = DiagramWriter(vcg_config) - project = get_project(os.path.join(os.path.dirname(__file__), "..", "data")) + project = get_project(TEST_DATA_DIR) yield from _setup(project, vcg_config, writer) @pytest.fixture() def setup_puml(puml_config: PyreverseConfig, get_project: Callable) -> Iterator: writer = DiagramWriter(puml_config) - project = get_project(os.path.join(os.path.dirname(__file__), "..", "data")) + project = get_project(TEST_DATA_DIR) yield from _setup(project, puml_config, writer) @@ -118,9 +117,7 @@ def setup_colorized_puml( colorized_puml_config: PyreverseConfig, get_project: Callable ) -> Iterator: writer = DiagramWriter(colorized_puml_config) - project = get_project( - os.path.join(os.path.dirname(__file__), "..", "data"), name="colorized" - ) + project = get_project(TEST_DATA_DIR, name="colorized") yield from _setup(project, colorized_puml_config, writer) -- cgit v1.2.1