Skip to content

Commit 1f8c3b5

Browse files
committed
merge bitcoin#24794: Convert Python linter to Python
1 parent 110b6ac commit 1f8c3b5

File tree

3 files changed

+139
-115
lines changed

3 files changed

+139
-115
lines changed

test/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,9 @@ Use the `-v` option for verbose output.
310310

311311
| Lint test | Dependency |
312312
|-----------|:----------:|
313-
| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8)
314-
| [`lint-python.sh`](lint/lint-python.sh) | [mypy](https://github.com/python/mypy)
315-
| [`lint-python.sh`](lint/lint-python.sh) | [pyzmq](https://github.com/zeromq/pyzmq)
313+
| [`lint-python.py`](lint/lint-python.py) | [flake8](https://gitlab.com/pycqa/flake8)
314+
| [`lint-python.py`](lint/lint-python.py) | [mypy](https://github.com/python/mypy)
315+
| [`lint-python.py`](lint/lint-python.py) | [pyzmq](https://github.com/zeromq/pyzmq)
316316
| [`lint-python-dead-code.py`](lint/lint-python-dead-code.py) | [vulture](https://github.com/jendrikseipp/vulture)
317317
| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck)
318318
| [`lint-spelling.py`](lint/lint-spelling.py) | [codespell](https://github.com/codespell-project/codespell)

test/lint/lint-python.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright (c) 2022 The Bitcoin Core developers
4+
# Distributed under the MIT software license, see the accompanying
5+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
6+
7+
"""
8+
Check for specified flake8 and mypy warnings in python files.
9+
"""
10+
11+
import os
12+
import pkg_resources
13+
import subprocess
14+
import sys
15+
16+
DEPS = ['flake8', 'mypy', 'pyzmq']
17+
MYPY_CACHE_DIR = f"{os.getenv('BASE_ROOT_DIR', '')}/test/.mypy_cache"
18+
FILES_ARGS = ['git', 'ls-files', '--','test/functional/*.py', 'contrib/devtools/*.py', ':(exclude)contrib/devtools/github-merge.py']
19+
EXCLUDE_DIRS = ['src/dashbls/',
20+
'src/immer/']
21+
22+
ENABLED = (
23+
'E101,' # indentation contains mixed spaces and tabs
24+
'E112,' # expected an indented block
25+
'E113,' # unexpected indentation
26+
'E115,' # expected an indented block (comment)
27+
'E116,' # unexpected indentation (comment)
28+
'E125,' # continuation line with same indent as next logical line
29+
'E129,' # visually indented line with same indent as next logical line
30+
'E131,' # continuation line unaligned for hanging indent
31+
'E133,' # closing bracket is missing indentation
32+
'E223,' # tab before operator
33+
'E224,' # tab after operator
34+
'E242,' # tab after ','
35+
'E266,' # too many leading '#' for block comment
36+
'E271,' # multiple spaces after keyword
37+
'E272,' # multiple spaces before keyword
38+
'E273,' # tab after keyword
39+
'E274,' # tab before keyword
40+
# TODO: enable it after bitcoin/bitcoin#26257 - too many warnings with newer flake
41+
# 'E275,' # missing whitespace after keyword
42+
'E304,' # blank lines found after function decorator
43+
'E306,' # expected 1 blank line before a nested definition
44+
'E401,' # multiple imports on one line
45+
'E402,' # module level import not at top of file
46+
'E502,' # the backslash is redundant between brackets
47+
'E701,' # multiple statements on one line (colon)
48+
'E702,' # multiple statements on one line (semicolon)
49+
'E703,' # statement ends with a semicolon
50+
'E711,' # comparison to None should be 'if cond is None:'
51+
'E714,' # test for object identity should be "is not"
52+
'E721,' # do not compare types, use "isinstance()"
53+
'E742,' # do not define classes named "l", "O", or "I"
54+
'E743,' # do not define functions named "l", "O", or "I"
55+
'E901,' # SyntaxError: invalid syntax
56+
'E902,' # TokenError: EOF in multi-line string
57+
'F401,' # module imported but unused
58+
'F402,' # import module from line N shadowed by loop variable
59+
'F403,' # 'from foo_module import *' used; unable to detect undefined names
60+
'F404,' # future import(s) name after other statements
61+
'F405,' # foo_function may be undefined, or defined from star imports: bar_module
62+
'F406,' # "from module import *" only allowed at module level
63+
'F407,' # an undefined __future__ feature name was imported
64+
'F601,' # dictionary key name repeated with different values
65+
'F602,' # dictionary key variable name repeated with different values
66+
'F621,' # too many expressions in an assignment with star-unpacking
67+
'F622,' # two or more starred expressions in an assignment (a, *b, *c = d)
68+
'F631,' # assertion test is a tuple, which are always True
69+
'F632,' # use ==/!= to compare str, bytes, and int literals
70+
'F701,' # a break statement outside of a while or for loop
71+
'F702,' # a continue statement outside of a while or for loop
72+
'F703,' # a continue statement in a finally block in a loop
73+
'F704,' # a yield or yield from statement outside of a function
74+
'F705,' # a return statement with arguments inside a generator
75+
'F706,' # a return statement outside of a function/method
76+
'F707,' # an except: block as not the last exception handler
77+
'F811,' # redefinition of unused name from line N
78+
'F812,' # list comprehension redefines 'foo' from line N
79+
'F821,' # undefined name 'Foo'
80+
'F822,' # undefined name name in __all__
81+
'F823,' # local variable name … referenced before assignment
82+
'F831,' # duplicate argument name in function definition
83+
'F841,' # local variable 'foo' is assigned to but never used
84+
'W191,' # indentation contains tabs
85+
'W291,' # trailing whitespace
86+
'W292,' # no newline at end of file
87+
'W293,' # blank line contains whitespace
88+
'W601,' # .has_key() is deprecated, use "in"
89+
'W602,' # deprecated form of raising exception
90+
'W603,' # "<>" is deprecated, use "!="
91+
'W604,' # backticks are deprecated, use "repr()"
92+
# 'W605,' # invalid escape sequence "x"
93+
'W606,' # 'async' and 'await' are reserved keywords starting with Python 3.7
94+
)
95+
96+
97+
def check_dependencies():
98+
working_set = {pkg.key for pkg in pkg_resources.working_set}
99+
100+
for dep in DEPS:
101+
if dep not in working_set:
102+
print(f"Skipping Python linting since {dep} is not installed.")
103+
exit(0)
104+
105+
106+
def main():
107+
check_dependencies()
108+
109+
if len(sys.argv) > 1:
110+
flake8_files = sys.argv[1:]
111+
else:
112+
files_args = ['git', 'ls-files', '--', '*.py']
113+
for dir in EXCLUDE_DIRS:
114+
files_args += [f':(exclude){dir}']
115+
flake8_files = subprocess.check_output(files_args).decode("utf-8").splitlines()
116+
117+
flake8_args = ['flake8', '--ignore=B,C,E,F,I,N,W', f'--select={ENABLED}'] + flake8_files
118+
flake8_env = os.environ.copy()
119+
flake8_env["PYTHONWARNINGS"] = "ignore"
120+
121+
try:
122+
subprocess.check_call(flake8_args, env=flake8_env)
123+
except subprocess.CalledProcessError:
124+
exit(1)
125+
126+
mypy_files = subprocess.check_output(FILES_ARGS).decode("utf-8").splitlines()
127+
mypy_args = ['mypy', '--ignore-missing-imports', '--show-error-codes'] + mypy_files
128+
129+
try:
130+
subprocess.check_call(mypy_args)
131+
except subprocess.CalledProcessError:
132+
exit(1)
133+
134+
135+
if __name__ == "__main__":
136+
main()

test/lint/lint-python.sh

Lines changed: 0 additions & 112 deletions
This file was deleted.

0 commit comments

Comments
 (0)