mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:16 +00:00
[ty] The runtime object typing.Protocol
is an instance of _ProtocolMeta
(#20488)
## Summary Fixes https://github.com/astral-sh/ty/issues/1218. This bug doesn't currently cause us any real-world issues, because we don't yet understand the signatures typeshed gives us for `isinstance()` and `issubclass()` (typeshed's annotations there use PEP-613 type aliases). #20107 demonstrates that this will start causing us issues as soon as we add support for PEP-613 aliases, however, so it makes sense to fix it now. ## Test Plan Added mdtests
This commit is contained in:
parent
3033d1e5a5
commit
f1aacd0f2c
3 changed files with 30 additions and 3 deletions
|
@ -264,9 +264,21 @@ def f(
|
|||
# fmt: on
|
||||
```
|
||||
|
||||
Nonetheless, `Protocol` can still be used as the second argument to `issubclass()` at runtime:
|
||||
Nonetheless, `Protocol` is an instance of `type` at runtime, and therefore can still be used as the
|
||||
second argument to `issubclass()` at runtime:
|
||||
|
||||
```py
|
||||
import abc
|
||||
import typing
|
||||
from ty_extensions import TypeOf
|
||||
|
||||
reveal_type(type(Protocol)) # revealed: <class '_ProtocolMeta'>
|
||||
# revealed: tuple[<class '_ProtocolMeta'>, <class 'ABCMeta'>, <class 'type'>, <class 'object'>]
|
||||
reveal_type(type(Protocol).__mro__)
|
||||
static_assert(is_subtype_of(TypeOf[Protocol], type))
|
||||
static_assert(is_subtype_of(TypeOf[Protocol], abc.ABCMeta))
|
||||
static_assert(is_subtype_of(TypeOf[Protocol], typing._ProtocolMeta))
|
||||
|
||||
# Could also be `Literal[True]`, but `bool` is fine:
|
||||
reveal_type(issubclass(MyProtocol, Protocol)) # revealed: bool
|
||||
```
|
||||
|
|
|
@ -3694,6 +3694,7 @@ pub enum KnownClass {
|
|||
ParamSpec,
|
||||
ParamSpecArgs,
|
||||
ParamSpecKwargs,
|
||||
ProtocolMeta,
|
||||
TypeVarTuple,
|
||||
TypeAliasType,
|
||||
NoDefaultType,
|
||||
|
@ -3821,6 +3822,7 @@ impl KnownClass {
|
|||
| Self::NamedTupleFallback
|
||||
| Self::NamedTupleLike
|
||||
| Self::ConstraintSet
|
||||
| Self::ProtocolMeta
|
||||
| Self::TypedDictFallback => Some(Truthiness::Ambiguous),
|
||||
|
||||
Self::Tuple => None,
|
||||
|
@ -3903,6 +3905,7 @@ impl KnownClass {
|
|||
| KnownClass::ConstraintSet
|
||||
| KnownClass::TypedDictFallback
|
||||
| KnownClass::BuiltinFunctionType
|
||||
| KnownClass::ProtocolMeta
|
||||
| KnownClass::Template => false,
|
||||
}
|
||||
}
|
||||
|
@ -3982,6 +3985,7 @@ impl KnownClass {
|
|||
| KnownClass::ConstraintSet
|
||||
| KnownClass::TypedDictFallback
|
||||
| KnownClass::BuiltinFunctionType
|
||||
| KnownClass::ProtocolMeta
|
||||
| KnownClass::Template => false,
|
||||
}
|
||||
}
|
||||
|
@ -4060,6 +4064,7 @@ impl KnownClass {
|
|||
| KnownClass::NamedTupleFallback
|
||||
| KnownClass::ConstraintSet
|
||||
| KnownClass::BuiltinFunctionType
|
||||
| KnownClass::ProtocolMeta
|
||||
| KnownClass::Template => false,
|
||||
}
|
||||
}
|
||||
|
@ -4151,6 +4156,7 @@ impl KnownClass {
|
|||
| Self::ConstraintSet
|
||||
| Self::TypedDictFallback
|
||||
| Self::BuiltinFunctionType
|
||||
| Self::ProtocolMeta
|
||||
| Self::Template => false,
|
||||
}
|
||||
}
|
||||
|
@ -4250,6 +4256,7 @@ impl KnownClass {
|
|||
Self::ConstraintSet => "ConstraintSet",
|
||||
Self::TypedDictFallback => "TypedDictFallback",
|
||||
Self::Template => "Template",
|
||||
Self::ProtocolMeta => "_ProtocolMeta",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4477,6 +4484,7 @@ impl KnownClass {
|
|||
| Self::StdlibAlias
|
||||
| Self::Iterable
|
||||
| Self::Iterator
|
||||
| Self::ProtocolMeta
|
||||
| Self::SupportsIndex => KnownModule::Typing,
|
||||
Self::TypeAliasType
|
||||
| Self::TypeVarTuple
|
||||
|
@ -4596,6 +4604,7 @@ impl KnownClass {
|
|||
| Self::ConstraintSet
|
||||
| Self::TypedDictFallback
|
||||
| Self::BuiltinFunctionType
|
||||
| Self::ProtocolMeta
|
||||
| Self::Template => Some(false),
|
||||
|
||||
Self::Tuple => None,
|
||||
|
@ -4680,6 +4689,7 @@ impl KnownClass {
|
|||
| Self::ConstraintSet
|
||||
| Self::TypedDictFallback
|
||||
| Self::BuiltinFunctionType
|
||||
| Self::ProtocolMeta
|
||||
| Self::Template => false,
|
||||
}
|
||||
}
|
||||
|
@ -4773,6 +4783,7 @@ impl KnownClass {
|
|||
"ConstraintSet" => Self::ConstraintSet,
|
||||
"TypedDictFallback" => Self::TypedDictFallback,
|
||||
"Template" => Self::Template,
|
||||
"_ProtocolMeta" => Self::ProtocolMeta,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
@ -4855,9 +4866,9 @@ impl KnownClass {
|
|||
| Self::TypeVarTuple
|
||||
| Self::Iterable
|
||||
| Self::Iterator
|
||||
| Self::ProtocolMeta
|
||||
| Self::NewType => matches!(module, KnownModule::Typing | KnownModule::TypingExtensions),
|
||||
Self::Deprecated => matches!(module, KnownModule::Warnings | KnownModule::TypingExtensions),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,9 +160,13 @@ impl SpecialFormType {
|
|||
| Self::Bottom
|
||||
| Self::Intersection
|
||||
| Self::CallableTypeOf
|
||||
| Self::Protocol // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
||||
| Self::ReadOnly => KnownClass::SpecialForm,
|
||||
|
||||
// Typeshed says it's an instance of `_SpecialForm`,
|
||||
// but then we wouldn't recognise things like `issubclass(`X, Protocol)`
|
||||
// as being valid.
|
||||
Self::Protocol => KnownClass::ProtocolMeta,
|
||||
|
||||
Self::Generic | Self::Any => KnownClass::Type,
|
||||
|
||||
Self::List
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue