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.

classification
Title: Get virtual subclasses of an ABC
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, pitrou, rhettinger, stutzbach
Priority: normal Keywords: patch

Created on 2013-08-14 13:13 by christian.heimes, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
virtual_subclasses.patch christian.heimes, 2013-08-14 13:13 review
Messages (8)
msg195150 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2013-08-14 13:13
ABCs are missing one important introspection feature. They have no API to get registered virtual subclasses. The patch implements a new method get_virtual_subclasses(recurse=False).

ABC.get_virtual_subclasses() returns the direct virtual subclasses of an ABC. ABC.get_virtual_subclasses(recuse=True) also takes subclasses of the ABC as well as subclasses of registered virtual classes into account.

Example:
>>> import numbers
>>> numbers.Number.get_virtual_subclasses()
set()
>>> numbers.Number.get_virtual_subclasses(True)
{<class 'float'>, <class 'bool'>, <class 'int'>, <class 'complex'>}
>>> numbers.Integral.get_virtual_subclasses()
{<class 'int'>}
>>> numbers.Integral.get_virtual_subclasses(True)
{<class 'int'>, <class 'bool'>}
msg195151 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-08-14 13:17
I'm not sure "recurse" is a relevant distinction here. A subclass of a subclass is still a subclass. "Virtual" subclasses should not be different.

At the very least, if "recurse" is kept, I would expect it to be True by default.
msg195152 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-08-14 13:22
Another problem is what happens when an implementation uses non-"virtual" inheritance:

>>> issubclass(collections.UserDict, collections.abc.Mapping)
True
>>> collections.UserDict in collections.abc.Mapping.get_virtual_subclasses(True)
False

IOW, I think this get_virtual_subclasses() proposal is too low-level to be commonly useful, since it depends on implementation details (whether subclassing is direct or not, whether registering is implicit or explicit).
msg195155 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2013-08-14 13:39
It's called get_VIRTUAL_subclasses() for a reason. You can get the real subclasses of an ABC with standard tool, e.g. recurse into __subclasses__(). For virtual subclasses you have to deal with the internals like _abc_registry. I could implement all four cases: recurse True/False, only virtual True/False. But I prefer not to do so.
msg195158 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-08-14 13:47
> It's called get_VIRTUAL_subclasses() for a reason. You can get the
> real subclasses of an ABC with standard tool, e.g. recurse into
> __subclasses__().

What use case are you trying to solve? If I want to find out all classes
which implement an ABC, I don't care whether they implement it "virtually"
or not. OTOH, I do care that the results are stable and reliable, i.e.
that they don't change when someone changes from virtual inheritance to
real inheritance as an implementation detail.

For comparison, issubclass() doesn't make a difference between real and
virtual subclasses, or direct and recursive.

> For virtual subclasses you have to deal with the
> internals like _abc_registry. I could implement all four cases:
> recurse True/False, only virtual True/False.

I don't care about all four cases. What I'm saying is that only
"recurse=True, only virtual=False" makes sense from an user's POV.
msg195182 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2013-08-14 15:47
I like to do something similar to marker interfaces [1] with ABCs. For introspection and documentation I need a way to get all non-abstract classes that are implemented by an ABC.

How about I change the implementation to get_subclasses(direct=False) to return all virtual and real subclasses of an ABC? I can filter out abstract types with inspect.isabstract() later.

[1] http://www.muthukadan.net/docs/zca.html#marker-interfaces
msg195183 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-08-14 15:54
> I like to do something similar to marker interfaces [1] with ABCs.
> For introspection and documentation I need a way to get all
> non-abstract classes that are implemented by an ABC.

You mean that implement an ABC? But you also need to return real
subclasses that implement the ABC (e.g. UserDict in the example above).

> How about I change the implementation to get_subclasses(direct=False)
> to return all virtual and real subclasses of an ABC? I can filter
> out abstract types with inspect.isabstract() later.

Sounds ok.
msg404485 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2021-10-20 16:11
My feature request has been around for 8 years without any progress. I don't even recall why I needed the feature in the first place.
History
Date User Action Args
2022-04-11 14:57:49adminsetgithub: 62937
2021-10-20 16:11:45christian.heimessetstatus: open -> closed
resolution: rejected
messages: + msg404485

stage: patch review -> resolved
2013-08-14 15:54:55pitrousetmessages: + msg195183
2013-08-14 15:47:17christian.heimessetmessages: + msg195182
2013-08-14 13:47:15pitrousetmessages: + msg195158
2013-08-14 13:39:49christian.heimessetmessages: + msg195155
2013-08-14 13:22:36pitrousetmessages: + msg195152
2013-08-14 13:17:31pitrousetnosy: + pitrou
messages: + msg195151
2013-08-14 13:13:13christian.heimescreate