Skip to content
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

Callable pretty #18245

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 6 additions & 20 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
from mypy.errorcodes import ErrorCode
from mypy.errors import ErrorInfo, Errors, ErrorWatcher
from mypy.nodes import (
ARG_NAMED,
ARG_NAMED_OPT,
ARG_OPT,
ARG_POS,
ARG_STAR,
ARG_STAR2,
Expand Down Expand Up @@ -112,17 +109,6 @@
"typing.cast",
}


ARG_CONSTRUCTOR_NAMES: Final = {
ARG_POS: "Arg",
ARG_OPT: "DefaultArg",
ARG_NAMED: "NamedArg",
ARG_NAMED_OPT: "DefaultNamedArg",
ARG_STAR: "VarArg",
ARG_STAR2: "KwArg",
}


# Map from the full name of a missing definition to the test fixture (under
# test-data/unit/fixtures/) that provides the definition. This is used for
# generating better error messages when running mypy tests only.
Expand Down Expand Up @@ -2039,6 +2025,7 @@ def report_non_method_protocol(
def note_call(
self, subtype: Type, call: Type, context: Context, *, code: ErrorCode | None
) -> None:
# breakpoint()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftovers from debugging?

self.note(
'"{}.__call__" has type {}'.format(
format_type_bare(subtype, self.options),
Expand Down Expand Up @@ -2487,11 +2474,10 @@ def format_callable_args(
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:
constructor = ARG_CONSTRUCTOR_NAMES[arg_kind]
if arg_kind.is_star() or arg_name is None:
arg_strings.append(f"{constructor}({format(arg_type)})")
arg_strings.append(f"{format(arg_type)}")
else:
arg_strings.append(f"{constructor}({format(arg_type)}, {repr(arg_name)})")
arg_strings.append(f"{arg_name}: {format(arg_type)}")

return ", ".join(arg_strings)

Expand Down Expand Up @@ -2709,14 +2695,14 @@ def format_literal_value(typ: LiteralType) -> str:
else:
return_type = format(func.ret_type)
if func.is_ellipsis_args:
return f"Callable[..., {return_type}]"
return f"(..., {return_type})"
param_spec = func.param_spec()
if param_spec is not None:
return f"Callable[{format(param_spec)}, {return_type}]"
return f"({format(param_spec)}, {return_type})"
args = format_callable_args(
func.arg_types, func.arg_kinds, func.arg_names, format, verbosity
)
return f"Callable[[{args}], {return_type}]"
return f"({args}) -> {return_type}"
else:
# Use a simple representation for function types; proper
# function types may result in long and difficult-to-read
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-assert-type-fail.test
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ def f(si: arr.array[int]):
[case testAssertTypeFailCallableArgKind]
from typing import assert_type, Callable
def myfunc(arg: int) -> None: pass
assert_type(myfunc, Callable[[int], None]) # E: Expression is of type "Callable[[Arg(int, 'arg')], None]", not "Callable[[int], None]"
assert_type(myfunc, Callable[[int], None]) # E: Expression is of type "(arg: int) -> None", not "(int) -> None"
16 changes: 8 additions & 8 deletions test-data/unit/check-callable.test
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ x = 5 # type: Union[int, Callable[[], str]]
if callable(x) and x() == 'test':
x()
else:
x + 5 # E: Unsupported left operand type for + ("Callable[[], str]") \
# N: Left operand is of type "Union[int, Callable[[], str]]"
x + 5 # E: Unsupported left operand type for + ("() -> str") \
# N: Left operand is of type "Union[int, () -> str]"

[builtins fixtures/callable.pyi]

Expand Down Expand Up @@ -605,14 +605,14 @@ class Call(Protocol):
def __call__(self, x: int, *args: Any, **kwargs: Any) -> None: ...

def f1() -> None: ...
a1: Call = f1 # E: Incompatible types in assignment (expression has type "Callable[[], None]", variable has type "Call") \
# N: "Call.__call__" has type "Callable[[Arg(int, 'x'), VarArg(Any), KwArg(Any)], None]"
a1: Call = f1 # E: Incompatible types in assignment (expression has type "() -> None", variable has type "Call") \
# N: "Call.__call__" has type "(x: int, Any, Any) -> None"
def f2(x: str) -> None: ...
a2: Call = f2 # E: Incompatible types in assignment (expression has type "Callable[[str], None]", variable has type "Call") \
# N: "Call.__call__" has type "Callable[[Arg(int, 'x'), VarArg(Any), KwArg(Any)], None]"
a2: Call = f2 # E: Incompatible types in assignment (expression has type "(str) -> None", variable has type "Call") \
# N: "Call.__call__" has type "(x: int, Any, Any) -> None"
def f3(y: int) -> None: ...
a3: Call = f3 # E: Incompatible types in assignment (expression has type "Callable[[int], None]", variable has type "Call") \
# N: "Call.__call__" has type "Callable[[Arg(int, 'x'), VarArg(Any), KwArg(Any)], None]"
a3: Call = f3 # E: Incompatible types in assignment (expression has type "(int) -> None", variable has type "Call") \
# N: "Call.__call__" has type "(x: int, Any, Any) -> None"
def f4(x: int) -> None: ...
a4: Call = f4

Expand Down
74 changes: 37 additions & 37 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ import typing
class A:
def f(self): pass
A().f = None # E: Cannot assign to a method \
# E: Incompatible types in assignment (expression has type "None", variable has type "Callable[[], Any]")
# E: Incompatible types in assignment (expression has type "None", variable has type "() -> Any")


[case testOverrideAttributeWithMethod]
Expand Down Expand Up @@ -145,7 +145,7 @@ class Base:
pass

class Derived(Base):
__hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "Callable[[Base], int]")
__hash__ = 1 # E: Incompatible types in assignment (expression has type "int", base class "Base" defined the type as "(Base) -> int")

[case testOverridePartialAttributeWithMethod]
# This was crashing: https://github.com/python/mypy/issues/11686.
Expand Down Expand Up @@ -740,13 +740,13 @@ class A:
f3: Callable[[str], None]

class B(A):
def f1(self, x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "Callable[[str], None]", override has type "Callable[[object], None]")
def f1(self, x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "(str) -> None", override has type "(object) -> None")

@classmethod
def f2(cls, x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "Callable[[str], None]", override has type "Callable[[object], None]")
def f2(cls, x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "(str) -> None", override has type "(object) -> None")

@staticmethod
def f3(x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "Callable[[str], None]", override has type "Callable[[object], None]")
def f3(x: object) -> None: pass # E: Covariant override of a mutable attribute (base class "A" defined the type as "(str) -> None", override has type "(object) -> None")
[builtins fixtures/classmethod.pyi]

[case testOverrideCallableAttributeWithSettableProperty]
Expand All @@ -770,7 +770,7 @@ class A:
f: Callable[[str], None]

class B(A):
@property # E: Covariant override of a mutable attribute (base class "A" defined the type as "Callable[[str], None]", override has type "Callable[[object], None]")
@property # E: Covariant override of a mutable attribute (base class "A" defined the type as "(str) -> None", override has type "(object) -> None")
def f(self) -> Callable[[object], None]: pass
@func.setter
def f(self, x: object) -> None: pass
Expand Down Expand Up @@ -812,18 +812,18 @@ class A:
f4: Union[Callable[[str], str], str]

class B(A):
def f1(self, x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[Callable[[str], str], str]", override has type "Callable[[str], str]")
def f1(self, x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[(str) -> str, str]", override has type "(str) -> str")
pass

def f2(self, x: object) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[Callable[[str], str], str]", override has type "Callable[[object], str]")
def f2(self, x: object) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[(str) -> str, str]", override has type "(object) -> str")
pass

@classmethod
def f3(cls, x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[Callable[[str], str], str]", override has type "Callable[[str], str]")
def f3(cls, x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[(str) -> str, str]", override has type "(str) -> str")
pass

@staticmethod
def f4(x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[Callable[[str], str], str]", override has type "Callable[[str], str]")
def f4(x: str) -> str: # E: Covariant override of a mutable attribute (base class "A" defined the type as "Union[(str) -> str, str]", override has type "(str) -> str")
pass
[builtins fixtures/classmethod.pyi]

Expand Down Expand Up @@ -1095,9 +1095,9 @@ class A:
if int():
h = f
g = h
ff = f # type: Callable[[B], None] # E: Incompatible types in assignment (expression has type "Callable[[A], None]", variable has type "Callable[[B], None]")
ff = f # type: Callable[[B], None] # E: Incompatible types in assignment (expression has type "(A) -> None", variable has type "(B) -> None")
if int():
g = ff # E: Incompatible types in assignment (expression has type "Callable[[B], None]", variable has type "Callable[[A], None]")
g = ff # E: Incompatible types in assignment (expression has type "(B) -> None", variable has type "(A) -> None")
[out]


Expand Down Expand Up @@ -1206,7 +1206,7 @@ import typing
class A:
def f(self): pass
A.f = None # E: Cannot assign to a method \
# E: Incompatible types in assignment (expression has type "None", variable has type "Callable[[A], Any]")
# E: Incompatible types in assignment (expression has type "None", variable has type "(A) -> Any")

[case testAssignToNestedClassViaClass]
import typing
Expand Down Expand Up @@ -2345,8 +2345,8 @@ class B:
class C:
def __radd__(self, other, oops) -> int: ...
[out]
tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]"
tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]"
tmp/foo.pyi:3: error: Invalid signature "(B) -> A"
tmp/foo.pyi:5: error: Invalid signature "(C, Any, Any) -> int"

[case testReverseOperatorOrderingCase1]
class A:
Expand Down Expand Up @@ -2934,8 +2934,8 @@ class C:
class D:
def __getattribute__(self, x: str) -> None: pass
[out]
main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattribute__"
main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattribute__"
main:4: error: Invalid signature "(B, A) -> B" for "__getattribute__"
main:6: error: Invalid signature "(C, str, str) -> C" for "__getattribute__"

[case testGetattr]
a: A
Expand Down Expand Up @@ -3004,7 +3004,7 @@ class C:

def do(cd: Callable[..., Any]) -> None: ...

do(C()) # E: Argument 1 to "do" has incompatible type "C"; expected "Callable[..., Any]"
do(C()) # E: Argument 1 to "do" has incompatible type "C"; expected "(..., Any)"

[case testGetattrWithCallableTypeVar]
from typing import Callable, Any, TypeVar
Expand Down Expand Up @@ -3040,8 +3040,8 @@ class C:
class D:
def __getattr__(self, x: str) -> None: pass
[out]
main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattr__"
main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattr__"
main:4: error: Invalid signature "(B, A) -> B" for "__getattr__"
main:6: error: Invalid signature "(C, str, str) -> C" for "__getattr__"

[case testSetattr]
from typing import Union, Any
Expand Down Expand Up @@ -3119,12 +3119,12 @@ b.bad = 'a' # E: Incompatible types in assignment (expression has type "str", v
from typing import Any

class Test:
def __setattr__() -> None: ... # E: Method must have at least one argument. Did you forget the "self" argument? # E: Invalid signature "Callable[[], None]" for "__setattr__"
def __setattr__() -> None: ... # E: Method must have at least one argument. Did you forget the "self" argument? # E: Invalid signature "() -> None" for "__setattr__"
t = Test()
t.crash = 'test' # E: "Test" has no attribute "crash"

class A:
def __setattr__(self): ... # E: Invalid signature "Callable[[A], Any]" for "__setattr__"
def __setattr__(self): ... # E: Invalid signature "(A) -> Any" for "__setattr__"
a = A()
a.test = 4 # E: "A" has no attribute "test"

Expand All @@ -3134,7 +3134,7 @@ b = B()
b.integer = 5

class C:
def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "Callable[[C, int, int], None]" for "__setattr__"
def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "(C, int, int) -> None" for "__setattr__"
c = C()
c.check = 13

Expand Down Expand Up @@ -3355,7 +3355,7 @@ class B:
a = A
bad = lambda: 42

B().bad() # E: Attribute function "bad" with type "Callable[[], int]" does not accept self argument
B().bad() # E: Attribute function "bad" with type "() -> int" does not accept self argument
reveal_type(B.a) # N: Revealed type is "def () -> __main__.A"
reveal_type(B().a) # N: Revealed type is "def () -> __main__.A"
reveal_type(B().a()) # N: Revealed type is "__main__.A"
Expand Down Expand Up @@ -4439,7 +4439,7 @@ class A:
def a(self) -> None: pass
b = 1
class B(A):
a = 1 # E: Incompatible types in assignment (expression has type "int", base class "A" defined the type as "Callable[[A], None]")
a = 1 # E: Incompatible types in assignment (expression has type "int", base class "A" defined the type as "(A) -> None")
def b(self) -> None: pass # E: Signature of "b" incompatible with supertype "A" \
# N: Superclass: \
# N: int \
Expand Down Expand Up @@ -4483,7 +4483,7 @@ class C(B):
def m(self, a: str) -> None: pass
n = m
[out]
main:5: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "B" defined the type as "Callable[[int], None]")
main:5: error: Incompatible types in assignment (expression has type "(str) -> None", base class "B" defined the type as "(int) -> None")

[case testInstanceMethodOverwriteTypevar]
from typing import Generic, TypeVar
Expand Down Expand Up @@ -4527,7 +4527,7 @@ class C(B):
n = m
[builtins fixtures/classmethod.pyi]
[out]
main:7: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "B" defined the type as "Callable[[int], None]")
main:7: error: Incompatible types in assignment (expression has type "(str) -> None", base class "B" defined the type as "(int) -> None")

[case testClassSpec]
from typing import Callable
Expand All @@ -4545,7 +4545,7 @@ class B(A):
def c(self, a: str) -> int: pass
b = c
[out]
main:6: error: Incompatible types in assignment (expression has type "Callable[[str], int]", base class "A" defined the type as "Callable[[int], int]")
main:6: error: Incompatible types in assignment (expression has type "(str) -> int", base class "A" defined the type as "(int) -> int")

[case testClassStaticMethod]
class A():
Expand All @@ -4557,7 +4557,7 @@ class B(A):
a = b
[builtins fixtures/staticmethod.pyi]
[out]
main:7: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "A" defined the type as "Callable[[int], None]")
main:7: error: Incompatible types in assignment (expression has type "(str) -> None", base class "A" defined the type as "(int) -> None")

[case testClassStaticMethodIndirect]
class A():
Expand All @@ -4570,7 +4570,7 @@ class B(A):
c = b
[builtins fixtures/staticmethod.pyi]
[out]
main:8: error: Incompatible types in assignment (expression has type "Callable[[str], None]", base class "A" defined the type as "Callable[[int], None]")
main:8: error: Incompatible types in assignment (expression has type "(str) -> None", base class "A" defined the type as "(int) -> None")

[case testClassStaticMethodSubclassing]
class A:
Expand Down Expand Up @@ -5053,9 +5053,9 @@ reveal_type(A.g4) # N: Revealed type is "def () -> def () -> __main__.A"
class B(metaclass=M):
def foo(self): pass

B.g1 # E: Invalid self argument "Type[B]" to attribute function "g1" with type "Callable[[Type[A]], A]"
B.g2 # E: Invalid self argument "Type[B]" to attribute function "g2" with type "Callable[[Type[TA]], TA]"
B.g3 # E: Invalid self argument "Type[B]" to attribute function "g3" with type "Callable[[TTA], TTA]"
B.g1 # E: Invalid self argument "Type[B]" to attribute function "g1" with type "(Type[A]) -> A"
B.g2 # E: Invalid self argument "Type[B]" to attribute function "g2" with type "(Type[TA]) -> TA"
B.g3 # E: Invalid self argument "Type[B]" to attribute function "g3" with type "(TTA) -> TTA"
reveal_type(B.g4) # N: Revealed type is "def () -> def () -> __main__.B"

# 4 examples of unsoundness - instantiation, classmethod, staticmethod and ClassVar:
Expand All @@ -5068,9 +5068,9 @@ reveal_type(ta.g3) # N: Revealed type is "def () -> Type[__main__.A]"
reveal_type(ta.g4) # N: Revealed type is "def () -> Type[__main__.A]"

x: M = ta
x.g1 # E: Invalid self argument "M" to attribute function "g1" with type "Callable[[Type[A]], A]"
x.g2 # E: Invalid self argument "M" to attribute function "g2" with type "Callable[[Type[TA]], TA]"
x.g3 # E: Invalid self argument "M" to attribute function "g3" with type "Callable[[TTA], TTA]"
x.g1 # E: Invalid self argument "M" to attribute function "g1" with type "(Type[A]) -> A"
x.g2 # E: Invalid self argument "M" to attribute function "g2" with type "(Type[TA]) -> TA"
x.g3 # E: Invalid self argument "M" to attribute function "g3" with type "(TTA) -> TTA"
reveal_type(x.g4) # N: Revealed type is "def () -> __main__.M"

def r(ta: Type[TA], tta: TTA) -> None:
Expand Down Expand Up @@ -7823,7 +7823,7 @@ class Foo:
def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined on line 5

def meth2(self, a: str) -> str: ...
from mod1 import meth2 # E: Incompatible import of "meth2" (imported name has type "Callable[[int], int]", local name has type "Callable[[Foo, str], str]")
from mod1 import meth2 # E: Incompatible import of "meth2" (imported name has type "(int) -> int", local name has type "(Foo, str) -> str")

class Bar:
from mod1 import foo # E: Unsupported class scoped import
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-custom-plugin.test
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ from mypy_extensions import DefaultArg
from m import Signal
s: Signal[[int, DefaultArg(str, 'x')]] = Signal()
reveal_type(s) # N: Revealed type is "m.Signal[def (builtins.int, x: builtins.str =)]"
s.x # E: "Signal[Callable[[int, str], None]]" has no attribute "x"
s.x # E: "Signal[(int, str) -> None]" has no attribute "x"
ss: Signal[int, str] # E: Invalid "Signal" type (expected "Signal[[t, ...]]")
[file m.py]
from typing import TypeVar, Generic, Callable
Expand Down
Loading
Loading