Skip to content

Commit 97029a2

Browse files
srittauVishal Kuo
authored and
Vishal Kuo
committed
Find unused stubtest whitelist entries (python#4157)
* Find unused stubtest whitelist entries This is currently a GitHub workflow that runs daily and lists all unused whitelist entries found by running stubtest against current Python versions on Linux and Windows. The workflow run will succeed if there are no such entries, and fail otherwise. In a second step, this should collate the output of the various runs and create a PR to remove the entries. In that case, the workflow should probably only run weekly or even monthly to keep the noise down. Cf. python#3728
1 parent 033eeb4 commit 97029a2

File tree

4 files changed

+97
-11
lines changed

4 files changed

+97
-11
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Find unused stubtest whitelist entries
2+
3+
on:
4+
schedule:
5+
- cron: '0 4 * * *'
6+
7+
jobs:
8+
find:
9+
runs-on: ${{ matrix.os }}
10+
strategy:
11+
matrix:
12+
os: ["ubuntu-latest", "windows-latest"]
13+
python-version: [3.5, 3.6, 3.7, 3.8]
14+
15+
steps:
16+
- uses: actions/checkout@v2
17+
- name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }}
18+
uses: actions/setup-python@v2
19+
with:
20+
python-version: ${{ matrix.python-version }}
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install -U pip
24+
pip install -U git+git://github.com/python/mypy@b3d43984
25+
- name: Run stubtest
26+
run: ./tests/stubtest_unused.py

.travis.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,44 +42,44 @@ jobs:
4242
- name: "stubtest py38"
4343
python: 3.8
4444
install: pip install -U git+git://github.com/python/mypy@b3d43984
45-
script: ./tests/stubtest_test.py
45+
script: ./tests/stubtest_test.py --ignore-unused-whitelist
4646
- name: "stubtest py37"
4747
python: 3.7
4848
install: pip install -U git+git://github.com/python/mypy@b3d43984
49-
script: ./tests/stubtest_test.py
49+
script: ./tests/stubtest_test.py --ignore-unused-whitelist
5050
- name: "stubtest py36"
5151
python: 3.6
5252
install: pip install -U git+git://github.com/python/mypy@b3d43984
53-
script: ./tests/stubtest_test.py
53+
script: ./tests/stubtest_test.py --ignore-unused-whitelist
5454
- name: "stubtest py35"
5555
python: 3.5
5656
install: pip install -U git+git://github.com/python/mypy@b3d43984
57-
script: ./tests/stubtest_test.py
57+
script: ./tests/stubtest_test.py --ignore-unused-whitelist
5858
- name: "stubtest py38 (Windows)"
5959
<<: *test_windows
6060
env:
6161
<<: *env_windows
6262
PYTHON_VERSION: 3.8.3
6363
install: pip install -U git+git://github.com/python/mypy@b3d43984
64-
script: python ./tests/stubtest_test.py
64+
script: python ./tests/stubtest_test.py --ignore-unused-whitelist
6565
- name: "stubtest py37 (Windows)"
6666
<<: *test_windows
6767
env:
6868
<<: *env_windows
6969
PYTHON_VERSION: 3.7.7
7070
install: pip install -U git+git://github.com/python/mypy@b3d43984
71-
script: python ./tests/stubtest_test.py
71+
script: python ./tests/stubtest_test.py --ignore-unused-whitelist
7272
- name: "stubtest py36 (Windows)"
7373
<<: *test_windows
7474
env:
7575
<<: *env_windows
7676
PYTHON_VERSION: 3.6.8
7777
install: pip install -U git+git://github.com/python/mypy@b3d43984
78-
script: python ./tests/stubtest_test.py
78+
script: python ./tests/stubtest_test.py --ignore-unused-whitelist
7979
- name: "stubtest py35 (Windows)"
8080
<<: *test_windows
8181
env:
8282
<<: *env_windows
8383
PYTHON_VERSION: 3.5.4
8484
install: pip install -U git+git://github.com/python/mypy@b3d43984
85-
script: python ./tests/stubtest_test.py
85+
script: python ./tests/stubtest_test.py --ignore-unused-whitelist

tests/stubtest_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ def run_stubtest(typeshed_dir: Path) -> int:
2121
platform_whitelist = "{}.txt".format(sys.platform)
2222
combined_whitelist = "{}-py{}{}.txt".format(sys.platform, sys.version_info.major, sys.version_info.minor)
2323

24+
ignore_unused_whitelist = "--ignore-unused-whitelist" in sys.argv[1:]
25+
2426
cmd = [
2527
sys.executable,
2628
"-m",
@@ -37,6 +39,8 @@ def run_stubtest(typeshed_dir: Path) -> int:
3739
"--whitelist",
3840
str(whitelist_dir / version_whitelist),
3941
]
42+
if ignore_unused_whitelist:
43+
cmd += ["--ignore-unused-whitelist"]
4044
if (whitelist_dir / platform_whitelist).exists():
4145
cmd += [
4246
"--whitelist",
@@ -59,9 +63,6 @@ def run_stubtest(typeshed_dir: Path) -> int:
5963
"\nNB: stubtest output depends on the Python version (and system) it is run with. "
6064
"See README.md for more details.\n"
6165
"NB: We only check positional-only arg accuracy for Python 3.9.\n"
62-
"If stubtest is complaining about 'unused whitelist entry' after your fix, please "
63-
"remove the entry from the whitelist file. Note you may have to do this for other "
64-
"version-specific whitelists as well. Thanks for helping burn the backlog of errors!\n"
6566
"\nCommand run was: {}\n".format(" ".join(cmd)),
6667
file=sys.stderr,
6768
)

tests/stubtest_unused.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env python3
2+
3+
# Runs stubtest and prints each unused whitelist entry with filename.
4+
5+
from typing import List, Tuple
6+
import os.path
7+
import subprocess
8+
import sys
9+
10+
_UNUSED_NOTE = "note: unused whitelist entry "
11+
_WHITELIST_PATH = os.path.join("tests", "stubtest_whitelists")
12+
13+
14+
def main() -> int:
15+
unused = run_stubtest()
16+
with_filenames = []
17+
for uu in unused:
18+
with_filenames.extend(unused_files(uu))
19+
for file, uu in with_filenames:
20+
print(file + ":" + uu)
21+
return 1 if with_filenames else 0
22+
23+
24+
def run_stubtest() -> List[str]:
25+
popen = subprocess.Popen(
26+
["./tests/stubtest_test.py"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
27+
)
28+
assert popen.stdout is not None
29+
unused = []
30+
for line in popen.stdout:
31+
if line.startswith(_UNUSED_NOTE):
32+
unused.append(line[len(_UNUSED_NOTE):].strip())
33+
popen.wait()
34+
return unused
35+
36+
37+
def unused_files(unused: str) -> List[Tuple[str, str]]:
38+
version = "py{}{}".format(sys.version_info[0], sys.version_info[1])
39+
files = ["py3_common.txt", version + ".txt", sys.platform + ".txt", sys.platform + "-" + version + ".txt"]
40+
found = []
41+
for file in files:
42+
path = os.path.join(_WHITELIST_PATH, file)
43+
if find_unused_in_file(unused, path):
44+
found.append((path, unused))
45+
if not found:
46+
raise ValueError("unused item {} not found in any whitelist file".format(unused))
47+
return found
48+
49+
50+
def find_unused_in_file(unused: str, path: str) -> bool:
51+
try:
52+
with open(path) as f:
53+
return any(line.strip().split(" ")[0] == unused for line in f)
54+
except FileNotFoundError:
55+
return False
56+
57+
58+
if __name__ == "__main__":
59+
sys.exit(main())

0 commit comments

Comments
 (0)