0

I have defined my singleton metaclass as follows:

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

Then I defined another class that I want to work as an interface for my implementations:

class ClientBase(metaclass = abc.ABCMeta):
    @classmethod
    def __subclasshook__(cls, subclass):
        return (hasattr(subclass, 'logout') and
                callable(subclass.logout) or
                NotImplemented)

    @abc.abstractmethod
    def logout(self, refresh_token: str):
        """
            Logout a user from OIDC Provider.
        :param refresh_token: refresh token to invalidate
        :return:
        """
        raise NotImplementedError

Now I define one implementation of my ClientBase interface as follows:

class ClientImplementation1(ClientBase, metaclass = Singleton):
    installed: bool
    client_secret: str

    def __init__(self):
        ...

However when I start my application I get an Error on the ClassImplementation1 defintion:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Can anyone help me find a way to have singleton class that can inherit from a base abstract class?

Thanks a lot!

Pablo Estrada
  • 3,182
  • 4
  • 30
  • 74
  • Sounds like you need a common base class above "Singleton" and "abc.ABCMeta" – JacobIRR Jun 23 '22 at 16:35
  • Does this answer your question? [Triple inheritance causes metaclass conflict... Sometimes](https://stackoverflow.com/questions/6557407/triple-inheritance-causes-metaclass-conflict-sometimes) – Nathaniel Ford Jun 23 '22 at 16:37
  • 1
    Welcome to why metaclasses should not be overused: they don't compose easily. I would think hard about why you think you need a `Singleton` metaclass at all. See https://nedbatchelder.com/blog/202204/singleton_is_a_bad_idea.html. – chepner Jun 23 '22 at 16:38
  • Thanks A lot guys! really insightful links there :) – Pablo Estrada Jun 23 '22 at 16:47

1 Answers1

1

Your issue is that you are trying to subclass two separate meta-classes, Singleton and abc.ABCMeta. This latter is a transitive subclass, because you're subclassing ClientBase.

If you can get away with it, ClientBase should also subclass Singleton. See this answer.

Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102