Skip to content

Commit

Permalink
Added black and isort and fixed pytest dev branch
Browse files Browse the repository at this point in the history
  • Loading branch information
carsongee committed Apr 21, 2021
1 parent e27a021 commit 33519cb
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 320 deletions.
7 changes: 6 additions & 1 deletion pylintrc
@@ -1,3 +1,8 @@
[TYPECHECK]
[MESSAGES CONTROL]
disable = C0330, C0326

[FORMAT]
max-line-length = 88

[TYPECHECK]
ignored-classes = pytest
154 changes: 61 additions & 93 deletions pytest_pylint/plugin.py
Expand Up @@ -6,68 +6,63 @@


from collections import defaultdict
from configparser import ConfigParser, NoSectionError, NoOptionError
from configparser import ConfigParser, NoOptionError, NoSectionError
from os import makedirs
from os.path import getmtime, exists, join, dirname
from os.path import dirname, exists, getmtime, join

from pylint import lint
from pylint.config import PYLINTRC
import pytest
import toml
from pylint import lint
from pylint.config import PYLINTRC

from .pylint_util import ProgrammaticReporter
from .util import get_rel_path, PyLintException, should_include_file
from .util import PyLintException, get_rel_path, should_include_file

HISTKEY = 'pylint/mtimes'
PYLINT_CONFIG_CACHE_KEY = 'pylintrc'
HISTKEY = "pylint/mtimes"
PYLINT_CONFIG_CACHE_KEY = "pylintrc"
FILL_CHARS = 80
MARKER = 'pylint'
MARKER = "pylint"


def pytest_addoption(parser):
"""Add all our command line options"""
group = parser.getgroup("pylint")
group.addoption(
"--pylint",
action="store_true", default=False,
help="run pylint on all"
"--pylint", action="store_true", default=False, help="run pylint on all"
)
group.addoption(
"--no-pylint",
action="store_true", default=False,
help="disable running pylint "
action="store_true",
default=False,
help="disable running pylint ",
)

group.addoption(
'--pylint-rcfile',
default=None,
help='Location of RC file if not pylintrc'
"--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).'
"--pylint-error-types",
default="CRWEF",
help="The types of pylint errors to consider failures by letter"
", default is all of them (CRWEF).",
)
group.addoption(
'--pylint-jobs',
"--pylint-jobs",
default=None,
help='Specify number of processes to use for pylint'
help="Specify number of processes to use for pylint",
)
group.addoption(
'--pylint-output-file',
"--pylint-output-file",
default=None,
help='Path to a file where Pylint report will be printed to.'
help="Path to a file where Pylint report will be printed to.",
)
group.addoption(
'--pylint-ignore',
default=None,
help='Files/directories that will be ignored'
"--pylint-ignore", default=None, help="Files/directories that will be ignored"
)
group.addoption(
'--pylint-ignore-patterns',
"--pylint-ignore-patterns",
default=None,
help='Files/directories patterns that will be ignored'
help="Files/directories patterns that will be ignored",
)


Expand All @@ -77,10 +72,7 @@ def pytest_configure(config):
:param _pytest.config.Config config: pytest config object
"""
config.addinivalue_line(
'markers',
"{0}: Tests which run pylint.".format(MARKER)
)
config.addinivalue_line("markers", "{0}: Tests which run pylint.".format(MARKER))
if config.option.pylint and not config.option.no_pylint:
pylint_plugin = PylintPlugin(config)
config.pluginmanager.register(pylint_plugin)
Expand All @@ -90,9 +82,10 @@ class PylintPlugin:
"""
The core plugin for pylint
"""

# pylint: disable=too-many-instance-attributes
def __init__(self, config):
if hasattr(config, 'cache'):
if hasattr(config, "cache"):
self.mtimes = config.cache.get(HISTKEY, {})
else:
self.mtimes = {}
Expand Down Expand Up @@ -136,36 +129,32 @@ def pytest_configure(self, config):

# Command line arguments take presedence over rcfile ones if set
if config.option.pylint_ignore is not None:
self.pylint_ignore = config.option.pylint_ignore.split(',')
self.pylint_ignore = config.option.pylint_ignore.split(",")
if config.option.pylint_ignore_patterns is not None:
self.pylint_ignore_patterns = (
config.option.pylint_ignore_patterns.split(',')
self.pylint_ignore_patterns = config.option.pylint_ignore_patterns.split(
","
)

def _load_rc_file(self, pylintrc_file):
self.pylint_config = ConfigParser()
self.pylint_config.read(pylintrc_file)

try:
ignore_string = self.pylint_config.get('MASTER', 'ignore')
ignore_string = self.pylint_config.get("MASTER", "ignore")
if ignore_string:
self.pylint_ignore = ignore_string.split(',')
self.pylint_ignore = ignore_string.split(",")
except (NoSectionError, NoOptionError):
pass

try:
ignore_patterns = self.pylint_config.get(
'MASTER', 'ignore-patterns'
)
ignore_patterns = self.pylint_config.get("MASTER", "ignore-patterns")
if ignore_patterns:
self.pylint_ignore_patterns = ignore_patterns.split(',')
self.pylint_ignore_patterns = ignore_patterns.split(",")
except (NoSectionError, NoOptionError):
pass

try:
self.pylint_msg_template = self.pylint_config.get(
'REPORTS', 'msg-template'
)
self.pylint_msg_template = self.pylint_config.get("REPORTS", "msg-template")
except (NoSectionError, NoOptionError):
pass

Expand All @@ -192,13 +181,9 @@ def _load_pyproject_toml(self, pylintrc_file):
ignore = master_section.get("ignore")
if ignore:
self.pylint_ignore = (
ignore.split(",")
if isinstance(ignore, str)
else ignore
ignore.split(",") if isinstance(ignore, str) else ignore
)
self.pylint_ignore_patterns = (
master_section.get("ignore-patterns") or []
)
self.pylint_ignore_patterns = master_section.get("ignore-patterns") or []
self.pylint_msg_template = reports_section.get("msg-template")

def pytest_sessionfinish(self, session):
Expand All @@ -207,7 +192,7 @@ def pytest_sessionfinish(self, session):
:param _pytest.main.Session session: the pytest session object
"""
if hasattr(session.config, 'cache'):
if hasattr(session.config, "cache"):
session.config.cache.set(HISTKEY, self.mtimes)

def pytest_collect_file(self, path, parent):
Expand All @@ -217,11 +202,9 @@ def pytest_collect_file(self, path, parent):

rel_path = get_rel_path(path.strpath, parent.session.fspath.strpath)
if should_include_file(
rel_path, self.pylint_ignore, self.pylint_ignore_patterns
rel_path, self.pylint_ignore, self.pylint_ignore_patterns
):
item = PylintFile.from_parent(
parent, fspath=path, plugin=self
)
item = PylintFile.from_parent(parent, fspath=path, plugin=self)
else:
return None

Expand All @@ -240,26 +223,20 @@ def pytest_collection_finish(self, session):
# Build argument list for pylint
args_list = list(self.pylint_files)
if self.pylintrc_file:
args_list.append('--rcfile={0}'.format(
self.pylintrc_file
))
args_list.append("--rcfile={0}".format(self.pylintrc_file))
if jobs is not None:
args_list.append('-j')
args_list.append("-j")
args_list.append(jobs)
# These allow the user to override the pylint configuration's
# ignore list
if self.pylint_ignore:
args_list.append(
'--ignore={0}'.format(','.join(self.pylint_ignore))
)
args_list.append("--ignore={0}".format(",".join(self.pylint_ignore)))
if self.pylint_ignore_patterns:
args_list.append(
'--ignore-patterns={0}'.format(
','.join(self.pylint_ignore_patterns)
)
"--ignore-patterns={0}".format(",".join(self.pylint_ignore_patterns))
)
print('-' * FILL_CHARS)
print('Linting files')
print("-" * FILL_CHARS)
print("Linting files")

# Run pylint over the collected files.

Expand All @@ -275,11 +252,12 @@ def pytest_collection_finish(self, session):
# Stores the messages in a dictionary for lookup in tests.
for message in messages:
self.pylint_messages[message.path].append(message)
print('-' * FILL_CHARS)
print("-" * FILL_CHARS)


class PylintFile(pytest.File):
"""File that pylint will run on."""

rel_path = None # : str
plugin = None # : PylintPlugin
should_skip = False # : bool
Expand All @@ -290,25 +268,19 @@ def from_parent(cls, parent, *, fspath, plugin):
# We add the ``plugin`` kwarg to get plugin level information so the
# signature differs
# pylint: disable=arguments-differ
_self = getattr(super(), 'from_parent', cls)(parent, fspath=fspath)
_self = getattr(super(), "from_parent", cls)(parent, fspath=fspath)
_self.plugin = plugin

_self.rel_path = get_rel_path(
fspath.strpath,
parent.session.fspath.strpath
)
_self.rel_path = get_rel_path(fspath.strpath, parent.session.fspath.strpath)
_self.mtime = fspath.mtime()
prev_mtime = _self.plugin.mtimes.get(_self.rel_path, 0)
_self.should_skip = (prev_mtime == _self.mtime)
_self.should_skip = prev_mtime == _self.mtime

return _self

def collect(self):
"""Create a PyLintItem for the File."""
yield PyLintItem.from_parent(
parent=self,
name='PYLINT'
)
yield PyLintItem.from_parent(parent=self, name="PYLINT")


class PyLintItem(pytest.Item):
Expand All @@ -324,13 +296,13 @@ def __init__(self, *args, **kwargs):

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

@classmethod
def from_parent(cls, parent, **kw):
return getattr(super(), 'from_parent', cls)(parent, **kw)
return getattr(super(), "from_parent", cls)(parent, **kw)

def setup(self):
"""Mark unchanged files as SKIPPED."""
Expand All @@ -343,18 +315,14 @@ def runtest(self):

def _loop_errors(writer):
reported_errors = []
for error in self.plugin.pylint_messages.get(
self.parent.rel_path, []
):
for error in self.plugin.pylint_messages.get(self.parent.rel_path, []):
if error.C in self.config.option.pylint_error_types:
reported_errors.append(
error.format(self._msg_format)
)
reported_errors.append(error.format(self._msg_format))

writer(
'{error_path}:{error_line}: [{error_msg_id}'
'({error_symbol}), {error_obj}] '
'{error_msg}\n'.format(
"{error_path}:{error_line}: [{error_msg_id}"
"({error_symbol}), {error_obj}] "
"{error_msg}\n".format(
error_path=error.path,
error_line=error.line,
error_msg_id=error.msg_id,
Expand All @@ -370,13 +338,13 @@ def _loop_errors(writer):
output_dir = dirname(pylint_output_file)
if output_dir:
makedirs(output_dir, exist_ok=True)
with open(pylint_output_file, 'a') as _file:
with open(pylint_output_file, "a") as _file:
reported_errors = _loop_errors(writer=_file.write)
else:
reported_errors = _loop_errors(writer=lambda *args, **kwargs: None)

if reported_errors:
raise PyLintException('\n'.join(reported_errors))
raise PyLintException("\n".join(reported_errors))

# Update the cache if the item passed pylint.
self.plugin.mtimes[self.parent.rel_path] = self.parent.mtime
Expand Down
7 changes: 4 additions & 3 deletions pytest_pylint/pylint_util.py
Expand Up @@ -8,8 +8,9 @@

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

__implements__ = IReporter
extension = 'prog'
extension = "prog"

def __init__(self, output=None):
BaseReporter.__init__(self, output)
Expand All @@ -29,10 +30,10 @@ def _display(self, layout):

def on_set_current_module(self, module, filepath):
"""Hook called when a module starts to be analysed."""
print('.', end='')
print(".", end="")
sys.stdout.flush()

def on_close(self, stats, previous_stats):
"""Hook called when all modules finished analyzing."""
# print a new line when pylint is finished
print('')
print("")

0 comments on commit 33519cb

Please sign in to comment.