Skip to content

Commit e959952

Browse files
authored
stubtest: use allowlist instead of whitelist (#9426)
Allows use of the old options to preserve backwards compatibility A step towards python/typeshed#4436 Co-authored-by: hauntsaninja <>
1 parent b4c5b80 commit e959952

File tree

2 files changed

+50
-47
lines changed

2 files changed

+50
-47
lines changed

mypy/stubtest.py

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ def _verify_property(stub: nodes.Decorator, runtime: Any) -> Iterator[str]:
755755
# It's enough like a property...
756756
return
757757
# Sometimes attributes pretend to be properties, for instance, to express that they
758-
# are read only. So whitelist if runtime_type matches the return type of stub.
758+
# are read only. So allowlist if runtime_type matches the return type of stub.
759759
runtime_type = get_mypy_type_of_runtime_value(runtime)
760760
func_type = (
761761
stub.func.type.ret_type if isinstance(stub.func.type, mypy.types.CallableType) else None
@@ -1001,14 +1001,14 @@ def get_typeshed_stdlib_modules(custom_typeshed_dir: Optional[str]) -> List[str]
10011001
return sorted(modules)
10021002

10031003

1004-
def get_whitelist_entries(whitelist_file: str) -> Iterator[str]:
1004+
def get_allowlist_entries(allowlist_file: str) -> Iterator[str]:
10051005
def strip_comments(s: str) -> str:
10061006
try:
10071007
return s[: s.index("#")].strip()
10081008
except ValueError:
10091009
return s.strip()
10101010

1011-
with open(whitelist_file) as f:
1011+
with open(allowlist_file) as f:
10121012
for line in f.readlines():
10131013
entry = strip_comments(line)
10141014
if entry:
@@ -1017,17 +1017,17 @@ def strip_comments(s: str) -> str:
10171017

10181018
def test_stubs(args: argparse.Namespace) -> int:
10191019
"""This is stubtest! It's time to test the stubs!"""
1020-
# Load the whitelist. This is a series of strings corresponding to Error.object_desc
1021-
# Values in the dict will store whether we used the whitelist entry or not.
1022-
whitelist = {
1020+
# Load the allowlist. This is a series of strings corresponding to Error.object_desc
1021+
# Values in the dict will store whether we used the allowlist entry or not.
1022+
allowlist = {
10231023
entry: False
1024-
for whitelist_file in args.whitelist
1025-
for entry in get_whitelist_entries(whitelist_file)
1024+
for allowlist_file in args.allowlist
1025+
for entry in get_allowlist_entries(allowlist_file)
10261026
}
1027-
whitelist_regexes = {entry: re.compile(entry) for entry in whitelist}
1027+
allowlist_regexes = {entry: re.compile(entry) for entry in allowlist}
10281028

1029-
# If we need to generate a whitelist, we store Error.object_desc for each error here.
1030-
generated_whitelist = set()
1029+
# If we need to generate an allowlist, we store Error.object_desc for each error here.
1030+
generated_allowlist = set()
10311031

10321032
modules = args.modules
10331033
if args.check_typeshed:
@@ -1061,37 +1061,37 @@ def set_strict_flags() -> None: # not needed yet
10611061
continue
10621062
if args.ignore_positional_only and error.is_positional_only_related():
10631063
continue
1064-
if error.object_desc in whitelist:
1065-
whitelist[error.object_desc] = True
1064+
if error.object_desc in allowlist:
1065+
allowlist[error.object_desc] = True
10661066
continue
1067-
is_whitelisted = False
1068-
for w in whitelist:
1069-
if whitelist_regexes[w].fullmatch(error.object_desc):
1070-
whitelist[w] = True
1071-
is_whitelisted = True
1067+
is_allowlisted = False
1068+
for w in allowlist:
1069+
if allowlist_regexes[w].fullmatch(error.object_desc):
1070+
allowlist[w] = True
1071+
is_allowlisted = True
10721072
break
1073-
if is_whitelisted:
1073+
if is_allowlisted:
10741074
continue
10751075

10761076
# We have errors, so change exit code, and output whatever necessary
10771077
exit_code = 1
1078-
if args.generate_whitelist:
1079-
generated_whitelist.add(error.object_desc)
1078+
if args.generate_allowlist:
1079+
generated_allowlist.add(error.object_desc)
10801080
continue
10811081
print(error.get_description(concise=args.concise))
10821082

1083-
# Print unused whitelist entries
1084-
if not args.ignore_unused_whitelist:
1085-
for w in whitelist:
1083+
# Print unused allowlist entries
1084+
if not args.ignore_unused_allowlist:
1085+
for w in allowlist:
10861086
# Don't consider an entry unused if it regex-matches the empty string
1087-
# This allows us to whitelist errors that don't manifest at all on some systems
1088-
if not whitelist[w] and not whitelist_regexes[w].fullmatch(""):
1087+
# This lets us allowlist errors that don't manifest at all on some systems
1088+
if not allowlist[w] and not allowlist_regexes[w].fullmatch(""):
10891089
exit_code = 1
1090-
print("note: unused whitelist entry {}".format(w))
1090+
print("note: unused allowlist entry {}".format(w))
10911091

1092-
# Print the generated whitelist
1093-
if args.generate_whitelist:
1094-
for e in sorted(generated_whitelist):
1092+
# Print the generated allowlist
1093+
if args.generate_allowlist:
1094+
for e in sorted(generated_allowlist):
10951095
print(e)
10961096
exit_code = 0
10971097

@@ -1121,24 +1121,27 @@ def parse_options(args: List[str]) -> argparse.Namespace:
11211121
"--check-typeshed", action="store_true", help="Check all stdlib modules in typeshed"
11221122
)
11231123
parser.add_argument(
1124+
"--allowlist",
11241125
"--whitelist",
11251126
action="append",
11261127
metavar="FILE",
11271128
default=[],
11281129
help=(
1129-
"Use file as a whitelist. Can be passed multiple times to combine multiple "
1130-
"whitelists. Whitelists can be created with --generate-whitelist"
1130+
"Use file as an allowlist. Can be passed multiple times to combine multiple "
1131+
"allowlists. Allowlists can be created with --generate-allowlist"
11311132
),
11321133
)
11331134
parser.add_argument(
1135+
"--generate-allowlist",
11341136
"--generate-whitelist",
11351137
action="store_true",
1136-
help="Print a whitelist (to stdout) to be used with --whitelist",
1138+
help="Print an allowlist (to stdout) to be used with --allowlist",
11371139
)
11381140
parser.add_argument(
1141+
"--ignore-unused-allowlist",
11391142
"--ignore-unused-whitelist",
11401143
action="store_true",
1141-
help="Ignore unused whitelist entries",
1144+
help="Ignore unused allowlist entries",
11421145
)
11431146
config_group = parser.add_argument_group(
11441147
title='mypy config file',

mypy/test/teststubtest.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def test(*args: Any, **kwargs: Any) -> None:
7575
output = run_stubtest(
7676
stub="\n\n".join(textwrap.dedent(c.stub.lstrip("\n")) for c in cases),
7777
runtime="\n\n".join(textwrap.dedent(c.runtime.lstrip("\n")) for c in cases),
78-
options=["--generate-whitelist"],
78+
options=["--generate-allowlist"],
7979
)
8080

8181
actual_errors = set(output.splitlines())
@@ -669,33 +669,33 @@ def test_ignore_flags(self) -> None:
669669
)
670670
assert not output
671671

672-
def test_whitelist(self) -> None:
672+
def test_allowlist(self) -> None:
673673
# Can't use this as a context because Windows
674-
whitelist = tempfile.NamedTemporaryFile(mode="w+", delete=False)
674+
allowlist = tempfile.NamedTemporaryFile(mode="w+", delete=False)
675675
try:
676-
with whitelist:
677-
whitelist.write("{}.bad # comment\n# comment".format(TEST_MODULE_NAME))
676+
with allowlist:
677+
allowlist.write("{}.bad # comment\n# comment".format(TEST_MODULE_NAME))
678678

679679
output = run_stubtest(
680680
stub="def bad(number: int, text: str) -> None: ...",
681681
runtime="def bad(asdf, text): pass",
682-
options=["--whitelist", whitelist.name],
682+
options=["--allowlist", allowlist.name],
683683
)
684684
assert not output
685685

686686
# test unused entry detection
687-
output = run_stubtest(stub="", runtime="", options=["--whitelist", whitelist.name])
688-
assert output == "note: unused whitelist entry {}.bad\n".format(TEST_MODULE_NAME)
687+
output = run_stubtest(stub="", runtime="", options=["--allowlist", allowlist.name])
688+
assert output == "note: unused allowlist entry {}.bad\n".format(TEST_MODULE_NAME)
689689

690690
output = run_stubtest(
691691
stub="",
692692
runtime="",
693-
options=["--whitelist", whitelist.name, "--ignore-unused-whitelist"],
693+
options=["--allowlist", allowlist.name, "--ignore-unused-allowlist"],
694694
)
695695
assert not output
696696

697697
# test regex matching
698-
with open(whitelist.name, mode="w+") as f:
698+
with open(allowlist.name, mode="w+") as f:
699699
f.write("{}.b.*\n".format(TEST_MODULE_NAME))
700700
f.write("(unused_missing)?\n")
701701
f.write("unused.*\n")
@@ -715,13 +715,13 @@ def bad(asdf): pass
715715
def also_bad(asdf): pass
716716
""".lstrip("\n")
717717
),
718-
options=["--whitelist", whitelist.name, "--generate-whitelist"],
718+
options=["--allowlist", allowlist.name, "--generate-allowlist"],
719719
)
720-
assert output == "note: unused whitelist entry unused.*\n{}.also_bad\n".format(
720+
assert output == "note: unused allowlist entry unused.*\n{}.also_bad\n".format(
721721
TEST_MODULE_NAME
722722
)
723723
finally:
724-
os.unlink(whitelist.name)
724+
os.unlink(allowlist.name)
725725

726726
def test_mypy_build(self) -> None:
727727
output = run_stubtest(stub="+", runtime="", options=[])

0 commit comments

Comments
 (0)