See, this discuss thread for context. Based on CPython abc.py
and _py_abc.py
at commit 2b379968
.
If the only reason why we can't implement
ABC
without metaclasses is because it's needed for virtual inheritance, then why don't we start by separating virtual inheritance and abstract method support.It's not immediately clear to me, why was virtual inheritance bundled together with abstract classes in the first place. The motivating examples for adding virtual inheritance in PEP-3119 seem to me like they should be represented by
Protocol
s rather than Abstract classes. So, it might just be historical happenstance thatABC
includes virtual inheritance support rather than an intentional design decision.So here is my proposal:
Extract just the virtual inheritance parts of
ABCMeta
into a new meta classVirtualMeta
. Also provide a helperVirtual
class similar to theABC
helper forABCMeta
.Extract just the abstract class parts of
ABCMeta
(without virtual inheritance support) into a new normal classAbstract
(implemented using__init_subclass__
).Re-implement
ABCMeta
andABC
in terms ofAbstract
,Virtual
andVirtualMeta
classes, keeping the current behaviour. The new inheritance hierarchy will be an extension of the old hierarchy, so every existing piece of code should continue working.(optional) Emit deprecation warnings whenever someone imports
ABC
orABCMeta
, suggesting that they should useAbstract
/Virtual
/VritualMeta
directly instead.With these changes, we would have the following:
Abstract
- a normal class that implements just the abstract base class functionality ofABC
(i.e. setting__abstractmethods__
). It doesn't use metaclasses. Most people that don't need virtual inheritance can just replaceABC
withAbstract
.
VirtualMeta
andVirtual
implement just the virtual inheritance part ofABC
(i.e.register
,isinstance
andissubclass
). As a bonus, people can now create non-abstract virtual inheritance hierarchies.
ABCMeta
inherits fromVirtualMeta
and automatically addsAbstract
andVirtual
as base classes in its__new__
method.ABC
is still just a helper class that doesmetaclass=ABCMeta
.
Keep in mind, that the current implementation:
-
Is written in pure Python. (The C
_warning
extension loading is disabled) -
Is not exhaustively tested or documented. (There are a few tests and some short docstrings, but it's probably not enough)
-
If we choose to deprecate
ABC
andABCMeta
, we'd need to also update all of the internal uses ofABC
/ABCMeta
in the standard library, typeshed etc.
You can run the provided tests with ./run_tests.sh
or ./run_tests_in_docker.sh
.