Open ilevkivskyi opened 6 years ago
Another thing to note here is that maybe we need to trim horizontally long signatures anyway. Some complex overloads in typeshed can produce huge error messages.
Increasing priority since Arg(...)
and VarArg(...)
can look quite confusing and ugly in error messages.
I think that we can always use the "native" format for complex callable types. We'd then only use Callable[...]
in messages if we can use one of these variants:
Callable[[X, ..., Y], Z]
(simple callable types with only positional arguments shown are okay)Callable[..., X]
(a type with explicit ...
is okay)For everything else we can probably use the more readable def (...) -> t
syntax. We should never need Arg(...)
, etc.
The relevant code is in mypy.messages.format_type_inner
. If anybody would like to contribute a PR, I'm happy to review it (feel free to cc me).
Hey, @JukkaL , I'm a newby in contributing to Mypy, so correct me if I'm wrong...
I thought about a solution. The changes involve the mypy.messages.format_callable_args
:
def format_callable_args(
tp: Type,
format: Callable[[Type], str],
verbosity: int,
) -> str:
"""Format a bunch of Callable arguments into a string"""
arg_strings = []
is_only_callable = False
has_non_positional_arguments = False
arg_names = []
arg_types = []
arg_kinds = []
if isinstance(tp, ParamSpecType):
arg_names = tp.prefix.arg_names
arg_types = tp.prefix.arg_types
arg_kinds = tp.prefix.arg_kinds
else:
is_only_callable = True
arg_names = tp.arg_names
arg_types = tp.arg_types
arg_kinds = tp.arg_kinds
for arg_name, arg_type, arg_kind in zip(arg_names, arg_types, arg_kinds):
if arg_kind == ARG_POS and arg_name is None or verbosity == 0 and arg_kind.is_positional():
arg_strings.append(format(arg_type))
else:
has_non_positional_arguments = True
constructor = ARG_CONSTRUCTOR_NAMES[arg_kind]
if arg_kind.is_star() or arg_name is None:
arg_strings.append(f"{constructor}({format(arg_type)})")
else:
arg_strings.append(f"{constructor}({format(arg_type)}, {repr(arg_name)})")
if is_only_callable and has_non_positional_arguments:
return "pretty callable"
return ", ".join(arg_strings)
And in the mypy.messages.format_type_inner
(in the isinstance(func, CallableType):
clause):
args = format_callable_args(
func, format, verbosity
)
if args == "pretty callable":
return pretty_callable(func)
return f"Callable[[{args}], {return_type}]"
Thank you for your attention!!
Currently callable types in many error messages are formatted as
We should probably switch to more "native" format that is already used in some errors (e.g. for protocol and overloads):
The main obstacle here is probably updating all tests that use the old format.
This is a follow up for https://github.com/python/mypy/pull/5463/