"""mixin module
"""
def add_mixin(cls, mixin, force=False):
"""Add the public attributes of a mixin to another class.
Attribute name collisions result in a TypeError if force is False.
If a mixin is an ABC, the decorated class is registered to it,
indicating that the class implements the mixin's interface.
"""
for name, value in mixin.__dict__.items():
if name.startswith("_"):
continue
if not force and hasattr(cls, name):
raise TypeError("name collision ({})".format(name))
setattr(cls, name, value)
try:
mixin.register(cls)
except AttributeError:
pass
def mixes_in(*mixins, force=False):
"""A class decorator factory that adds mixins using add_mixin.
"""
def decorator(cls):
for mixin in mixins:
add_mixin(cls, mixin, force)
return cls
return decorator