diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index e850744b5c71..47e9d3c351a1 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -71,6 +71,7 @@ callable_type, try_getting_str_literals, custom_special_method, is_literal_type_like, ) +from mypy.message_registry import ErrorMessage import mypy.errorcodes as codes # Type of callback user for checking individual function arguments. See @@ -1265,7 +1266,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, if isinstance(first_arg, (NoneType, UninhabitedType)): inferred_args[0] = self.named_type('builtins.str') elif not first_arg or not is_subtype(self.named_type('builtins.str'), first_arg): - self.msg.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, + self.chk.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, context) else: # In dynamically typed functions use implicit 'Any' types for @@ -1656,8 +1657,7 @@ def check_overload_call(self, callable_name=callable_name, object_type=object_type) if union_interrupted: - self.chk.fail("Not all union combinations were tried" - " because there are too many unions", context) + self.chk.fail(message_registry.TOO_MANY_UNION_COMBINATIONS, context) return result def plausible_overload_call_targets(self, @@ -3674,7 +3674,7 @@ def _super_arg_types(self, e: SuperExpr) -> Union[Type, Tuple[Type, Type]]: return AnyType(TypeOfAny.unannotated) elif len(e.call.args) == 0: if self.chk.options.python_version[0] == 2: - self.chk.fail(message_registry.TOO_FEW_ARGS_FOR_SUPER, e, code=codes.CALL_ARG) + self.chk.fail(message_registry.TOO_FEW_ARGS_FOR_SUPER, e) return AnyType(TypeOfAny.from_error) elif not e.info: # This has already been reported by the semantic analyzer. @@ -4064,7 +4064,7 @@ def visit_await_expr(self, e: AwaitExpr) -> Type: return self.check_awaitable_expr(actual_type, e, message_registry.INCOMPATIBLE_TYPES_IN_AWAIT) - def check_awaitable_expr(self, t: Type, ctx: Context, msg: str) -> Type: + def check_awaitable_expr(self, t: Type, ctx: Context, msg: Union[str, ErrorMessage]) -> Type: """Check the argument to `await` and extract the type of value. Also used by `async for` and `async with`. diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 53d496bbb1d6..2a07bbb8597b 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -30,7 +30,7 @@ def __str__(self) -> str: ATTR_DEFINED: Final = ErrorCode("attr-defined", "Check that attribute exists", "General") NAME_DEFINED: Final = ErrorCode("name-defined", "Check that name is defined", "General") -CALL_ARG: Final = ErrorCode( +CALL_ARG: Final[ErrorCode] = ErrorCode( "call-arg", "Check number, names and kinds of arguments in calls", "General" ) ARG_TYPE: Final = ErrorCode("arg-type", "Check argument types in calls", "General") diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 9ddb1604ca27..9b19fa2b9120 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -51,8 +51,8 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": YIELD_VALUE_EXPECTED: Final = ErrorMessage("Yield value expected") INCOMPATIBLE_TYPES: Final = "Incompatible types" INCOMPATIBLE_TYPES_IN_ASSIGNMENT: Final = "Incompatible types in assignment" +INCOMPATIBLE_TYPES_IN_AWAIT: Final = ErrorMessage('Incompatible types in "await"') INCOMPATIBLE_REDEFINITION: Final = ErrorMessage("Incompatible redefinition") -INCOMPATIBLE_TYPES_IN_AWAIT: Final = 'Incompatible types in "await"' INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AENTER: Final = ( 'Incompatible types in "async with" for "__aenter__"' ) @@ -61,14 +61,14 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": ) INCOMPATIBLE_TYPES_IN_ASYNC_FOR: Final = 'Incompatible types in "async for"' -INCOMPATIBLE_TYPES_IN_YIELD: Final = 'Incompatible types in "yield"' -INCOMPATIBLE_TYPES_IN_YIELD_FROM: Final = 'Incompatible types in "yield from"' +INCOMPATIBLE_TYPES_IN_YIELD: Final = ErrorMessage('Incompatible types in "yield"') +INCOMPATIBLE_TYPES_IN_YIELD_FROM: Final = ErrorMessage('Incompatible types in "yield from"') INCOMPATIBLE_TYPES_IN_STR_INTERPOLATION: Final = "Incompatible types in string interpolation" MUST_HAVE_NONE_RETURN_TYPE: Final = ErrorMessage('The return type of "{}" must be None') -INVALID_TUPLE_INDEX_TYPE: Final = "Invalid tuple index type" -TUPLE_INDEX_OUT_OF_RANGE: Final = "Tuple index out of range" -INVALID_SLICE_INDEX: Final = "Slice index must be an integer or None" -CANNOT_INFER_LAMBDA_TYPE: Final = "Cannot infer type of lambda" +INVALID_TUPLE_INDEX_TYPE: Final = ErrorMessage("Invalid tuple index type") +TUPLE_INDEX_OUT_OF_RANGE: Final = ErrorMessage("Tuple index out of range") +INVALID_SLICE_INDEX: Final = ErrorMessage("Slice index must be an integer or None") +CANNOT_INFER_LAMBDA_TYPE: Final = ErrorMessage("Cannot infer type of lambda") CANNOT_ACCESS_INIT: Final = 'Cannot access "__init__" directly' NON_INSTANCE_NEW_TYPE: Final = ErrorMessage('"__new__" must return a class instance (got {})') INVALID_NEW_TYPE: Final = ErrorMessage('Incompatible return type for "__new__"') @@ -102,14 +102,16 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": ARGUMENT_TYPE_EXPECTED: Final = ErrorMessage( "Function is missing a type annotation for one or more arguments", codes.NO_UNTYPED_DEF ) -KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE: Final = ( +KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE: Final = ErrorMessage( 'Keyword argument only valid with "str" key type in call to "dict"' ) ALL_MUST_BE_SEQ_STR: Final = ErrorMessage("Type of __all__ must be {}, not {}") -INVALID_TYPEDDICT_ARGS: Final = ( +INVALID_TYPEDDICT_ARGS: Final = ErrorMessage( "Expected keyword arguments, {...}, or dict(...) in TypedDict constructor" ) -TYPEDDICT_KEY_MUST_BE_STRING_LITERAL: Final = "Expected TypedDict key to be string literal" +TYPEDDICT_KEY_MUST_BE_STRING_LITERAL: Final = ErrorMessage( + "Expected TypedDict key to be string literal" +) MALFORMED_ASSERT: Final = ErrorMessage("Assertion is always true, perhaps remove parentheses?") DUPLICATE_TYPE_SIGNATURES: Final = "Function has duplicate type signatures" DESCRIPTOR_SET_NOT_CALLABLE: Final = ErrorMessage("{}.__set__ is not callable") @@ -154,17 +156,23 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": INVALID_TYPEVAR_ARG_VALUE: Final = 'Invalid type argument value for "{}"' # Super -TOO_MANY_ARGS_FOR_SUPER: Final = 'Too many arguments for "super"' -TOO_FEW_ARGS_FOR_SUPER: Final = 'Too few arguments for "super"' -SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED: Final = '"super" with a single argument not supported' -UNSUPPORTED_ARG_1_FOR_SUPER: Final = 'Unsupported argument 1 for "super"' -UNSUPPORTED_ARG_2_FOR_SUPER: Final = 'Unsupported argument 2 for "super"' -SUPER_VARARGS_NOT_SUPPORTED: Final = 'Varargs not supported with "super"' -SUPER_POSITIONAL_ARGS_REQUIRED: Final = '"super" only accepts positional arguments' -SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1: Final = 'Argument 2 for "super" not an instance of argument 1' -TARGET_CLASS_HAS_NO_BASE_CLASS: Final = "Target class has no base class" -SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED: Final = "super() outside of a method is not supported" -SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED: Final = ( +TOO_MANY_ARGS_FOR_SUPER: Final = ErrorMessage('Too many arguments for "super"') +TOO_FEW_ARGS_FOR_SUPER: Final = ErrorMessage('Too few arguments for "super"', codes.CALL_ARG) +SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED: Final = ErrorMessage( + '"super" with a single argument not supported' +) +UNSUPPORTED_ARG_1_FOR_SUPER: Final = ErrorMessage('Unsupported argument 1 for "super"') +UNSUPPORTED_ARG_2_FOR_SUPER: Final = ErrorMessage('Unsupported argument 2 for "super"') +SUPER_VARARGS_NOT_SUPPORTED: Final = ErrorMessage('Varargs not supported with "super"') +SUPER_POSITIONAL_ARGS_REQUIRED: Final = ErrorMessage('"super" only accepts positional arguments') +SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1: Final = ErrorMessage( + 'Argument 2 for "super" not an instance of argument 1' +) +TARGET_CLASS_HAS_NO_BASE_CLASS: Final = ErrorMessage("Target class has no base class") +SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED: Final = ErrorMessage( + "super() outside of a method is not supported" +) +SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED: Final = ErrorMessage( "super() requires one or more positional arguments in enclosing function" ) @@ -204,6 +212,9 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": "Only @runtime_checkable protocols can be used with instance and class checks" ) CANNOT_INSTANTIATE_PROTOCOL: Final = ErrorMessage('Cannot instantiate protocol class "{}"') +TOO_MANY_UNION_COMBINATIONS: Final = ErrorMessage( + "Not all union combinations were tried because there are too many unions" +) CONTIGUOUS_ITERABLE_EXPECTED: Final = ErrorMessage("Contiguous iterable with same type expected") ITERABLE_TYPE_EXPECTED: Final = ErrorMessage("Invalid type '{}' for *expr (iterable expected)") diff --git a/mypy/plugin.py b/mypy/plugin.py index c88fba4eb188..3772d7039b05 100644 --- a/mypy/plugin.py +++ b/mypy/plugin.py @@ -120,7 +120,7 @@ class C: pass """ from abc import abstractmethod -from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict +from typing import Any, Callable, List, Tuple, Optional, NamedTuple, TypeVar, Dict, Union from mypy_extensions import trait, mypyc_attr from mypy.nodes import ( @@ -134,6 +134,7 @@ class C: pass from mypy.options import Options from mypy.lookup import lookup_fully_qualified from mypy.errorcodes import ErrorCode +from mypy.message_registry import ErrorMessage @trait @@ -223,7 +224,8 @@ def type_context(self) -> List[Optional[Type]]: raise NotImplementedError @abstractmethod - def fail(self, msg: str, ctx: Context, *, code: Optional[ErrorCode] = None) -> None: + def fail(self, msg: Union[str, ErrorMessage], ctx: Context, *, + code: Optional[ErrorCode] = None) -> None: """Emit an error message at given location.""" raise NotImplementedError