Skip to content

Commit

Permalink
Fix error code handling in stubtest with --mypy-config-file (#17629)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sobolevn committed Aug 3, 2024
1 parent a0dbbd5 commit 6eb3ee5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 16 deletions.
17 changes: 1 addition & 16 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
validate_package_allow_list,
)
from mypy.error_formatter import OUTPUT_CHOICES
from mypy.errorcodes import error_codes
from mypy.errors import CompileError
from mypy.find_sources import InvalidSourceList, create_source_list
from mypy.fscache import FileSystemCache
Expand Down Expand Up @@ -1336,21 +1335,7 @@ def set_strict_flags() -> None:

validate_package_allow_list(options.untyped_calls_exclude)

# Process `--enable-error-code` and `--disable-error-code` flags
disabled_codes = set(options.disable_error_code)
enabled_codes = set(options.enable_error_code)

valid_error_codes = set(error_codes.keys())

invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes
if invalid_codes:
parser.error(f"Invalid error code(s): {', '.join(sorted(invalid_codes))}")

options.disabled_error_codes |= {error_codes[code] for code in disabled_codes}
options.enabled_error_codes |= {error_codes[code] for code in enabled_codes}

# Enabling an error code always overrides disabling
options.disabled_error_codes -= options.enabled_error_codes
options.process_error_codes(error_callback=parser.error)

# Validate incomplete features.
for feature in options.enable_incomplete_feature:
Expand Down
17 changes: 17 additions & 0 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,23 @@ def snapshot(self) -> dict[str, object]:
def __repr__(self) -> str:
return f"Options({pprint.pformat(self.snapshot())})"

def process_error_codes(self, *, error_callback: Callable[[str], Any]) -> None:
# Process `--enable-error-code` and `--disable-error-code` flags
disabled_codes = set(self.disable_error_code)
enabled_codes = set(self.enable_error_code)

valid_error_codes = set(error_codes.keys())

invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes
if invalid_codes:
error_callback(f"Invalid error code(s): {', '.join(sorted(invalid_codes))}")

self.disabled_error_codes |= {error_codes[code] for code in disabled_codes}
self.enabled_error_codes |= {error_codes[code] for code in enabled_codes}

# Enabling an error code always overrides disabling
self.disabled_error_codes -= self.enabled_error_codes

def apply_changes(self, changes: dict[str, object]) -> Options:
# Note: effects of this method *must* be idempotent.
new_options = Options()
Expand Down
6 changes: 6 additions & 0 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,12 @@ def set_strict_flags() -> None: # not needed yet

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

def error_callback(msg: str) -> typing.NoReturn:
print(_style("error:", color="red", bold=True), msg)
sys.exit(1)

options.process_error_codes(error_callback=error_callback)

try:
modules = build_stubs(modules, options, find_submodules=not args.check_typeshed)
except StubtestFailure as stubtest_failure:
Expand Down
13 changes: 13 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2477,6 +2477,19 @@ def test_config_file(self) -> None:
output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file)
assert output == "Success: no issues found in 1 module\n"

def test_config_file_error_codes(self) -> None:
runtime = "temp = 5\n"
stub = "temp = SOME_GLOBAL_CONST"
output = run_stubtest(stub=stub, runtime=runtime, options=[])
assert output == (
"error: not checking stubs due to mypy build errors:\n"
'test_module.pyi:1: error: Name "SOME_GLOBAL_CONST" is not defined [name-defined]\n'
)

config_file = "[mypy]\ndisable_error_code = name-defined\n"
output = run_stubtest(stub=stub, runtime=runtime, options=[], config_file=config_file)
assert output == "Success: no issues found in 1 module\n"

def test_no_modules(self) -> None:
output = io.StringIO()
with contextlib.redirect_stdout(output):
Expand Down

0 comments on commit 6eb3ee5

Please sign in to comment.