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

Class with function fields incorrectly thinks first argument is self #5485

Closed
Dentosal opened this issue Aug 15, 2018 · 25 comments · Fixed by #10548 or #13400
Closed

Class with function fields incorrectly thinks first argument is self #5485

Dentosal opened this issue Aug 15, 2018 · 25 comments · Fixed by #10548 or #13400
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-dataclasses

Comments

@Dentosal
Copy link

This is a bug report.

Minimal repro

from dataclasses import dataclass
from typing import Callable

@dataclass
class Repro:
    fn: Callable[[int], str]

r = Repro(fn=repr)
assert "1" == r.fn(1)

Works correctly when dataclass is not used, i.e. when Repro is

class Repro:
    def __init__(self, fn: Callable[[int], str]) -> None:
        self.fn = fn

Actual behavior

repro.py:9: error: Invalid self argument "Repro" to attribute function "fn" with type "Callable[[int], str]"
repro.py:9: error: Too many arguments

When running with Python, works correctly. Doesn't throw any exceptions.

Expected behavior

Successful type check

Environment

Versions

Tested with two versions, 0.620 and current version from GitHub.

  • Python 3.7.0
  • mypy 0.620
  • mypy 0.630+dev-a2ffde90635baf05e264f8d899f5705c52b27c2a

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
@ilevkivskyi
Copy link
Member

This is not something specific to dataclasses. There is a simpler repro that gives same errors:

class Repro:
    fn: Callable[[int], str]

r = Repro()
r.fn(1)

The problem is the same as in #708. I would however not close this as a duplicate, because this issue highlights another aspect of the problem.

@ilevkivskyi ilevkivskyi added bug mypy got something wrong priority-1-normal false-positive mypy gave an error on correct code labels Aug 15, 2018
@vim345
Copy link

vim345 commented Sep 24, 2018

I just came across the same issue. I guess a lot of people are going to face this issue very soon, as it's very easy to reproduce it using dataclasses.

@ilevkivskyi ilevkivskyi added the topic-plugins The plugin API and ideas for new plugins label Sep 25, 2018
@ilevkivskyi
Copy link
Member

I guess this should be not hard to fix, mypy cares whether a callable was assigned in class (to match what Python does), so we should just tweak the Vars in plugin to pretend they were assigned on self. But we still need a volunteer who will fix this.

@ojii
Copy link

ojii commented Nov 27, 2018

If someone needs a workaround, this works:

from dataclasses import dataclass
from typing import *

T = TypeVar("T")


@dataclass
class Box(Generic[T]):
    inner: T

    @property
    def unboxed(self) -> T:
        return self.inner


@dataclass
class Repro:
    fn: Box[Callable[[int], str]]


Repro(fn=Box(repr)).fn.unboxed(1)

@s-knibbs
Copy link

I've found that another workaround to this is to use a callback protocol instead of Callable

@rightfold
Copy link

rightfold commented Jul 17, 2019

When using NamedTuple instead of dataclass this problem does not arise.

@JukkaL JukkaL changed the title Dataclass with function fields incorrectly thinks first argument is self Class with function fields incorrectly thinks first argument is self Aug 29, 2019
@TH3CHARLie
Copy link
Collaborator

TH3CHARLie commented Jan 21, 2020

I volunteer to fix this and any guidances will be greatly helpful @ilevkivskyi

@ilevkivskyi
Copy link
Member

@TH3CHARLie Fixing this in general may be tricky, but fixing just the dataclass case, should be easy. In any case, please go ahead!

jacob414 added a commit to jacob414/kingston that referenced this issue Jun 12, 2020
jacob414 added a commit to jacob414/kingston that referenced this issue Jun 12, 2020
commit a2887b7
Author: Jacob Oscarson <jacob@414soft.com>
Date:   Fri Jun 12 11:02:50 2020 +0200

    Polish

commit 5f78d1f
Author: Jacob Oscarson <jacob@414soft.com>
Date:   Thu Jun 11 17:34:12 2020 +0200

    More test coverage, clean up

commit 94a3842
Author: Jacob Oscarson <jacob@414soft.com>
Date:   Thu Jun 11 17:31:56 2020 +0200

    Small typing fixes

commit 0d0f9c9
Author: Jacob Oscarson <jacob@414soft.com>
Date:   Thu Jun 11 17:28:25 2020 +0200

    No coverage on kind.py until problems due to python/mypy#5485 is ok
@Kein

This comment has been minimized.

@jordan-bucholtz
Copy link

I'm still running into this issue with dataclasses. @TH3CHARLie @ilevkivskyi Any resolution on this? 😃

versions

mypy 0.782
Python 3.8.7

@altendky
Copy link

@jordan-bucholtz i don't know if it makes any difference but fyi there is 0.800 (and 0.790 in between).

https://pypi.org/project/mypy/0.800/

@NeilGirdhar
Copy link
Contributor

NeilGirdhar commented Feb 11, 2021

@altendky I'm using 0.800, and this is still broken for me.

@jp-larose
Copy link

Wondering if the solution is to somehow flag the Callable instance variable as a static method. Because that's essentially the intended use. Now, I'm not sure if the fix should be in mypy or in the typing library.

jecluis added a commit to jecluis/aquarium that referenced this issue Mar 9, 2021
We're not ignoring it just because we don't like it, but because mypy is
having a hard time dealing with a callback's type.

  See python/mypy#5485

Signed-off-by: Joao Eduardo Luis <joao@suse.com>
jecluis added a commit to jecluis/aquarium that referenced this issue Mar 9, 2021
We're not ignoring it just because we don't like it, but because mypy is
having a hard time dealing with a callback's type.

  See python/mypy#5485

Signed-off-by: Joao Eduardo Luis <joao@suse.com>
votdev pushed a commit to votdev/aquarium that referenced this issue Mar 10, 2021
We're not ignoring it just because we don't like it, but because mypy is
having a hard time dealing with a callback's type.

  See python/mypy#5485

Signed-off-by: Joao Eduardo Luis <joao@suse.com>
DanAlbert added a commit to dcs-liberation/dcs_liberation that referenced this issue Dec 21, 2021
The newer version includes a partial fix for
python/mypy#5485 (it doesn't fix the problem
for frozen dataclasses, but fixes other cases).
@AlexWaygood AlexWaygood added topic-dataclasses and removed topic-plugins The plugin API and ideas for new plugins labels Mar 25, 2022
@asib
Copy link

asib commented Apr 25, 2022

I've found that another workaround to this is to use a callback protocol instead of Callable

@s-knibbs Could you make an example?

Probably too late for @nh2, but for anyone else who could use an example:

from dataclasses import dataclass
from typing import Callable
from typing_extensions import Protocol

class FunctionType(Protocol):
    def __call__(self, x: int) -> int:
        pass

@dataclass(frozen=True)
class A:
    fn: Callable[[int], int]
    
@dataclass(frozen=True)
class B:
    fn: FunctionType


A(fn=lambda x: x).fn(1) # Invalid self argument "A" to attribute function "fn" with type "Callable[[int], int]"
B(fn=lambda x: x).fn(1)

Hovercross added a commit to Hovercross/django-quick-jobs that referenced this issue May 3, 2022
This is really just for MyPy, it was triggering python/mypy#5485
@eternal-sorrow
Copy link

eternal-sorrow commented Jul 1, 2022

I encoutered this with pathlib.Path('/my/path').stat().st_size. I got

Invalid self argument "stat_result" to attribute function "st_size" with type "Callable[[stat_result], int]"

This way I can't use any of the workarounds because I can't modify the standard stat_result type.

PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 5, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 8, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Aug 10, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
ilevkivskyi pushed a commit to ilevkivskyi/mypy that referenced this issue Aug 12, 2022
Fixes python#708 and Fixes python#5485

Prevent handling as bounded method of callable members declared as instance variables.
ilevkivskyi added a commit that referenced this issue Aug 13, 2022
Fixes #708
Fixes #5485

This builds on the original proposal, but handles three important issues/edge cases:
* This PR fixes serialization of `is_inferred` so that the distinction works correctly in incremental mode (I added a test)
* Dunder operator methods are always considered class variables (this is a relatively common pattern and matches Python semantics; there is an existing tests that previously needed `ClassVar[...]`)
* If we detect a `Too few arguments` error for a variable with callable type we give a note suggesting to try `ClassVar[...]`

I also add a short doc paragraph on this.

Co-authored-by: wyfo <joperez@hotmail.fr>
PIG208 added a commit to PIG208/django-stubs that referenced this issue Sep 3, 2022
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
sobolevn pushed a commit to typeddjango/django-stubs that referenced this issue Sep 3, 2022
* Reflect the deprecation of get_response being None.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>

* Type get_response with a callback protocol.

Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.

This is a workaround for python/mypy#5485.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-dataclasses
Projects
None yet