Skip to content

Commit 6eb3ee5

Browse files
authored
Fix error code handling in stubtest with --mypy-config-file (#17629)
This is the first PR in the series of unifing configuration parsing for different mypy tools. I would like to have the simple and focused.
1 parent a0dbbd5 commit 6eb3ee5

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

mypy/main.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
validate_package_allow_list,
2020
)
2121
from mypy.error_formatter import OUTPUT_CHOICES
22-
from mypy.errorcodes import error_codes
2322
from mypy.errors import CompileError
2423
from mypy.find_sources import InvalidSourceList, create_source_list
2524
from mypy.fscache import FileSystemCache
@@ -1336,21 +1335,7 @@ def set_strict_flags() -> None:
13361335

13371336
validate_package_allow_list(options.untyped_calls_exclude)
13381337

1339-
# Process `--enable-error-code` and `--disable-error-code` flags
1340-
disabled_codes = set(options.disable_error_code)
1341-
enabled_codes = set(options.enable_error_code)
1342-
1343-
valid_error_codes = set(error_codes.keys())
1344-
1345-
invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes
1346-
if invalid_codes:
1347-
parser.error(f"Invalid error code(s): {', '.join(sorted(invalid_codes))}")
1348-
1349-
options.disabled_error_codes |= {error_codes[code] for code in disabled_codes}
1350-
options.enabled_error_codes |= {error_codes[code] for code in enabled_codes}
1351-
1352-
# Enabling an error code always overrides disabling
1353-
options.disabled_error_codes -= options.enabled_error_codes
1338+
options.process_error_codes(error_callback=parser.error)
13541339

13551340
# Validate incomplete features.
13561341
for feature in options.enable_incomplete_feature:

mypy/options.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,23 @@ def snapshot(self) -> dict[str, object]:
416416
def __repr__(self) -> str:
417417
return f"Options({pprint.pformat(self.snapshot())})"
418418

419+
def process_error_codes(self, *, error_callback: Callable[[str], Any]) -> None:
420+
# Process `--enable-error-code` and `--disable-error-code` flags
421+
disabled_codes = set(self.disable_error_code)
422+
enabled_codes = set(self.enable_error_code)
423+
424+
valid_error_codes = set(error_codes.keys())
425+
426+
invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes
427+
if invalid_codes:
428+
error_callback(f"Invalid error code(s): {', '.join(sorted(invalid_codes))}")
429+
430+
self.disabled_error_codes |= {error_codes[code] for code in disabled_codes}
431+
self.enabled_error_codes |= {error_codes[code] for code in enabled_codes}
432+
433+
# Enabling an error code always overrides disabling
434+
self.disabled_error_codes -= self.enabled_error_codes
435+
419436
def apply_changes(self, changes: dict[str, object]) -> Options:
420437
# Note: effects of this method *must* be idempotent.
421438
new_options = Options()

mypy/stubtest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,6 +1941,12 @@ def set_strict_flags() -> None: # not needed yet
19411941

19421942
parse_config_file(options, set_strict_flags, options.config_file, sys.stdout, sys.stderr)
19431943

1944+
def error_callback(msg: str) -> typing.NoReturn:
1945+
print(_style("error:", color="red", bold=True), msg)
1946+
sys.exit(1)
1947+
1948+
options.process_error_codes(error_callback=error_callback)
1949+
19441950
try:
19451951
modules = build_stubs(modules, options, find_submodules=not args.check_typeshed)
19461952
except StubtestFailure as stubtest_failure:

mypy/test/teststubtest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,6 +2477,19 @@ def test_config_file(self) -> None:
24772477
output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file)
24782478
assert output == "Success: no issues found in 1 module\n"
24792479

2480+
def test_config_file_error_codes(self) -> None:
2481+
runtime = "temp = 5\n"
2482+
stub = "temp = SOME_GLOBAL_CONST"
2483+
output = run_stubtest(stub=stub, runtime=runtime, options=[])
2484+
assert output == (
2485+
"error: not checking stubs due to mypy build errors:\n"
2486+
'test_module.pyi:1: error: Name "SOME_GLOBAL_CONST" is not defined [name-defined]\n'
2487+
)
2488+
2489+
config_file = "[mypy]\ndisable_error_code = name-defined\n"
2490+
output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file)
2491+
assert output == "Success: no issues found in 1 module\n"
2492+
24802493
def test_no_modules(self) -> None:
24812494
output = io.StringIO()
24822495
with contextlib.redirect_stdout(output):

0 commit comments

Comments
 (0)