From 3a4ea4e998d9860e327fe115111820d90fedd066 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 11:34:39 +0200 Subject: [PATCH 01/11] 20 - Replaced closure+function to keep state with classes implementing __call__ - Added initial version for setup.cfg - Added initial documentation for testing --- .gitignore | 3 + .travis.yml | 1 + README.md | 28 ++++++++ pylint_plugin_utils/__init__.py | 122 ++++++++++++++++++-------------- setup.cfg | 9 +++ setup.py | 18 +++-- tests.py | 1 - tests/__init__.py | 0 tests/conftest.py | 21 ++++++ tests/input/__init__.py | 0 tests/input/empty.py | 0 tests/test_linter_pickle.py | 44 ++++++++++++ 12 files changed, 187 insertions(+), 60 deletions(-) create mode 100644 setup.cfg delete mode 100755 tests.py create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/input/__init__.py create mode 100644 tests/input/empty.py create mode 100644 tests/test_linter_pickle.py diff --git a/.gitignore b/.gitignore index d2d6f36..1f1f267 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ pip-log.txt .coverage .tox nosetests.xml +.pytest_cache # Translations *.mo @@ -33,3 +34,5 @@ nosetests.xml .mr.developer.cfg .project .pydevproject +.pylint-plugin-utils +.idea \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b2d15a8..8ad8d7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "3.5" - "3.6" - "3.7" + - "3.8" env: - PYLINT=2.0.0 - PYLINT=2.1.1 diff --git a/README.md b/README.md index 460be3b..5aa5813 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,34 @@ Utilities and helpers for writing Pylint plugins. This is not a direct Pylint plugin, but rather a set of tools and functions used by other plugins such as [pylint-django](https://github.com/PyCQA/pylint-django) and [pylint-celery](https://github.com/PyCQA/pylint-celery). +# Testing +We use [tox](https://tox.readthedocs.io/en/latest/) and [pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/latest/index.html) for running the test suite. You should be able to install it with: +```bash +pip install tox pytest pytest-benchmark +``` + +To run the test suite for a particular Python version, you can do: +```bash +tox -e py37 +``` + +To run individual tests with ``tox``, you can do:: +```bash +tox -e py37 -- -k name_of_the_test +``` + +We use pytest_ for testing ``pylint``, which you can use without using ``tox`` for a faster development cycle. + +If you want to run tests on a specific portion of the code with [pytest](https://docs.pytest.org/en/latest/), [pytest-cov](https://pypi.org/project/pytest-cov/) and your local python version:: +```bash +pip install pytest-cov +# Everything: +python3 -m pytest tests/ --cov=pylint_plugin_utils +coverage html +``` + + + # License `pylint-plugin-utils` is available under the GPLv2 License. diff --git a/pylint_plugin_utils/__init__.py b/pylint_plugin_utils/__init__.py index e871dbc..bea76fb 100644 --- a/pylint_plugin_utils/__init__.py +++ b/pylint_plugin_utils/__init__.py @@ -1,6 +1,7 @@ -import sys +from typing import List from pylint.exceptions import UnknownMessageError +from pylint.lint import PyLinter def get_class(module_name, kls): @@ -21,14 +22,14 @@ def __repr__(self): return self.message -def get_checker(linter, checker_class): +def get_checker(linter: PyLinter, checker_class): for checker in linter.get_checkers(): if isinstance(checker, checker_class): return checker raise NoSuchChecker(checker_class) -def augment_visit(linter, checker_method, augmentation): +def augment_visit(linter: PyLinter, checker_method, augmentation): """ Augmenting a visit enables additional errors to be raised (although that case is better served using a new checker) or to suppress all warnings in certain circumstances. @@ -39,25 +40,34 @@ def augment_visit(linter, checker_method, augmentation): prevent any further checking. """ - if sys.version_info[0] <= 2: - checker = get_checker(linter, checker_method.im_class) - else: - try: - checker = get_checker(linter, checker_method.__self__.__class__) - except AttributeError: - checker = get_checker(linter, get_class(checker_method.__module__, checker_method.__qualname__)) + try: + checker = get_checker(linter, checker_method.__self__.__class__) + except AttributeError: + checker = get_checker(linter, get_class(checker_method.__module__, checker_method.__qualname__)) old_method = getattr(checker, checker_method.__name__) + setattr(checker, checker_method.__name__, AugmentFunc(old_method, augmentation)) + + +class AugmentFunc: + def __init__(self, old_method, augmentation_func): + self.old_method = old_method + self.augmentation_func = augmentation_func + + def __call__(self, node): + self.augmentation_func(Chain(self.old_method, node), node) + - def augment_func(node): - def chain(): - old_method(node) - augmentation(chain, node) +class Chain: + def __init__(self, old_method, node): + self.old_method = old_method + self.node = node - setattr(checker, checker_method.__name__, augment_func) + def __call__(self): + self.old_method(self.node) -class Suppress(object): +class Suppress: def __init__(self, linter): self._linter = linter @@ -91,31 +101,54 @@ def __exit__(self, exc_type, exc_val, exc_tb): self._linter.add_message(*to_append_args, **to_append_kwargs) -def supress_message(linter, checker_method, message_id, test_func): - import warnings - warnings.warn("'supress_message' has been deprecated in favour of the correctly-spelled 'suppress_message'", - DeprecationWarning) - return suppress_message(linter, checker_method, message_id, test_func) - - -def suppress_message(linter, checker_method, message_id_or_symbol, test_func): +def suppress_message(linter: PyLinter, checker_method, message_id_or_symbol, test_func): """ This wrapper allows the suppression of a message if the supplied test function returns True. It is useful to prevent one particular message from being raised in one particular case, while leaving the rest of the messages intact. """ - # At some point, pylint started preferring message symbols to message IDs. However this is not done - # consistently or uniformly - occasionally there are some message IDs with no matching symbols. - # We try to work around this here by suppressing both the ID and the symbol, if we can find it. - # This also gives us compatability with a broader range of pylint versions. - - # Similarly, a commit between version 1.2 and 1.3 changed where the messages are stored - see: - # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py - # Therefore here, we try the new attribute name, and fall back to the old version for - # compatability with <=1.2 and >=1.3 - msgs_store = getattr(linter, 'msgs_store', linter) - - def get_message_definitions(message_id_or_symbol): + augment_visit(linter, checker_method, DoSuppress(linter, message_id_or_symbol, test_func)) + + +class DoSuppress: + def __init__(self, linter: PyLinter, message_id_or_symbol, test_func): + self.linter = linter + self.message_id_or_symbol = message_id_or_symbol + self.test_func = test_func + + def __call__(self, chain, node): + with Suppress(self.linter) as s: + if self.test_func(node): + s.suppress(*self.symbols) + chain() + + @property + def symbols(self) -> List: + # At some point, pylint started preferring message symbols to message IDs. However this is not done + # consistently or uniformly - occasionally there are some message IDs with no matching symbols. + # We try to work around this here by suppressing both the ID and the symbol, if we can find it. + # This also gives us compatability with a broader range of pylint versions. + + # Similarly, a commit between version 1.2 and 1.3 changed where the messages are stored - see: + # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py + # Therefore here, we try the new attribute name, and fall back to the old version for + # compatability with <=1.2 and >=1.3 + + try: + pylint_messages = self.get_message_definitions(self.message_id_or_symbol) + the_symbols = [symbol + for pylint_message in pylint_messages + for symbol in (pylint_message.msgid, pylint_message.symbol) + if symbol is not None] + except UnknownMessageError: + # This can happen due to mismatches of pylint versions and plugin expectations of available messages + the_symbols = [self.message_id_or_symbol] + + return the_symbols + + def get_message_definitions(self, message_id_or_symbol): + msgs_store = getattr(self.linter, 'msgs_store', self.linter) + if hasattr(msgs_store, 'check_message_id'): return [msgs_store.check_message_id(message_id_or_symbol)] # pylint 2.0 renamed check_message_id to get_message_definition in: @@ -128,20 +161,3 @@ def get_message_definitions(message_id_or_symbol): return msgs_store.get_message_definitions(message_id_or_symbol) else: raise ValueError('pylint.utils.MessagesStore does not have a get_message_definition(s) method') - - try: - pylint_messages = get_message_definitions(message_id_or_symbol) - symbols = [symbol - for pylint_message in pylint_messages - for symbol in (pylint_message.msgid, pylint_message.symbol) - if symbol is not None] - except UnknownMessageError: - # This can happen due to mismatches of pylint versions and plugin expectations of available messages - symbols = [message_id_or_symbol] - - def do_suppress(chain, node): - with Suppress(linter) as s: - if test_func(node): - s.suppress(*symbols) - chain() - augment_visit(linter, checker_method, do_suppress) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..ac8c476 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,9 @@ +[aliases] +test = pytest + +[tool:pytest] +testpaths = tests +python_files = *test_*.py + +[isort] +profile = black \ No newline at end of file diff --git a/setup.py b/setup.py index c6d4fe3..a4b4a63 100644 --- a/setup.py +++ b/setup.py @@ -12,21 +12,27 @@ 'Intended Audience :: Developers', 'Operating System :: Unix', 'Topic :: Software Development :: Quality Assurance', - 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3' + 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', ] setup( name='pylint-plugin-utils', - url='https://github.com/landscapeio/pylint-plugin-utils', - author='landscape.io', - author_email='code@landscape.io', + url='https://github.com/PyCQA/pylint-plugin-utils', + author='Python Code Quality Authority', + author_email='code-quality@python.org', description=_short_description, version=_version, - install_requires=['pylint>=1.7'], + install_requires=['pylint>=1.7', 'pytest'], packages=_packages, license='GPLv2', classifiers=_classifiers, - keywords='pylint plugin helpers' + keywords='pylint plugin helpers', + python_requires='>=3.6.2', ) diff --git a/tests.py b/tests.py deleted file mode 100755 index 75485b5..0000000 --- a/tests.py +++ /dev/null @@ -1 +0,0 @@ -import pylint_plugin_utils diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..5ddcc09 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,21 @@ +# pylint: disable=redefined-outer-name +import os +from pathlib import Path + +import pytest + +from pylint import checkers +from pylint.lint import PyLinter +from pylint.testutils import MinimalTestReporter + + +@pytest.fixture() +def tests_directory(): + return Path(__file__).parent + + +@pytest.fixture +def linter(): + _linter = PyLinter() + return _linter + diff --git a/tests/input/__init__.py b/tests/input/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/input/empty.py b/tests/input/empty.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_linter_pickle.py b/tests/test_linter_pickle.py new file mode 100644 index 0000000..1aaf1fb --- /dev/null +++ b/tests/test_linter_pickle.py @@ -0,0 +1,44 @@ +import os +import pickle +from typing import List + +import pytest +from pylint.checkers.typecheck import TypeChecker +from pylint.lint import PyLinter +from pylint.testutils import FunctionalTestFile + +from pylint_plugin_utils import augment_visit, suppress_message + + +def get_tests(input_dir: str) -> List[FunctionalTestFile]: + cwd = os.path.dirname(os.path.abspath(__file__)) + input_dir = os.path.join(cwd, input_dir) + + suite = [] + for file_name in os.listdir(input_dir): + if file_name != '__init__.py' and file_name.endswith('.py'): + suite.append(FunctionalTestFile(input_dir, file_name)) + + return suite + + +TESTS = get_tests(input_dir='input') +TESTS_NAMES = [t.base for t in TESTS] + + +def fake_augmentation_func(*args, **kwargs): + ... + + +def fake_suppress_func(*args, **kwargs): + ... + + +@pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES) +def test_augment_visit_is_pickleable_for_multithreading_as_default_for_py38_or_above(test_file): + pylinter = PyLinter() + pylinter.register_checker(TypeChecker()) + augment_visit(pylinter, TypeChecker.visit_attribute, fake_augmentation_func) + suppress_message(pylinter, TypeChecker.visit_attribute, 'no-member', fake_suppress_func) + + pickle.dumps(pylinter) From 17a6476fcc6ec921721d6b7e4d35502782e79bbb Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 12:29:36 +0200 Subject: [PATCH 02/11] 20 - Added pre-commit + fixing all black and isort issues - Better coverage configuration --- .coveragerc | 20 ++++++++- .flake8 | 6 +++ .gitignore | 4 +- .pre-commit-config.yaml | 24 ++++++++++ README.md | 11 ++++- pylint_plugin_utils/__init__.py | 75 +++++++++++++++++--------------- requirements_test.txt | 4 ++ requirements_test_min.txt | 2 + requirements_test_pre_commit.txt | 6 +++ setup.cfg | 2 +- setup.py | 42 +++++++++--------- tests/conftest.py | 5 --- tests/test_linter_pickle.py | 14 ++++-- tox.ini | 32 ++++++++++++++ 14 files changed, 176 insertions(+), 71 deletions(-) create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml create mode 100644 requirements_test.txt create mode 100644 requirements_test_min.txt create mode 100644 requirements_test_pre_commit.txt create mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc index 5c730da..aa9d3be 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,19 @@ +[paths] +source = + pylint_plugin_utils -[run] -source=pylint_plugin_utils +[report] +include = + pylint_plugin_utils/* +omit = + */test/* +exclude_lines = + # Re-enable default pragma + pragma: no cover + + # Debug-only code + def __repr__ + + # Type checking code not executed during pytest runs + if TYPE_CHECKING: + @overload diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..8b98ed4 --- /dev/null +++ b/.flake8 @@ -0,0 +1,6 @@ +[flake8] +ignore = + E203, W503, # Incompatible with black see https://github.com/ambv/black/issues/315 + +max-line-length=88 +max-complexity=39 diff --git a/.gitignore b/.gitignore index 1f1f267..f84c18d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ pip-log.txt .tox nosetests.xml .pytest_cache +.benchmarks +htmlcov # Translations *.mo @@ -35,4 +37,4 @@ nosetests.xml .project .pydevproject .pylint-plugin-utils -.idea \ No newline at end of file +.idea diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0ff6c8b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,24 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + - repo: https://github.com/psf/black + rev: 21.12b0 + hooks: + - id: black + args: [--safe, --quiet] + - repo: https://github.com/Pierre-Sassoulas/black-disable-checker/ + rev: 1.0.1 + hooks: + - id: black-disable-checker + - repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + additional_dependencies: [flake8-typing-imports==1.10.1] diff --git a/README.md b/README.md index 5aa5813..d0ce4d1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,13 @@ Utilities and helpers for writing Pylint plugins. This is not a direct Pylint plugin, but rather a set of tools and functions used by other plugins such as [pylint-django](https://github.com/PyCQA/pylint-django) and [pylint-celery](https://github.com/PyCQA/pylint-celery). # Testing +Create virtualenv: +```bash +python3.8 -m venv .pylint-plugin-utils +source .pylint-plugin-utils/bin/activate +pip install --upgrade pip setuptools +``` + We use [tox](https://tox.readthedocs.io/en/latest/) and [pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/latest/index.html) for running the test suite. You should be able to install it with: ```bash pip install tox pytest pytest-benchmark @@ -18,12 +25,12 @@ pip install tox pytest pytest-benchmark To run the test suite for a particular Python version, you can do: ```bash -tox -e py37 +tox -e py38 ``` To run individual tests with ``tox``, you can do:: ```bash -tox -e py37 -- -k name_of_the_test +tox -e py38 -- -k name_of_the_test ``` We use pytest_ for testing ``pylint``, which you can use without using ``tox`` for a faster development cycle. diff --git a/pylint_plugin_utils/__init__.py b/pylint_plugin_utils/__init__.py index bea76fb..0340683 100644 --- a/pylint_plugin_utils/__init__.py +++ b/pylint_plugin_utils/__init__.py @@ -5,16 +5,15 @@ def get_class(module_name, kls): - parts = kls.split('.') + parts = kls.split(".") m = __import__(module_name) - for mp in module_name.split('.')[1:]: + for mp in module_name.split(".")[1:]: m = getattr(m, mp) klass = getattr(m, parts[0]) return klass class NoSuchChecker(Exception): - def __init__(self, checker_class): self.message = "Checker class %s was not found" % checker_class @@ -32,18 +31,21 @@ def get_checker(linter: PyLinter, checker_class): def augment_visit(linter: PyLinter, checker_method, augmentation): """ Augmenting a visit enables additional errors to be raised (although that case is - better served using a new checker) or to suppress all warnings in certain circumstances. + better served using a new checker) or to suppress all warnings in certain + circumstances. - Augmenting functions should accept a 'chain' function, which runs the checker method - and possibly any other augmentations, and secondly an Astroid node. "chain()" can be - called at any point to trigger the continuation of other checks, or not at all to - prevent any further checking. + Augmenting functions should accept a 'chain' function, which runs the checker + method and possibly any other augmentations, and secondly an Astroid node. + "chain()" can be called at any point to trigger the continuation of other + checks, or not at all to prevent any further checking. """ try: checker = get_checker(linter, checker_method.__self__.__class__) except AttributeError: - checker = get_checker(linter, get_class(checker_method.__module__, checker_method.__qualname__)) + checker = get_checker( + linter, get_class(checker_method.__module__, checker_method.__qualname__) + ) old_method = getattr(checker, checker_method.__name__) setattr(checker, checker_method.__name__, AugmentFunc(old_method, augmentation)) @@ -68,7 +70,6 @@ def __call__(self): class Suppress: - def __init__(self, linter): self._linter = linter self._suppress = [] @@ -89,13 +90,6 @@ def suppress(self, *symbols): def __exit__(self, exc_type, exc_val, exc_tb): self._linter.add_message = self._orig_add_message for to_append_args, to_append_kwargs in self._messages_to_append: - # Depending on the Pylint version, the add_message API is different. - # Either a single object called 'message' is passed, or the first argument - # is a message symbol. - if hasattr('symbol', to_append_args[0]): - code = to_append_args[0].symbol - else: - code = to_append_args[0] if to_append_args[0] in self._suppress: continue self._linter.add_message(*to_append_args, **to_append_kwargs) @@ -107,7 +101,9 @@ def suppress_message(linter: PyLinter, checker_method, message_id_or_symbol, tes returns True. It is useful to prevent one particular message from being raised in one particular case, while leaving the rest of the messages intact. """ - augment_visit(linter, checker_method, DoSuppress(linter, message_id_or_symbol, test_func)) + augment_visit( + linter, checker_method, DoSuppress(linter, message_id_or_symbol, test_func) + ) class DoSuppress: @@ -124,40 +120,49 @@ def __call__(self, chain, node): @property def symbols(self) -> List: - # At some point, pylint started preferring message symbols to message IDs. However this is not done - # consistently or uniformly - occasionally there are some message IDs with no matching symbols. - # We try to work around this here by suppressing both the ID and the symbol, if we can find it. + # At some point, pylint started preferring message symbols to message IDs. + # However, this is not done consistently or uniformly + # - occasionally there are some message IDs with no matching symbols. + # We try to work around this here by suppressing both the ID and the symbol. # This also gives us compatability with a broader range of pylint versions. - # Similarly, a commit between version 1.2 and 1.3 changed where the messages are stored - see: - # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py - # Therefore here, we try the new attribute name, and fall back to the old version for - # compatability with <=1.2 and >=1.3 + # Similarly, between version 1.2 and 1.3 changed where the messages are stored + # - see: + # https://bitbucket.org/logilab/pylint/commits/0b67f42799bed08aebb47babdc9fb0e761efc4ff#chg-reporters/__init__.py + # Therefore here, we try the new attribute name, and fall back to the old + # version for compatability with <=1.2 and >=1.3 try: pylint_messages = self.get_message_definitions(self.message_id_or_symbol) - the_symbols = [symbol - for pylint_message in pylint_messages - for symbol in (pylint_message.msgid, pylint_message.symbol) - if symbol is not None] + the_symbols = [ + symbol + for pylint_message in pylint_messages + for symbol in (pylint_message.msgid, pylint_message.symbol) + if symbol is not None + ] except UnknownMessageError: - # This can happen due to mismatches of pylint versions and plugin expectations of available messages + # This can happen due to mismatches of pylint versions and plugin + # expectations of available messages the_symbols = [self.message_id_or_symbol] return the_symbols def get_message_definitions(self, message_id_or_symbol): - msgs_store = getattr(self.linter, 'msgs_store', self.linter) + msgs_store = getattr(self.linter, "msgs_store", self.linter) - if hasattr(msgs_store, 'check_message_id'): + if hasattr(msgs_store, "check_message_id"): return [msgs_store.check_message_id(message_id_or_symbol)] # pylint 2.0 renamed check_message_id to get_message_definition in: # https://github.com/PyCQA/pylint/commit/5ccbf9eaa54c0c302c9180bdfb745566c16e416d - elif hasattr(msgs_store, 'get_message_definition'): + elif hasattr(msgs_store, "get_message_definition"): return [msgs_store.get_message_definition(message_id_or_symbol)] # pylint 2.3.0 renamed get_message_definition to get_message_definitions in: # https://github.com/PyCQA/pylint/commit/da67a9da682e51844fbc674229ff6619eb9c816a - elif hasattr(msgs_store, 'get_message_definitions'): + elif hasattr(msgs_store, "get_message_definitions"): return msgs_store.get_message_definitions(message_id_or_symbol) else: - raise ValueError('pylint.utils.MessagesStore does not have a get_message_definition(s) method') + msg = ( + "pylint.utils.MessagesStore does not have a " + "get_message_definition(s) method" + ) + raise ValueError(msg) diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 0000000..edef958 --- /dev/null +++ b/requirements_test.txt @@ -0,0 +1,4 @@ +-r requirements_test_pre_commit.txt +-r requirements_test_min.txt +pre-commit~=2.16 +pytest-cov~=3.0 diff --git a/requirements_test_min.txt b/requirements_test_min.txt new file mode 100644 index 0000000..4d0e9fa --- /dev/null +++ b/requirements_test_min.txt @@ -0,0 +1,2 @@ +-e . +pytest~=6.2 diff --git a/requirements_test_pre_commit.txt b/requirements_test_pre_commit.txt new file mode 100644 index 0000000..93c1adf --- /dev/null +++ b/requirements_test_pre_commit.txt @@ -0,0 +1,6 @@ +# Everything in this file should reflect the pre-commit configuration +# in .pre-commit-config.yaml +black==21.12b0 +flake8==4.0.1 +flake8-typing-imports==1.12.0 +isort==5.10.1 diff --git a/setup.cfg b/setup.cfg index ac8c476..2adfc0a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,4 +6,4 @@ testpaths = tests python_files = *test_*.py [isort] -profile = black \ No newline at end of file +profile = black diff --git a/setup.py b/setup.py index a4b4a63..4374772 100644 --- a/setup.py +++ b/setup.py @@ -7,32 +7,32 @@ _short_description = "Utilities and helpers for writing Pylint plugins" _classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Operating System :: Unix', - 'Topic :: Software Development :: Quality Assurance', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3' - 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "Operating System :: Unix", + "Topic :: Software Development :: Quality Assurance", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", ] setup( - name='pylint-plugin-utils', - url='https://github.com/PyCQA/pylint-plugin-utils', - author='Python Code Quality Authority', - author_email='code-quality@python.org', + name="pylint-plugin-utils", + url="https://github.com/PyCQA/pylint-plugin-utils", + author="Python Code Quality Authority", + author_email="code-quality@python.org", description=_short_description, version=_version, - install_requires=['pylint>=1.7', 'pytest'], + install_requires=["pylint>=1.7", "pytest"], packages=_packages, - license='GPLv2', + license="GPLv2", classifiers=_classifiers, - keywords='pylint plugin helpers', - python_requires='>=3.6.2', + keywords="pylint plugin helpers", + python_requires=">=3.6.2", ) diff --git a/tests/conftest.py b/tests/conftest.py index 5ddcc09..41d3627 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,8 @@ # pylint: disable=redefined-outer-name -import os from pathlib import Path import pytest - -from pylint import checkers from pylint.lint import PyLinter -from pylint.testutils import MinimalTestReporter @pytest.fixture() @@ -18,4 +14,3 @@ def tests_directory(): def linter(): _linter = PyLinter() return _linter - diff --git a/tests/test_linter_pickle.py b/tests/test_linter_pickle.py index 1aaf1fb..f62a522 100644 --- a/tests/test_linter_pickle.py +++ b/tests/test_linter_pickle.py @@ -16,13 +16,13 @@ def get_tests(input_dir: str) -> List[FunctionalTestFile]: suite = [] for file_name in os.listdir(input_dir): - if file_name != '__init__.py' and file_name.endswith('.py'): + if file_name != "__init__.py" and file_name.endswith(".py"): suite.append(FunctionalTestFile(input_dir, file_name)) return suite -TESTS = get_tests(input_dir='input') +TESTS = get_tests(input_dir="input") TESTS_NAMES = [t.base for t in TESTS] @@ -35,10 +35,16 @@ def fake_suppress_func(*args, **kwargs): @pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES) -def test_augment_visit_is_pickleable_for_multithreading_as_default_for_py38_or_above(test_file): +def test_linter_pickleable_for_multithreading_as_default_for_py38_or_above( + test_file, +): + # Setup pylinter = PyLinter() pylinter.register_checker(TypeChecker()) augment_visit(pylinter, TypeChecker.visit_attribute, fake_augmentation_func) - suppress_message(pylinter, TypeChecker.visit_attribute, 'no-member', fake_suppress_func) + suppress_message( + pylinter, TypeChecker.visit_attribute, "no-member", fake_suppress_func + ) + # Act and Assert pickle.dumps(pylinter) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..2ef35cd --- /dev/null +++ b/tox.ini @@ -0,0 +1,32 @@ +[tox] +minversion = 2.4 +envlist = formatting, py36, py37, py38, py39, py310, pypy +skip_missing_interpreters = true +requires = pip >=21.3.1 + +[testenv:formatting] +basepython = python3 +deps = + -r {toxinidir}/requirements_test_min.txt + pre-commit~=2.16 +commands = + pre-commit run --all-files + +[testenv] +setenv = + COVERAGE_FILE = {toxinidir}/.coverage.{envname} +deps = + !pypy: -r {toxinidir}/requirements_test.txt + pypy: -r {toxinidir}/requirements_test_min.txt +commands = + pytest {toxinidir}/tests/ {posargs:} + +[testenv:coverage-html] +setenv = + COVERAGE_FILE = {toxinidir}/.coverage +deps = + -r {toxinidir}/requirements_test.txt +skip_install = true +commands = + coverage combine + coverage html --ignore-errors --rcfile={toxinidir}/.coveragerc From 39cdaeed969ad1b58c88b20bb4a013837599e3fc Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 12:45:44 +0200 Subject: [PATCH 03/11] 20 - Removing unsed code --- README.md | 8 +++----- setup.py | 2 +- tests/conftest.py | 8 -------- tests/input/__init__.py | 0 tests/input/empty.py | 0 tests/test_linter_pickle.py | 35 +++++------------------------------ 6 files changed, 9 insertions(+), 44 deletions(-) delete mode 100644 tests/input/__init__.py delete mode 100644 tests/input/empty.py diff --git a/README.md b/README.md index d0ce4d1..3e6330f 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ source .pylint-plugin-utils/bin/activate pip install --upgrade pip setuptools ``` -We use [tox](https://tox.readthedocs.io/en/latest/) and [pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/latest/index.html) for running the test suite. You should be able to install it with: +We use [tox](https://tox.readthedocs.io/en/latest/) for running the test suite. You should be able to install it with: ```bash -pip install tox pytest pytest-benchmark +pip install tox pytest ``` To run the test suite for a particular Python version, you can do: @@ -30,7 +30,7 @@ tox -e py38 To run individual tests with ``tox``, you can do:: ```bash -tox -e py38 -- -k name_of_the_test +tox -e py38 -- -k test_linter_should_be_pickleable ``` We use pytest_ for testing ``pylint``, which you can use without using ``tox`` for a faster development cycle. @@ -43,8 +43,6 @@ python3 -m pytest tests/ --cov=pylint_plugin_utils coverage html ``` - - # License `pylint-plugin-utils` is available under the GPLv2 License. diff --git a/setup.py b/setup.py index 4374772..65f3b21 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ author_email="code-quality@python.org", description=_short_description, version=_version, - install_requires=["pylint>=1.7", "pytest"], + install_requires=["pylint>=1.7"], packages=_packages, license="GPLv2", classifiers=_classifiers, diff --git a/tests/conftest.py b/tests/conftest.py index 41d3627..768e42d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,15 +1,7 @@ -# pylint: disable=redefined-outer-name -from pathlib import Path - import pytest from pylint.lint import PyLinter -@pytest.fixture() -def tests_directory(): - return Path(__file__).parent - - @pytest.fixture def linter(): _linter = PyLinter() diff --git a/tests/input/__init__.py b/tests/input/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/input/empty.py b/tests/input/empty.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_linter_pickle.py b/tests/test_linter_pickle.py index f62a522..cce6916 100644 --- a/tests/test_linter_pickle.py +++ b/tests/test_linter_pickle.py @@ -1,31 +1,10 @@ -import os import pickle -from typing import List -import pytest from pylint.checkers.typecheck import TypeChecker -from pylint.lint import PyLinter -from pylint.testutils import FunctionalTestFile from pylint_plugin_utils import augment_visit, suppress_message -def get_tests(input_dir: str) -> List[FunctionalTestFile]: - cwd = os.path.dirname(os.path.abspath(__file__)) - input_dir = os.path.join(cwd, input_dir) - - suite = [] - for file_name in os.listdir(input_dir): - if file_name != "__init__.py" and file_name.endswith(".py"): - suite.append(FunctionalTestFile(input_dir, file_name)) - - return suite - - -TESTS = get_tests(input_dir="input") -TESTS_NAMES = [t.base for t in TESTS] - - def fake_augmentation_func(*args, **kwargs): ... @@ -34,17 +13,13 @@ def fake_suppress_func(*args, **kwargs): ... -@pytest.mark.parametrize("test_file", TESTS, ids=TESTS_NAMES) -def test_linter_pickleable_for_multithreading_as_default_for_py38_or_above( - test_file, -): +def test_linter_should_be_pickleable(linter): # Setup - pylinter = PyLinter() - pylinter.register_checker(TypeChecker()) - augment_visit(pylinter, TypeChecker.visit_attribute, fake_augmentation_func) + linter.register_checker(TypeChecker()) + augment_visit(linter, TypeChecker.visit_attribute, fake_augmentation_func) suppress_message( - pylinter, TypeChecker.visit_attribute, "no-member", fake_suppress_func + linter, TypeChecker.visit_attribute, "no-member", fake_suppress_func ) # Act and Assert - pickle.dumps(pylinter) + pickle.dumps(linter) From 4b87f8aea3443100116abd508bb69a07e9bed82d Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 13:02:36 +0200 Subject: [PATCH 04/11] 20 - Added all supported python versions under travis.yaml and changed the coverage command to pytest-cov --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ad8d7e..e1c70ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,11 @@ dist: xenial language: python python: - - "3.5" - "3.6" - "3.7" - "3.8" + - "3.9" + - "3.10" env: - PYLINT=2.0.0 - PYLINT=2.1.1 @@ -13,7 +14,7 @@ env: - PYLINT=master install: - | - pip install coverage coveralls + pip install pytest pytest-cov coveralls if [ "$PYLINT" == "master" ]; then pip install https://github.com/PyCQA/astroid/zipball/master pip install https://github.com/PyCQA/pylint/zipball/master @@ -22,6 +23,6 @@ install: fi script: - - coverage run tests.py + - pytest tests/ --cov=pylint_plugin_utils after_success: - coveralls From 40c5cbe61ca22f2dd2005392acb20e3f29153511 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 13:58:23 +0200 Subject: [PATCH 05/11] 20 - Github Actions inspired (copied) from pylint project --- .github/workflows/ci.yaml | 396 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..c55db39 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,396 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: ~ + +env: + CACHE_VERSION: 3 + DEFAULT_PYTHON: 3.8 + PRE_COMMIT_CACHE: ~/.cache/pre-commit + +jobs: + prepare-base: + name: Prepare base dependencies + runs-on: ubuntu-latest + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + pre-commit-key: ${{ steps.generate-pre-commit-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + - name: Generate partial Python venv restore key + id: generate-python-key + run: >- + echo "::set-output name=key::base-venv-${{ env.CACHE_VERSION }}-${{ + hashFiles('setup.cfg', 'requirements_test.txt', 'requirements_test_min.txt') + }}" + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: >- + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + steps.generate-python-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-base-venv-${{ env.CACHE_VERSION }}- + - name: Create Python virtual environment + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + python -m venv venv + . venv/bin/activate + python -m pip install -U pip setuptools wheel + pip install -U -r requirements_test.txt + - name: Generate pre-commit restore key + id: generate-pre-commit-key + run: >- + echo "::set-output name=key::pre-commit-${{ env.CACHE_VERSION }}-${{ + hashFiles('.pre-commit-config.yaml') }}" + - name: Restore pre-commit environment + id: cache-precommit + uses: actions/cache@v2.1.7 + with: + path: ${{ env.PRE_COMMIT_CACHE }} + key: >- + ${{ runner.os }}-${{ steps.generate-pre-commit-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-pre-commit-${{ env.CACHE_VERSION }}- + - name: Install pre-commit dependencies + if: steps.cache-precommit.outputs.cache-hit != 'true' + run: | + . venv/bin/activate + pre-commit install --install-hooks + + formatting: + name: Run pre-commit checks + runs-on: ubuntu-latest + needs: prepare-base + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-base.outputs.python-key }} + - name: Fail job if Python cache restore failed + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + echo "Failed to restore Python venv from cache" + exit 1 + - name: Restore pre-commit environment + id: cache-precommit + uses: actions/cache@v2.1.7 + with: + path: ${{ env.PRE_COMMIT_CACHE }} + key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }} + - name: Fail job if pre-commit cache restore failed + if: steps.cache-precommit.outputs.cache-hit != 'true' + run: | + echo "Failed to restore pre-commit environment from cache" + exit 1 + - name: Run formatting check + run: | + . venv/bin/activate + pip install -e . + pre-commit run pylint --all-files + + prepare-tests-linux: + name: Prepare tests for Python ${{ matrix.python-version }} (Linux) + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, "3.10"] + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Generate partial Python venv restore key + id: generate-python-key + run: >- + echo "::set-output name=key::venv-${{ env.CACHE_VERSION }}-${{ + hashFiles('setup.cfg', 'requirements_test.txt', 'requirements_test_min.txt') + }}" + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: >- + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + steps.generate-python-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ env.CACHE_VERSION }}- + - name: Create Python virtual environment + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + python -m venv venv + . venv/bin/activate + python -m pip install -U pip setuptools wheel + pip install -U -r requirements_test.txt + + pytest-linux: + name: Run tests Python ${{ matrix.python-version }} (Linux) + runs-on: ubuntu-latest + needs: prepare-tests-linux + strategy: + fail-fast: false + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, "3.10"] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-tests-linux.outputs.python-key }} + - name: Fail job if Python cache restore failed + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + echo "Failed to restore Python venv from cache" + exit 1 + - name: Run pytest + run: | + . venv/bin/activate + pytest --cov --cov-report= tests/ + - name: Upload coverage artifact + uses: actions/upload-artifact@v2.3.1 + with: + name: coverage-${{ matrix.python-version }} + path: .coverage + + coverage: + name: Process test coverage + runs-on: ubuntu-latest + needs: ["prepare-tests-linux", "pytest-linux"] + strategy: + matrix: + python-version: [3.8] + env: + COVERAGERC_FILE: .coveragerc + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-tests-linux.outputs.python-key }} + - name: Fail job if Python cache restore failed + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + echo "Failed to restore Python venv from cache" + exit 1 + - name: Download all coverage artifacts + uses: actions/download-artifact@v2.1.0 + - name: Combine coverage results + run: | + . venv/bin/activate + coverage combine coverage*/.coverage + coverage report --rcfile=${{ env.COVERAGERC_FILE }} + - name: Upload coverage to Coveralls + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + . venv/bin/activate + coveralls --rcfile=${{ env.COVERAGERC_FILE }} --service=github + + prepare-tests-windows: + name: Prepare tests for Python ${{ matrix.python-version }} (Windows) + runs-on: windows-latest + strategy: + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, "3.10"] + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Generate partial Python venv restore key + id: generate-python-key + run: >- + echo "::set-output name=key::venv-${{ env.CACHE_VERSION }}-${{ + hashFiles('setup.cfg', 'requirements_test_min.txt') + }}" + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: >- + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + steps.generate-python-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ env.CACHE_VERSION }}- + - name: Create Python virtual environment + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + python -m venv venv + . venv\\Scripts\\activate + python -m pip install -U pip setuptools wheel + pip install -U -r requirements_test_min.txt + + pytest-windows: + name: Run tests Python ${{ matrix.python-version }} (Windows) + runs-on: windows-latest + needs: prepare-tests-windows + strategy: + fail-fast: false + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, "3.10"] + steps: + - name: Set temp directory + run: echo "TEMP=$env:USERPROFILE\AppData\Local\Temp" >> $env:GITHUB_ENV + # Workaround to set correct temp directory on Windows + # https://github.com/actions/virtual-environments/issues/712 + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-tests-windows.outputs.python-key }} + - name: Fail job if Python cache restore failed + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + echo "Failed to restore Python venv from cache" + exit 1 + - name: Run pytest + run: | + . venv\\Scripts\\activate + pytest tests/ + + prepare-tests-pypy: + name: Prepare tests for Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["pypy3"] + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Generate partial Python venv restore key + id: generate-python-key + run: >- + echo "::set-output name=key::venv-${{ env.CACHE_VERSION }}-${{ + hashFiles('setup.cfg', 'requirements_test_min.txt') + }}" + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: >- + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + steps.generate-python-key.outputs.key }} + restore-keys: | + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ env.CACHE_VERSION }}- + - name: Create Python virtual environment + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + python -m venv venv + . venv/bin/activate + python -m pip install -U pip setuptools wheel + pip install -U -r requirements_test_min.txt + + pytest-pypy: + name: Run tests Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + needs: prepare-tests-pypy + strategy: + fail-fast: false + matrix: + python-version: ["pypy3"] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v2.4.0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python-version }} + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v2.1.7 + with: + path: venv + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-tests-pypy.outputs.python-key }} + - name: Fail job if Python cache restore failed + if: steps.cache-venv.outputs.cache-hit != 'true' + run: | + echo "Failed to restore Python venv from cache" + exit 1 + - name: Run pytest + run: | + . venv/bin/activate + pytest tests/ From 9aac81bce8938af05a3621f9379bdbf29ddf4e02 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:04:39 +0200 Subject: [PATCH 06/11] 20 - Trying to trigger github actions --- .github/workflows/ci.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c55db39..3fc2692 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,11 +1,6 @@ name: CI -on: - push: - branches: - - main - - master - pull_request: ~ +on: [push] env: CACHE_VERSION: 3 From 8f2135cd3eab381dd185ee1b91c1b1ac835be7ff Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:11:50 +0200 Subject: [PATCH 07/11] 20 - Removing pylint hook from ci --- .github/workflows/ci.yaml | 42 --------------------------------------- 1 file changed, 42 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3fc2692..06042df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,48 +67,6 @@ jobs: . venv/bin/activate pre-commit install --install-hooks - formatting: - name: Run pre-commit checks - runs-on: ubuntu-latest - needs: prepare-base - steps: - - name: Check out code from GitHub - uses: actions/checkout@v2.4.0 - - name: Set up Python ${{ env.DEFAULT_PYTHON }} - id: python - uses: actions/setup-python@v2.3.1 - with: - python-version: ${{ env.DEFAULT_PYTHON }} - - name: Restore Python virtual environment - id: cache-venv - uses: actions/cache@v2.1.7 - with: - path: venv - key: - ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ - needs.prepare-base.outputs.python-key }} - - name: Fail job if Python cache restore failed - if: steps.cache-venv.outputs.cache-hit != 'true' - run: | - echo "Failed to restore Python venv from cache" - exit 1 - - name: Restore pre-commit environment - id: cache-precommit - uses: actions/cache@v2.1.7 - with: - path: ${{ env.PRE_COMMIT_CACHE }} - key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }} - - name: Fail job if pre-commit cache restore failed - if: steps.cache-precommit.outputs.cache-hit != 'true' - run: | - echo "Failed to restore pre-commit environment from cache" - exit 1 - - name: Run formatting check - run: | - . venv/bin/activate - pip install -e . - pre-commit run pylint --all-files - prepare-tests-linux: name: Prepare tests for Python ${{ matrix.python-version }} (Linux) runs-on: ubuntu-latest From 992e972dd847a96348f23dd4b4e088cbe6438afd Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:13:08 +0200 Subject: [PATCH 08/11] 20 - Added coveralls dedependency --- requirements_test.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements_test.txt b/requirements_test.txt index edef958..6dae003 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -2,3 +2,4 @@ -r requirements_test_min.txt pre-commit~=2.16 pytest-cov~=3.0 +coveralls~=3.3 \ No newline at end of file From cb85ee2b81783c77cece0a1dc960f4d0f86b8373 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:17:47 +0200 Subject: [PATCH 09/11] 20 - Changed build badge to point to github actions and removed code health badge --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e6330f..a821926 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ ## Status -[![Build Status](https://travis-ci.org/PyCQA/pylint-plugin-utils.svg?branch=master)](https://travis-ci.org/PyCQA/pylint-plugin-utils) -[![Code Health](https://landscape.io/github/PyCQA/pylint-plugin-utils/master/landscape.svg?style=flat)](https://landscape.io/github/PyCQA/pylint-plugin-utils/master) +[![Build Status](https://github.com/PyCQA/pylint/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/PyCQA/pylint/actions) [![Coverage Status](https://coveralls.io/repos/github/PyCQA/pylint-plugin-utils/badge.svg?branch=master)](https://coveralls.io/github/PyCQA/pylint-plugin-utils?branch=master) # About From f91e0e4b5cdf0be539c2b282c57ba4a45bd177c2 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:20:25 +0200 Subject: [PATCH 10/11] 20 - Added black style badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a821926..280f55d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Build Status](https://github.com/PyCQA/pylint/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/PyCQA/pylint/actions) [![Coverage Status](https://coveralls.io/repos/github/PyCQA/pylint-plugin-utils/badge.svg?branch=master)](https://coveralls.io/github/PyCQA/pylint-plugin-utils?branch=master) +[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) # About From 17cbb58cec899891940f2051e428a7a98ff907a8 Mon Sep 17 00:00:00 2001 From: Dinesh Trivedi Date: Fri, 24 Dec 2021 14:27:20 +0200 Subject: [PATCH 11/11] 20 - Removed travis.yml file --- .travis.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e1c70ac..0000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -dist: xenial -language: python -python: - - "3.6" - - "3.7" - - "3.8" - - "3.9" - - "3.10" -env: - - PYLINT=2.0.0 - - PYLINT=2.1.1 - - PYLINT=2.2.2 - - PYLINT=2.3.0 - - PYLINT=master -install: - - | - pip install pytest pytest-cov coveralls - if [ "$PYLINT" == "master" ]; then - pip install https://github.com/PyCQA/astroid/zipball/master - pip install https://github.com/PyCQA/pylint/zipball/master - else - pip install pylint==$PYLINT - fi - -script: - - pytest tests/ --cov=pylint_plugin_utils -after_success: - - coveralls