Another ABC
implementation without metaclass
.
It is a little bit annoying to have metaclass
conflict,
especially when trying to use ABC along with other libraries.
plain-abc
provides a simple ABC
implementation without metaclass
.
pip install plain-abc
But you can also use plain-abc
to solve the problem:
from abc import abstractmethod
from plain_abc import PlainABC
class _SomeHiddenMetaclass(type):
pass
class Base(metaclass=_SomeHiddenMetaclass):
pass
class IFoo(PlainABC):
@abstractmethod
def foo(self): ...
class Foo(Base, IFoo):
def foo(self): ...
To extend an abstract class as another abstract class,
PlainABC
is required to be one of the bases:
from abc import abstractmethod
from plain_abc import PlainABC
class IEntity(PlainABC):
@abstractmethod
def get_id(self) -> str: ...
class IProjectile(IEntity, PlainABC):
@abstractmethod
def get_speed(self) -> float: ...
class Arrow(IProjectile):
def get_id(self) -> str: ...
def get_speed(self) -> float: ...
To skip signature checking,
you can add the member names in __abc_concrete_members__
of a subclass:
from abc import abstractmethod
from enum import Enum
from plain_abc import PlainABC
class IEnum(PlainABC):
@property
@abstractmethod
def foo(self) -> str:
...
class Foo(IEnum, Enum):
# for python 3.10 or lower
__abc_concrete_members__ = ('foo',)
foo = 'foo'
assert Foo.foo.value == 'foo'
Here is an example of metaclass
conflict
and how to mix ABCMeta
with other metaclass
es.
from abc import ABC, ABCMeta, abstractmethod
class _SomeHiddenMetaclass(type):
...
class Base(metaclass=_SomeHiddenMetaclass):
...
class IFoo(ABC):
@abstractmethod
def foo(self): ...
# oh no, metaclass conflict!
# class Foo(Base, IFoo):
# def foo(self): ...
# create a new metaclass to solve the conflict
class NewMetaclass(_SomeHiddenMetaclass, ABCMeta):
...
class Foo(Base, IFoo, metaclass=NewMetaclass):
def foo(self): ...