Reduce metaclass conflicts with less eager proclamation, automatic metaclass merges

Yes absolutely. More reason to free developers from fear of using metaclasses.

By using the metaclass wrapper I posted in the Help forum, it is able to pass your test case since it calls __init_subclass__ to register the class object only after the dataclass decorator returns the new class.

As for passing on kwargs it’s certainly a problem as well, and I have to work around it by storing it in a _dataclass_kwargs attribute to pass it on:

_dataclass_keywords = set((code := dataclass.__code__).co_varnames[
    code.co_argcount:code.co_argcount + code.co_kwonlyargcount])

class DataclassMeta(type):
    def __new__(metacls, name, bases, namespace, **kwargs):
        class InitSubclassBlocker:
            def __init_subclass__(cls, **kwargs):
                pass
        dataclass_kwargs = namespace.get('_dataclass_kwargs') or {
            key: kwargs[key] for key in kwargs.keys() & _dataclass_keywords}
        configured_dataclass = dataclass(**dataclass_kwargs)
        cls = super().__new__(
            metacls, name, (InitSubclassBlocker,) + bases, namespace, **kwargs)
        if classcell := namespace.get('__classcell__'):
            cls.__classcell__ = classcell
        cls._dataclass_kwargs = dataclass_kwargs
        if 'slots' not in dataclass_kwargs or '__slots__' not in namespace:
            cls = configured_dataclass(cls)
        if hasattr(cls, '__classcell__'):
            del cls.__classcell__
        del InitSubclassBlocker.__init_subclass__
        super(cls, cls).__init_subclass__(**kwargs)
        return cls

and with the helper class Dataclass now inheriting from a base class that defines a __init_subclass__ to remove known dataclass keywords:

class DataclassBase:
    def __init_subclass__(cls, **kwargs):
        for key in kwargs.keys() & _dataclass_keywords:
            del kwargs[key]
        super().__init_subclass__(**kwargs)

@dataclass_transform()
class Dataclass(DataclassBase, metaclass=DataclassMeta):
    pass

Your test case woutld then output True:

class RegistryClass:
    registry = defaultdict(list)

    def __init_subclass__(cls, **kwargs):
        if (key := kwargs.pop('key', None)) is not None:
            cls.registry[key].append(cls)
        super().__init_subclass__(**kwargs)

class SlottedDataclass(RegistryClass, Dataclass, key="slotted", slots=True):
    a: int

print(RegistryClass.registry['slotted'][0] is SlottedDataclass) # outputs True

Demo here

And a full demo of your PlayingCards test case mixing RegistryClass, Dataclass and Enum with the proposed combine_meta here

class Card(RegistryClass, Dataclass, key="slotted", slots=True):
    value_: Literal[2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
    suite: Literal['heart', 'diamond', 'club', 'spade']

class PlayingCards(Card, Enum, metaclass=combine_meta):
    TWO_OF_HEART = 2, 'heart'
    THREE_OF_SPADES = 3, 'spade'

print(list(PlayingCards)) # outputs [<PlayingCards.TWO_OF_HEART: value_=2, suite='heart'>, <PlayingCards.THREE_OF_SPADES: value_=3, suite='spade'>]

print(PlayingCards.__slots__) # outputs ('value_', 'suite')
print(PlayingCards.registry['slotted']) # outputs [<class '__main__.Card'>]

Things should just work like putting together building blocks. :grinning: