You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
typing.Reversible doesn't fully support the reversing protocol #170
typing.Reversible doesn't work with types that are supported by reserved() but don't have the __reversed__ method. E.g. tuple, str, bytes, bytearray, and array.
The reversing protocol as well as the iterating protocol is supported not only by special method, but implicitly if the class has implemented __getitem__ and __len__ methods.
Yeah, the _ProtocolMeta metaclass that implements the structural check is pretty simple-minded. However, the BDFL-delegate for PEP 484 decreed that the classes in typing should not support isinstance() or issubclass() at all. I ripped out isinstance() support, but ripping out issubclass() support is still on the TODO list (see #136). So I'm not sure it's worth adding this.
The place where this really should be implemented is in the type checker, e.g. mypy (https://github.com/JukkaL/mypy). I don't know whether mypy currently supports this, but it's worth trying and searching its issue tracker. (I would, but I'm home sick and can't concentrate very long.)
This is the same problem as Iterable being defined as "has __iter__" instead of "has __iter__ or implements the old-style sequence protocol". As far as I can tell, the only reason Iterable passes such types today is that they're all registered with collections.abc.Sequence, which is a subclass of collections.abc.Iterable, and typing.Iterable has extra=collections.abc.Iterable attached and defers to the ABC to do the check. (I'm not sure if/how #136 will affect that.) So the obvious way to fix this problem seems to be doing the equivalent thing that makes Iterable work:
Add collections.abc.Reversible, which is a subtype of Iterable, and has a __subclasshook__ that checks for __reversed__.
Change collections.abc.Sequence to be a subtype of Reversible instead of Iterable, so that everything registered as a Sequence or MutableSequence is now Reversible as well as Iterable as far as the ABCs are concerned.
Change typing.Reversible to add extra=collections.abc.Reversible.
Any third-party types that want to be Reversible based on the old-style sequence protocol despite not being Sequences could call collections.abc.Reversible.register.
Alternatively, is Reversible even useful in practice? If the only thing it's used for is as a type hint for reverse, and it doesn't get that right, and can't get that right without adding a lot of complexity, maybe it just shouldn't be there.
The type checker (e.g. mypy) is independent from the issubclass()
implementation in typing.py. As I wrote in a different thread we shouldn't
even have the latter, per decree from the BDFL-delegate for PEP 484. AFAICT
mypy does the right thing for Reversible and those builtin types.
IOW Reversible does get things right in practice (in the type checker).
FWIW, maybe we should try to deprecate supporting iteration using the old-style protocol? It's really a very old backwards compatibility measure (from when iterators were first introduced). Then eventually we could do the same for reversing using the old-style protocol.
Hm. The example given there is a toy though. Something with a getitem
that maps its argument to its square might as well be a mapping. I really
think it's time to slowly let go of this (no need to rush into removing
support, but we could still frown upon its use).
@serhiy-storchaka Yes, I also noticed this some time ago. But now typing.Reversible just defers all checks to collections.abc.Reversible, so that if we fix the latter, then this will be automatically fixed.
Activity
gvanrossum commentedon Dec 26, 2015
Yeah, the
_ProtocolMetametaclass that implements the structural check is pretty simple-minded. However, the BDFL-delegate for PEP 484 decreed that the classes in typing should not support isinstance() or issubclass() at all. I ripped out isinstance() support, but ripping out issubclass() support is still on the TODO list (see #136). So I'm not sure it's worth adding this.The place where this really should be implemented is in the type checker, e.g. mypy (https://github.com/JukkaL/mypy). I don't know whether mypy currently supports this, but it's worth trying and searching its issue tracker. (I would, but I'm home sick and can't concentrate very long.)
abarnert commentedon Dec 26, 2015
This is the same problem as
Iterablebeing defined as "has__iter__" instead of "has__iter__or implements the old-style sequence protocol". As far as I can tell, the only reasonIterablepasses such types today is that they're all registered withcollections.abc.Sequence, which is a subclass ofcollections.abc.Iterable, andtyping.Iterablehasextra=collections.abc.Iterableattached and defers to the ABC to do the check. (I'm not sure if/how #136 will affect that.) So the obvious way to fix this problem seems to be doing the equivalent thing that makesIterablework:collections.abc.Reversible, which is a subtype ofIterable, and has a__subclasshook__that checks for__reversed__.collections.abc.Sequenceto be a subtype ofReversibleinstead ofIterable, so that everything registered as aSequenceorMutableSequenceis now Reversible as well as Iterable as far as the ABCs are concerned.typing.Reversibleto addextra=collections.abc.Reversible.Reversiblebased on the old-style sequence protocol despite not beingSequences could callcollections.abc.Reversible.register.Alternatively, is
Reversibleeven useful in practice? If the only thing it's used for is as a type hint forreverse, and it doesn't get that right, and can't get that right without adding a lot of complexity, maybe it just shouldn't be there.gvanrossum commentedon Dec 26, 2015
The type checker (e.g. mypy) is independent from the issubclass()
implementation in typing.py. As I wrote in a different thread we shouldn't
even have the latter, per decree from the BDFL-delegate for PEP 484. AFAICT
mypy does the right thing for Reversible and those builtin types.
gvanrossum commentedon Dec 26, 2015
IOW Reversible does get things right in practice (in the type checker).
FWIW, maybe we should try to deprecate supporting iteration using the old-style protocol? It's really a very old backwards compatibility measure (from when iterators were first introduced). Then eventually we could do the same for reversing using the old-style protocol.
abarnert commentedon Dec 27, 2015
The last time deprecating the old-style protocol came up, Stephen d'Aprano strongly objected (http://article.gmane.org/gmane.comp.python.ideas/23369/match=old+sequence+protocol), citing an earlier objection by Raymond Hettinger (which I don't have a link for).
gvanrossum commentedon Dec 27, 2015
On Sat, Dec 26, 2015 at 6:24 PM, Andrew Barnert notifications@github.com
wrote:
--Guido van Rossum (python.org/~guido)
serhiy-storchaka commentedon Mar 5, 2017
The issue is fixed for
tuple,str,bytesandbytearray. But theissubclass()check still doesn't work forarray.arrayand sampleCounterclass.ilevkivskyi commentedon Mar 5, 2017
@serhiy-storchaka Yes, I also noticed this some time ago. But now
typing.Reversiblejust defers all checks tocollections.abc.Reversible, so that if we fix the latter, then this will be automatically fixed.srittau commentedon Nov 4, 2021
If this is still an issue, it should be reported to bpo.