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.

Title: Cannot extend collections ABCs with protocol
Type: behavior Stage: resolved
Components: Documentation Versions: Python 3.11, Python 3.10
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: JelleZijlstra, anuppari, docs@python, gvanrossum, kj, miss-islington, pablogsal, rhettinger
Priority: normal Keywords: patch

Created on 2021-08-27 01:29 by anuppari, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 28218 merged rhettinger, 2021-09-07 17:26
PR 28266 merged miss-islington, 2021-09-10 02:52
Messages (8)
msg400387 - (view) Author: Anup Parikh (anuppari) Date: 2021-08-27 01:29
Since the container ABCs are normal classes, and Protocol cannot subclass normal classes, there's no way to create a protocol that extends the ABCs without explicitly listing out all the methods needed for the collection. e.g., can't do this:

from typing import Iterable, Protocol

class IterableWithMethod(Iterable, Protocol):
    def method(self) -> None: pass

Since the ABCs don't provide any default implementations (I think?), maybe they should just be defined as runtime checkable protocols instead of ABCs?
msg400465 - (view) Author: Ken Jin (kj) * (Python committer) Date: 2021-08-28 09:11
Thanks for the bug report Anup. I'm mildly confused by what you meant, so please help me here:

I interpreted your request as wanting any type that implements `method` and `__iter__` to be considered a subtype of `IterableWithMethod`. But this already works at runtime and with mypy.

Are you perhaps saying that you want issubclass(Foo, IterableWithMethod) to work?
msg400502 - (view) Author: Anup Parikh (anuppari) Date: 2021-08-28 20:35
Yeah, you got the gist of what I meant, though, I guess that was a confusing example since there are apparently protocols for Iterable. But not for many of the other collection ABCs such as Sequence, e.g., the following doesn't work:

from typing import Sequence, Protocol

class SequenceWithMethod(Sequence, Protocol):
    def method(self) -> None: pass

In which case, anything that implements `method`, `__getitem__`, `__len__`, `__contains__`, `__iter__`, `__reversed__`, `index`,  and `count` would be considered a subtype of `SequenceWithMethod`
msg400924 - (view) Author: Ken Jin (kj) * (Python committer) Date: 2021-09-02 15:28
I suspect this may be intentional. See related issues and

Copying verbatim from what Ivan said in the first issue:

The separation may look arbitrary, but the idea is quite simple. Only those classes with few methods support structural checks. Those classes have few independent abstract methods (or even just one method), while in classes with large APIs like `Sequence`, the methods are not logically independent, so you can't say a class is 100% a `Sequence` even if types/signatures of all methods are correct, because e.g. `__contains__()` and `index()` should behave in agreement with `__getitem__()`.
msg400953 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-09-02 20:36
The docs need to clarify which ABCs can satisfy isinstance() based solely on hasattr() logic and which ABCs require registration or direct subclassing.

The docs should also explain why the more complex ABCs can't reliably be recognized based on the presence of desired method names.  

One of the original motivating reasons for the ABCs was that the presence of __getitem__ was insufficient for determining whether a class was intended to be a Mapping or a Sequence.  Accordingly, those classes have to subclass from an ABC or register with the ABC in order to declare intent.
msg401547 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-09-10 02:51
New changeset 62fa613f6a6e872723505ee9d56242c31a654a9d by Raymond Hettinger in branch 'main':
bpo-45024 and bpo-23864: Document how interface testing works with the collections ABCs (GH-28218)
msg401550 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-09-10 03:58
New changeset 89edd18779e382c5fa7f57722b0b897a907ed2c4 by Miss Islington (bot) in branch '3.10':
bpo-45024 and bpo-23864: Document how interface testing works with the collections ABCs (GH-28218) (GH-28266)
msg403162 - (view) Author: Pablo Galindo Salgado (pablogsal) * (Python committer) Date: 2021-10-04 19:18
New changeset 9d8a64a7ccebb288094d4e9da66f30d2ada9a973 by Pablo Galindo (Miss Islington (bot)) in branch '3.10':
bpo-45024 and bpo-23864: Document how interface testing works with the collections ABCs (GH-28218) (GH-28266)
Date User Action Args
2022-04-11 14:59:49adminsetgithub: 89187
2021-10-04 19:18:42pablogsalsetnosy: + pablogsal
messages: + msg403162
2021-09-10 04:00:18rhettingersetstatus: open -> closed
assignee: docs@python -> rhettinger
stage: patch review -> resolved
resolution: fixed
versions: + Python 3.10, Python 3.11
2021-09-10 03:58:55rhettingersetmessages: + msg401550
2021-09-10 02:52:01miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request26686
2021-09-10 02:51:15rhettingersetmessages: + msg401547
2021-09-07 17:26:35rhettingersetkeywords: + patch
stage: patch review
pull_requests: + pull_request26643
2021-09-02 20:36:41rhettingersetnosy: + rhettinger, docs@python
messages: + msg400953

assignee: docs@python
components: + Documentation, - Library (Lib)
2021-09-02 15:28:45kjsetmessages: + msg400924
2021-08-28 20:35:26anupparisetstatus: pending -> open

messages: + msg400502
2021-08-28 09:11:01kjsetstatus: open -> pending

nosy: + gvanrossum, JelleZijlstra, kj, - lys.nikolaou, pablogsal
messages: + msg400465

components: - Parser
2021-08-27 01:29:49anupparicreate