lint: Replace pycodestyle with Flake8.

Flake8 combines pycodestyle with pyflakes and automatically gives us
support for noqa comments, parallelism, configuration files, plugins,
and easy editor integration.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
Anders Kaseorg 2020-04-18 15:11:33 -07:00 committed by Tim Abbott
parent f616b9259e
commit b573c1daf3
4 changed files with 62 additions and 105 deletions

59
.flake8 Normal file
View file

@ -0,0 +1,59 @@
[flake8]
ignore =
# Each of these rules are ignored for the explained reason.
# "multiple spaces before operator"
# There are several typos here, but also several instances that are
# being used for alignment in dict keys/values using the `dict`
# constructor. We could fix the alignment cases by switching to the `{}`
# constructor, but it makes fixing this rule a little less
# straightforward.
E221,
# 'missing whitespace around arithmetic operator'
# This should possibly be cleaned up, though changing some of
# these may make the code less readable.
E226,
# "unexpected spaces around keyword / parameter equals"
# Many of these should be fixed, but many are also being used for
# alignment/making the code easier to read.
E251,
# "block comment should start with '#'"
# These serve to show which lines should be changed in files customized
# by the user. We could probably resolve one of E265 or E266 by
# standardizing on a single style for lines that the user might want to
# change.
E265,
# "too many leading '#' for block comment"
# Most of these are there for valid reasons.
E266,
# "expected 2 blank lines after class or function definition"
# Zulip only uses 1 blank line after class/function
# definitions; the PEP-8 recommendation results in super sparse code.
E302, E305,
# "module level import not at top of file"
# Most of these are there for valid reasons, though there might be a
# few that could be eliminated.
E402,
# "line too long"
# Zulip is a bit less strict about line length, and has its
# own check for this (see max_length)
E501,
# "line break before binary operator"
# This was obsoleted in favor of the opposite W504.
W503,
# "do not assign a lambda expression, use a def"
# Fixing these would probably reduce readability in most cases.
E731,
exclude =
# third-party
zulip/integrations/perforce/git_p4.py,

View file

@ -1,7 +1,7 @@
crayons crayons
twine twine
coverage>=4.4.1 coverage>=4.4.1
pycodestyle==2.3.1 flake8
mock mock
pytest pytest
-e ./zulip -e ./zulip

View file

@ -5,7 +5,6 @@ import argparse
from zulint.command import add_default_linter_arguments, LinterConfig from zulint.command import add_default_linter_arguments, LinterConfig
from custom_check import python_rules, non_py_rules from custom_check import python_rules, non_py_rules
from pep8 import check_pep8
EXCLUDED_FILES = [ EXCLUDED_FILES = [
# This is an external file that doesn't comply with our codestyle # This is an external file that doesn't comply with our codestyle
@ -24,6 +23,8 @@ def run() -> None:
linter_config.external_linter('mypy', ['tools/run-mypy'], ['py'], pass_targets=False, linter_config.external_linter('mypy', ['tools/run-mypy'], ['py'], pass_targets=False,
description="Static type checker for Python (config: mypy.ini)") description="Static type checker for Python (config: mypy.ini)")
linter_config.external_linter('flake8', ['flake8'], ['py'],
description="Standard Python linter (config: .flake8)")
@linter_config.lint @linter_config.lint
def custom_py() -> int: def custom_py() -> int:
@ -39,12 +40,6 @@ def run() -> None:
failed = failed or rule.check(by_lang, verbose=args.verbose) failed = failed or rule.check(by_lang, verbose=args.verbose)
return 1 if failed else 0 return 1 if failed else 0
@linter_config.lint
def pep8() -> int:
"""Standard Python style linter on 50% of files (config: tools/linter_lib/pep8.py)"""
failed = check_pep8(by_lang['py'])
return 1 if failed else 0
linter_config.do_lint() linter_config.do_lint()
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -1,97 +0,0 @@
# This file has been copied and modified from the Zulip server repository
# Original path: zulip/tools/linter_lib/pep8.py
import subprocess
from zulint.printer import print_err, colors
from typing import List
def check_pep8(files: List[str]) -> bool:
def run_pycodestyle(files: List[str], ignored_rules: List[str]) -> bool:
failed = False
color = next(colors)
pep8 = subprocess.Popen(
['pycodestyle'] + files + ['--ignore={rules}'.format(rules=','.join(ignored_rules))],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(pep8.stdout.readline, b''):
print_err('pep8', color, line)
failed = True
return failed
failed = False
ignored_rules = [
# Each of these rules are ignored for the explained reason.
# "multiple spaces before operator"
# There are several typos here, but also several instances that are
# being used for alignment in dict keys/values using the `dict`
# constructor. We could fix the alignment cases by switching to the `{}`
# constructor, but it makes fixing this rule a little less
# straightforward.
'E221',
# 'missing whitespace around arithmetic operator'
# This should possibly be cleaned up, though changing some of
# these may make the code less readable.
'E226',
# "unexpected spaces around keyword / parameter equals"
# Many of these should be fixed, but many are also being used for
# alignment/making the code easier to read.
'E251',
# "block comment should start with '#'"
# These serve to show which lines should be changed in files customized
# by the user. We could probably resolve one of E265 or E266 by
# standardizing on a single style for lines that the user might want to
# change.
'E265',
# "too many leading '#' for block comment"
# Most of these are there for valid reasons.
'E266',
# "expected 2 blank lines after class or function definition"
# Zulip only uses 1 blank line after class/function
# definitions; the PEP-8 recommendation results in super sparse code.
'E302', 'E305',
# "module level import not at top of file"
# Most of these are there for valid reasons, though there might be a
# few that could be eliminated.
'E402',
# "line too long"
# Zulip is a bit less strict about line length, and has its
# own check for this (see max_length)
'E501',
# "line break before binary operator"
# This was obsoleted in favor of the opposite W504.
'W503',
# "do not assign a lambda expression, use a def"
# Fixing these would probably reduce readability in most cases.
'E731',
]
# TODO: Clear up this list of violations.
IGNORE_FILES_PEPE261 = []
filtered_files = [fn for fn in files if fn not in IGNORE_FILES_PEPE261]
filtered_files_E261 = [fn for fn in files if fn in IGNORE_FILES_PEPE261]
if len(files) == 0:
return False
if not len(filtered_files) == 0:
failed = run_pycodestyle(filtered_files, ignored_rules)
if not len(filtered_files_E261) == 0:
# Adding an extra ignore rule for these files since they still remain in
# violation of PEP-E261.
failed_ignore_e261 = run_pycodestyle(filtered_files_E261, ignored_rules + ['E261'])
if not failed:
failed = failed_ignore_e261
return failed