summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAlexey Pelykh <alexey.pelykh@gmail.com>2023-02-09 20:16:02 +0100
committerGitHub <noreply@github.com>2023-02-09 20:16:02 +0100
commit71b6325c8499c8a66e90d90e88c75d7c7ab13b23 (patch)
tree5469f59cc6762feef6721f57f71d84f56ed81bb2 /tests
parent70e2178dcaecdc4e90ac1cb45e06be261bd1e03b (diff)
downloadpylint-git-71b6325c8499c8a66e90d90e88c75d7c7ab13b23.tar.gz
Support Implicit Namespace Packages (PEP 420) (#8153)
Co-authored-by: Andreas Finkler <3929834+DudeNr33@users.noreply.github.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/lint/unittest_expand_modules.py3
-rw-r--r--tests/lint/unittest_lint.py72
-rw-r--r--tests/primer/packages_to_prime.json5
-rw-r--r--tests/pyreverse/conftest.py4
-rw-r--r--tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.dot5
-rw-r--r--tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.mmd3
-rw-r--r--tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.puml5
-rw-r--r--tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.py2
-rw-r--r--tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.rc3
-rw-r--r--tests/pyreverse/test_main.py4
-rw-r--r--tests/pyreverse/test_pyreverse_functional.py19
-rw-r--r--tests/regrtest_data/pep420/basic/project/namespace/package/__init__.py0
-rw-r--r--tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/__init__.py5
-rw-r--r--tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/wrapper/__init__.py5
-rw-r--r--tests/test_check_parallel.py20
-rw-r--r--tests/test_deprecation.py14
16 files changed, 147 insertions, 22 deletions
diff --git a/tests/lint/unittest_expand_modules.py b/tests/lint/unittest_expand_modules.py
index 1c3f23b00..a8c46498c 100644
--- a/tests/lint/unittest_expand_modules.py
+++ b/tests/lint/unittest_expand_modules.py
@@ -151,6 +151,7 @@ class TestExpandModules(CheckerTestCase):
ignore_list_re: list[re.Pattern[str]] = []
modules, errors = expand_modules(
files_or_modules,
+ [],
ignore_list,
ignore_list_re,
self.linter.config.ignore_paths,
@@ -180,6 +181,7 @@ class TestExpandModules(CheckerTestCase):
ignore_list_re: list[re.Pattern[str]] = []
modules, errors = expand_modules(
files_or_modules,
+ [],
ignore_list,
ignore_list_re,
self.linter.config.ignore_paths,
@@ -209,6 +211,7 @@ class TestExpandModules(CheckerTestCase):
ignore_list_re: list[re.Pattern[str]] = []
modules, errors = expand_modules(
files_or_modules,
+ [],
ignore_list,
ignore_list_re,
self.linter.config.ignore_paths,
diff --git a/tests/lint/unittest_lint.py b/tests/lint/unittest_lint.py
index 3c91eba7f..23cde4967 100644
--- a/tests/lint/unittest_lint.py
+++ b/tests/lint/unittest_lint.py
@@ -39,8 +39,7 @@ from pylint.constants import (
_warn_about_old_home,
)
from pylint.exceptions import InvalidMessageError
-from pylint.lint import PyLinter
-from pylint.lint.utils import fix_import_path
+from pylint.lint import PyLinter, expand_modules
from pylint.message import Message
from pylint.reporters import text
from pylint.testutils import create_files
@@ -117,8 +116,17 @@ def fake_path() -> Iterator[list[str]]:
sys.path[:] = orig
+def test_deprecated() -> None:
+ """Test that fix_import_path() and get_python_path() are deprecated"""
+ with tempdir():
+ create_files(["__init__.py"])
+ with pytest.deprecated_call():
+ with lint.fix_import_path([""]):
+ expand_modules.get_python_path("__init__.py")
+
+
def test_no_args(fake_path: list[str]) -> None:
- with lint.fix_import_path([]):
+ with lint.augmented_sys_path([]):
assert sys.path == fake_path
assert sys.path == fake_path
@@ -131,8 +139,12 @@ def test_one_arg(fake_path: list[str], case: list[str]) -> None:
create_files(["a/b/__init__.py"])
expected = [join(chroot, "a")] + fake_path
+ extra_sys_paths = [
+ expand_modules.discover_package_path(arg, []) for arg in case
+ ]
+
assert sys.path == fake_path
- with lint.fix_import_path(case):
+ with lint.augmented_sys_path(extra_sys_paths):
assert sys.path == expected
assert sys.path == fake_path
@@ -151,8 +163,12 @@ def test_two_similar_args(fake_path: list[str], case: list[str]) -> None:
create_files(["a/b/__init__.py", "a/c/__init__.py"])
expected = [join(chroot, "a")] + fake_path
+ extra_sys_paths = [
+ expand_modules.discover_package_path(arg, []) for arg in case
+ ]
+
assert sys.path == fake_path
- with lint.fix_import_path(case):
+ with lint.augmented_sys_path(extra_sys_paths):
assert sys.path == expected
assert sys.path == fake_path
@@ -173,8 +189,12 @@ def test_more_args(fake_path: list[str], case: list[str]) -> None:
for suffix in (sep.join(("a", "b")), "a", sep.join(("a", "e")))
] + fake_path
+ extra_sys_paths = [
+ expand_modules.discover_package_path(arg, []) for arg in case
+ ]
+
assert sys.path == fake_path
- with lint.fix_import_path(case):
+ with lint.augmented_sys_path(extra_sys_paths):
assert sys.path == expected
assert sys.path == fake_path
@@ -1188,6 +1208,39 @@ def test_recursive_ignore(ignore_parameter: str, ignore_parameter_value: str) ->
assert module in linted_file_paths
+def test_recursive_implicit_namespace() -> None:
+ run = Run(
+ [
+ "--verbose",
+ "--recursive",
+ "y",
+ "--source-roots",
+ join(REGRTEST_DATA_DIR, "pep420", "basic", "project"),
+ join(REGRTEST_DATA_DIR, "pep420", "basic"),
+ ],
+ exit=False,
+ )
+ run.linter.set_reporter(testutils.GenericTestReporter())
+ run.linter.check([join(REGRTEST_DATA_DIR, "pep420", "basic")])
+ assert run.linter.file_state.base_name == "namespace.package"
+
+
+def test_recursive_implicit_namespace_wrapper() -> None:
+ run = Run(
+ [
+ "--recursive",
+ "y",
+ "--source-roots",
+ join(REGRTEST_DATA_DIR, "pep420", "wrapper", "project"),
+ join(REGRTEST_DATA_DIR, "pep420", "wrapper"),
+ ],
+ exit=False,
+ )
+ run.linter.set_reporter(testutils.GenericTestReporter())
+ run.linter.check([join(REGRTEST_DATA_DIR, "pep420", "wrapper")])
+ assert run.linter.reporter.messages == []
+
+
def test_relative_imports(initialized_linter: PyLinter) -> None:
"""Regression test for https://github.com/PyCQA/pylint/issues/3651"""
linter = initialized_linter
@@ -1235,8 +1288,10 @@ print(submodule1)
"""
)
os.chdir("namespace")
+ extra_sys_paths = [expand_modules.discover_package_path(tmpdir, [])]
+
# Add the parent directory to sys.path
- with fix_import_path([tmpdir]):
+ with lint.augmented_sys_path(extra_sys_paths):
linter.check(["submodule2.py"])
assert not linter.stats.by_msg
@@ -1257,6 +1312,7 @@ def test_lint_namespace_package_under_dir_on_path(initialized_linter: PyLinter)
with tempdir() as tmpdir:
create_files(["namespace_on_path/submodule1.py"])
os.chdir(tmpdir)
- with fix_import_path([tmpdir]):
+ extra_sys_paths = [expand_modules.discover_package_path(tmpdir, [])]
+ with lint.augmented_sys_path(extra_sys_paths):
linter.check(["namespace_on_path"])
assert linter.file_state.base_name == "namespace_on_path"
diff --git a/tests/primer/packages_to_prime.json b/tests/primer/packages_to_prime.json
index 547c3ea58..fa1457773 100644
--- a/tests/primer/packages_to_prime.json
+++ b/tests/primer/packages_to_prime.json
@@ -61,7 +61,8 @@
},
"poetry-core": {
"branch": "main",
- "directories": ["src/poetry/core"],
- "url": "https://github.com/python-poetry/poetry-core"
+ "directories": ["src"],
+ "url": "https://github.com/python-poetry/poetry-core",
+ "pylint_additional_args": ["--recursive=y", "--source-roots=src"]
}
}
diff --git a/tests/pyreverse/conftest.py b/tests/pyreverse/conftest.py
index a37e4bde1..02a19e613 100644
--- a/tests/pyreverse/conftest.py
+++ b/tests/pyreverse/conftest.py
@@ -9,7 +9,7 @@ from collections.abc import Callable
import pytest
from astroid.nodes.scoped_nodes import Module
-from pylint.lint import fix_import_path
+from pylint.lint import augmented_sys_path, discover_package_path
from pylint.pyreverse.inspector import Project, project_from_files
from pylint.testutils.pyreverse import PyreverseConfig
from pylint.typing import GetProjectCallable
@@ -74,7 +74,7 @@ def get_project() -> GetProjectCallable:
def _astroid_wrapper(func: Callable[[str], Module], modname: str) -> Module:
return func(modname)
- with fix_import_path([module]):
+ with augmented_sys_path([discover_package_path(module, [])]):
project = project_from_files([module], _astroid_wrapper, project_name=name)
return project
diff --git a/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.dot b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.dot
new file mode 100644
index 000000000..b01a46f38
--- /dev/null
+++ b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.dot
@@ -0,0 +1,5 @@
+digraph "classes" {
+rankdir=BT
+charset="utf-8"
+"namespaces.pep420.pep420.PEP420" [color="black", fontcolor="black", label=<{PEP420|<br ALIGN="LEFT"/>|}>, shape="record", style="solid"];
+}
diff --git a/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.mmd b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.mmd
new file mode 100644
index 000000000..4deda423b
--- /dev/null
+++ b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.mmd
@@ -0,0 +1,3 @@
+classDiagram
+ class PEP420 {
+ }
diff --git a/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.puml b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.puml
new file mode 100644
index 000000000..5819158ae
--- /dev/null
+++ b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.puml
@@ -0,0 +1,5 @@
+@startuml classes
+set namespaceSeparator none
+class "PEP420" as namespaces.pep420.pep420.PEP420 {
+}
+@enduml
diff --git a/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.py b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.py
new file mode 100644
index 000000000..f2d568c47
--- /dev/null
+++ b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.py
@@ -0,0 +1,2 @@
+class PEP420:
+ pass
diff --git a/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.rc b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.rc
new file mode 100644
index 000000000..0ae3403a9
--- /dev/null
+++ b/tests/pyreverse/functional/class_diagrams/namespaces/pep420/pep420.rc
@@ -0,0 +1,3 @@
+[testoptions]
+source_roots=../..
+output_formats=mmd,dot,puml
diff --git a/tests/pyreverse/test_main.py b/tests/pyreverse/test_main.py
index 4cc0573d6..1e6196270 100644
--- a/tests/pyreverse/test_main.py
+++ b/tests/pyreverse/test_main.py
@@ -16,7 +16,7 @@ import pytest
from _pytest.capture import CaptureFixture
from _pytest.fixtures import SubRequest
-from pylint.lint import fix_import_path
+from pylint.lint import augmented_sys_path, discover_package_path
from pylint.pyreverse import main
TEST_DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "data"))
@@ -61,7 +61,7 @@ def test_project_root_in_sys_path() -> None:
"""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]):
+ with augmented_sys_path([discover_package_path(TEST_DATA_DIR, [])]):
assert sys.path == [PROJECT_ROOT_DIR]
diff --git a/tests/pyreverse/test_pyreverse_functional.py b/tests/pyreverse/test_pyreverse_functional.py
index 15fd1978b..aab500b81 100644
--- a/tests/pyreverse/test_pyreverse_functional.py
+++ b/tests/pyreverse/test_pyreverse_functional.py
@@ -1,7 +1,7 @@
# 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
-
+import os
from pathlib import Path
import pytest
@@ -13,7 +13,8 @@ from pylint.testutils.pyreverse import (
)
FUNCTIONAL_DIR = Path(__file__).parent / "functional"
-CLASS_DIAGRAM_TESTS = get_functional_test_files(FUNCTIONAL_DIR / "class_diagrams")
+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]
@@ -24,9 +25,23 @@ CLASS_DIAGRAM_TEST_IDS = [testfile.source.stem for testfile in CLASS_DIAGRAM_TES
)
def test_class_diagrams(testfile: FunctionalPyreverseTestfile, tmp_path: Path) -> None:
input_file = testfile.source
+ input_path = os.path.dirname(input_file)
+ if testfile.options["source_roots"]:
+ source_roots = ",".join(
+ [
+ os.path.realpath(
+ os.path.expanduser(os.path.join(input_path, source_root))
+ )
+ for source_root in testfile.options["source_roots"]
+ ]
+ )
+ else:
+ source_roots = ""
for output_format in testfile.options["output_formats"]:
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(testfile.options["command_line_args"])
args += [str(input_file)]
Run(args)
diff --git a/tests/regrtest_data/pep420/basic/project/namespace/package/__init__.py b/tests/regrtest_data/pep420/basic/project/namespace/package/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/regrtest_data/pep420/basic/project/namespace/package/__init__.py
diff --git a/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/__init__.py b/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/__init__.py
new file mode 100644
index 000000000..8bd4f6df2
--- /dev/null
+++ b/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/__init__.py
@@ -0,0 +1,5 @@
+"""
+A drop-in replacement for `logging`.
+"""
+
+from .wrapper import * # noqa: F403
diff --git a/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/wrapper/__init__.py b/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/wrapper/__init__.py
new file mode 100644
index 000000000..50a2ac814
--- /dev/null
+++ b/tests/regrtest_data/pep420/wrapper/project/namespace/package/logging/wrapper/__init__.py
@@ -0,0 +1,5 @@
+"""
+A wrapper for original logging module
+"""
+
+from logging import * # noqa: F403
diff --git a/tests/test_check_parallel.py b/tests/test_check_parallel.py
index 96e67517e..9134d485b 100644
--- a/tests/test_check_parallel.py
+++ b/tests/test_check_parallel.py
@@ -10,6 +10,7 @@ from __future__ import annotations
import argparse
import os
+import sys
from concurrent.futures import ProcessPoolExecutor
from concurrent.futures.process import BrokenProcessPool
from pickle import PickleError
@@ -21,7 +22,7 @@ from astroid import nodes
import pylint.interfaces
import pylint.lint.parallel
from pylint.checkers import BaseRawFileChecker
-from pylint.lint import PyLinter
+from pylint.lint import PyLinter, augmented_sys_path
from pylint.lint.parallel import _worker_check_single_file as worker_check_single_file
from pylint.lint.parallel import _worker_initialize as worker_initialize
from pylint.lint.parallel import check_parallel
@@ -173,6 +174,14 @@ class TestCheckParallelFramework:
worker_initialize(linter=dill.dumps(linter))
assert isinstance(pylint.lint.parallel._worker_linter, type(linter))
+ def test_worker_initialize_with_package_paths(self) -> None:
+ linter = PyLinter(reporter=Reporter())
+ with augmented_sys_path([]):
+ worker_initialize(
+ linter=dill.dumps(linter), extra_packages_paths=["fake-path"]
+ )
+ assert "fake-path" in sys.path
+
@pytest.mark.needs_two_cores
def test_worker_initialize_pickling(self) -> None:
"""Test that we can pickle objects that standard pickling in multiprocessing can't.
@@ -324,7 +333,6 @@ class TestCheckParallel:
linter,
jobs=1,
files=iter(single_file_container),
- arguments=["--enable", "R9999"],
)
assert len(linter.get_checkers()) == 2, (
"We should only have the 'main' and 'sequential-checker' "
@@ -390,7 +398,9 @@ class TestCheckParallel:
# Invoke the lint process in a multi-process way, although we only specify one
# job.
check_parallel(
- linter, jobs=1, files=iter(single_file_container), arguments=None
+ linter,
+ jobs=1,
+ files=iter(single_file_container),
)
assert {
@@ -504,7 +514,6 @@ class TestCheckParallel:
linter,
jobs=num_jobs,
files=file_infos,
- arguments=None,
)
stats_check_parallel = linter.stats
assert linter.msg_status == 0, "We should not fail the lint"
@@ -572,7 +581,6 @@ class TestCheckParallel:
linter,
jobs=num_jobs,
files=file_infos,
- arguments=None,
)
stats_check_parallel = linter.stats
assert str(stats_single_proc.by_msg) == str(
@@ -600,5 +608,5 @@ class TestCheckParallel:
files=iter(single_file_container),
# This will trigger an exception in the initializer for the parallel jobs
# because arguments has to be an Iterable.
- arguments=1, # type: ignore[arg-type]
+ extra_packages_paths=1, # type: ignore[arg-type]
)
diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py
index d30e69b85..ed57c7306 100644
--- a/tests/test_deprecation.py
+++ b/tests/test_deprecation.py
@@ -11,6 +11,7 @@ from typing import Any
import pytest
from astroid import nodes
+from pylint import lint
from pylint.checkers import BaseChecker
from pylint.checkers.mapreduce_checker import MapReduceMixin
from pylint.config import load_results, save_results
@@ -106,3 +107,16 @@ def test_collectblocklines() -> None:
state = FileState("foo", MessageDefinitionStore())
with pytest.warns(DeprecationWarning):
state.collect_block_lines(MessageDefinitionStore(), nodes.Module("foo"))
+
+
+def test_patch_sys_path() -> None:
+ """Test that _patch_sys_path() is deprecated"""
+ with pytest.deprecated_call():
+ lint._patch_sys_path([])
+
+
+def test_fix_import_path() -> None:
+ """Test that fix_import_path() is deprecated"""
+ with pytest.deprecated_call():
+ with lint.fix_import_path([]):
+ pass