diff --git a/.github/workflows/stubtest-unused-whitelist.yml b/.github/workflows/stubtest-unused-whitelist.yml index b863b0779..f18870ea0 100644 --- a/.github/workflows/stubtest-unused-whitelist.yml +++ b/.github/workflows/stubtest-unused-whitelist.yml @@ -1,4 +1,4 @@ -name: Find unused stubtest whitelist entries +name: Remove unused stubtest whitelist entries on: workflow_dispatch: @@ -39,11 +39,20 @@ jobs: runs-on: ubuntu-latest needs: stubtest steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.8 - name: Get stubtest outputs uses: actions/download-artifact@v2 with: name: stubtest-output - - name: Remove duplicates - run: | - cat stubtest-output-* | sort -u | tee stubtest-output - test "$(wc -l stubtest-output | cut -d ' ' -f 1)" = 0 + - name: Collate duplicates + run: cat stubtest-output-* | sort -u | tee stubtest-output + - name: Remove entries from whitelists + run: python/scripts/update-stubtest-whitelist.py stubtest-output + - name: Create pull request + uses: peter-evans/create-pull-request@v2 + with: + commit-message: Remove unused stubtest whitelist entries + title: "[gh-action] Remove unused stubtest whitelist entries" diff --git a/.gitignore b/.gitignore index d211927a9..a800141bd 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ htmlcov/ .cache nosetests.xml coverage.xml +stubtest-output* # Translations *.mo diff --git a/scripts/update-stubtest-whitelist.py b/scripts/update-stubtest-whitelist.py new file mode 100755 index 000000000..36177d0b8 --- /dev/null +++ b/scripts/update-stubtest-whitelist.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +# This script removes lines from stubtest whitelists, according to +# an input file. The input file has one entry to remove per line. +# Each line consists of a whitelist filename and an entry, separated +# by a colon. + +# This script is used by the workflow to remove unused whitelist entries. + +import sys +from collections import defaultdict +from typing import Dict, List, Set, Tuple + + +def main() -> None: + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} FILENAME", file=sys.stderr) + sys.exit(1) + + to_remove = parse_input_file(sys.argv[1]) + for filename, entries in to_remove.items(): + remove_entries_from_whitelist(filename, entries) + + +def parse_input_file(input_file: str) -> Dict[str, Set[str]]: + to_remove = defaultdict(set) + with open(input_file) as f: + for filename, wl_entry in [parse_input_line(li) for li in f if li.strip()]: + to_remove[filename].add(wl_entry) + return to_remove + + +# Returns a (filename, entry) tuple. +def parse_input_line(line: str) -> Tuple[str, str]: + line = line.strip() + return line.split(":", maxsplit=1) + + +def remove_entries_from_whitelist(filename: str, entries: Set[str]) -> None: + new_lines: List[str] = [] + with open(filename) as f: + for line in f: + entry = line.strip().split(" #")[0] + if entry in entries: + entries.remove(entry) + else: + new_lines.append(line) + if entries: + print(f"WARNING: The following entries were not found in '{filename}':", filename=sys.stderr) + for entry in entries: + print(f" * {entry}") + with open(filename, "w") as f: + for line in new_lines: + f.write(line) + + +if __name__ == "__main__": + main()