diff options
author | MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> | 2024-07-31 08:33:01 +0200 |
---|---|---|
committer | MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> | 2024-08-09 08:11:16 +0200 |
commit | fac7b7ff7f453a9ba14053a99ce0a113509bf600 (patch) | |
tree | 3629c2edbf2a1c866a23893ede52940360b041d4 | |
parent | df241970a3a3e7e24c001c399435d1baf3b8a2ae (diff) |
lint: Find function calls in default arguments
-rwxr-xr-x | ci/lint/04_install.sh | 1 | ||||
-rwxr-xr-x | test/lint/lint-python-mutable-default-parameters.py | 72 | ||||
-rw-r--r-- | test/lint/test_runner/src/main.rs | 34 |
3 files changed, 35 insertions, 72 deletions
diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index ff9206fb6f..acec2f32e9 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -53,6 +53,7 @@ ${CI_RETRY_EXE} pip3 install \ lief==0.13.2 \ mypy==1.4.1 \ pyzmq==25.1.0 \ + ruff==0.5.5 \ vulture==2.6 SHELLCHECK_VERSION=v0.8.0 diff --git a/test/lint/lint-python-mutable-default-parameters.py b/test/lint/lint-python-mutable-default-parameters.py deleted file mode 100755 index 820595ea34..0000000000 --- a/test/lint/lint-python-mutable-default-parameters.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2019-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. - -""" -Detect when a mutable list or dict is used as a default parameter value in a Python function. -""" - -import subprocess -import sys - - -def main(): - command = [ - "git", - "grep", - "-E", - r"^\s*def [a-zA-Z0-9_]+\(.*=\s*(\[|\{)", - "--", - "*.py", - ] - output = subprocess.run(command, stdout=subprocess.PIPE, text=True) - if len(output.stdout) > 0: - error_msg = ( - "A mutable list or dict seems to be used as default parameter value:\n\n" - f"{output.stdout}\n" - f"{example()}" - ) - print(error_msg) - sys.exit(1) - else: - sys.exit(0) - - -def example(): - return """This is how mutable list and dict default parameter values behave: - ->>> def f(i, j=[], k={}): -... j.append(i) -... k[i] = True -... return j, k -... ->>> f(1) -([1], {1: True}) ->>> f(1) -([1, 1], {1: True}) ->>> f(2) -([1, 1, 2], {1: True, 2: True}) - -The intended behaviour was likely: - ->>> def f(i, j=None, k=None): -... if j is None: -... j = [] -... if k is None: -... k = {} -... j.append(i) -... k[i] = True -... return j, k -... ->>> f(1) -([1], {1: True}) ->>> f(1) -([1], {1: True}) ->>> f(2) -([2], {2: True})""" - - -if __name__ == "__main__": - main() diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs index 2ba58a6da2..77388b78ff 100644 --- a/test/lint/test_runner/src/main.rs +++ b/test/lint/test_runner/src/main.rs @@ -36,6 +36,11 @@ fn get_linter_list() -> Vec<&'static Linter> { lint_fn: lint_markdown }, &Linter { + description: "Check the default arguments in python", + name: "py_mut_arg_default", + lint_fn: lint_py_mut_arg_default, + }, + &Linter { description: "Check that std::filesystem is not used directly", name: "std_filesystem", lint_fn: lint_std_filesystem @@ -180,6 +185,35 @@ fn lint_subtree() -> LintResult { } } +fn lint_py_mut_arg_default() -> LintResult { + let bin_name = "ruff"; + let checks = ["B006", "B008"] + .iter() + .map(|c| format!("--select={}", c)) + .collect::<Vec<_>>(); + let files = check_output( + git() + .args(["ls-files", "--", "*.py"]) + .args(get_pathspecs_exclude_subtrees()), + )?; + + let mut cmd = Command::new(bin_name); + cmd.arg("check").args(checks).args(files.lines()); + + match cmd.status() { + Ok(status) if status.success() => Ok(()), + Ok(_) => Err(format!("`{}` found errors!", bin_name)), + Err(e) if e.kind() == ErrorKind::NotFound => { + println!( + "`{}` was not found in $PATH, skipping those checks.", + bin_name + ); + Ok(()) + } + Err(e) => Err(format!("Error running `{}`: {}", bin_name, e)), + } +} + fn lint_std_filesystem() -> LintResult { let found = git() .args([ |