-
Notifications
You must be signed in to change notification settings - Fork 73
Add pylint #251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
proteusvacuum
wants to merge
4
commits into
markstory:master
Choose a base branch
from
proteusvacuum:add-pylint
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add pylint #251
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ pep8>=1.7.0,<2.0.0 | |
flake8>=3.3.0,<3.4.0 | ||
autopep8>=1.3.0,<2.0.0 | ||
black==18.6b4 | ||
pylint>=2.3.1,<3.0.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,32 @@ | ||
from __future__ import absolute_import | ||
import os | ||
|
||
import logging | ||
import lintreview.docker as docker | ||
from lintreview.tools import Tool, process_quickfix, stringify | ||
|
||
from lintreview.tools import stringify | ||
from lintreview.tools.pylint import Pylint | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class Py3k(Tool): | ||
class Py3k(Pylint): | ||
""" | ||
$ pylint --py3k is a special mode for porting to python 3 which | ||
disables other pylint checkers. | ||
see https://github.com/PyCQA/pylint/issues/761 | ||
""" | ||
|
||
name = 'py3k' | ||
accepted_options = ('ignore', ) | ||
python_version = 'python2' | ||
|
||
def check_dependencies(self): | ||
""" | ||
See if python image is available | ||
""" | ||
return docker.image_exists('python2') | ||
|
||
def match_file(self, filename): | ||
base = os.path.basename(filename) | ||
name, ext = os.path.splitext(base) | ||
return ext == '.py' | ||
|
||
def process_files(self, files): | ||
""" | ||
Run code checks with pylint --py3k. | ||
Only a single process is made for all files | ||
to save resources. | ||
""" | ||
log.debug('Processing %s files with %s', files, self.name) | ||
command = self.make_command(files) | ||
output = docker.run('python2', command, self.base_path) | ||
if not output: | ||
log.debug('No py3k errors found.') | ||
return False | ||
|
||
output = output.split("\n") | ||
output = [line for line in output if not line.startswith("*********")] | ||
def make_command(self, files): | ||
self.check_options() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The py3k tool needs to remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, updated here: 61d75fb |
||
|
||
process_quickfix(self.problems, output, docker.strip_base) | ||
command = self._base_command | ||
command.append('--py3k') | ||
|
||
def make_command(self, files): | ||
msg_template = '{path}:{line}:{column}:{msg_id} {msg}' | ||
command = [ | ||
'pylint', | ||
'--py3k', | ||
'--reports=n', | ||
'--msg-template', | ||
msg_template, | ||
] | ||
accepted_options = ('ignore') | ||
if 'ignore' in self.options: | ||
command.extend(['-d', stringify(self.options['ignore'])]) | ||
|
||
for option in self.options: | ||
if option in accepted_options: | ||
continue | ||
log.warning('Set non-existent py3k option: %s', option) | ||
command.extend(files) | ||
return command |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from __future__ import absolute_import | ||
|
||
import logging | ||
import os | ||
|
||
import lintreview.docker as docker | ||
from lintreview.tools import Tool, process_quickfix, python_image, stringify | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class Pylint(Tool): | ||
|
||
name = 'pylint' | ||
|
||
accepted_options = ('python', 'disable', 'enable', 'config') | ||
|
||
@property | ||
def _base_command(self): | ||
return [ | ||
'pylint', | ||
'--persistent=n', | ||
'--reports=n', | ||
'--score=n', | ||
'--msg-template', | ||
'{path}:{line}:{column}:{msg_id} {msg}' | ||
] | ||
|
||
@property | ||
def python_version(self): | ||
return python_image(self.options) | ||
|
||
def check_dependencies(self): | ||
""" | ||
See if python image is available | ||
""" | ||
return docker.image_exists(self.python_version) | ||
|
||
def match_file(self, filename): | ||
base = os.path.basename(filename) | ||
name, ext = os.path.splitext(base) | ||
return ext == '.py' | ||
|
||
def process_files(self, files): | ||
log.debug('Processing %s files with %s', files, self.name) | ||
command = self.make_command(files) | ||
output = docker.run(self.python_version, command, source_dir=self.base_path) | ||
if not output: | ||
log.debug('No %s errors found.', self.name) | ||
return False | ||
|
||
output = output.split("\n") | ||
output = [line for line in output if not line.startswith("*********")] | ||
|
||
process_quickfix(self.problems, output, docker.strip_base) | ||
|
||
def make_command(self, files): | ||
self.check_options() | ||
|
||
command = self._base_command | ||
|
||
if self.options.get('disable'): | ||
command.extend(['--disable', stringify(self.options['disable'])]) | ||
|
||
if self.options.get('enable'): | ||
command.extend(['--enable', stringify(self.options['enable'])]) | ||
|
||
if self.options.get('config'): | ||
command.extend(['--rcfile', docker.apply_base(stringify(self.options['config']))]) | ||
|
||
command.extend(files) | ||
return command | ||
|
||
def check_options(self): | ||
for unaccepted_option in set(self.options.keys()) - set(self.accepted_options): | ||
log.warning('Set non-existent %s option: %s', self.name, unaccepted_option) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Create unused imports | ||
import os, re | ||
|
||
def thing(self): | ||
return thing_two('arg1', | ||
'arg2') | ||
|
||
|
||
def thing_two(arg1, arg2, arg3): | ||
"""A thinger for thinging but returning nothing | ||
""" | ||
result=arg1*arg2 | ||
if result == arg1: | ||
pass | ||
elif result == '': | ||
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
"""Sample python file with no pylint errors. | ||
used for testing the pylint.Tool | ||
""" | ||
|
||
from __future__ import print_function | ||
|
||
|
||
def does_something(thing): | ||
"""Function docstring | ||
""" | ||
print('hello') | ||
return thing.buzz() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[MASTER] | ||
load-plugins=pylint.extensions.emptystring | ||
|
||
[MESSAGES CONTROL] | ||
|
||
disable=W0611, | ||
E1120, | ||
W0613, | ||
C0111, | ||
C0330, | ||
C0326, | ||
C0410 | ||
|
||
[REPORTS] | ||
# test that msg_template is not overwritten by the rcfile, otherwise | ||
# lint-review won't know what to do with the messages | ||
msg-template="{path}:{line}:{column}:{msg_id} foo" | ||
|
||
[FORMAT] | ||
|
||
# Maximum number of characters on a single line. | ||
max-line-length=50 | ||
|
||
# Maximum number of lines in a module | ||
max-module-lines=3 | ||
|
||
[DESIGN] | ||
|
||
# Maximum number of arguments for function / method | ||
max-args=1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
from __future__ import absolute_import | ||
|
||
from unittest import TestCase | ||
|
||
from nose.tools import eq_ | ||
from tests import requires_image, root_dir | ||
|
||
from lintreview.review import Comment, Problems | ||
from lintreview.tools.pylint import Pylint | ||
|
||
|
||
class TestPylint(TestCase): | ||
|
||
fixtures = [ | ||
'tests/fixtures/pylint/no_errors.py', | ||
'tests/fixtures/pylint/has_errors.py', | ||
] | ||
|
||
def setUp(self): | ||
self.problems = Problems() | ||
self.tool = Pylint(self.problems, {}, root_dir) | ||
|
||
def test_match_file(self): | ||
self.assertFalse(self.tool.match_file('test.php')) | ||
self.assertFalse(self.tool.match_file('test.js')) | ||
self.assertFalse(self.tool.match_file('dir/name/test.js')) | ||
self.assertTrue(self.tool.match_file('test.py')) | ||
self.assertTrue(self.tool.match_file('dir/name/test.py')) | ||
|
||
def test_process_files__one_file_pass(self): | ||
self.tool.process_files([self.fixtures[0]]) | ||
eq_([], self.problems.all(self.fixtures[0])) | ||
|
||
@requires_image('python2') | ||
def test_process_files__one_file_fail(self): | ||
self.tool.process_files([self.fixtures[1]]) | ||
problems = self.problems.all(self.fixtures[1]) | ||
eq_(7, len(problems)) | ||
|
||
fname = self.fixtures[1] | ||
# pylint outputs are sorted by 'category', not line number | ||
eq_([ | ||
Comment(fname, 6, 6, "C0330 Wrong continued indentation (add 17 spaces)."), | ||
Comment(fname, 12, 12, "C0326 Exactly one space required around assignment"), | ||
Comment(fname, 1, 1, "C0111 Missing module docstring"), | ||
Comment(fname, 2, 2, "C0410 Multiple imports on one line (os, re)\n" | ||
"W0611 Unused import re\nW0611 Unused import os"), | ||
Comment(fname, 4, 4, "C0111 Missing function docstring\nW0613 Unused argument 'self'"), | ||
Comment(fname, 5, 5, "E1120 No value for argument 'arg3' in function call"), | ||
Comment(fname, 9, 9, "W0613 Unused argument 'arg3'") | ||
], problems) | ||
|
||
@requires_image('python2') | ||
def test_process_files_two_files(self): | ||
self.tool.process_files(self.fixtures) | ||
|
||
eq_([], self.problems.all(self.fixtures[0])) | ||
|
||
problems = self.problems.all(self.fixtures[1]) | ||
eq_(7, len(problems)) | ||
expected = Comment(self.fixtures[1], 6, 6, | ||
"C0330 Wrong continued indentation (add 17 spaces).") | ||
eq_(expected, problems[0]) | ||
|
||
@requires_image('python3') | ||
def test_process_files_two_files__python3(self): | ||
self.tool.options['python'] = 3 | ||
self.tool.process_files(self.fixtures) | ||
|
||
eq_([], self.problems.all(self.fixtures[0])) | ||
|
||
problems = self.problems.all(self.fixtures[1]) | ||
eq_(7, len(problems)) | ||
expected = Comment(self.fixtures[1], 6, 6, | ||
"C0330 Wrong continued indentation (add 17 spaces).") | ||
eq_(expected, problems[0]) | ||
|
||
@requires_image('python2') | ||
def test_process_absolute_container_path(self): | ||
fixtures = ['/src/' + path for path in self.fixtures] | ||
self.tool.process_files(fixtures) | ||
|
||
eq_([], self.problems.all(self.fixtures[0])) | ||
|
||
problems = self.problems.all(self.fixtures[1]) | ||
assert len(problems) >= 6 | ||
|
||
@requires_image('python2') | ||
def test_process_files__disable(self): | ||
options = { | ||
'disable': 'C,W0611,E1120', | ||
} | ||
self.tool = Pylint(self.problems, options, root_dir) | ||
self.tool.process_files([self.fixtures[1]]) | ||
problems = self.problems.all(self.fixtures[1]) | ||
eq_([ | ||
Comment(self.fixtures[1], 4, 4, "W0613 Unused argument 'self'"), | ||
Comment(self.fixtures[1], 9, 9, "W0613 Unused argument 'arg3'"), | ||
], problems) | ||
|
||
@requires_image('python2') | ||
def test_process_files__enable(self): | ||
options = { | ||
'disable': 'C,W,E', | ||
'enable': 'W0613', | ||
} | ||
self.tool = Pylint(self.problems, options, root_dir) | ||
self.tool.process_files([self.fixtures[1]]) | ||
problems = self.problems.all(self.fixtures[1]) | ||
eq_([ | ||
Comment(self.fixtures[1], 4, 4, "W0613 Unused argument 'self'"), | ||
Comment(self.fixtures[1], 9, 9, "W0613 Unused argument 'arg3'"), | ||
], problems) | ||
|
||
@requires_image('python2') | ||
def test_process_files__config(self): | ||
options = { | ||
'config': 'tests/fixtures/pylint/sample_rcfile', | ||
} | ||
self.tool = Pylint(self.problems, options, root_dir) | ||
filename = self.fixtures[1] | ||
self.tool.process_files([filename]) | ||
problems = self.problems.all(self.fixtures[1]) | ||
eq_([ | ||
Comment(filename, 10, 10, "C0301 Line too long (51/50)"), | ||
Comment(filename, 1, 1, "C0302 Too many lines in module (16/3)"), | ||
Comment(filename, 9, 9, "R0913 Too many arguments (3/1)"), | ||
Comment(filename, 15, 15, "C1901 Avoid comparisons to empty string"), | ||
], problems) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does pylint have native extensions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you asking if there are more dependencies that are required here? Pylint does have a concept of an "extension", but I don't see any that require external libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are no additional dependencies why do you need musl-dev and gcc?