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

Skip to content

Disallow type(x) if x has a protocol type #16919

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

Open
JukkaL opened this issue Feb 15, 2024 · 4 comments · May be fixed by #18095
Open

Disallow type(x) if x has a protocol type #16919

JukkaL opened this issue Feb 15, 2024 · 4 comments · May be fixed by #18095
Labels
bug mypy got something wrong topic-protocols

Comments

@JukkaL
Copy link
Collaborator

JukkaL commented Feb 15, 2024

Modules can implement protocols, so type(x) is not necessarily a type object if x has a protocol type.

from typing import Protocol

class P(Protocol):
    def f(self) -> None: ...


def f(p: P) -> None:
    reveal_type(type(p))  # type[P] (incorrect!)

It's probably best to to generate an error if type is called on an object with a protocol type, as suggested by @hauntsaninja in #16890 (comment).

See #16890 for more context.

@beauxq
Copy link

beauxq commented Mar 20, 2024

I think an error should not be reported for calling type on any Python object.

The example here doesn't show any problematic code. It only shows mypy reporting incorrect information.

The fact that mypy reports incorrect information (in one version) is not a reason to report an error with that code (in a later version).


In the example of the linked issue, there is problematic code, but the problem is not in calling type. The problem is assuming that the result of the type call has foo.

A better solution would be that if type is called on an object with a protocol type, the result of the type call could be object.

Then it won't assume that it has a foo, and an error will be reported when accessing foo from the result of the type call.
error: "object" has no attribute "foo" [attr-defined]

@beauxq
Copy link

beauxq commented Mar 20, 2024

or maybe the return type should be
type[P] | type[ModuleType]

hauntsaninja added a commit to hauntsaninja/mypy that referenced this issue Nov 3, 2024
@hauntsaninja hauntsaninja linked a pull request Nov 3, 2024 that will close this issue
hauntsaninja added a commit to hauntsaninja/mypy that referenced this issue Nov 3, 2024
hauntsaninja added a commit to hauntsaninja/mypy that referenced this issue Nov 3, 2024
@randolf-scholz
Copy link
Contributor

randolf-scholz commented Nov 5, 2024

Modules can implement protocols, so type(x) is not necessarily a type object if x has a protocol type.

What exactly does this sentence mean? The following raises no errors at runtime:

import typing
cls = type(typing)
assert isinstance(cls, type)  # ✅

Apologies if I am missing the obvious...

Using type(x) or annotating something as type[P] seems very reasonable. What if I want to do something very simple, like create a dict[str, type[P]] that holds all available implementations for a given Protocol?

@JelleZijlstra
Copy link
Member

type(module) is a type object, but it (probably) isn't a type object implementing the protocol that the module implements. For example, in Jukka's post above, a module with an f() function would implement the protocol, but type(module) would return types.ModuleType, which isn't a type[P].

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

Successfully merging a pull request may close this issue.

4 participants