From f6142988fba0c8671ac9e0d36f005ea3e5e57763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Wed, 12 Oct 2022 17:05:45 +0200 Subject: [PATCH 1/5] Use the modern tomllib/tomli backends for reading TOML Replace the deprecated `toml` package with the built-in `tomllib` module in Python 3.11, with fallback to the modern `tomli` package in older Python versions. --- pytest_pylint/plugin.py | 13 +++++++++---- setup.py | 6 +++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pytest_pylint/plugin.py b/pytest_pylint/plugin.py index 7cc751d..b37cd77 100644 --- a/pytest_pylint/plugin.py +++ b/pytest_pylint/plugin.py @@ -4,6 +4,7 @@ """ +import sys from collections import defaultdict from configparser import ConfigParser, NoOptionError, NoSectionError from os import getcwd, makedirs, sep @@ -11,13 +12,17 @@ from pathlib import Path import pytest -import toml from pylint import config as pylint_config from pylint import lint from .pylint_util import ProgrammaticReporter from .util import PyLintException, get_rel_path, should_include_file +if sys.version_info >= (3, 11): + import tomllib +else: + import tomli as tomllib + HISTKEY = "pylint/mtimes" PYLINT_CONFIG_CACHE_KEY = "pylintrc" FILL_CHARS = 80 @@ -184,10 +189,10 @@ def _load_rc_file(self, pylintrc_file): pass def _load_pyproject_toml(self, pylintrc_file): - with open(pylintrc_file, "r", encoding="utf-8") as f_p: + with open(pylintrc_file, "rb") as f_p: try: - content = toml.load(f_p) - except (TypeError, toml.decoder.TomlDecodeError): + content = tomllib.load(f_p) + except (TypeError, tomllib.TOMLDecodeError): return try: diff --git a/setup.py b/setup.py index 748a511..4b36780 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,11 @@ packages=["pytest_pylint"], entry_points={"pytest11": ["pylint = pytest_pylint.plugin"]}, python_requires=">=3.7", - install_requires=["pytest>=5.4", "pylint>=2.3.0", "toml>=0.7.1"], + install_requires=[ + "pytest>=5.4", + "pylint>=2.3.0", + "tomli>=1.1.0; python_version < '3.11'", + ], setup_requires=["pytest-runner"], tests_require=["coverage", "flake8", "black", "isort"], classifiers=[ From ca95924b1b909cb4769404fc4ab88dc99773f175 Mon Sep 17 00:00:00 2001 From: Carson Gee Date: Thu, 5 Oct 2023 20:17:59 -0600 Subject: [PATCH 2/5] Update plugin.py --- pytest_pylint/plugin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest_pylint/plugin.py b/pytest_pylint/plugin.py index 63c5f05..23e9403 100644 --- a/pytest_pylint/plugin.py +++ b/pytest_pylint/plugin.py @@ -21,6 +21,7 @@ if sys.version_info >= (3, 11): import tomllib else: + # pylint: disable=import-error import tomli as tomllib HISTKEY = "pylint/mtimes" From 4613bf2cfe9ba1a7c568f2aa4ef67b1cdf395609 Mon Sep 17 00:00:00 2001 From: Carson Gee Date: Thu, 5 Oct 2023 20:57:24 -0600 Subject: [PATCH 3/5] Dropped older pylint and pytest dependencies --- pytest_pylint/plugin.py | 29 +++++++++++------------------ setup.py | 2 +- tox.ini | 13 +++++-------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/pytest_pylint/plugin.py b/pytest_pylint/plugin.py index a5c1b0a..86d343f 100644 --- a/pytest_pylint/plugin.py +++ b/pytest_pylint/plugin.py @@ -105,14 +105,7 @@ def pytest_configure(self, config): if config.option.pylint_rcfile: pylintrc_file = config.option.pylint_rcfile else: - # handling files apart from pylintrc was only introduced in pylint - # 2.5, if we can't use find_default_config_files(), fall back on PYLINTRC - # once we drop support below 2.5 we can get rid of this - try: - pylintrc_file = next(pylint_config.find_default_config_files(), None) - except AttributeError: - # pylint: disable=no-member - pylintrc_file = pylint_config.PYLINTRC + pylintrc_file = next(pylint_config.find_default_config_files(), None) if pylintrc_file and not exists(pylintrc_file): # The directory of pytest.ini got a chance @@ -226,11 +219,11 @@ def pytest_collect_file(self, path, parent): if path.ext != ".py": return None - rel_path = get_rel_path(path.strpath, parent.session.fspath.strpath) + rel_path = get_rel_path(path.strpath, str(parent.session.path)) if should_include_file( rel_path, self.pylint_ignore, self.pylint_ignore_patterns ): - item = PylintFile.from_parent(parent, fspath=path, plugin=self) + item = PylintFile.from_parent(parent, path=Path(path), plugin=self) else: return None @@ -305,15 +298,15 @@ class PylintFile(pytest.File): mtime = None # : float @classmethod - def from_parent(cls, parent, *, fspath, plugin): + def from_parent(cls, parent, *, path, plugin, **kw): + # pylint: disable=arguments-differ # We add the ``plugin`` kwarg to get plugin level information so the # signature differs - # pylint: disable=arguments-differ - _self = getattr(super(), "from_parent", cls)(parent, fspath=fspath) + _self = getattr(super(), "from_parent", cls)(parent, path=path, **kw) _self.plugin = plugin - _self.rel_path = get_rel_path(fspath.strpath, parent.session.fspath.strpath) - _self.mtime = fspath.mtime() + _self.rel_path = get_rel_path(str(path), str(parent.session.path)) + _self.mtime = path.stat().st_mtime prev_mtime = _self.plugin.mtimes.get(_self.rel_path, 0) _self.should_skip = prev_mtime == _self.mtime @@ -330,8 +323,8 @@ class PyLintItem(pytest.Item): parent = None # : PylintFile plugin = None # : PylintPlugin - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, *args, **kw): + super().__init__(*args, **kw) self.add_marker(MARKER) self.plugin = self.parent.plugin @@ -393,4 +386,4 @@ def repr_failure(self, excinfo, style=None): def reportinfo(self): """Generate our test report""" # pylint: disable=no-member - return self.fspath, None, f"[pylint] {self.parent.rel_path}" + return self.path, None, f"[pylint] {self.parent.rel_path}" diff --git a/setup.py b/setup.py index de7dba0..1c4d25d 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ packages=["pytest_pylint"], entry_points={"pytest11": ["pylint = pytest_pylint.plugin"]}, python_requires=">=3.7", - install_requires=["pytest>=5.4,<8.0", "pylint>=2.3.0", "toml>=0.7.1"], + install_requires=["pytest>=7.0", "pylint>=2.13.0", "toml>=0.7.1"], setup_requires=["pytest-runner"], tests_require=["coverage", "flake8", "black", "isort"], classifiers=[ diff --git a/tox.ini b/tox.ini index 4fe59f6..fc98e58 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,8 @@ [tox] envlist = - py3{8, 9}-pylint{26, 30}-pytest{54} - py3{8, 9, 10}-pylint{213, 214, 30}-pytest{71} - py3{8, 9, 10, 11}-pylint{215, latest, main}-pytest{71, latest} - py3{12}-pylint{latest, main}-pytest{71, latest} + py3{8, 9, 10}-pylint{213, 30}-pytest{7} + py3{8, 9, 10, 11}-pylint{213, latest, main}-pytest{7, latest, main} + py3{12}-pylint{latest, main}-pytest{7, latest, main} coverage qa skip_missing_interpreters = true @@ -11,15 +10,13 @@ skip_missing_interpreters = true [testenv] usedevelop = true deps = - pylint30: pylint~=3.0 - pylint26: pylint~=2.6.0 pylint213: pylint~=2.13.9 pylint214: pylint~=2.14.5 - pylint215: pylint~=2.15.0 + pylint30: pylint~=3.0 pylintlatest: pylint pylintmain: git+https://github.com/PyCQA/pylint.git@main#egg=pylint pylintmain: git+https://github.com/PyCQA/astroid.git@main#egg=astroid - pytest7: pytest~=7.1.2 + pytest7: pytest~=7.0.0 pytestlatest: pytest pytestmain: git+https://github.com/pytest-dev/pytest.git@main#egg=pytest coverage From db0edbeacd8d1b5f252d390aca423eb7a4787ac4 Mon Sep 17 00:00:00 2001 From: Carson Gee Date: Thu, 5 Oct 2023 21:37:47 -0600 Subject: [PATCH 4/5] Updated tests to use pathlib --- pytest_pylint/tests/test_pytest_pylint.py | 12 ++++++------ setup.py | 2 +- tox.ini | 7 +++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/pytest_pylint/tests/test_pytest_pylint.py b/pytest_pylint/tests/test_pytest_pylint.py index c26af26..4c87ac3 100644 --- a/pytest_pylint/tests/test_pytest_pylint.py +++ b/pytest_pylint/tests/test_pytest_pylint.py @@ -2,7 +2,7 @@ """ Unit testing module for pytest-pylint plugin """ -import os +import pathlib import re from textwrap import dedent from unittest import mock @@ -312,8 +312,8 @@ def test_output_file(testdir): """Verify pylint report output""" testdir.makepyfile("import sys") testdir.runpytest("--pylint", "--pylint-output-file=pylint.report") - output_file = os.path.join(testdir.tmpdir.strpath, "pylint.report") - assert os.path.isfile(output_file) + output_file = pathlib.Path(testdir.tmpdir.strpath) / "pylint.report" + assert output_file.is_file() with open(output_file, "r", encoding="utf-8") as _file: report = _file.read() @@ -339,10 +339,10 @@ def test_output_file(testdir): def test_output_file_makes_dirs(testdir): """Verify output works with folders properly.""" testdir.makepyfile("import sys") - output_path = os.path.join("reports", "pylint.report") + output_path = pathlib.Path("reports", "pylint.report") testdir.runpytest("--pylint", f"--pylint-output-file={output_path}") - output_file = os.path.join(testdir.tmpdir.strpath, output_path) - assert os.path.isfile(output_file) + output_file = pathlib.Path(testdir.tmpdir.strpath) / output_path + assert output_file.is_file() # Run again to make sure we don't crash trying to make a dir that exists testdir.runpytest("--pylint", f"--pylint-output-file={output_path}") diff --git a/setup.py b/setup.py index 1c4d25d..556488a 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ packages=["pytest_pylint"], entry_points={"pytest11": ["pylint = pytest_pylint.plugin"]}, python_requires=">=3.7", - install_requires=["pytest>=7.0", "pylint>=2.13.0", "toml>=0.7.1"], + install_requires=["pytest>=7.0", "pylint>=2.15.0", "toml>=0.7.1"], setup_requires=["pytest-runner"], tests_require=["coverage", "flake8", "black", "isort"], classifiers=[ diff --git a/tox.ini b/tox.ini index fc98e58..b790165 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = - py3{8, 9, 10}-pylint{213, 30}-pytest{7} - py3{8, 9, 10, 11}-pylint{213, latest, main}-pytest{7, latest, main} + py3{8, 9, 10}-pylint{215, 30}-pytest{7} + py3{8, 9, 10, 11}-pylint{215, latest, main}-pytest{7, latest, main} py3{12}-pylint{latest, main}-pytest{7, latest, main} coverage qa @@ -10,8 +10,7 @@ skip_missing_interpreters = true [testenv] usedevelop = true deps = - pylint213: pylint~=2.13.9 - pylint214: pylint~=2.14.5 + pylint215: pylint~=2.15.10 pylint30: pylint~=3.0 pylintlatest: pylint pylintmain: git+https://github.com/PyCQA/pylint.git@main#egg=pylint From ea70b075c3ef2e872ba41afabec6508145cd432d Mon Sep 17 00:00:00 2001 From: Carson Gee Date: Thu, 5 Oct 2023 22:05:11 -0600 Subject: [PATCH 5/5] Released 0.21.0 --- README.rst | 7 +++++++ setup.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index c3f65bb..9d0ef65 100644 --- a/README.rst +++ b/README.rst @@ -54,6 +54,13 @@ If you want to help development, there is Releases ======== +0.21.0 +~~~~~~ +- Dropped support for pytest < 7.0 in preparation for pytest 8.0 (should work with it when it comes out) +- Dropped support for pylint < 2.15 to work better with Python 3.11 and drop backwards compatibility code +- Use baked in TOML support with fallback to newer tomli library thanks to `mgorny `__ + + 0.20.0 ~~~~~~ - Corrected issues introduced by deprecations in pylint diff --git a/setup.py b/setup.py index 9c1e40f..f966a5e 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ description="pytest plugin to check source code with pylint", long_description=LONG_DESCRIPTION, license="MIT", - version="0.20.0", + version="0.21.0", author="Carson Gee", author_email="x@carsongee.com", url="https://github.com/carsongee/pytest-pylint",