Code Monkey home page Code Monkey logo

pytest-pylint's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pytest-pylint's Issues

print something while pylint is running so CI services know it's still running

Issue

CircleCI and probably other services timeout the test if no output is received. It would be helpful to print something while pylint is running to indicate the test hasn't stalled.

One Idea

Print something during handle_message, for example:

    def handle_message(self, msg):
        """Get message and append to our data structure"""
        self.data.append(msg)
        print('.', end='')
        sys.stdout.flush()

And add another argument to enable this behavior. Downside is it just creates a lot of .. Don't know if there's something quick and more clever.

I'm happy to create a PR with this if you like.

Edit: A better option would probably be to override on_set_current_module
https://github.com/PyCQA/pylint/blob/3a8635a9ef85759f96bfefd8edcd70e223fd12bb/pylint/reporters/__init__.py#L96
so we only have one dot per file.

Wrong relative path passed to lint.Run()

After #23, it seems pytest-pylint no longer passes the absolute paths to the files to lint but instead relative paths. In our case the paths are relative to the wrong directory, leading to this kind of error:

__________________________ [pylint] axis/__init__.py ___________________________
F:  1, 0: No module py in axis/__init__ (fatal)

This happens when I run py.test src/axis --pylint. On closer inspection pytest-pylint apparently passes axis/__init__.py to lint.Run(), but this assumes that the current directory is src, which it clearly isn't. If I step into the src directory and run py.test axis --pylint things work fine. This seems like a regression.

All files deselected when running pytest -m pylint --pylint

Between 0.15.0 and 0.16.0 there was a change in the way that an empty ignore_patterns= is parsed from the .pylintrc. Starting with 0.16.0, ignore patterns gets loaded as an empty string'', which matches all files, deselecting all from analysis:

platform darwin -- Python 3.7.5, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
...
plugins: pylint-0.17.0, cov-2.8.1
collected 26 items / 26 deselected 

The solution is to comment out the empty ignore_patterns= entry in the .pylintrc:

platform darwin -- Python 3.7.5, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
...
plugins: pylint-0.17.0, cov-2.8.1
collected 38 items / 26 deselected / 12 selected

Side note: I'm not sure if this is a bug or just an API change, but I had trouble finding any information about it. The closest was #89, but I think it was a different root cause.

Passing multiple pylint-ignore args broken

Passing multiple ignore paths with --pylint-ignore does not seem to exclude paths entirely.
For example: pytest --pylint --pylint-ignore=migrations,tests --pylint-output-file=pylint.txt

In the pylint.txt output file, there are still entries for "migrations" - but not for "tests".

Ignore paths not working

Hi!

If I use full path (ignore=models/migrations/) in ignore option in my .pylintrc it doesn't work.

False positives after adding another fixture

Thank you for this excellent plugin.
It initially got rid of all the false positives as promised, but after I added another fixture it now gives false positives again.
I have attached a zip with an example.
The error is related to import of application code. Removing an import makes the false positive go away, see the comments in the file test/false_positive_for_fixture_test.py
pylint_pytest_bug.zip
.

Ignore files from pylintrc

pylint ignored/file.py --ignore=ignored or having ignored in the pylintrc file still does checking. I think that probably makes sense for pylint, but pytest-pylint should skip these files when checking. I think this will just involve parsing the pylintrc file enough to grab ignore and skip files based on it, or add a pytest-pylint specific option to ignore certain files as an alternative.

No errors, unless file explicitly selected

This problem happens to me in the Diofant project (see all relevant configs here).

Consider adding a trailing space:

$ git diff diofant/core/
diff --git a/diofant/core/expr.py b/diofant/core/expr.py
index c7857e0a5a..9fae5c3793 100644
--- a/diofant/core/expr.py
+++ b/diofant/core/expr.py
@@ -30,7 +30,7 @@ class Expr(Basic, EvalfMixin, metaclass=ManagedProperties):
 
     def __new__(cls, *args):
         obj = Basic.__new__(cls, *args)
-        obj._assumptions = cls.default_assumptions
+        obj._assumptions = cls.default_assumptions 
         return obj
 
     @property

Now run py.test with this file selected:


rootdir: /home/sk/src/diofant, inifile: setup.cfg
plugins: xdist-1.22.5, timeout-1.3.1, pylint-0.12.1, forked-0.2, cov-2.5.1, hypothesis-3.66.23
timeout: 600.0s
timeout method: signal
timeout func_only: False
collected 34 items / 33 deselected                                                                                                     
-----------------------------------------------------------------
Linting files
.
-----------------------------------------------------------------

diofant/core/expr.py F                                                                                                           [100%]

=============================================================== FAILURES ===============================================================
____________________________________________________ [pylint] diofant/core/expr.py _____________________________________________________
C: 33,50: Trailing whitespace (trailing-whitespace)
====================================================== slowest 30 test durations =======================================================
0.00s setup    diofant/core/expr.py
0.00s call     diofant/core/expr.py
0.00s teardown diofant/core/expr.py

Great, a problem detected.

But what if we run py.test without arguments or using directory instead of file? Unfortunately, there will be no error in this case. For example:

$ py.test -n0 --pylint -m pylint diofant/core
========================================================= test session starts ==========================================================
platform linux -- Python 3.5.3, pytest-3.7.1, py-1.5.4, pluggy-0.7.1

cache: True
ground types: gmpy

rootdir: /home/sk/src/diofant, inifile: setup.cfg
plugins: xdist-1.22.5, timeout-1.3.1, pylint-0.12.1, forked-0.2, cov-2.5.1, hypothesis-3.66.23
timeout: 600.0s
timeout method: signal
timeout func_only: False
collected 1489 items / 1422 deselected                                                                                                 
-----------------------------------------------------------------
Linting files
.
-----------------------------------------------------------------

diofant/core/__init__.py .                                                                                                       [  1%]
diofant/core/add.py .                                                                                                            [  2%]
diofant/core/alphabets.py .                                                                                                      [  4%]
diofant/core/assumptions.py .                                                                                                    [  5%]
diofant/core/basic.py .                                                                                                          [  7%]
diofant/core/cache.py .                                                                                                          [  8%]
diofant/core/compatibility.py .                                                                                                  [ 10%]
diofant/core/containers.py .                                                                                                     [ 11%]
diofant/core/coreerrors.py .                                                                                                     [ 13%]
diofant/core/decorators.py .                                                                                                     [ 14%]
diofant/core/evalf.py .                                                                                                          [ 16%]
diofant/core/evaluate.py .                                                                                                       [ 17%]
diofant/core/expr.py .                                                                                                           [ 19%]
diofant/core/exprtools.py .                                                                                                      [ 20%]
diofant/core/facts.py .                                                                                                          [ 22%]
diofant/core/function.py .                                                                                                       [ 23%]
diofant/core/logic.py .                                                                                                          [ 25%]
diofant/core/mod.py .                                                                                                            [ 26%]
diofant/core/mul.py .                                                                                                            [ 28%]
diofant/core/multidimensional.py .                                                                                               [ 29%]
diofant/core/numbers.py .                                                                                                        [ 31%]
diofant/core/operations.py .                                                                                                     [ 32%]
diofant/core/power.py .                                                                                                          [ 34%]
diofant/core/relational.py .                                                                                                     [ 35%]
diofant/core/rules.py .                                                                                                          [ 37%]
diofant/core/singleton.py .                                                                                                      [ 38%]
diofant/core/strategies.py .                                                                                                     [ 40%]
diofant/core/symbol.py .                                                                                                         [ 41%]
diofant/core/sympify.py .                                                                                                        [ 43%]
diofant/core/trace.py .                                                                                                          [ 44%]
diofant/core/tests/__init__.py .                                                                                                 [ 46%]
diofant/core/tests/test_args.py .                                                                                                [ 47%]
diofant/core/tests/test_arit.py .                                                                                                [ 49%]
diofant/core/tests/test_assumptions.py .                                                                                         [ 50%]
diofant/core/tests/test_basic.py .                                                                                               [ 52%]
diofant/core/tests/test_cache.py .                                                                                               [ 53%]
diofant/core/tests/test_compatibility.py .                                                                                       [ 55%]
diofant/core/tests/test_complex.py .                                                                                             [ 56%]
diofant/core/tests/test_containers.py .                                                                                          [ 58%]
diofant/core/tests/test_count_ops.py .                                                                                           [ 59%]
diofant/core/tests/test_diff.py .                                                                                                [ 61%]
diofant/core/tests/test_equal.py .                                                                                               [ 62%]
diofant/core/tests/test_eval.py .                                                                                                [ 64%]
diofant/core/tests/test_eval_power.py .                                                                                          [ 65%]
diofant/core/tests/test_evalf.py .                                                                                               [ 67%]
diofant/core/tests/test_evaluate.py .                                                                                            [ 68%]
diofant/core/tests/test_expand.py .                                                                                              [ 70%]
diofant/core/tests/test_expr.py .                                                                                                [ 71%]
diofant/core/tests/test_exprtools.py .                                                                                           [ 73%]
diofant/core/tests/test_facts.py .                                                                                               [ 74%]
diofant/core/tests/test_function.py .                                                                                            [ 76%]
diofant/core/tests/test_logic.py .                                                                                               [ 77%]
diofant/core/tests/test_match.py .                                                                                               [ 79%]
diofant/core/tests/test_multidimensional.py .                                                                                    [ 80%]
diofant/core/tests/test_noncommutative.py .                                                                                      [ 82%]
diofant/core/tests/test_numbers.py .                                                                                             [ 83%]
diofant/core/tests/test_operations.py .                                                                                          [ 85%]
diofant/core/tests/test_priority.py .                                                                                            [ 86%]
diofant/core/tests/test_relational.py .                                                                                          [ 88%]
diofant/core/tests/test_rules.py .                                                                                               [ 89%]
diofant/core/tests/test_strategies.py .                                                                                          [ 91%]
diofant/core/tests/test_subs.py .                                                                                                [ 92%]
diofant/core/tests/test_symbol.py .                                                                                              [ 94%]
diofant/core/tests/test_sympify.py .                                                                                             [ 95%]
diofant/core/tests/test_trace.py .                                                                                               [ 97%]
diofant/core/tests/test_truediv.py .                                                                                             [ 98%]
diofant/core/tests/test_var.py .                                                                                                 [100%]

====================================================== slowest 30 test durations =======================================================
0.01s call     diofant/core/evalf.py
0.00s teardown diofant/core/expr.py
0.00s teardown diofant/core/coreerrors.py
0.00s setup    diofant/core/alphabets.py
0.00s setup    diofant/core/tests/test_args.py
0.00s setup    diofant/core/expr.py
0.00s setup    diofant/core/coreerrors.py
0.00s setup    diofant/core/add.py
0.00s setup    diofant/core/__init__.py
0.00s setup    diofant/core/tests/test_equal.py
0.00s setup    diofant/core/tests/test_expand.py
0.00s call     diofant/core/strategies.py
0.00s teardown diofant/core/tests/test_subs.py
0.00s teardown diofant/core/tests/test_operations.py
0.00s call     diofant/core/tests/test_truediv.py
0.00s call     diofant/core/tests/test_exprtools.py
0.00s setup    diofant/core/tests/test_numbers.py
0.00s call     diofant/core/tests/test_eval_power.py
0.00s call     diofant/core/tests/test_multidimensional.py
0.00s setup    diofant/core/tests/test_evaluate.py
0.00s setup    diofant/core/tests/test_function.py
0.00s teardown diofant/core/exprtools.py
0.00s teardown diofant/core/logic.py
0.00s setup    diofant/core/compatibility.py
0.00s setup    diofant/core/tests/test_noncommutative.py
0.00s call     diofant/core/__init__.py
0.00s setup    diofant/core/cache.py
0.00s setup    diofant/core/tests/test_subs.py
0.00s setup    diofant/core/tests/test_evalf.py
0.00s setup    diofant/core/tests/test_cache.py
============================================= 67 passed, 1422 deselected in 103.55 seconds =============================================

W:171, 0: Method 'collect' is abstract in class 'Collector' but is not overridden (abstract-method)

pylint 1.8.3 shows warning on pytest_pylint.py

"Fixed" in Debian by disabling this pylint test: issue commit

$ pylint --version
No config file found, using default configuration
pylint 1.8.3,
astroid 1.6.3
Python 2.7.15 (default, May  1 2018, 05:55:50)
[GCC 7.3.0]

$ pylint pytest_pylint.py
No config file found, using default configuration
************* Module pytest_pylint
W:171, 0: Method 'collect' is abstract in class 'Collector' but is not overridden (abstract-method)

------------------------------------------------------------------
Your code has been rated at 9.92/10 (previous run: 9.92/10, +0.00)

Got an unexpected keyword argument 'exit' in lint.Run.

There seem to have been a breaking change in Pytest interface in version 2.2. (25/11/2018)

INTERNALERROR> result = lint.Run(args_list, reporter=reporter, exit=False)
INTERNALERROR> TypeError: init() got an unexpected keyword argument 'exit'

mtimes cache uses basenames resulting in collisions

The mtimes cache ends up with a mixture of simple names and rootdir relative paths. This causes collisions when files with the same name are entered with only the basename, resulting in incorrect timestamps being compared.

It appears that packages with no init.py (python3 style) get rootdir relative paths, but packages that have an init.py end up being relative to the closest parent, leading to the collisions.

I think the full root-relative path should always be used when storing values in the mtimes dict to avoid collisions.

Option --pylint-output-file does not deal with nonexistant directory

Sample pytest.ini

[pytest]
addopts = --cov=src --cov-report xml:reports/coverage.xml --pylint --pylint-error-types=F --pylint-output-file reports/pylint.txt --junitxml=reports/xunit-result.xml
junit_family = xunit2

Running pytest fails on pylint when the folder "reports" does not exist.
It does however create the folder and places coverage.xml and xunit-result.xml in it.
When running pytest a second time (or creating the folder beforehand), everything works as intended.

Invalidate cache if config changed

The cache uses the mtime of the files, but doesn't check if config is still the same. I've stopped disabling a message and pylint passed on my machine. But it didn't pass in the CI/CD pipeline (no cache).

It took me some time to figure out why it passed on my machine and I guess others might have the same problem. It would be nice to discard the cache on config changes.

test_pytest_pylint.py tests failure with pylint 2.4.4

The build is failing with pylint 2.4.4 on Ubuntu
https://launchpadlibrarian.net/454058807/buildlog_ubuntu-focal-amd64.pytest-pylint_0.14.1-2_BUILDING.txt.gz

'-----------------------------------------------------------------

pytest_pylint.py PASSED [ 5%]
setup.py PASSED [ 11%]
test_pytest_pylint.py FAILED [ 17%]

=================================== FAILURES ===================================
________________________ [pylint] test_pytest_pylint.py ________________________
C:131, 4: Import outside toplevel (pytest_pylint) (import-outside-toplevel)
C:171, 4: Import outside toplevel (pytest_pylint) (import-outside-toplevel)
C:194, 4: Import outside toplevel (pytest_pylint) (import-outside-toplevel)
=============================== warnings summary ===============================
/usr/lib/python3/dist-packages/isort/pie_slice.py:362
/usr/lib/python3/dist-packages/isort/pie_slice.py:362: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
class OrderedSet(collections.MutableSet):

-- Docs: https://docs.pytest.org/en/latest/warnings.html'

Unittest test_pytest_pylint.py FAILED

Hi, I am trying build new release (0.7.1) for Debian experimental.
My sbuild fails during unit tests with following error:

I: pybuild base:184: python2.7 -m pytest -v -x
============================= test session starts ==============================
platform linux2 -- Python 2.7.13, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- /usr/bin/python2.7
cachedir: .cache
rootdir: /<<PKGBUILDDIR>>, inifile: tox.ini
plugins: pylint-0.7.1
collecting ... collected 12 items
Unable to create directory /sbuild-nonexistent/.pylint.d
Unable to create file /sbuild-nonexistent/.pylint.d/test_pytest_pylint1.stats: [Errno 2] No such file or directory: u'/sbuild-nonexistent/.pylint.d/test_pytest_pylint1.stats'
-----------------------------------------------------------------
Linting files
-----------------------------------------------------------------

pytest_pylint.py PASSED
setup.py PASSED
test_pytest_pylint.py FAILED

=================================== FAILURES ===================================
________________________ [pylint] test_pytest_pylint.py ________________________
R:  1, 0: Similar lines in 3 files
==pytest_pylint:1
==pytest_pylint:1
==pytest_pylint:1
from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import print_function
from os import sep
from os.path import exists, join, dirname
from six.moves.configparser import (  # pylint: disable=import-error
    ConfigParser,
    NoSectionError,
    NoOptionError
)

from pylint import lint
from pylint.config import PYLINTRC
from pylint.interfaces import IReporter
from pylint.reporters import BaseReporter
import pytest


class PyLintException(Exception):
    """Exception to raise if a file has a specified pylint error"""
    pass


class ProgrammaticReporter(BaseReporter):
    """Reporter that replaces output with storage in list of dictionaries"""

    __implements__ = IReporter
    extension = 'prog'

    def __init__(self, output=None):
        BaseReporter.__init__(self, output)
        self.current_module = None
        self.data = []

    def add_message(self, msg_id, location, msg):
        """Deprecated, but required"""
        raise NotImplementedError

    def handle_message(self, msg):
        """Get message and append to our data structure"""
        self.data.append(msg)

    def _display(self, layout):
        """launch layouts display"""


def get_rel_path(path, parent_path):
    """
    Give the path to object relative to ``parent_path``.
    """
    replaced_path = path.replace(parent_path, '', 1)
    if replaced_path[0] == sep:
        rel_path = replaced_path[1:]
    else:
        rel_path = replaced_path
    return rel_path


def pytest_addoption(parser):
    """Add all our command line options"""
    group = parser.getgroup("general")
    group.addoption(
        "--pylint",
        action="store_true", default=False,
        help="run pylint on all"
    )
    group.addoption(
        '--pylint-rcfile',
        default=None,
        help='Location of RC file if not pylintrc'
    )
    group.addoption(
        '--pylint-error-types',
        default='CRWEF',
        help='The types of pylint errors to consider failures by letter'
        ', default is all of them (CRWEF).'
    )


def pytest_sessionstart(session):
    """Storing pylint settings on the session"""
    session.pylint_files = set()
    session.pylint_messages = {}
    session.pylint_config = None
    session.pylintrc_file = None
    session.pylint_ignore = []
    session.pylint_msg_template = None
    config = session.config

    # Find pylintrc to check ignore list
    pylintrc_file = config.option.pylint_rcfile or PYLINTRC

    if pylintrc_file and not exists(pylintrc_file):
        # The directory of pytest.ini got a chance
        pylintrc_file = join(dirname(str(config.inifile)), pylintrc_file)

    if pylintrc_file and exists(pylintrc_file):
        session.pylintrc_file = pylintrc_file
        session.pylint_config = ConfigParser()
        session.pylint_config.read(pylintrc_file)
        try:
            ignore_string = session.pylint_config.get('MASTER', 'ignore')
            if ignore_string:
                session.pylint_ignore = ignore_string.split(',')
        except (NoSectionError, NoOptionError):
            pass
        try:
            session.pylint_msg_template = session.pylint_config.get(
                'REPORTS', 'msg-template'
            )
        except (NoSectionError, NoOptionError):
            pass


def pytest_collect_file(path, parent):
    """Collect files on which pylint should run"""
    config = parent.config
    if not config.option.pylint:
        return
    if path.ext != ".py":
        return
    rel_path = get_rel_path(path.strpath, parent.fspath.strpath)
    if parent.pylint_config is None:
        parent.pylint_files.add(rel_path)
        # No pylintrc, therefore no ignores, so return the item.
        return PyLintItem(path, parent)

    if not any(basename in rel_path for basename in parent.pylint_ignore):
        parent.pylint_files.add(rel_path)
        return PyLintItem(
            path, parent, parent.pylint_msg_template, parent.pylintrc_file
        )


def pytest_collection_finish(session):
    """Lint collected files and store messages on session."""
    if not session.pylint_files:
        return
    reporter = ProgrammaticReporter()
    # Build argument list for pylint
    args_list = list(session.pylint_files)
    if session.pylintrc_file:
        args_list.append('--rcfile={0}'.format(
            session.pylintrc_file
        ))
    print('-' * 65)
    print('Linting files')
    # Run pylint over the collected files.
    result = lint.Run(args_list, reporter=reporter, exit=False)
    messages = result.linter.reporter.data
    # Stores the messages in a dictionary for lookup in tests.
    for message in messages:
        if message.path not in session.pylint_messages:
            session.pylint_messages[message.path] = []
        session.pylint_messages[message.path].append(message)
    print('-' * 65)


class PyLintItem(pytest.Item, pytest.File):
    """pylint test running class."""
    # pylint doesn't deal well with dynamic modules and there isn't an
    # astng plugin for pylint in pypi yet, so we'll have to disable
    # the checks.
    # pylint: disable=no-member,super-on-old-class
    def __init__(self, fspath, parent, msg_format=None, pylintrc_file=None):
        super(PyLintItem, self).__init__(fspath, parent)

        self.add_marker("pylint")
        self.rel_path = get_rel_path(fspath.strpath, parent.fspath.strpath)

        if msg_format is None:
            self._msg_format = '{C}:{line:3d},{column:2d}: {msg} ({symbol})'
        else:
            self._msg_format = msg_format

        self.pylintrc_file = pylintrc_file

    def runtest(self):
        """Check the pylint messages to see if any errors were reported."""
        reported_errors = []
        for error in self.session.pylint_messages.get(self.rel_path, []):
            if error.C in self.config.option.pylint_error_types:
                reported_errors.append(
                    error.format(self._msg_format)
                )
        if reported_errors:
            raise PyLintException('\n'.join(reported_errors))

    def repr_failure(self, excinfo):
        """Handle any test failures by checkint that they were ours."""
        if excinfo.errisinstance(PyLintException):
            return excinfo.value.args[0]
        return super(PyLintItem, self).repr_failure(excinfo)

    def reportinfo(self):
        """Generate our test report"""
        return self.fspath, None, "[pylint] {0}".format(self.name) (duplicate-code)
!!!!!!!!!!!!!!!!!!!! Interrupted: stopping after 1 failures !!!!!!!!!!!!!!!!!!!!
====================== 1 failed, 2 passed in 1.14 seconds ======================
E: pybuild pybuild:283: test: plugin custom failed with: exit code=2: python2.7 -m pytest -v -x

How to run it? Tried many options

Tried many options like following but they mostly just run tests without any checks:

py.test --pylint
py.test --pylint --pylint-rcfile .pylintrc
py.test --pylint -m pylint

Updated setup.cfg

[tool:pytest]
testpaths = tests
addopts = --pylint tests --pylint-rcfile .pylintrc

Python v.3.6.3
requirements.txt includes:

pytest==3.1.2
pylint==1.8.2
pytest-pylint==0.9.0

p.s. pylint app works for main app but not for tests

Support ignoring warnings on a per-file basis

In pytest-flake8, you can ignore errors on a per-file basis, for example:

[pytest]
flake8-ignore = populate_db.py ALL
    config.py E501  ; Long lines happen in the config file

This would be nice to support in pytest-pylint as well, as currently the only equivalent is ignoring all errors in a certain file, which is not always desirable.

feat: search for config file

Currently the config file is retrieved from pylint.config.PYLINTRC if this exists, otherwise it requires being specified at call time on the command line, which is a bit of a pain. pylint itself supports searching in a set of different locations for config via its pylint.config.find_default_config_files() function which is able to correctly find setup.cfg and pyproject.toml config files in the standard places. Please can we add support for doing this in pytest-pylint to support more efficient calling of pytest? I have already prepared a PR which achieves this and passes all tests.

pytest option --no-pylint is ignored

I have a pytest.ini with addopts=--cov=. --no-cov-on-fail --pylint.

Sometimes when I don't want to run pylint, I add --no-pylint option to the pytest command. The existence of such option means it should force-disable pylint if it was enabled by default. But option --no-pylint is just ignored.

Testcase:

pytest --pylint --no-pylint  # pylint should not run here

TypeError: __init__() got multiple values for argument 'fspath'

==================================== ERRORS ====================================
________________________ ERROR collecting test session _________________________
../../../virtualenv/python3.8.0/lib/python3.8/site-packages/pluggy/hooks.py:286: in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
../../../virtualenv/python3.8.0/lib/python3.8/site-packages/pluggy/manager.py:92: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
../../../virtualenv/python3.8.0/lib/python3.8/site-packages/pluggy/manager.py:83: in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
../../../virtualenv/python3.8.0/lib/python3.8/site-packages/pytest_pylint/plugin.py:222: in pytest_collect_file
    item = PylintFile.from_parent(
../../../virtualenv/python3.8.0/lib/python3.8/site-packages/pytest_pylint/plugin.py:295: in from_parent
    _self = getattr(super(), 'from_parent', cls)(parent, fspath=fspath)
E   TypeError: __init__() got multiple values for argument 'fspath'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.10s ===============================

typed-ast version issue with python 3.6 on linux

I have an error since the new release of pytest-pylint on conda-forge.

I test my project with various python version on Linux and MacOS and I have an issue only with Python 3.6 on Linux. It works on MacOS with the same version of pylint (2.3.1), pytest (4.3.0), typed-ast (1.3.1) and pytest-pylint (0.14.0).

The error message is

pluggy.manager.PluginValidationError: Plugin 'pylint' could not be loaded: (typed-ast 1.3.1 (/home/travis/miniconda/envs/pylbm_env/lib/python3.6/site-packages), Requirement.parse('typed-ast<1.3.0; python_version < "3.7" and implementation_name == "cpython"'), {'astroid'})!

If you want to see the logs for both:

Tell me if it's not related to pytest-pylint

PytestDeprecationWarning

I'm getting a warning running pytest with pytest-pylint:

venv/lib/python3.8/site-packages/pytest_pylint/plugin.py:140
  /home/alex/q/venv/lib/python3.8/site-packages/pytest_pylint/plugin.py:140: PytestDeprecationWarning: direct construction of PyLintItem has been deprecated, please use PyLintItem.from_parent
    item = PyLintItem(path, parent, pylint_plugin=self)
pylint            2.4.4  
pytest            5.4.1  
pytest-pylint     0.15.1 

Pylint passes on MacOSX but fails on Linux

hoping someone can assist

I am running pylint tests which pass locally (MacOSX) but fail on CI servers (linux).

Local run :

✗ python setup.py test
running pytest
running egg_info
writing xxxx.egg-info/PKG-INFO
writing dependency_links to xxxx/dependency_links.txt
writing top-level names to xxxx.egg-info/top_level.txt
reading manifest file 'xxxx.egg-info/SOURCES.txt'
writing manifest file 'xxxx.egg-info/SOURCES.txt'
running build_ext
============================================================================================================================= test session starts ==============================================================================================================================
platform darwin -- Python 3.7.2, pytest-4.0.2, py-1.8.0, pluggy-0.9.0
rootdir: /Users/xxxx/repos/xxxx, inifile: pytest.ini
plugins: pylint-0.14.0, pycodestyle-1.4.0, flakes-4.0.0, docstyle-1.5.0, cov-2.6.0
collected 545 items
-----------------------------------------------------------------
Linting files
.
-----------------------------------------------------------------
------- CUT FOR BREVITY -------

TOTAL                                                                                   771     83    89%

Required test coverage of 70% reached. Total coverage: 89.23%
============================================================================================================= 127 passed, 418 skipped, 1 warnings in 7.65 seconds ==============================================================================================================
✗

CI server

[Container] 2019/03/26 12:05:44 Running command python setup.py test 
running pytest 
running egg_info 
creating xxxx.egg-info 
writing xxxx.egg-info/PKG-INFO 
writing dependency_links to xxxx.egg-info/dependency_links.txt 
writing top-level names to xxxx.egg-info/top_level.txt 
writing manifest file 'xxxx.egg-info/SOURCES.txt' 
reading manifest file 'xxxx.egg-info/SOURCES.txt' 
writing manifest file 'xxxx.egg-info/SOURCES.txt' 
running build_ext 
============================= test session starts ============================== 
platform linux -- Python 3.7.1, pytest-4.0.2, py-1.8.0, pluggy-0.9.0 
rootdir: xxxx, inifile: pytest.ini 
plugins: pylint-0.14.0, pycodestyle-1.4.0, flakes-4.0.0, docstyle-1.5.0, cov-2.6.0 
collected 545 items 
----------------------------------------------------------------- 
Linting files 
............................................................................................................... 


------ CUT FOR BREVITY -------
----------------------------------------------------------------- 
=================================== FAILURES =================================== 
___ [pylint] product_price/infrastructure/test/test_product_price_mapper.py ____ 
R:  1, 0: Similar lines in 2 files 
==elasticsearch_infrastructure.infrastructure.test.test_elasticsearch_entity_repository:85 
==product_price.infrastructure.test.test_product_service_http_repo:104 
       } 

   @staticmethod 
   @pytest.fixture 
   def test_response(): 
       return mock.Mock() 

   @staticmethod 
   @pytest.fixture 
   def test_get_found_response(): 
       return json.dumps( 
           { (duplicate-code) 
R:  1, 0: Similar lines in 2 files 
==elasticsearch_infrastructure.infrastructure.test.test_elasticsearch_entity_repository:24 
==product_price.infrastructure.test.test_product_service_http_repo:27 
       self._identifier = identifier 

   @property 
   def field1(self): 
       return self._field1 

   @property 
   def field2(self): 
       return self._field2 

   @property (duplicate-code) 
R:  1, 0: Similar lines in 2 files 
==elasticsearch_infrastructure.infrastructure.test.test_elasticsearch_entity_repository:43 
==product_price.infrastructure.test.test_product_service_http_repo:61 
               and self.identifier == other.identifier 
return False 






----------- CUT FOR BREVITY ------


--------------------------------------------------------------------------------------------------------- 
TOTAL                                                                                   771     83    89% 

Required test coverage of 70% reached. Total coverage: 89.23% 
============== 1 failed, 544 passed, 1 warnings in 19.22 seconds =============== 

[Container] 2019/03/26 12:06:05 Command did not exit successfully python setup.py test exit status 1 



setup.cfg file

[aliases]
test=pytest

[pycodestyle]
count = False
ignore = W605,E226,E302,E41
statistics = True

pytest.ini file

[pytest]
filterwarnings =
    ignore::PendingDeprecationWarning
    ignore::DeprecationWarning
docstyle_add_ignore = D101 D107 D103 D104 D100 D203 D205 D204 D212 D102 D105
codestyle_max_line_length = 120
codestyle_ignore = W605
addopts =
    --pylint
    --pylint-rcfile=.pylintrc
    --docstyle
    --codestyle
    --flakes
    --cov=product_price/
    --cov-fail-under=70

I compared all libraries installed on both environments and they are identical.

Is there anything I am missing?

Missing first letter in module

When running pytest-pylint in a windows environment, all files in package 'mypackage' fail with the No module named ypackage\mymodule\myfile.py (fatal) error

Debugger tracks the error to pytest_pylint.py:157 (PyLintItem.__init__)

self.rel_path = fspath.strpath.replace(
    parent.fspath.strpath, '', 1
)[1:]

fspath is a correct LocalPath pointing to 'mypackage\mymodule\myfile.py'
self.rel_path is missing the m in 'mypackage'

Python version: 3.4.3 (32 bit)
pytest-pylint version: 0.7.0

doesn't work if using "enable" in pylintrc

Can I get a confirmation that this doesn't work if we're using the "enable" config value in the pylintrc?

For example:

[MASTER]
persistent=yes
load-plugins=pylint_pytest
jobs=1

[MESSAGES CONTROL]
disable=all
enable=W0621

With said config, if linting a test file using pylint fixtures, I see the "redefined-outer-name" lint message.

Seems like any rules that are "enabled" take precedencece over the plugin?

Mysterious error when using pytest-pylint

Hello,

I seem to be getting weird behavior when using pylint on this repo:

https://github.com/PlasmaSheep/pylint-bug

(issue present in python2 and python3)

pip install -r requirements.txt
py.test --pylint

Will cause:


    def test_index():
>       create_app()

tests/test_views_core.py:7: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def create_app():
        """Create and return an instance of this application.
        """
>       from cacophony.views.core import core
E       ImportError: No module named 'cacophony.views.core'

Which clearly exists. However, py.test without pylint does not cause this error.

cache property not available

I'm getting this when running teamcity-messages tests for pylint:

Traceback (most recent call last):
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/_pytest/main.py", line 80, in wrap_session
     config.do_configure()
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/_pytest/config.py", line 618, in do_configure
     self.hook.pytest_configure(config=self)
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/_pytest/core.py", line 521, in __call__
     return self._docall(self.methods, kwargs)
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/_pytest/core.py", line 528, in _docall
     firstresult=self.firstresult).execute()
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/_pytest/core.py", line 394, in execute
     res = method(*args)
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/pytest_pylint.py", line 164, in pytest_configure
     config.pylint = PylintPlugin(config)
   File "/tmp/teamcity-python-venv/27pyst27pynt/lib/python2.7/site-packages/pytest_pylint.py", line 176, in __init__
     self.mtimes = config.cache.get(HISTKEY, {})
 AttributeError: 'Config' object has no attribute 'cache'

which appears to be related to #83. Maybe pytest-dev/pytest@e478f66 is related? I can't see why the cacheprovider has not yet set the cache property, since it should be loaded first.

Support disabling pylint via the command line

Hey, thank you for this package! I have a small feature request - we add --pylint to our setup.cfg file so that it is always run alongside our tests:

[tool:pytest]
addopts = -p no:cacheprovider -n auto --junitxml /tmp/unit_results.xml --pylint

This works fine, but I find myself wishing to just run our tests locally without the linting (which is a bit faster).

I'd love the ability to run pytest --no-pylint and have it override the auto-included --pylint flag, so that pytest --pylint --no-pylint will not run pylint.

Support --pylint-ignore and --pylint-ignore-patterns flags

Pass through these options to pylint equivalents. I have seen the option for patterns now working in .pylintrc via issue #81. When running tox for multiple environments, I had a use case where for a py2.7 run I wanted to ignore a certain file. Happy to raise a PR for this if it is desired/fits the goals of the project.

Cannot install packages (travis only) when this package is in the requirements.

It appears to have a version conflict with six. Which is weird considering this project doesn't pin the version and the venv build works locally but the venv build on travis fails.

Any method to get this working?

Here's the build showing the error:
https://travis-ci.org/vangorra/python_withings_api/jobs/594694196

Here's the error:

Using /home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages
Searching for six==1.12.0
Best match: six 1.12.0
Processing six-1.12.0-py3.7.egg
Adding six 1.12.0 to easy-install.pth file
Using /home/travis/build/vangorra/python_withings_api/.eggs/six-1.12.0-py3.7.egg
Finished processing dependencies for withings-api==0.0.0a0
  File "build/bdist.linux-x86_64/egg/oauth_hook/hook.py", line 93
    except TypeError, e:
                    ^
SyntaxError: invalid syntax
  File "build/bdist.linux-x86_64/egg/tests/tests.py", line 111
    print "Go to https://api.twitter.com/oauth/authenticate?oauth_token=%s and sign in into the application, then enter your PIN" % oauth_token[0]
                                                                                                                                ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Go to https://api.twitter.com/oauth/authenticate?oauth_token=%s and sign in into the application, then enter your PIN" % oauth_token[0])?
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/requests_oauth-0.4.1-py3.7.egg/oauth_hook/hook.py", line 93
    except TypeError, e:
                    ^
SyntaxError: invalid syntax
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/requests_oauth-0.4.1-py3.7.egg/tests/tests.py", line 111
    print "Go to https://api.twitter.com/oauth/authenticate?oauth_token=%s and sign in into the application, then enter your PIN" % oauth_token[0]
                                                                                                                                ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Go to https://api.twitter.com/oauth/authenticate?oauth_token=%s and sign in into the application, then enter your PIN" % oauth_token[0])?
Running tests.
Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/manager.py", line 267, in load_setuptools_entrypoints
    plugin = ep.load()
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2410, in load
    self.require(*args, **kwargs)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2433, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pkg_resources/__init__.py", line 791, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.ContextualVersionConflict: (six 1.11.0 (/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages), Requirement.parse('six==1.12'), {'astroid'})
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "setup.py", line 47, in <module>
    "Programming Language :: Python :: Implementation :: PyPy",
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/setuptools/__init__.py", line 145, in setup
    return distutils.core.setup(**attrs)
  File "/opt/python/3.7.1/lib/python3.7/distutils/core.py", line 148, in setup
    dist.run_commands()
  File "/opt/python/3.7.1/lib/python3.7/distutils/dist.py", line 966, in run_commands
    self.run_command(cmd)
  File "/opt/python/3.7.1/lib/python3.7/distutils/dist.py", line 985, in run_command
    cmd_obj.run()
  File "/home/travis/build/vangorra/python_withings_api/.eggs/pytest_runner-5.1-py3.7.egg/ptr.py", line 209, in run
    return self.run_tests()
  File "/home/travis/build/vangorra/python_withings_api/.eggs/pytest_runner-5.1-py3.7.egg/ptr.py", line 220, in run_tests
    result_code = __import__('pytest').main()
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/config/__init__.py", line 60, in main
    config = _prepareconfig(args, plugins)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/config/__init__.py", line 195, in _prepareconfig
    pluginmanager=pluginmanager, args=args
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/hooks.py", line 284, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/manager.py", line 67, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/manager.py", line 61, in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/callers.py", line 203, in _multicall
    gen.send(outcome)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/helpconfig.py", line 93, in pytest_cmdline_parse
    config = outcome.get_result()
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/config/__init__.py", line 654, in pytest_cmdline_parse
    self.parse(args)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/config/__init__.py", line 871, in parse
    self._preparse(args, addopts=addopts)
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/_pytest/config/__init__.py", line 816, in _preparse
    self.pluginmanager.load_setuptools_entrypoints("pytest11")
  File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/pluggy/manager.py", line 273, in load_setuptools_entrypoints
    message="Plugin %r could not be loaded: %s!" % (ep.name, e),
pluggy.manager.PluginValidationError: Plugin 'pylint' could not be loaded: (six 1.11.0 (/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages), Requirement.parse('six==1.12'), {'astroid'})!
The command "./scripts/build.sh" exited with 1.

pylint check only unsed imports

Hi,

I would like to check only unsed imports & compiling issues - can it be done somehow? (i don't mind for now about line size, dots, etc).

I'm unable to get the plugin to complain on my module under test

I currently have pylint + py.test setup in my project. The basic structure is...

project-dir/
  setup.cfg
  .pylintrc
  mypackage/
  tests/
    mypackage/

I run py.test using a command like so

PYTHONPATH=. py.test --pylint --pylint-rcfile=.pylintrc

I don't get an error from py.test when I know that files in mypackage are not clean.

I'm using versions
py.test==2.8.2
pytest-pylint==0.4.0
pylint==1.1.0
atroid==1.0.1
Python=2.7.6
OS Ubuntu 14.04 LTS

Collection skipped based on partial matches

In my current project I have an ignore path set in pylintrc

# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=hooks,data

The intent is to ignore all files under the "hooks" or "data" directories. I also have a file called "read_data.py". If I run pylint directly, the data directory is ignored and the read_data.py is checked (as intended). However if I run through pytest-pylint the read_data.py is ignored.

I've traced the issue back to the pytest_collect_file function which does the following:

if not any(basename in rel_path for basename in session.pylint_ignore):

Since rel_path is a string if will match the basename (data) anywhere in the path. My idea would be to break this into a separate function (pytest_valid_path) and in there split rel_path into it's parts and check if any of those are equal to basename,

I'll try get a PR (with unit test) together for this soon to demonstrate.

nodeids generated by this plugin on Windows are not escaped

Hello!

I help maintain pytest-html and I've been looking into pytest-dev/pytest-html#342, which is an issue that involves both pytest-html and pytest-pylint.

It would appear that the node ids ( like my_tests/test_me.py::C:\Users\glebi\Documents\programming_environment\my_tests\test_me.py::PYLINT, for example ) created by this plugin are not escaped on Windows, and this causes problems for pytest-html when we generate reports and try to encode/decode the node ids. Specifically, it is the \U in the path that causes issues as it is also the start of a unicode code point. Unfortunately we can't escape \U on all node ids, since there are times where the sequence is valid ( see pytest-dev/pytest-html#342 (comment) for a detailed example ).

Is there any way that we could either escape the node ids in this plugin or have them conerted to Unix style paths? Without this change, it would appear that our plugins are unfortunately not compatible on Windows.

pytest-pylint is not available in conda-forge

Hello,
I need your package as a dependency to be available in conda-forge.
I created conda-forge/staged-recipes#5106 and added your package.

My question is now, do you want to be added as conda-forge maintainer for the pytest-pylint package?
This means that you have write rights for the pytest-pylint-feedstock package and could push new releases to cona-forge.

Best regards
Holger

'.pylintrc' file not working

I've moved my pytest call to outside of the directory, and the pymintrc file no longer works.

This works perfectly

pylint code/python/dynamo --rcfile=code/python/.pylintrc

This does not read the rc file

pytest --pylint --pylint-rcfile=./code/python/.pylintrc code/python/dynamo

How am I supposed to handle this?

pylint warnings

Hello,
I would like similar options as pylint-error-types for warnings reporting

for example

--pylint-error-types=EF --pylint-warnings-types=CRW

produce something like:

project.py PASSED                                        [100%]

=============================== warnings summary ===============================
_____________________ [pylint] project.py ______________________
C:  1, 0: Missing module docstring (missing-docstring)
C: 16, 0: Argument name "e" doesn't conform to snake_case naming style (invalid-name)


-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================== 21 passed, 2 warnings in 3.67 seconds =====================

thank you

TypeError: __init__() got an unexpected keyword argument 'do_exit'

pylint 2.5.1 changed the lint.Run class definition and rename the parameter do_exit to exit.
According to pylint-dev/pylint#3554 this is a revert of an incorrectly named parameter.

INTERNALERROR>   File "/home/stefanga/projects/oe-fwrt/.tox/scripts/lib/python3.5/site-packages/pytest_pylint/plugin.py", line 174, in pytest_collection_finish
INTERNALERROR>     result = lint.Run(args_list, reporter=reporter, do_exit=False)
INTERNALERROR> TypeError: __init__() got an unexpected keyword argument 'do_exit'

To get the latest version of pytest-pylint to work one must lock the pylint dependency to <2.5.1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.