diff --git a/spiffworkflow-backend/bin/codemod/remove_all_unused_functions b/spiffworkflow-backend/bin/codemod/remove_all_unused_functions new file mode 100755 index 00000000..fcc384ae --- /dev/null +++ b/spiffworkflow-backend/bin/codemod/remove_all_unused_functions @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +function error_handler() { + >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." + exit "$2" +} +trap 'error_handler ${LINENO} $?' ERR +set -o errtrace -o errexit -o nounset + +# HELP: remove all unused functions from python files + +if ! command -v dead >/dev/null 2>&1; then + echo "dead is not installed. installing..." + echo "pip install dead" +fi + +list_of_unused_things="$(dead | grep -E '^[a-z].*is never read')" + +while read -r line; do + function_name="$(echo "$line" | awk '{print $1}')" + echo "function_name: ${function_name}" + file_name_and_line_number="$(echo "$line" | perl -p -e "s/.*is never read, defined in //g")" + file_name="$(echo "$file_name_and_line_number" | awk -F ':' '{print $1}')" + echo "trying to remove $function_name from: ${file_name}" + if python bin/codemod/update_file_to_remove_function.py "$file_name" "$function_name"; then + # TODO: run exhaustive tests, and if they pass, report success + echo "function ${function_name} removed from ${file_name}. yay!" + exit 0 + fi +done <<< "$list_of_unused_things" diff --git a/spiffworkflow-backend/bin/codemod/update_file_to_remove_function.py b/spiffworkflow-backend/bin/codemod/update_file_to_remove_function.py new file mode 100644 index 00000000..9362fabb --- /dev/null +++ b/spiffworkflow-backend/bin/codemod/update_file_to_remove_function.py @@ -0,0 +1,33 @@ +from bowler import Query +from bowler.types import Leaf + +# This came about because vulture (actually dead, from the list of Similar programs at https://pypi.org/project/vulture/) +# actually found unused stuff, and I wanted to remove it. +# See also https://github.com/craigds/decrapify + +def remove_function(filename: str, function_name: str) -> None: + + def remove_statement(node, capture, filename): + node.remove() + + bowler_query = (Query(filename) + .select_function(function_name) + .modify(remove_statement) + .execute(write=True)) + + if len(bowler_query.exceptions) > 0: + print(f"Failed to remove function {function_name} from {filename}.") + raise Exception(bowler_query.exceptions[0]) + + print(f"Function {function_name} successfully removed from {filename}.") + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Remove a function from a Python file while preserving comments.") + parser.add_argument("filename", help="the file to modify") + parser.add_argument("function_name", help="the name of the function to remove") + args = parser.parse_args() + + remove_function(args.filename, args.function_name)