diff --git a/docs/source/command_line.rst b/docs/source/command_line.rst index b455e287017e..dab4d6885159 100644 --- a/docs/source/command_line.rst +++ b/docs/source/command_line.rst @@ -372,7 +372,7 @@ definitions or calls. .. option:: --untyped-calls-exclude - This flag allows to selectively disable :option:`--disallow-untyped-calls` + This flag allows one to selectively disable :option:`--disallow-untyped-calls` for functions and methods defined in specific packages, modules, or classes. Note that each exclude entry acts as a prefix. For example (assuming there are no type annotations for ``third_party_lib`` available): @@ -562,7 +562,7 @@ potentially problematic or redundant in some way. .. option:: --deprecated-calls-exclude - This flag allows to selectively disable :ref:`deprecated` warnings + This flag allows one to selectively disable :ref:`deprecated` warnings for functions and methods defined in specific packages, modules, or classes. Note that each exclude entry acts as a prefix. For example (assuming ``foo.A.func`` is deprecated): @@ -754,8 +754,10 @@ of the above sections. strict will catch type errors as long as intentional methods like type ignore or casting were not used.) - Note: the :option:`--warn-unreachable` flag - is not automatically enabled by the strict flag. + Note: the :option:`--warn-unreachable` flag, among others, is not + enabled by the strict flag. If you are interested in enabling even more + useful checks, you may be interested in :option:`--enable-all-error-codes` + and/or :option:`--enable-error-code`. The strict flag does not take precedence over other strict-related flags. Directly specifying a flag of alternate behavior will override the @@ -768,7 +770,7 @@ of the above sections. .. option:: --disable-error-code - This flag allows disabling one or multiple error codes globally. + This flag disables one or multiple error codes globally. See :ref:`error-codes` for more information. .. code-block:: python @@ -783,7 +785,7 @@ of the above sections. .. option:: --enable-error-code - This flag allows enabling one or multiple error codes globally. + This flag enables one or multiple error codes globally. See :ref:`error-codes` for more information. Note: This flag will override disabled error codes from the @@ -799,6 +801,30 @@ of the above sections. x = 'a string' x.trim() # error: "str" has no attribute "trim" [attr-defined] +.. option:: --enable-all-error-codes + + This flag enables all of the error codes for mypy, + including the optional ones that are off by default. + See :ref:`error-codes` and :ref:`error-codes-optional` + for more information. + + (Unlike the other flag for error code enablement, these can be countermanded + with :option:`--disable-error-code`.) + + Note that future releases of mypy will likely introduce more error codes, + so the effective result of using this flag will change from release to + release. + + While often useful, keep in mind that this flag will enable **all** error + codes, including any that may be experimental, wrongheaded, or + contradictory. + + Enabling all codes is not the same as enabling all checks that mypy could + perform; for example, :option:`--strict-bytes` is not enabled by this flag. + However, :option:`--strict` and :option:`--enable-all-error-codes` used in + tandem should be sufficient to get you virtually every useful check mypy + can perform. + .. _configuring-error-messages: Configuring error messages diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index de51f0c796fd..be3d3721dd21 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -761,6 +761,15 @@ section of the command line docs. Note: This option will override disabled error codes from the disable_error_code option. +.. confval:: enable_all_error_codes + + :type: boolean + :default: False + + Enables all mypy error codes. + + Note: This option will be overridden by disabled error codes from the disable_error_code option. + .. confval:: extra_checks :type: boolean diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 49cb8a0c06c1..7e8dd445c584 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -1003,8 +1003,8 @@ Warn about top level await expressions [top-level-await] This error code is separate from the general ``[syntax]`` errors, because in some environments (e.g. IPython) a top level ``await`` is allowed. In such environments a user may want to use ``--disable-error-code=top-level-await``, -that allows to still have errors for other improper uses of ``await``, for -example: +which allows one to still have errors for other improper uses of ``await``, +for example: .. code-block:: python diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index dfe2e30874f7..6dee37c595b9 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -458,9 +458,12 @@ Example: # Error: unused "type: ignore" comment return a + b # type: ignore -Note that due to a specific nature of this comment, the only way to selectively -silence it, is to include the error code explicitly. Also note that this error is -not shown if the ``# type: ignore`` is not used due to code being statically +Mypy errors can typically be silenced by putting a ``# type: ignore`` comment after them, +but because this is *already* a ``# type: ignore`` comment, the only way to selectively +silence it is to include the error code explicitly, making the comment +``# type: ignore[unused-ignore]``. + +This error is not shown if the ``# type: ignore`` is not used due to code being statically unreachable (e.g. due to platform or version checks). Example: diff --git a/docs/source/error_codes.rst b/docs/source/error_codes.rst index 485d70cb59bc..91c956d73702 100644 --- a/docs/source/error_codes.rst +++ b/docs/source/error_codes.rst @@ -50,6 +50,10 @@ and :option:`--disable-error-code ` to enable or disable specific error codes that don't have a dedicated command-line flag or config file setting. +:option:`--enable-all-error-codes ` enables +all optional error codes. (Unlike the other flag for error code enablement, +these can be countermanded with :option:`--disable-error-code `.) + Per-module enabling/disabling error codes ----------------------------------------- diff --git a/docs/source/mypy_daemon.rst b/docs/source/mypy_daemon.rst index 6c511e14eb95..e0fc8129a0b8 100644 --- a/docs/source/mypy_daemon.rst +++ b/docs/source/mypy_daemon.rst @@ -252,16 +252,16 @@ command. Statically inspect expressions ****************************** -The daemon allows to get declared or inferred type of an expression (or other +The daemon allows one to get the declared or inferred type of an expression (or other information about an expression, such as known attributes or definition location) -using ``dmypy inspect LOCATION`` command. The location of the expression should be +using the ``dmypy inspect LOCATION`` command. The location of the expression should be specified in the format ``path/to/file.py:line:column[:end_line:end_column]``. Both line and column are 1-based. Both start and end position are inclusive. These rules match how mypy prints the error location in error messages. If a span is given (i.e. all 4 numbers), then only an exactly matching expression is inspected. If only a position is given (i.e. 2 numbers, line and column), mypy -will inspect all *expressions*, that include this position, starting from the +will inspect all expressions that include this position, starting from the innermost one. Consider this Python code snippet: diff --git a/mypy/main.py b/mypy/main.py index b2abf06897de..26fcfbe8a2e2 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -953,6 +953,12 @@ def add_invertible_flag( default=[], help="Enable a specific error code", ) + strictness_group.add_argument( + "--enable-all-error-codes", + action="store_true", + help="Enable all error codes. Unlike the other flag for error code enablement," + + " these can be countermanded by --disable-error-code", + ) error_group = parser.add_argument_group( title="Configuring error messages", diff --git a/mypy/options.py b/mypy/options.py index 52afd27211ed..91014e3b5ebb 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -254,6 +254,7 @@ def __init__(self) -> None: # Error codes to enable self.enable_error_code: list[str] = [] self.enabled_error_codes: set[ErrorCode] = set() + self.enable_all_error_codes = False # Use script name instead of __main__ self.scripts_are_modules = False @@ -456,6 +457,13 @@ def process_error_codes(self, *, error_callback: Callable[[str], Any]) -> None: # Enabling an error code always overrides disabling self.disabled_error_codes -= self.enabled_error_codes + # enable_all_error_codes codes can be countermanded by disabled_error_codes, which + # can in turn be countermanded by enabled_error_codes. But we've just computed the + # latter countermanding, so we can use the set of disabled_error_codes that weren't + # countermanded to figure out what to really turn off. + if self.enable_all_error_codes: + self.enabled_error_codes = set(error_codes.values()) - self.disabled_error_codes + def process_incomplete_features( self, *, error_callback: Callable[[str], Any], warning_callback: Callable[[str], Any] ) -> None: diff --git a/mypy/traverser.py b/mypy/traverser.py index 7d7794822396..3c249391bdf8 100644 --- a/mypy/traverser.py +++ b/mypy/traverser.py @@ -504,7 +504,7 @@ class ExtendedTraverserVisitor(TraverserVisitor): In addition to the base traverser it: * has visit_ methods for leaf nodes * has common method that is called for all nodes - * allows to skip recursing into a node + * allows skipping recursing into a node Note that this traverser still doesn't visit some internal mypy constructs like _promote expression and Var. diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index 2a75b465099b..e0fa52ed1126 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -2467,3 +2467,78 @@ A = Union[C, List] # OK -- check_untyped_defs is False by default. def f(): x: int = "no" # N: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs + +[case testSpotCheckEnableAllErrorCodes] +# flags: --enable-all-error-codes +# It would be annoying to check every error here, so let's just check a couple. +from typing_extensions import override + +class Parent: + def f(self, x: int) -> None: + pass + + def g(self, y: int) -> None: + pass + +class Child(Parent): + def f(self, x: int) -> None: # E: Method "f" is not using @override but is overriding a method in class "__main__.Parent" + pass + + @override + def g(self, y: int) -> None: #type: ignore # E: Unused "type: ignore" comment # E: "type: ignore" comment without error code + pass +[builtins fixtures/tuple-simple.pyi] + +[case testSpotCheckEnableAllErrorCodesNot] +# This test case exists purely to ensure that the testSpotCheckErrorCodeAll test does not become obsolete. +# (For example, if all the errors expected by testSpotCheckErrorCodeAll get turned on by default, then +# the testSpotCheckErrorCodeAll test would fail to guarantee the enablement of any additional errors! +# (hint: if that does happen, breaking this test, then consider changing these two tests to pick *different*, +# not-enabled-by-default, error codes. Also, testSpotCheckEnableAllErrorCodesConfig.)) +from typing_extensions import override + +class Parent: + def f(self, x: int) -> None: + pass + + def g(self, y: int) -> None: + pass + +class Child(Parent): + def f(self, x: int) -> None: + pass + + @override + def g(self, y: int) -> None: #type: ignore + pass +[builtins fixtures/tuple-simple.pyi] + +[case testSpotCheckEnableAllErrorCodesConfig] +# flags: --config-file tmp/mypy.ini +# This test just makes sure that the user can still countermand +# enable_all_error_codes on a more-specific level. +import tests.foo +import bar +[file bar.py] +def foo() -> int: ... +if foo: ... # E: Function "foo" could always be true in boolean context +42 + "no" # type: ignore # E: "type: ignore" comment without error code (consider "type: ignore[operator]" instead) +[file tests/__init__.py] +[file tests/foo.py] +def foo() -> int: ... +if foo: ... # E: Function "foo" could always be true in boolean context +42 + "no" # type: ignore +[file mypy.ini] +\[mypy] +enable_all_error_codes = True + +\[mypy-tests.*] +disable_error_code = ignore-without-code + +[case testSpotCheckEnableAllErrorCodesCountermand] +# flags: --enable-all-error-codes --disable-error-code unused-ignore +x = 2 # type: ignore # E: "type: ignore" comment without error code + +[case testSpotCheckEnableAllErrorCodesCountermandCountermand] +# flags: --enable-all-error-codes --disable-error-code ignore-without-code --disable-error-code unused-ignore --enable-error-code ignore-without-code +x = 2 # type: ignore # E: "type: ignore" comment without error code diff --git a/test-data/unit/fixtures/tuple-simple.pyi b/test-data/unit/fixtures/tuple-simple.pyi index 07f9edf63cdd..6a16fbd510bc 100644 --- a/test-data/unit/fixtures/tuple-simple.pyi +++ b/test-data/unit/fixtures/tuple-simple.pyi @@ -19,3 +19,6 @@ class function: pass class int: pass class str: pass # For convenience class dict: pass + +# Had to define this for testSpotCheckErrorCodeAll*, for whatever reason: +class ellipsis: pass