Meta-class to allow inspection of all __slots__of a class If classes provide __slots__ and at the same time inherit from another class also providing __slots__, there is no straightforward way to access and list each and every slot of the class. Especially when you consider chaining of inheritance.

I've written this meta-class that adds the __all_slots__ property, listing all unique slots:

class MetaSlotMachine(type):
    """Meta-class that adds the attribute `__all_slots__` to a class.

    `__all_slots__`  is a set that contains all unique slots of a class,
    including the ones that are inherited from parents.

    """
    def __init__(cls, name, bases, dictionary):
        super(MetaSlotMachine, cls).__init__(name, bases, dictionary)
        slots_iterator = (getattr(c, '__slots__', ()) for c in cls.__mro__)
        # `__slots__` might only be a single string, 
        # so we need to put the strings into a tuple.
        # `basestring` becomes just `str` in Python 3
        slots_converted = ((slots,) if isinstance(slots, basestring) else slots 
                                    for slots in slots_iterator)
        cls.__all_slots__ = set()
        cls.__all_slots__.update(*slots_converted)


Let's consider classes that inherit slots, like the following:

class HasSlots1(object):
    __metaclass__ = MetaSlotMachine   # Python 2 Syntax
    __slots__ = ['x', 'y']

class HasSlots2(HasSlots1):
    __slots__ = 'zz'

class HasSlots3(HasSlots2):
    __slots__ = ()


If we create and instance via

myslots = HasSlots3()


and ask for

myslots.__slots__


Python will return the empty tuple:

 ()


However, now we can get hold of all slots via

myslots.__all_slots__


which returns all inherited slots:

{'y', 'x', 'zz'}


Is there anything flawed with the design of the meta-class? What about listing all slots based on the __mro__ in _get_all_slots function?



EDIT: Revised version with gathering slots within the init function. Moreover, special care is taken about __slots__ that only consist of a single string, like __slots__ = '__weakref__'.
This is a clever use of metaclasses - in a good way. The only thing I would change is to use set().union over update (this is debatable).