Skip to content

Constructor defined after classmethod is considered to have no args in the classmethod #1727

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
alexsydell opened this issue Jun 20, 2016 · 12 comments · Fixed by #5646
Closed
Assignees
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-0-high

Comments

@alexsydell
Copy link

The type of cls within bar() in the following code is def () -> Foo unless the __init__ is moved to before the classmethod:

class Foo(object):

  @classmethod
  def bar(cls):
    # type: () -> Foo
    reveal_type(cls)
    return cls("bar")

  def __init__(self, baz):
    # type: (str) -> None
    self.baz = baz
@gvanrossum gvanrossum added the bug mypy got something wrong label Jun 23, 2016
@gvanrossum gvanrossum added this to the Future milestone Jun 23, 2016
@rzimmerman
Copy link

Probably related:

class Example:

    @classmethod
    def example(cls, arg1: float, arg2: str) -> Example:
        return cls(arg1=arg1, arg2=arg2)

    def __init__(self, arg1: float, arg2: str) -> None:
        pass

Reports:

example3.py: note: In member "example" of class "Example":
example3.py:7: error: Unexpected keyword argument "arg1" for "Example"
example3.py:7: error: Unexpected keyword argument "arg2" for "Example"

But passes checks if __init__ is moved before the classmethod.

Adding reveal_type with the __init__ method last shows:
example3.py:7: error: Revealed type is 'def () -> example3.Example'

And with __init__ first:
example3.py:11: error: Revealed type is 'def (arg1: builtins.float, arg2: builtins.str) -> example3.Example'

@ilevkivskyi
Copy link
Member

(Raising priority to normal, since this have been reported twice after the original issue.)

@Lordnibbler
Copy link

+1 on this, thanks @ilevkivskyi

@matthewgrossman
Copy link

+1, this is also affecting my work

@mckaysalisbury
Copy link

Yeah, my behavior shows that it sometimes works in the wrong order. (see #4290)

@JelleZijlstra
Copy link
Member

Bumping to high-pri because this is happening frequently and the workaround is non-obvious (see #2324).

@VadimPushtaev
Copy link

Hello! We encountered this bug on the very first day of mypy usage. Is there any reason it's not fixed yet? I would like to solve this issue, but it's nice to know up front if it's extremely hard to do something about it.

@JukkaL
Copy link
Collaborator

JukkaL commented Aug 16, 2018

There probably isn't any particular reason why this hasn't been fixed -- other than there being a lot of other high-priority work as well.

This doesn't sound like it would be very hard to fix (but probably not entirely trivial either). The core team is planning to allocate a block of time focused on fixing high-priority bugs in the next couple of months, and hopefully this gets fixed then.

VadimPushtaev added a commit to VadimPushtaev/mypy that referenced this issue Aug 18, 2018
Constructor defined after classmethod was considered
to have no args in the classmethod.
This commit fixes that bug.
@VadimPushtaev
Copy link

I've spent some time trying to find a solution, and here is my attempt: #5501

VadimPushtaev added a commit to VadimPushtaev/mypy that referenced this issue Aug 19, 2018
Constructor defined after classmethod was considered
to have no args in the classmethod.
This commit fixes that bug.
VadimPushtaev added a commit to VadimPushtaev/mypy that referenced this issue Aug 20, 2018
VadimPushtaev added a commit to VadimPushtaev/mypy that referenced this issue Aug 20, 2018
VadimPushtaev added a commit to VadimPushtaev/mypy that referenced this issue Aug 20, 2018
@msullivan
Copy link
Collaborator

I've got a PR about to go up that fixes this as a side effect of changing the type of classmethod first arguments to be a TypeType

@ilevkivskyi
Copy link
Member

@msullivan There is an existing PR. Please take a look at the questions that appeared there (interactions with fine-grained mode, plugins, forward references, generics, and overloads).

@ilevkivskyi
Copy link
Member

@msullivan Forgot to add the PR number, here it is #5501

msullivan added a commit that referenced this issue Sep 19, 2018
Currently the first argument to `__new__` and classmethods is a
callable type that is constructed during semantic analysis by
typechecker code (!) that looks for the `__init__`/`__new__` methods.

This causes a number of problems, including not being able to call
`object.__new__` in a subclass's `__new__` if it took arguments
(#4190) and giving the wrong type if `__init__` appeared after the
class method (#1727).

Taking a `Type` instead lets us solve those problems, and postpone
computing the callable version of the type until typechecking if it is
needed.

This also lets us drop a bunch of plugin code that tries to fix up the
types of its cls arguments post-hoc, sometimes incorrectly (#5263).

Fixes #1727.
Fixes #4190.
Fixes #5263.
msullivan added a commit that referenced this issue Sep 21, 2018
Currently the first argument to `__new__` and classmethods is a
callable type that is constructed during semantic analysis by
typechecker code (!) that looks for the `__init__`/`__new__` methods.

This causes a number of problems, including not being able to call
`object.__new__` in a subclass's `__new__` if it took arguments
(#4190) and giving the wrong type if `__init__` appeared after the
class method (#1727).

Taking a `Type` instead lets us solve those problems, and postpone
computing the callable version of the type until typechecking if it is
needed.

This also lets us drop a bunch of plugin code that tries to fix up the
types of its cls arguments post-hoc, sometimes incorrectly (#5263).

Fixes #1727.
Fixes #4190.
Fixes #5263.
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-0-high
Projects
None yet
Development

Successfully merging a pull request may close this issue.