This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author paul-dest
Recipients gvanrossum, kj, levkivskyi, paul-dest
Date 2021-03-18.10:45:02
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1616064303.65.0.357689459528.issue43512@roundup.psfhosted.org>
In-reply-to
Content
Regarding "At runtime, protocol classes will be simple ABCs." (PEP 544):
Unfortunately, this is currently not the case. Actually, there is an extra metaclass for protocols, solely to provide an __instancecheck__.
https://github.com/python/cpython/blob/3.9/Lib/typing.py#L1096

```
class _ProtocolMeta(ABCMeta):
    # This metaclass is really unfortunate and exists only because of
    # the lack of __instancehook__.
    def __instancecheck__(cls, instance):
        # We need this method for situations where attributes are
        # assigned in __init__.
        if ((not getattr(cls, '_is_protocol', False) or
                _is_callable_members_only(cls)) and
                issubclass(instance.__class__, cls)):
            return True
        if cls._is_protocol:
            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 _get_protocol_attrs(cls)):
                return True
        return super().__instancecheck__(instance)
```


Regarding "There is no intent to provide sophisticated runtime instance and class checks against protocol classes." (PEP 544):
I fully understand that. But a runtime instance check that simply checks, if a protocol member is there, is not sophisticated. And as you can see in the code above, these checks are already implemented, but unfortunately they don't cover the case reported by me in the initial message.

I could provide a patch for the _ProtocolMeta to cover the case reported by me. It's just a matter of a couple of lines. Even if the runtime isinstance() checking is not required to give the right answer, I think the right answer would be nice - at least for the most basic checks as "Are the protocol members there?"

Regarding "if you inherit from a protocol you are deemed to implement it":
I couldn't find a rule with this meaning in any of the typing PEPs.

But in my point of view, the problem is a different one:
If the instance to check is of a class implemented by another developer (maybe the class is from a third-party library - Bob's library), then such a rule does not help the first developer (Alice). Alice doesn't know anything about such-a-rule-compliance of Bob's classes. She just wants to check if the instance returned by one of Bob's functions complies to the protocol.

-------------

The bottom line is:
I'd like to provide a patch if you want me to.

If you think the current implementation must not be touched, then I would appreciate if the reported case could be documented. I could deliver a draft for this, as well. Currently, the last examples in the sections "Protocol members" and "Explicitly declaring implementation" in PEP 544 contain protocol members with no default implementation in the protocol, but do not suggest the behavior reported above.
History
Date User Action Args
2021-03-18 10:45:03paul-destsetrecipients: + paul-dest, gvanrossum, levkivskyi, kj
2021-03-18 10:45:03paul-destsetmessageid: <1616064303.65.0.357689459528.issue43512@roundup.psfhosted.org>
2021-03-18 10:45:03paul-destlinkissue43512 messages
2021-03-18 10:45:02paul-destcreate