gh-102433: Use inspect.getattr_static in typing._ProtocolMeta.__instancecheck__ (#103034)

This commit is contained in:
Alex Waygood 2023-04-02 14:22:19 +01:00 committed by GitHub
parent d828b35785
commit 6d59c9e32e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 7 deletions

View file

@ -1998,6 +1998,17 @@ _PROTO_ALLOWLIST = {
}
@functools.cache
def _lazy_load_getattr_static():
# Import getattr_static lazily so as not to slow down the import of typing.py
# Cache the result so we don't slow down _ProtocolMeta.__instancecheck__ unnecessarily
from inspect import getattr_static
return getattr_static
_cleanups.append(_lazy_load_getattr_static.cache_clear)
class _ProtocolMeta(ABCMeta):
# This metaclass is really unfortunate and exists only because of
# the lack of __instancehook__.
@ -2025,12 +2036,17 @@ class _ProtocolMeta(ABCMeta):
return True
if is_protocol_cls:
if all(hasattr(instance, attr) and
# All *methods* can be blocked by setting them to None.
(not callable(getattr(cls, attr, None)) or
getattr(instance, attr) is not None)
for attr in protocol_attrs):
getattr_static = _lazy_load_getattr_static()
for attr in protocol_attrs:
try:
val = getattr_static(instance, attr)
except AttributeError:
break
if callable(getattr(cls, attr, None)) and val is None:
break
else:
return True
return super().__instancecheck__(instance)