New submission from Ivan Levkivskyi <levkivs...@gmail.com>:

The PEP 544 specifies that:

A protocol can be used as a second argument in isinstance() and issubclass() 
only if it is explicitly opt-in by @runtime_checkable decorator.

It is not specified exactly whether this should be enforced by static type 
checkers or at runtime. Currently it is enforced in both cases: mypy flags this 
as error, and a TypeError is raised at runtime.

There is however a problem with current runtime implementation: abc and 
functools modules may call issubclass() on non-runtime checkable protocols if 
they appear as explicit superclasses. This is currently solved by a 
sys._getframe() hack in  typing module.

The problem is that current solution is incomplete. For example, the TypeError 
is not raised in the case of non-method protocols:

>>> class P(Protocol):
...     x: int
... 
>>> 
>>> class C: ...
... 
>>> isinstance(C(), P)
False  # should be TypeError

I tried to fix it this morning but after an hour of attempts to tweak the 
existing hack I gave up. It looks like there are only two reasonable solutions:

* Don't enforce @typing.runtime_checkable at runtime, make it a 
type-checker-only feature (like @typing.final).
* Add a little helper to abc module that would skip classes in MRO for which 
C._is_protocol is True but C._is_runtime_protocol is False.

Any thoughts/preferences?

----------
components: Library (Lib)
messages: 357400
nosy: gvanrossum, levkivskyi
priority: normal
severity: normal
status: open
title: Troubles with @runtime_checkable protocols
type: behavior
versions: Python 3.8, Python 3.9

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue38908>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to