mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +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
|
# 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
|
```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:
|
# Could also be `Literal[True]`, but `bool` is fine:
|
||||||
reveal_type(issubclass(MyProtocol, Protocol)) # revealed: bool
|
reveal_type(issubclass(MyProtocol, Protocol)) # revealed: bool
|
||||||
```
|
```
|
||||||
|
|
|
@ -3694,6 +3694,7 @@ pub enum KnownClass {
|
||||||
ParamSpec,
|
ParamSpec,
|
||||||
ParamSpecArgs,
|
ParamSpecArgs,
|
||||||
ParamSpecKwargs,
|
ParamSpecKwargs,
|
||||||
|
ProtocolMeta,
|
||||||
TypeVarTuple,
|
TypeVarTuple,
|
||||||
TypeAliasType,
|
TypeAliasType,
|
||||||
NoDefaultType,
|
NoDefaultType,
|
||||||
|
@ -3821,6 +3822,7 @@ impl KnownClass {
|
||||||
| Self::NamedTupleFallback
|
| Self::NamedTupleFallback
|
||||||
| Self::NamedTupleLike
|
| Self::NamedTupleLike
|
||||||
| Self::ConstraintSet
|
| Self::ConstraintSet
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::TypedDictFallback => Some(Truthiness::Ambiguous),
|
| Self::TypedDictFallback => Some(Truthiness::Ambiguous),
|
||||||
|
|
||||||
Self::Tuple => None,
|
Self::Tuple => None,
|
||||||
|
@ -3903,6 +3905,7 @@ impl KnownClass {
|
||||||
| KnownClass::ConstraintSet
|
| KnownClass::ConstraintSet
|
||||||
| KnownClass::TypedDictFallback
|
| KnownClass::TypedDictFallback
|
||||||
| KnownClass::BuiltinFunctionType
|
| KnownClass::BuiltinFunctionType
|
||||||
|
| KnownClass::ProtocolMeta
|
||||||
| KnownClass::Template => false,
|
| KnownClass::Template => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3982,6 +3985,7 @@ impl KnownClass {
|
||||||
| KnownClass::ConstraintSet
|
| KnownClass::ConstraintSet
|
||||||
| KnownClass::TypedDictFallback
|
| KnownClass::TypedDictFallback
|
||||||
| KnownClass::BuiltinFunctionType
|
| KnownClass::BuiltinFunctionType
|
||||||
|
| KnownClass::ProtocolMeta
|
||||||
| KnownClass::Template => false,
|
| KnownClass::Template => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4060,6 +4064,7 @@ impl KnownClass {
|
||||||
| KnownClass::NamedTupleFallback
|
| KnownClass::NamedTupleFallback
|
||||||
| KnownClass::ConstraintSet
|
| KnownClass::ConstraintSet
|
||||||
| KnownClass::BuiltinFunctionType
|
| KnownClass::BuiltinFunctionType
|
||||||
|
| KnownClass::ProtocolMeta
|
||||||
| KnownClass::Template => false,
|
| KnownClass::Template => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4151,6 +4156,7 @@ impl KnownClass {
|
||||||
| Self::ConstraintSet
|
| Self::ConstraintSet
|
||||||
| Self::TypedDictFallback
|
| Self::TypedDictFallback
|
||||||
| Self::BuiltinFunctionType
|
| Self::BuiltinFunctionType
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::Template => false,
|
| Self::Template => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4250,6 +4256,7 @@ impl KnownClass {
|
||||||
Self::ConstraintSet => "ConstraintSet",
|
Self::ConstraintSet => "ConstraintSet",
|
||||||
Self::TypedDictFallback => "TypedDictFallback",
|
Self::TypedDictFallback => "TypedDictFallback",
|
||||||
Self::Template => "Template",
|
Self::Template => "Template",
|
||||||
|
Self::ProtocolMeta => "_ProtocolMeta",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4477,6 +4484,7 @@ impl KnownClass {
|
||||||
| Self::StdlibAlias
|
| Self::StdlibAlias
|
||||||
| Self::Iterable
|
| Self::Iterable
|
||||||
| Self::Iterator
|
| Self::Iterator
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::SupportsIndex => KnownModule::Typing,
|
| Self::SupportsIndex => KnownModule::Typing,
|
||||||
Self::TypeAliasType
|
Self::TypeAliasType
|
||||||
| Self::TypeVarTuple
|
| Self::TypeVarTuple
|
||||||
|
@ -4596,6 +4604,7 @@ impl KnownClass {
|
||||||
| Self::ConstraintSet
|
| Self::ConstraintSet
|
||||||
| Self::TypedDictFallback
|
| Self::TypedDictFallback
|
||||||
| Self::BuiltinFunctionType
|
| Self::BuiltinFunctionType
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::Template => Some(false),
|
| Self::Template => Some(false),
|
||||||
|
|
||||||
Self::Tuple => None,
|
Self::Tuple => None,
|
||||||
|
@ -4680,6 +4689,7 @@ impl KnownClass {
|
||||||
| Self::ConstraintSet
|
| Self::ConstraintSet
|
||||||
| Self::TypedDictFallback
|
| Self::TypedDictFallback
|
||||||
| Self::BuiltinFunctionType
|
| Self::BuiltinFunctionType
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::Template => false,
|
| Self::Template => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4773,6 +4783,7 @@ impl KnownClass {
|
||||||
"ConstraintSet" => Self::ConstraintSet,
|
"ConstraintSet" => Self::ConstraintSet,
|
||||||
"TypedDictFallback" => Self::TypedDictFallback,
|
"TypedDictFallback" => Self::TypedDictFallback,
|
||||||
"Template" => Self::Template,
|
"Template" => Self::Template,
|
||||||
|
"_ProtocolMeta" => Self::ProtocolMeta,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4855,9 +4866,9 @@ impl KnownClass {
|
||||||
| Self::TypeVarTuple
|
| Self::TypeVarTuple
|
||||||
| Self::Iterable
|
| Self::Iterable
|
||||||
| Self::Iterator
|
| Self::Iterator
|
||||||
|
| Self::ProtocolMeta
|
||||||
| Self::NewType => matches!(module, KnownModule::Typing | KnownModule::TypingExtensions),
|
| Self::NewType => matches!(module, KnownModule::Typing | KnownModule::TypingExtensions),
|
||||||
Self::Deprecated => matches!(module, KnownModule::Warnings | KnownModule::TypingExtensions),
|
Self::Deprecated => matches!(module, KnownModule::Warnings | KnownModule::TypingExtensions),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,13 @@ impl SpecialFormType {
|
||||||
| Self::Bottom
|
| Self::Bottom
|
||||||
| Self::Intersection
|
| Self::Intersection
|
||||||
| Self::CallableTypeOf
|
| Self::CallableTypeOf
|
||||||
| Self::Protocol // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
|
||||||
| Self::ReadOnly => KnownClass::SpecialForm,
|
| 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::Generic | Self::Any => KnownClass::Type,
|
||||||
|
|
||||||
Self::List
|
Self::List
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue