mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 03:22:47 +01:00
merge bitcoin#24794: Convert Python linter to Python
This commit is contained in:
parent
110b6ac3dc
commit
1f8c3b5e95
@ -310,9 +310,9 @@ Use the `-v` option for verbose output.
|
||||
|
||||
| Lint test | Dependency |
|
||||
|-----------|:----------:|
|
||||
| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8)
|
||||
| [`lint-python.sh`](lint/lint-python.sh) | [mypy](https://github.com/python/mypy)
|
||||
| [`lint-python.sh`](lint/lint-python.sh) | [pyzmq](https://github.com/zeromq/pyzmq)
|
||||
| [`lint-python.py`](lint/lint-python.py) | [flake8](https://gitlab.com/pycqa/flake8)
|
||||
| [`lint-python.py`](lint/lint-python.py) | [mypy](https://github.com/python/mypy)
|
||||
| [`lint-python.py`](lint/lint-python.py) | [pyzmq](https://github.com/zeromq/pyzmq)
|
||||
| [`lint-python-dead-code.py`](lint/lint-python-dead-code.py) | [vulture](https://github.com/jendrikseipp/vulture)
|
||||
| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck)
|
||||
| [`lint-spelling.py`](lint/lint-spelling.py) | [codespell](https://github.com/codespell-project/codespell)
|
||||
|
136
test/lint/lint-python.py
Executable file
136
test/lint/lint-python.py
Executable file
@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2022 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
"""
|
||||
Check for specified flake8 and mypy warnings in python files.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pkg_resources
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
DEPS = ['flake8', 'mypy', 'pyzmq']
|
||||
MYPY_CACHE_DIR = f"{os.getenv('BASE_ROOT_DIR', '')}/test/.mypy_cache"
|
||||
FILES_ARGS = ['git', 'ls-files', '--','test/functional/*.py', 'contrib/devtools/*.py', ':(exclude)contrib/devtools/github-merge.py']
|
||||
EXCLUDE_DIRS = ['src/dashbls/',
|
||||
'src/immer/']
|
||||
|
||||
ENABLED = (
|
||||
'E101,' # indentation contains mixed spaces and tabs
|
||||
'E112,' # expected an indented block
|
||||
'E113,' # unexpected indentation
|
||||
'E115,' # expected an indented block (comment)
|
||||
'E116,' # unexpected indentation (comment)
|
||||
'E125,' # continuation line with same indent as next logical line
|
||||
'E129,' # visually indented line with same indent as next logical line
|
||||
'E131,' # continuation line unaligned for hanging indent
|
||||
'E133,' # closing bracket is missing indentation
|
||||
'E223,' # tab before operator
|
||||
'E224,' # tab after operator
|
||||
'E242,' # tab after ','
|
||||
'E266,' # too many leading '#' for block comment
|
||||
'E271,' # multiple spaces after keyword
|
||||
'E272,' # multiple spaces before keyword
|
||||
'E273,' # tab after keyword
|
||||
'E274,' # tab before keyword
|
||||
# TODO: enable it after bitcoin/bitcoin#26257 - too many warnings with newer flake
|
||||
# 'E275,' # missing whitespace after keyword
|
||||
'E304,' # blank lines found after function decorator
|
||||
'E306,' # expected 1 blank line before a nested definition
|
||||
'E401,' # multiple imports on one line
|
||||
'E402,' # module level import not at top of file
|
||||
'E502,' # the backslash is redundant between brackets
|
||||
'E701,' # multiple statements on one line (colon)
|
||||
'E702,' # multiple statements on one line (semicolon)
|
||||
'E703,' # statement ends with a semicolon
|
||||
'E711,' # comparison to None should be 'if cond is None:'
|
||||
'E714,' # test for object identity should be "is not"
|
||||
'E721,' # do not compare types, use "isinstance()"
|
||||
'E742,' # do not define classes named "l", "O", or "I"
|
||||
'E743,' # do not define functions named "l", "O", or "I"
|
||||
'E901,' # SyntaxError: invalid syntax
|
||||
'E902,' # TokenError: EOF in multi-line string
|
||||
'F401,' # module imported but unused
|
||||
'F402,' # import module from line N shadowed by loop variable
|
||||
'F403,' # 'from foo_module import *' used; unable to detect undefined names
|
||||
'F404,' # future import(s) name after other statements
|
||||
'F405,' # foo_function may be undefined, or defined from star imports: bar_module
|
||||
'F406,' # "from module import *" only allowed at module level
|
||||
'F407,' # an undefined __future__ feature name was imported
|
||||
'F601,' # dictionary key name repeated with different values
|
||||
'F602,' # dictionary key variable name repeated with different values
|
||||
'F621,' # too many expressions in an assignment with star-unpacking
|
||||
'F622,' # two or more starred expressions in an assignment (a, *b, *c = d)
|
||||
'F631,' # assertion test is a tuple, which are always True
|
||||
'F632,' # use ==/!= to compare str, bytes, and int literals
|
||||
'F701,' # a break statement outside of a while or for loop
|
||||
'F702,' # a continue statement outside of a while or for loop
|
||||
'F703,' # a continue statement in a finally block in a loop
|
||||
'F704,' # a yield or yield from statement outside of a function
|
||||
'F705,' # a return statement with arguments inside a generator
|
||||
'F706,' # a return statement outside of a function/method
|
||||
'F707,' # an except: block as not the last exception handler
|
||||
'F811,' # redefinition of unused name from line N
|
||||
'F812,' # list comprehension redefines 'foo' from line N
|
||||
'F821,' # undefined name 'Foo'
|
||||
'F822,' # undefined name name in __all__
|
||||
'F823,' # local variable name … referenced before assignment
|
||||
'F831,' # duplicate argument name in function definition
|
||||
'F841,' # local variable 'foo' is assigned to but never used
|
||||
'W191,' # indentation contains tabs
|
||||
'W291,' # trailing whitespace
|
||||
'W292,' # no newline at end of file
|
||||
'W293,' # blank line contains whitespace
|
||||
'W601,' # .has_key() is deprecated, use "in"
|
||||
'W602,' # deprecated form of raising exception
|
||||
'W603,' # "<>" is deprecated, use "!="
|
||||
'W604,' # backticks are deprecated, use "repr()"
|
||||
# 'W605,' # invalid escape sequence "x"
|
||||
'W606,' # 'async' and 'await' are reserved keywords starting with Python 3.7
|
||||
)
|
||||
|
||||
|
||||
def check_dependencies():
|
||||
working_set = {pkg.key for pkg in pkg_resources.working_set}
|
||||
|
||||
for dep in DEPS:
|
||||
if dep not in working_set:
|
||||
print(f"Skipping Python linting since {dep} is not installed.")
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
check_dependencies()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
flake8_files = sys.argv[1:]
|
||||
else:
|
||||
files_args = ['git', 'ls-files', '--', '*.py']
|
||||
for dir in EXCLUDE_DIRS:
|
||||
files_args += [f':(exclude){dir}']
|
||||
flake8_files = subprocess.check_output(files_args).decode("utf-8").splitlines()
|
||||
|
||||
flake8_args = ['flake8', '--ignore=B,C,E,F,I,N,W', f'--select={ENABLED}'] + flake8_files
|
||||
flake8_env = os.environ.copy()
|
||||
flake8_env["PYTHONWARNINGS"] = "ignore"
|
||||
|
||||
try:
|
||||
subprocess.check_call(flake8_args, env=flake8_env)
|
||||
except subprocess.CalledProcessError:
|
||||
exit(1)
|
||||
|
||||
mypy_files = subprocess.check_output(FILES_ARGS).decode("utf-8").splitlines()
|
||||
mypy_args = ['mypy', '--ignore-missing-imports', '--show-error-codes'] + mypy_files
|
||||
|
||||
try:
|
||||
subprocess.check_call(mypy_args)
|
||||
except subprocess.CalledProcessError:
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,112 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2017-2020 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
# Check for specified flake8 warnings in python files.
|
||||
|
||||
export LC_ALL=C
|
||||
export MYPY_CACHE_DIR="${BASE_ROOT_DIR}/test/.mypy_cache"
|
||||
|
||||
enabled=(
|
||||
E101 # indentation contains mixed spaces and tabs
|
||||
E112 # expected an indented block
|
||||
E113 # unexpected indentation
|
||||
E115 # expected an indented block (comment)
|
||||
E116 # unexpected indentation (comment)
|
||||
E125 # continuation line with same indent as next logical line
|
||||
E129 # visually indented line with same indent as next logical line
|
||||
E131 # continuation line unaligned for hanging indent
|
||||
E133 # closing bracket is missing indentation
|
||||
E223 # tab before operator
|
||||
E224 # tab after operator
|
||||
E242 # tab after ','
|
||||
E266 # too many leading '#' for block comment
|
||||
E271 # multiple spaces after keyword
|
||||
E272 # multiple spaces before keyword
|
||||
E273 # tab after keyword
|
||||
E274 # tab before keyword
|
||||
# TODO: enable it after bitcoin/bitcoin#26257 - too many warnings with newer flake
|
||||
#E275 # missing whitespace after keyword
|
||||
E304 # blank lines found after function decorator
|
||||
E306 # expected 1 blank line before a nested definition
|
||||
E401 # multiple imports on one line
|
||||
E402 # module level import not at top of file
|
||||
E502 # the backslash is redundant between brackets
|
||||
E701 # multiple statements on one line (colon)
|
||||
E702 # multiple statements on one line (semicolon)
|
||||
E703 # statement ends with a semicolon
|
||||
E711 # comparison to None should be 'if cond is None:'
|
||||
E714 # test for object identity should be "is not"
|
||||
E721 # do not compare types, use "isinstance()"
|
||||
E742 # do not define classes named "l", "O", or "I"
|
||||
E743 # do not define functions named "l", "O", or "I"
|
||||
E901 # SyntaxError: invalid syntax
|
||||
E902 # TokenError: EOF in multi-line string
|
||||
F401 # module imported but unused
|
||||
F402 # import module from line N shadowed by loop variable
|
||||
F403 # 'from foo_module import *' used; unable to detect undefined names
|
||||
F404 # future import(s) name after other statements
|
||||
F405 # foo_function may be undefined, or defined from star imports: bar_module
|
||||
F406 # "from module import *" only allowed at module level
|
||||
F407 # an undefined __future__ feature name was imported
|
||||
F601 # dictionary key name repeated with different values
|
||||
F602 # dictionary key variable name repeated with different values
|
||||
F621 # too many expressions in an assignment with star-unpacking
|
||||
F622 # two or more starred expressions in an assignment (a, *b, *c = d)
|
||||
F631 # assertion test is a tuple, which are always True
|
||||
F632 # use ==/!= to compare str, bytes, and int literals
|
||||
F701 # a break statement outside of a while or for loop
|
||||
F702 # a continue statement outside of a while or for loop
|
||||
F703 # a continue statement in a finally block in a loop
|
||||
F704 # a yield or yield from statement outside of a function
|
||||
F705 # a return statement with arguments inside a generator
|
||||
F706 # a return statement outside of a function/method
|
||||
F707 # an except: block as not the last exception handler
|
||||
F811 # redefinition of unused name from line N
|
||||
F812 # list comprehension redefines 'foo' from line N
|
||||
F821 # undefined name 'Foo'
|
||||
F822 # undefined name name in __all__
|
||||
F823 # local variable name … referenced before assignment
|
||||
F831 # duplicate argument name in function definition
|
||||
F841 # local variable 'foo' is assigned to but never used
|
||||
W191 # indentation contains tabs
|
||||
W291 # trailing whitespace
|
||||
W292 # no newline at end of file
|
||||
W293 # blank line contains whitespace
|
||||
W601 # .has_key() is deprecated, use "in"
|
||||
W602 # deprecated form of raising exception
|
||||
W603 # "<>" is deprecated, use "!="
|
||||
W604 # backticks are deprecated, use "repr()"
|
||||
# W605 # invalid escape sequence "x"
|
||||
W606 # 'async' and 'await' are reserved keywords starting with Python 3.7
|
||||
)
|
||||
|
||||
if ! command -v flake8 > /dev/null; then
|
||||
echo "Skipping Python linting since flake8 is not installed."
|
||||
exit 0
|
||||
elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then
|
||||
echo "Skipping Python linting since flake8 is running under Python 2. Install the Python 3 version of flake8."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
EXIT_CODE=0
|
||||
|
||||
# shellcheck disable=SC2046
|
||||
if ! PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=$(IFS=","; echo "${enabled[*]}") $(
|
||||
if [[ $# == 0 ]]; then
|
||||
git ls-files "*.py" | grep -vE "src/(immer)/"
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
); then
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
mapfile -t FILES < <(git ls-files "test/functional/*.py" "contrib/devtools/*.py" | grep -v contrib/devtools/github-merge.py)
|
||||
if ! mypy --ignore-missing-imports --show-error-codes "${FILES[@]}"; then
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
exit $EXIT_CODE
|
Loading…
Reference in New Issue
Block a user