Skip to content

Disallow calling type on Protocol#18095

Open
hauntsaninja wants to merge 2 commits intopython:masterfrom
hauntsaninja:type-protocol
Open

Disallow calling type on Protocol#18095
hauntsaninja wants to merge 2 commits intopython:masterfrom
hauntsaninja:type-protocol

Conversation

@hauntsaninja
Copy link
Copy Markdown
Collaborator

@hauntsaninja hauntsaninja commented Nov 3, 2024

Fixes #16919, fixes #16890

It's possible we should not issue the diagnostic and only return object, but that may confuse users. Let's see the primer.

Should also probably disallow type[P] as well.

@hauntsaninja hauntsaninja force-pushed the type-protocol branch 2 times, most recently from 3d3a3be to afa72b9 Compare November 3, 2024 09:03
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@JukkaL
Copy link
Copy Markdown
Collaborator

JukkaL commented Nov 4, 2024

The websockets error is an interesting one:

        elif isinstance(message, AsyncIterable):
            ... type(message).__aiter__ ...

This is kind of reasonable, since modules can't really implement __aiter__.

Maybe we could infer that protocols with certain dunder methods can only be implemented by regular class instances, and fall back to the to the old type(x) behavior? This would imply that a module object, for example, can never be assignable to AsyncIterable.

Comment thread mypy/checkexpr.py Outdated
ret_type=UnionType(
[
self.named_type("builtins.type"),
self.named_type("types.ModuleType"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sorry, I got confused myself, deleted & reposted)

self.named_type('types.ModuleType') isn't the correct type here:

import types
assert type(types) is types.ModuleType

When you call type(some_module), you obtain types.ModuleType class itself, not its instance. So this union isn't type | types.ModuleType | Any, it should be type | type[ModuleType] | Any, and at this point type[ModuleType] member is redundant (it's also a type, isn't it?).

@github-actions
Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

pydantic (https://github.com/pydantic/pydantic)
+ pydantic/dataclasses.py:266: error: "type" has no attribute "__pydantic_validator__"  [attr-defined]

scrapy (https://github.com/scrapy/scrapy)
+ scrapy/utils/python.py:268: error: Unused "type: ignore" comment  [unused-ignore]

hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- src/hydra_zen/structured_configs/_implementations.py:1155: error: No overload variant of "builds" of "BuildsFn" matches argument types "type[DataclassInstance]", "dict[str, int | float | Path | DataClass_ | type[DataClass_] | ListConfig | DictConfig | Enum | Sequence[HydraSupportedType] | Mapping[Any, HydraSupportedType] | None]", "bool | None", "Literal['none', 'partial', 'all', 'object'] | None", "DataclassOptions"  [call-overload]
+ src/hydra_zen/structured_configs/_implementations.py:1155: error: No overload variant of "builds" of "BuildsFn" matches argument types "type", "dict[str, int | float | Path | DataClass_ | type[DataClass_] | ListConfig | DictConfig | Enum | Sequence[HydraSupportedType] | Mapping[Any, HydraSupportedType] | None]", "bool | None", "Literal['none', 'partial', 'all', 'object'] | None", "DataclassOptions"  [call-overload]

websockets (https://github.com/aaugustin/websockets)
+ src/websockets/legacy/protocol.py:682: error: "type" has no attribute "__aiter__" (not async iterable)  [attr-defined]
+ src/websockets/legacy/protocol.py:689: error: "type" has no attribute "__anext__"  [attr-defined]

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

Successfully merging this pull request may close these issues.

Disallow type(x) if x has a protocol type (🐞) Modules don't really conform to Protocols do they

4 participants