carsongee / pytest-pylint Goto Github PK
View Code? Open in Web Editor NEWpytest plugin for running pylint against your codebase
License: MIT License
pytest plugin for running pylint against your codebase
License: MIT License
I wondered why my test suite failed and it was because my pylint checking - done with something like:
pytest --pylint -m pylint mymodule
ends up "collecting 0 items" to check.
Works fine with 0.13.0.
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.
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.
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.
On my project executing just "pytest" I get ModuleNotFoundError, but with "python -m pytest" it works. It's related to https://medium.com/@dirk.avery/pytest-modulenotfounderror-no-module-named-requests-a770e6926ac5 , but none of the suggestions there work.
With "py.test --pylint" I also get ModuleNotFoundError. Any suggestion?
thanks
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 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".
Hi!
If I use full path (ignore=models/migrations/) in ignore option in my .pylintrc it doesn't work.
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
.
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.
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 =============================================
Pytest deprecated storing items on the pytest module, so we need to replace it with a new pattern
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)
I currently have all my configuration in a setup.cfg
. Adding this seems not to have an effect:
[pylint]
disable = W1202
ignore-patterns=test_.*?py
Does it work differently?
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'
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.
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.
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.
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):
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
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
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.
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.
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
==================================== 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 ===============================
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
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
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?
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
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?
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.
Please publish the current package version to pypi :-)
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.
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.
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.
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.
Development section has a broken link for the overview documentation.
Updated to 0.12.3 and all of my pylint: disable
s are being ignored. Downgraded back to 0.12.1 and it's working.
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 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
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.
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.
How can I run pylint-pytest from a test (rather than from command line) for c:\git\example*.py?
I guess the topic states it all.
I want to use violation plugin (jenkins) and the pytest-pylint package :)
Can it be done?
If so,
How?
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
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?
Please create release tag for 0.14.0.
If pylintrc looks something like:
[MASTER]
ignore-patterns =
^mypattern/.*,
^otherpattern/.*
Then what actually gets evaluated is \n^mypattern/.*
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
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.