Skip to content

Commit e7333a2

Browse files
committed
Review comments and clean up
Improve documentation english wording Remove state mutation on ErrorCode and move back to ErrorCode set approach Add test cases for commandline exit for invalid codes Decrease parser error message verbosity for invalid codes
1 parent c683ae3 commit e7333a2

File tree

8 files changed

+91
-47
lines changed

8 files changed

+91
-47
lines changed

docs/source/command_line.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ of the above sections.
572572

573573
This flag allows enabling one or multiple error codes globally.
574574

575-
NOTE: Will override disabled error codes from the --disable-error-code
575+
Note: This flag will override disabled error codes from the --disable-error-code
576576
flag
577577

578578
.. code-block:: python

mypy/build.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ def _build(sources: List[BuildSource],
223223
options.show_error_codes,
224224
options.pretty,
225225
lambda path: read_py_file(path, cached_read, options.python_version),
226-
options.show_absolute_path)
226+
options.show_absolute_path,
227+
options.enabled_error_codes,
228+
options.disabled_error_codes)
227229
plugin, snapshot = load_plugins(options, errors, stdout, extra_plugins)
228230

229231
# Add catch-all .gitignore to cache dir if we created it

mypy/errorcodes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ def __init__(self, code: str,
2222
self.description = description
2323
self.category = category
2424
self.default_enabled = default_enabled
25-
self.enabled = default_enabled
2625
error_codes[code] = self
2726

2827
def __str__(self) -> str:

mypy/errors.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,18 @@ def __init__(self,
164164
show_error_codes: bool = False,
165165
pretty: bool = False,
166166
read_source: Optional[Callable[[str], Optional[List[str]]]] = None,
167-
show_absolute_path: bool = False) -> None:
167+
show_absolute_path: bool = False,
168+
enabled_error_codes: Optional[Set[ErrorCode]] = None,
169+
disabled_error_codes: Optional[Set[ErrorCode]] = None) -> None:
168170
self.show_error_context = show_error_context
169171
self.show_column_numbers = show_column_numbers
170172
self.show_error_codes = show_error_codes
171173
self.show_absolute_path = show_absolute_path
172174
self.pretty = pretty
173175
# We use fscache to read source code when showing snippets.
174176
self.read_source = read_source
177+
self.enabled_error_codes = enabled_error_codes or set()
178+
self.disabled_error_codes = disabled_error_codes or set()
175179
self.initialize()
176180

177181
def initialize(self) -> None:
@@ -195,7 +199,9 @@ def copy(self) -> 'Errors':
195199
self.show_error_codes,
196200
self.pretty,
197201
self.read_source,
198-
self.show_absolute_path)
202+
self.show_absolute_path,
203+
self.enabled_error_codes,
204+
self.disabled_error_codes)
199205
new.file = self.file
200206
new.import_ctx = self.import_ctx[:]
201207
new.function_or_member = self.function_or_member[:]
@@ -351,17 +357,25 @@ def add_error_info(self, info: ErrorInfo) -> None:
351357
self._add_error_info(file, info)
352358

353359
def is_ignored_error(self, line: int, info: ErrorInfo, ignores: Dict[int, List[str]]) -> bool:
354-
if info.code and info.code.enabled is False:
360+
if info.code and self.is_error_code_enabled(info.code) is False:
355361
return True
356362
elif line not in ignores:
357363
return False
358364
elif not ignores[line]:
359365
# Empty list means that we ignore all errors
360366
return True
361-
elif info.code:
367+
elif info.code and self.is_error_code_enabled(info.code) is True:
362368
return info.code.code in ignores[line]
363369
return False
364370

371+
def is_error_code_enabled(self, error_code: ErrorCode) -> bool:
372+
if error_code in self.disabled_error_codes:
373+
return False
374+
elif error_code in self.enabled_error_codes:
375+
return True
376+
else:
377+
return error_code.default_enabled
378+
365379
def clear_errors_in_targets(self, path: str, targets: Set[str]) -> None:
366380
"""Remove errors in specific fine-grained targets within a file."""
367381
if path in self.error_info_map:

mypy/main.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
import time
99

10-
from typing import Any, Dict, IO, Iterable, List, Optional, Sequence, Tuple, TextIO, Union
10+
from typing import Any, Dict, IO, List, Optional, Sequence, Tuple, TextIO, Union
1111
from typing_extensions import Final, NoReturn
1212

1313
from mypy import build
@@ -869,24 +869,22 @@ def set_strict_flags() -> None:
869869
parser.error("You can't make a variable always true and always false (%s)" %
870870
', '.join(sorted(overlap)))
871871

872-
# Process disabled (--disable-error-code) codes
872+
# Process `--enable-error-code` and `--disable-error-code` flags
873873
disabled_codes = set(options.disable_error_code)
874-
if disabled_codes:
875-
invalid_error_codes = process_error_codes(disabled_codes, enable=False)
874+
enabled_codes = set(options.enable_error_code)
876875

877-
if invalid_error_codes:
878-
parser.error("Disabled error codes provided invalid values: (%s)" %
879-
', '.join(sorted(invalid_error_codes)))
876+
valid_error_codes = set(error_codes.keys())
880877

881-
# Process enabled (--enable-error-code) codes
882-
# If a flag is both enabled and disabled the result is enabled
883-
enabled_codes = set(options.enable_error_code)
884-
if enabled_codes:
885-
invalid_error_codes = process_error_codes(enabled_codes, enable=True)
878+
invalid_codes = (enabled_codes | disabled_codes) - valid_error_codes
879+
if invalid_codes:
880+
parser.error("Invalid error code(s): %s" %
881+
', '.join(sorted(invalid_codes)))
886882

887-
if invalid_error_codes:
888-
parser.error("Enabled error codes provided invalid values: (%s)" %
889-
', '.join(sorted(invalid_error_codes)))
883+
options.disabled_error_codes |= {error_codes[code] for code in disabled_codes}
884+
options.enabled_error_codes |= {error_codes[code] for code in enabled_codes}
885+
886+
# Enabling an error code always overrides disabling
887+
options.disabled_error_codes -= options.enabled_error_codes
890888

891889
# Set build flags.
892890
if options.strict_optional_whitelist is not None:
@@ -1012,20 +1010,6 @@ def process_cache_map(parser: argparse.ArgumentParser,
10121010
options.cache_map[source] = (meta_file, data_file)
10131011

10141012

1015-
def process_error_codes(codes: Iterable[str], enable: bool) -> List[str]:
1016-
invalid_error_codes = [] # type: List[str]
1017-
1018-
# process globally disabled error codes
1019-
for code in codes:
1020-
as_code = error_codes.get(code)
1021-
if not as_code:
1022-
invalid_error_codes.append(code)
1023-
continue
1024-
as_code.enabled = enable
1025-
1026-
return invalid_error_codes
1027-
1028-
10291013
def maybe_write_junit_xml(td: float, serious: bool, messages: List[str], options: Options) -> None:
10301014
if options.junit_xml:
10311015
py_version = '{}_{}'.format(options.python_version[0], options.python_version[1])

mypy/options.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import pprint
44
import sys
55

6-
from typing_extensions import Final
6+
from typing_extensions import Final, TYPE_CHECKING
77
from typing import Dict, List, Mapping, Optional, Pattern, Set, Tuple, Callable, Any
88

99
from mypy import defaults
1010
from mypy.util import get_class_descriptors, replace_object_state
1111

12+
if TYPE_CHECKING:
13+
from mypy.errors import ErrorCode
14+
1215

1316
class BuildType:
1417
STANDARD = 0 # type: Final[int]
@@ -179,9 +182,11 @@ def __init__(self) -> None:
179182

180183
# Error codes to disable
181184
self.disable_error_code = [] # type: List[str]
185+
self.disabled_error_codes = set() # type: Set[ErrorCode]
182186

183187
# Error codes to enable
184188
self.enable_error_code = [] # type: List[str]
189+
self.enabled_error_codes = set() # type: Set[ErrorCode]
185190

186191
# Use script name instead of __main__
187192
self.scripts_are_modules = False

mypy/test/testcheck.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
retry_on_error, update_testcase_output, parse_options,
1919
copy_and_fudge_mtime, assert_target_equivalence, check_test_output_files
2020
)
21-
from mypy import errorcodes
2221
from mypy.errors import CompileError
2322
from mypy.semanal_main import core_modules
2423

@@ -254,15 +253,6 @@ def run_case_once(self, testcase: DataDrivenTestCase,
254253
if testcase.output_files:
255254
check_test_output_files(testcase, incremental_step, strip_prefix='tmp/')
256255

257-
# Post run cleanup step to reset the state of the ErrorCodes that may
258-
# have been enabled or disabled by flags
259-
if options.disable_error_code or options.enable_error_code:
260-
altered_error_codes = set(
261-
options.disable_error_code).union(set(options.enable_error_code))
262-
for code in altered_error_codes:
263-
error_code = errorcodes.error_codes[code]
264-
error_code.enabled = error_code.default_enabled
265-
266256
def verify_cache(self, module_data: List[Tuple[str, str, str]], a: List[str],
267257
manager: build.BuildManager, graph: Graph) -> None:
268258
# There should be valid cache metadata for each module except

test-data/unit/cmdline.test

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,3 +1092,53 @@ import foo.bar
10921092
[out]
10931093
src/foo/bar.py: error: Source file found twice under different module names: 'src.foo.bar' and 'foo.bar'
10941094
== Return code: 2
1095+
1096+
[case testEnableInvalidErrorCode]
1097+
# cmd: mypy --enable-error-code YOLO test.py
1098+
[file test.py]
1099+
x = 1
1100+
[out]
1101+
usage: mypy [-h] [-v] [-V] [more options; see below]
1102+
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
1103+
mypy: error: Invalid error code(s): YOLO
1104+
== Return code: 2
1105+
1106+
[case testDisableInvalidErrorCode]
1107+
# cmd: mypy --disable-error-code YOLO test.py
1108+
[file test.py]
1109+
x = 1
1110+
[out]
1111+
usage: mypy [-h] [-v] [-V] [more options; see below]
1112+
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
1113+
mypy: error: Invalid error code(s): YOLO
1114+
== Return code: 2
1115+
1116+
[case testEnableAndDisableInvalidErrorCode]
1117+
# cmd: mypy --disable-error-code YOLO --enable-error-code YOLO2 test.py
1118+
[file test.py]
1119+
x = 1
1120+
[out]
1121+
usage: mypy [-h] [-v] [-V] [more options; see below]
1122+
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
1123+
mypy: error: Invalid error code(s): YOLO, YOLO2
1124+
== Return code: 2
1125+
1126+
[case testEnableValidAndInvalidErrorCode]
1127+
# cmd: mypy --enable-error-code attr-defined --enable-error-code YOLO test.py
1128+
[file test.py]
1129+
x = 1
1130+
[out]
1131+
usage: mypy [-h] [-v] [-V] [more options; see below]
1132+
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
1133+
mypy: error: Invalid error code(s): YOLO
1134+
== Return code: 2
1135+
1136+
[case testDisableValidAndInvalidErrorCode]
1137+
# cmd: mypy --disable-error-code attr-defined --disable-error-code YOLO test.py
1138+
[file test.py]
1139+
x = 1
1140+
[out]
1141+
usage: mypy [-h] [-v] [-V] [more options; see below]
1142+
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
1143+
mypy: error: Invalid error code(s): YOLO
1144+
== Return code: 2

0 commit comments

Comments
 (0)