Skip to content

Function in dataclass seen as function's return type not Callable #7404

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
verisimilidude2 opened this issue Aug 28, 2019 · 3 comments
Closed

Comments

@verisimilidude2
Copy link

This is a bug report.

Minimal (?) repro

""" Script showing a function stored in a dataclass comes back in mypy
    as the return type of the function. Runs fine in Python.
"""
from dataclasses import dataclass
from typing import Callable, Mapping

MyFuncType = Callable[[int], float]


@dataclass
class ADataClass:
    my_func: MyFuncType


def standard(qty: int) -> float:
    return float(qty)


def main() -> None:
    # variable holds a function
    pos_fun0: MyFuncType = standard
    # function is put into a dataclass
    stock_type_var: ADataClass = ADataClass(pos_fun0)
    # get the function out and into a new variable
    pos_fun1: MyFuncType = stock_type_var.my_func


    # mypy has two problems with the previous line:
#tester.py:25: error: Incompatible types in assignment (expression has type "float", variable has type "Callable[[int], float]")
#tester.py:25: error: Invalid self argument "ADataClass" to attribute function "my_func" with type "Callable[[int], float]"

    # two functions should be the same
    assert pos_fun1 == pos_fun0
    print("Worked")

if __name__ == '__main__':
    main()

Actual behavior

tester.py:25: error: Incompatible types in assignment (expression has type "float", variable has type "Callable[[int], float]")
tester.py:25: error: Invalid self argument "ADataClass" to attribute function "my_func" with type "Callable[[int], float]"

Expected behavior

Successful type check

Environment

Versions

Tested with:

Python 3.7.0
mypy 0.720

Mypy config

[mypy]
warn_redundant_casts = True
warn_unused_ignores = True
incremental = True

follow_imports = normal
ignore_missing_imports = True
disallow_untyped_calls = True
disallow_untyped_defs = True
check_untyped_defs = True
warn_return_any = True
warn_no_return = True
no_implicit_optional = True
strict_optional = True

Somewhat similar, possibly related

Dataclass with function fields incorrectly thinks first argument is self #5485
Not finding type specifications in make_dataclass #6063
Cannot assign to field of Callable type #708

@verisimilidude2
Copy link
Author

Workaround - changed the dataclass to a typing.NamedTuple

5c5,6
< from typing import Callable, Mapping
---
> from typing import Callable, Mapping, NamedTuple
> from collections import namedtuple
10,13c11
< @dataclass
< class ADataClass:
<     my_func: MyFuncType 
< 
---
> StockType: NamedTuple = namedtuple("StockType", "my_func")
23c21
<     stock_type_var: ADataClass = ADataClass(pos_fun0)
---
>     stock_type_var: StockType = StockType(pos_fun0,)

@refi64
Copy link
Contributor

refi64 commented Aug 29, 2019

This is actually completely unrelated to dataclasses, reduced:

from typing import Callable

class A:
    func: Callable[[int], None]

a: A
reveal_type(a.func)

Which shows:

x.py:7: note: Revealed type is 'def ()'
x.py:7: error: Invalid self argument "A" to attribute function "func" with
type "Callable[[int], None]"

Off the top of my head this should work... I guess mypy is assuming that
func becomes a bound method? Afaik in this case it wouldn't, only if it
were a ClassVar.

Also side note, your workaround only works because you didn't specify any
types in the NamedTuple, so everything is of type Any. A type-safe but ugly
workaround for your example is to define the type of the attribute as
Callable[[A, int], float], which isn't correct but type checks on the class
instances.

EDIT: Welp this is indeed a complete duplicate of #5485, this is what I get for skimming the issue. IMO that issue should be renamed to signify it's not just dataclasses though.

@JukkaL
Copy link
Collaborator

JukkaL commented Aug 29, 2019

Updated the name of #5485. Closing as duplicate.

@JukkaL JukkaL closed this as completed Aug 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants