diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index 270125e96cb6..51a508ea4b96 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -866,6 +866,12 @@ of the above sections. x = 'a string' x.trim() # error: "str" has no attribute "trim" [attr-defined] +.. option:: --disable-ignores + + This flag makes mypy act as though no ``# type: ignore`` comments are placed inline. + Effectively, it makes mypy "ignore ignores", therefore reporting all of the errors that would otherwise be ignored by those comments. + Beware: other configuration options and flags may still enable or disable various error codes. + The main use of this flag is to audit code that has ``# type: ignore`` comments in it (potentially masking problems in a subtle way). .. _configuring-error-messages: diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 7abd1f02db68..01a7514dd656 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -800,6 +800,14 @@ section of the command line docs. Note: This option will override disabled error codes from the disable_error_code option. +.. confval:: disable_ignores + + :type: boolean + :default: false + :availability: global + + Ignores ignores. See :option:`mypy --disable-ignores`. + .. confval:: extra_checks :type: boolean diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 6b2eb532003c..4024e753c876 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -896,12 +896,13 @@ def translate_module_id(self, id: str) -> str: def visit_Module(self, mod: ast3.Module) -> MypyFile: self.type_ignores = {} - for ti in mod.type_ignores: - parsed = parse_type_ignore_tag(ti.tag) - if parsed is not None: - self.type_ignores[ti.lineno] = parsed - else: - self.fail(message_registry.INVALID_TYPE_IGNORE, ti.lineno, -1, blocker=False) + if not self.options.disable_ignores: + for ti in mod.type_ignores: + parsed = parse_type_ignore_tag(ti.tag) + if parsed is not None: + self.type_ignores[ti.lineno] = parsed + else: + self.fail(message_registry.INVALID_TYPE_IGNORE, ti.lineno, -1, blocker=False) body = self.fix_function_overloads(self.translate_stmt_list(mod.body, ismodule=True)) diff --git a/mypy/main.py b/mypy/main.py index 9ebbf78ded09..e952bfad294a 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -956,6 +956,10 @@ def add_invertible_flag( help="Enable a specific error code", ) + strictness_group.add_argument( + "--disable-ignores", action="store_true", help="Don't honor '# type: ignore' comments" + ) + error_group = parser.add_argument_group( title="Configuring error messages", description="Adjust the amount of detail shown in error messages.", diff --git a/mypy/options.py b/mypy/options.py index b1456934c6c9..27a51d9c11a5 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -262,6 +262,9 @@ def __init__(self) -> None: self.enable_error_code: list[str] = [] self.enabled_error_codes: set[ErrorCode] = set() + # Disable all type ignore comments + self.disable_ignores = False + # Use script name instead of __main__ self.scripts_are_modules = False diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 8eec979029d0..ca6a3058054d 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -4,6 +4,25 @@ def f(x): pass [out] main:2: error: Function is missing a type annotation +[case testDisableIgnores] +# flags: --disable-ignores +# type: ignore # a type ignore before everything usually ignores the entire file. But not now! +a # E: Name "a" is not defined +a #type: ignore # E: Name "a" is not defined +a #type: ignore[golly] # E: Name "a" is not defined +a #type: ignore[name-defined] # E: Name "a" is not defined + +[case testDisableIgnoresConfig] +# flags: --config-file tmp/mypy.ini +# type: ignore # a type ignore before everything usually ignores the entire file. But not now! +a # E: Name "a" is not defined +a #type: ignore # E: Name "a" is not defined +a #type: ignore[golly] # E: Name "a" is not defined +a #type: ignore[name-defined] # E: Name "a" is not defined +[file mypy.ini] +\[mypy] +disable_ignores=True + [case testUnannotatedArgument] # flags: --disallow-untyped-defs def f(x) -> int: pass