Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Protocol can't constrain __init__ #12970

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
glyph opened this issue Jun 11, 2022 · 3 comments
Closed

Protocol can't constrain __init__ #12970

glyph opened this issue Jun 11, 2022 · 3 comments
Labels
bug mypy got something wrong topic-protocols

Comments

@glyph
Copy link

glyph commented Jun 11, 2022

Bug Report

The following code produces an error when var() is called, but not when it is declared. If you can declare __init__ on Protocols, shouldn't implementations have to match, at least when assigned as Types?

from typing import Protocol, Type

class Proto(Protocol):
    def __init__(self, x: int) -> None:
        ...

class Impl:
    def __init__(self) -> None:
        ...

var: Type[Proto] = Impl
var()

Your Environment

  • Mypy version used: mypy 0.961 (compiled: yes)
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: Python 3.10.4 (python.org)
  • Operating system and version:
ProductName:	macOS
ProductVersion:	12.4
BuildVersion:	21F79
@glyph glyph added the bug mypy got something wrong label Jun 11, 2022
@glyph
Copy link
Author

glyph commented Jun 11, 2022

(This is particularly annoying when one wants to have a class decorator, which it seems must have a bound somewhere in the vicinity of Type, that validates something about the constructor of the type it's decorating...)

@AlexWaygood
Copy link
Member

Constructors (and, in Python, initializers) are generally seen as irrelevant to LSP, because LSP concerns the properties of constructed objects; if a subclass has an incompatible signature with a superclass, that's basically outside the scope of LSP.

If you can declare __init__ on Protocols, shouldn't implementations have to match, at least when assigned as Types?

I believe the reason why this is allowed is to enable patterns such as the following. In this snippet, Abstract does not have to be explicitly subclassed in order for Concrete to be considered a subtype of Abstract. But classes who do subclass Abstract are allowed to call super().__init__() and use the implementation of Abstract.__init__() in Concrete.__init__().

from typing import Protocol

class Abstract(Protocol):
    foo: str
    def __init__(self, foo: str) -> None:
        self.foo = foo

class Concrete(Abstract):
    def __init__(self, foo: str, bar: int) -> None:
        super().__init__(foo)
        self.bar = bar

@ilevkivskyi
Copy link
Member

This is a duplicate of #3823 (also see exactly the point about Type[...] in the original issue). FWIW I agree with this, just never had time for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-protocols
Projects
None yet
Development

No branches or pull requests

3 participants