Skip to content

Refactor error messages into a single file #10947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
549d0c4
Migrate checker to use ErrorMessage
tushar-deepsource Aug 4, 2021
63000bd
Migrate typeanal.py
tushar-deepsource Aug 5, 2021
ae2aefb
Finish typeanal migration
tushar-deepsource Aug 5, 2021
5d3396f
Migrate newtype errors
tushar-deepsource Aug 6, 2021
17ad1da
Migrate TypedDict errors
tushar-deepsource Aug 6, 2021
fcd8cfe
Merge upstream branch 'master'
tushar-deepsource Aug 6, 2021
a7abf61
Migrate enum messages
tushar-deepsource Aug 6, 2021
ac23b04
Migrate namedtuple errors
tushar-deepsource Aug 6, 2021
49286a7
Migrate typeargs.py
tushar-deepsource Aug 6, 2021
07a4842
Migrate fastparse and fastparse2
tushar-deepsource Aug 7, 2021
1b6d735
Migrate some amount of messages.py
tushar-deepsource Aug 8, 2021
d04195b
Refactor and migrate incompatible_types function
tushar-deepsource Aug 8, 2021
b25daf4
Add repr to ErrorMessage
tushar-deepsource Aug 8, 2021
a5fe406
Migrate more of messages.py
tushar-deepsource Aug 8, 2021
89f5c24
Migrate messages.py and checkstrformat.py
tushar-deepsource Aug 8, 2021
5f4dfd3
Remove unused message
tushar-deepsource Aug 8, 2021
b9a93e9
Clean up fail function from checker.py
tushar-deepsource Aug 8, 2021
3d3c000
Formatting
tushar-deepsource Aug 9, 2021
65e5dc9
Add another type ignore ErrorMessage
tushar-deepsource Aug 9, 2021
25e442b
Fix failing tests
tushar-deepsource Aug 9, 2021
2838f53
Fix type ignore test
tushar-deepsource Aug 9, 2021
207f2ed
Fix type not callable mismatch
tushar-deepsource Aug 9, 2021
cfb1a21
Merge branch 'python:master' into error-messages
tushar-deepsource Aug 9, 2021
77e7c08
Use NamedTuple to clean up ErrorMessage type
tushar-deepsource Aug 9, 2021
207ee05
Fix missing return
tushar-deepsource Aug 9, 2021
a64595f
Migrate semanal
tushar-deepsource Aug 9, 2021
bf2e1f9
Migrate plugins
tushar-deepsource Aug 9, 2021
2ac803f
Simplify ctypes fail calls
tushar-deepsource Aug 9, 2021
117cee9
Fix abstract class method signatures
tushar-deepsource Aug 9, 2021
a6734d9
Format semanal messages
tushar-deepsource Aug 9, 2021
00f2625
Format plugin messages
tushar-deepsource Aug 9, 2021
e0789da
Fix fail signature in singledispatch
tushar-deepsource Aug 9, 2021
7ece654
Fix check_subtype type signature
tushar-deepsource Aug 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions misc/proper_plugin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from mypy import message_registry
from mypy.plugin import Plugin, FunctionContext
from mypy.types import (
Type, Instance, CallableType, UnionType, get_proper_type, ProperType,
Expand Down Expand Up @@ -40,8 +41,7 @@ def isinstance_proper_hook(ctx: FunctionContext) -> Type:
isinstance(get_proper_type(arg), AnyType) and is_dangerous_target(right)):
if is_special_target(right):
return ctx.default_return_type
ctx.api.fail('Never apply isinstance() to unexpanded types;'
' use mypy.types.get_proper_type() first', ctx.context)
ctx.api.fail(message_registry.ISINSTANCE_ON_UNEXPANDED_TYPE, ctx.context)
ctx.api.note('If you pass on the original type' # type: ignore[attr-defined]
' after the check, always use its unexpanded version', ctx.context)
return ctx.default_return_type
Expand Down Expand Up @@ -109,7 +109,7 @@ def proper_type_hook(ctx: FunctionContext) -> Type:
# Minimize amount of spurious errors from overload machinery.
# TODO: call the hook on the overload as a whole?
if isinstance(arg_type, (UnionType, Instance)):
ctx.api.fail('Redundant call to get_proper_type()', ctx.context)
ctx.api.fail(message_registry.REDUNDANT_GET_PROPER_TYPE, ctx.context)
return ctx.default_return_type


Expand All @@ -122,7 +122,7 @@ def proper_types_hook(ctx: FunctionContext) -> Type:
item_type = UnionType.make_union([NoneTyp(), proper_type])
ok_type = ctx.api.named_generic_type('typing.Iterable', [item_type])
if is_proper_subtype(arg_type, ok_type):
ctx.api.fail('Redundant call to get_proper_types()', ctx.context)
ctx.api.fail(message_registry.REDUNDANT_GET_PROPER_TYPE, ctx.context)
return ctx.default_return_type


Expand Down
59 changes: 29 additions & 30 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
is_literal_type_like,
)
from mypy import message_registry
from mypy.message_registry import ErrorMessage
from mypy.subtypes import (
is_subtype, is_equivalent, is_proper_subtype, is_more_precise,
restrict_subtype_away, is_subtype_ignoring_tvars, is_callable_compatible,
Expand Down Expand Up @@ -1000,10 +1001,9 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str])
# entirely pass/Ellipsis/raise NotImplementedError.
if isinstance(return_type, UninhabitedType):
# This is a NoReturn function
self.msg.fail(message_registry.INVALID_IMPLICIT_RETURN, defn)
self.fail(message_registry.INVALID_IMPLICIT_RETURN, defn)
else:
self.msg.fail(message_registry.MISSING_RETURN_STATEMENT, defn,
code=codes.RETURN)
self.fail(message_registry.MISSING_RETURN_STATEMENT, defn)

self.return_types.pop()

Expand Down Expand Up @@ -1059,31 +1059,25 @@ def is_unannotated_any(t: Type) -> bool:
if fdef.type is None and self.options.disallow_untyped_defs:
if (not fdef.arguments or (len(fdef.arguments) == 1 and
(fdef.arg_names[0] == 'self' or fdef.arg_names[0] == 'cls'))):
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
if not has_return_statement(fdef) and not fdef.is_generator:
self.note('Use "-> None" if function does not return a value', fdef,
code=codes.NO_UNTYPED_DEF)
else:
self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.FUNCTION_TYPE_EXPECTED, fdef)
elif isinstance(fdef.type, CallableType):
ret_type = get_proper_type(fdef.type.ret_type)
if is_unannotated_any(ret_type):
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
elif fdef.is_generator:
if is_unannotated_any(self.get_generator_return_type(ret_type,
fdef.is_coroutine)):
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
elif fdef.is_coroutine and isinstance(ret_type, Instance):
if is_unannotated_any(self.get_coroutine_return_type(ret_type)):
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.RETURN_TYPE_EXPECTED, fdef)
if any(is_unannotated_any(t) for t in fdef.type.arg_types):
self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef,
code=codes.NO_UNTYPED_DEF)
self.fail(message_registry.ARGUMENT_TYPE_EXPECTED, fdef)

def check___new___signature(self, fdef: FuncDef, typ: CallableType) -> None:
self_type = fill_typevars_with_any(fdef.info)
Expand Down Expand Up @@ -1358,7 +1352,7 @@ def check_getattr_method(self, typ: Type, context: Context, name: str) -> None:
if len(self.scope.stack) == 1:
# module scope
if name == '__getattribute__':
self.msg.fail(message_registry.MODULE_LEVEL_GETATTRIBUTE, context)
self.fail(message_registry.MODULE_LEVEL_GETATTRIBUTE, context)
return
# __getattr__ is fine at the module level as of Python 3.7 (PEP 562). We could
# show an error for Python < 3.7, but that would be annoying in code that supports
Expand Down Expand Up @@ -2544,16 +2538,16 @@ def check_assignment_to_multiple_lvalues(self, lvalues: List[Lvalue], rvalue: Ex
elif self.type_is_iterable(typs) and isinstance(typs, Instance):
if (iterable_type is not None
and iterable_type != self.iterable_item_type(typs)):
self.fail("Contiguous iterable with same type expected", context)
self.fail(message_registry.CONTIGUOUS_ITERABLE_EXPECTED, context)
else:
if last_idx is None or last_idx + 1 == idx_rval:
rvalues.append(rval)
last_idx = idx_rval
iterable_type = self.iterable_item_type(typs)
else:
self.fail("Contiguous iterable with same type expected", context)
self.fail(message_registry.CONTIGUOUS_ITERABLE_EXPECTED, context)
else:
self.fail("Invalid type '{}' for *expr (iterable expected)".format(typs),
self.fail(message_registry.ITERABLE_TYPE_EXPECTED.format(typs),
context)
else:
rvalues.append(rval)
Expand Down Expand Up @@ -3085,7 +3079,7 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type,

dunder_set = attribute_type.type.get_method('__set__')
if dunder_set is None:
self.msg.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type),
self.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type),
context)
return AnyType(TypeOfAny.from_error), get_type, False

Expand Down Expand Up @@ -3269,8 +3263,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
# Functions returning a value of type None are allowed to have a None return.
if is_lambda or isinstance(typ, NoneType):
return
self.fail(message_registry.NO_RETURN_VALUE_EXPECTED, s,
code=codes.RETURN_VALUE)
self.fail(message_registry.NO_RETURN_VALUE_EXPECTED, s)
else:
self.check_subtype(
subtype_label='got',
Expand All @@ -3292,7 +3285,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
return

if self.in_checked_function():
self.fail(message_registry.RETURN_VALUE_EXPECTED, s, code=codes.RETURN_VALUE)
self.fail(message_registry.RETURN_VALUE_EXPECTED, s)

def visit_if_stmt(self, s: IfStmt) -> None:
"""Type check an if statement."""
Expand Down Expand Up @@ -4164,7 +4157,7 @@ def find_isinstance_check_helper(self, node: Expression) -> Tuple[TypeMap, TypeM
if node.callee.type_guard is not None:
# TODO: Follow keyword args or *args, **kwargs
if node.arg_kinds[0] != nodes.ARG_POS:
self.fail("Type guard requires positional argument", node)
self.fail(message_registry.TYPE_GUARD_POS_ARG_REQUIRED, node)
return {}, {}
if literal(expr) == LITERAL_TYPE:
return {expr: TypeGuardType(node.callee.type_guard)}, {}
Expand Down Expand Up @@ -4685,7 +4678,7 @@ def check_subtype(self,
subtype: Type,
supertype: Type,
context: Context,
msg: str = message_registry.INCOMPATIBLE_TYPES,
msg: Union[str, ErrorMessage] = message_registry.INCOMPATIBLE_TYPES,
subtype_label: Optional[str] = None,
supertype_label: Optional[str] = None,
*,
Expand All @@ -4695,9 +4688,14 @@ def check_subtype(self,
if is_subtype(subtype, supertype):
return True

if isinstance(msg, ErrorMessage):
msg_text = msg.value
code = msg.code
else:
msg_text = msg
subtype = get_proper_type(subtype)
supertype = get_proper_type(supertype)
if self.msg.try_report_long_tuple_assignment_error(subtype, supertype, context, msg,
if self.msg.try_report_long_tuple_assignment_error(subtype, supertype, context, msg_text,
subtype_label, supertype_label, code=code):
return False
if self.should_suppress_optional_error([subtype]):
Expand All @@ -4716,8 +4714,9 @@ def check_subtype(self,
if isinstance(subtype, Instance) and isinstance(supertype, Instance):
notes = append_invariance_notes([], subtype, supertype)
if extra_info:
msg += ' (' + ', '.join(extra_info) + ')'
self.fail(msg, context, code=code)
msg_text += ' (' + ', '.join(extra_info) + ')'

self.fail(ErrorMessage(msg_text, code=code), context)
for note in notes:
self.msg.note(note, context, code=code)
if note_msg:
Expand Down Expand Up @@ -4988,9 +4987,9 @@ def temp_node(self, t: Type, context: Optional[Context] = None) -> TempNode:
"""Create a temporary node with the given, fixed type."""
return TempNode(t, context=context)

def fail(self, msg: str, context: Context, *, code: Optional[ErrorCode] = None) -> None:
def fail(self, msg: ErrorMessage, context: Context, *, code: Optional[ErrorCode] = None) -> None:
"""Produce an error message."""
self.msg.fail(msg, context, code=code)
self.msg.fail(msg, context)

def note(self,
msg: str,
Expand Down
5 changes: 2 additions & 3 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1637,8 +1637,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,
Expand Down Expand Up @@ -3641,7 +3640,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.
Expand Down
Loading