diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 1654c5910f98..f935e025e589 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -323,6 +323,38 @@ Example: else: raise ValueError('not defined for zero') +.. _code-empty-body: + +Check that functions don't have empty bodies outside stubs [empty-body] +----------------------------------------------------------------------- + +This error code is similar to the ``[return]`` code but is emitted specifically +for functions and methods with empty bodies (if they are annotated with +non-trivial return type). Such a distinction exists because in some contexts +an empty body can be valid, for example for an abstract method or in a stub +file. Also old versions of mypy used to unconditionally allow functions with +empty bodies, so having a dedicated error code simplifies cross-version +compatibility. + +Note that empty bodies are allowed for methods in *protocols*, and such methods +are considered implicitly abstract: + +.. code-block:: python + + from abc import abstractmethod + from typing import Protocol + + class RegularABC: + @abstractmethod + def foo(self) -> int: + pass # OK + def bar(self) -> int: + pass # Error: Missing return statement [empty-body] + + class Proto(Protocol): + def bar(self) -> int: + pass # OK + .. _code-return-value: Check that return value is compatible [return-value] @@ -947,6 +979,28 @@ otherwise unused variable: _ = f() # No error +.. _code-top-level-await: + +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: + +.. code-block:: python + + async def f() -> None: + ... + + top = await f() # Error: "await" outside function [top-level-await] + + def g() -> None: + # This is a blocker error and cannot be silenced. + await f() # Error: "await" outside coroutine ("async def") + .. _code-assert-type: Check types in assert_type [assert-type] @@ -978,6 +1032,27 @@ Functions will always evaluate to true in boolean contexts. if f: # Error: Function "Callable[[], Any]" could always be true in boolean context [truthy-function] pass +.. _code-str-format: + +Check that string formatting/interpolation is type-safe [str-format] +-------------------------------------------------------------------- + +Mypy will check that f-strings, ``str.format()`` calls, and ``%`` interpolations +are valid (when corresponding template is a literal string). This includes +checking number and types of replacements, for example: + +.. code-block:: python + + # Error: Cannot find replacement for positional format specifier 1 [str-format] + "{} and {}".format("spam") + "{} and {}".format("spam", "eggs") # OK + # Error: Not all arguments converted during string formatting [str-format] + "{} and {}".format("spam", "eggs", "cheese") + + # Error: Incompatible types in string interpolation + # (expression has type "float", placeholder has type "int") [str-format] + "{:d}".format(3.14) + .. _code-str-bytes-safe: Check for implicit bytes coercions [str-bytes-safe] @@ -998,6 +1073,28 @@ Warn about cases where a bytes object may be converted to a string in an unexpec print(f"The alphabet starts with {b!r}") # The alphabet starts with b'abc' print(f"The alphabet starts with {b.decode('utf-8')}") # The alphabet starts with abc +.. _code-annotation-unchecked: + +Notify about an annotation in an unchecked function [annotation-unchecked] +-------------------------------------------------------------------------- + +Sometimes a user may accidentally omit an annotation for a function, and mypy +will not check the body of this function (unless one uses +:option:`--check-untyped-defs ` or +:option:`--disallow-untyped-defs `). To avoid +such situations go unnoticed, mypy will show a note, if there are any type +annotations in an unchecked function: + +.. code-block:: python + + def test_assignment(): # "-> None" return annotation is missing + # Note: By default the bodies of untyped functions are not checked, + # consider using --check-untyped-defs [annotation-unchecked] + x: int = "no way" + +Note that mypy will still exit with return code ``0``, since such behaviour is +specified by :pep:`484`. + .. _code-syntax: Report syntax errors [syntax] diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index 11f463f93018..e1d47f7cbec0 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -255,6 +255,32 @@ mypy generates an error if it thinks that an expression is redundant. [i for i in range(x) if isinstance(i, int)] +.. _code-possibly-undefined: + +Warn about variables that are defined only in some execution paths [possibly-undefined] +--------------------------------------------------------------------------------------- + +If you use :option:`--enable-error-code possibly-undefined `, +mypy generates an error if it cannot verify that a variable will be defined in +all execution paths. This includes situations when a variable definition +appears in a loop, in a conditional branch, in an except handler, etc. For +example: + +.. code-block:: python + + # Use "mypy --enable-error-code possibly-undefined ..." + + from typing import Iterable + + def test(values: Iterable[int], flag: bool) -> None: + if flag: + a = 1 + z = a + 1 # Error: Name "a" may be undefined [possibly-undefined] + + for v in values: + b = v + z = b + 1 # Error: Name "b" may be undefined [possibly-undefined] + .. _code-truthy-bool: Check that expression is not implicitly true in boolean context [truthy-bool] diff --git a/docs/source/html_builder.py b/docs/source/html_builder.py index 405b80ac53d2..3064833b5631 100644 --- a/docs/source/html_builder.py +++ b/docs/source/html_builder.py @@ -23,19 +23,7 @@ def write_doc(self, docname: str, doctree: document) -> None: def _verify_error_codes(self) -> None: from mypy.errorcodes import error_codes - known_missing = { - # TODO: fix these before next release - "annotation-unchecked", - "empty-body", - "possibly-undefined", - "str-format", - "top-level-await", - } - missing_error_codes = { - c - for c in error_codes - if f"code-{c}" not in self._ref_to_doc and c not in known_missing - } + missing_error_codes = {c for c in error_codes if f"code-{c}" not in self._ref_to_doc} if missing_error_codes: raise ValueError( f"Some error codes are not documented: {', '.join(sorted(missing_error_codes))}" diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index e87b04b6f473..b9448f3d5af9 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -144,7 +144,7 @@ def __hash__(self) -> int: "safe-super", "Warn about calls to abstract methods with empty/trivial bodies", "General" ) TOP_LEVEL_AWAIT: Final = ErrorCode( - "top-level-await", "Warn about top level await experessions", "General" + "top-level-await", "Warn about top level await expressions", "General" ) # These error codes aren't enabled by default.