@classmethod
def _propagate_attributes(mcs, bases, attrs, clsname):
    """
        For attributes specified by to_propagate, their values will be a union of
        that specified for cls and its bases (cls values overriding those of bases
        in case of conflicts).

        """
    for prop_attr, attr_cls, attr_collector_cls in mcs.to_propagate:
        should_propagate = False
        propagated = attr_collector_cls(attr_cls)
        for base in bases:
            if hasattr(base, prop_attr):
                propagated += getattr(base, prop_attr) or []
                should_propagate = True
        if prop_attr in attrs:
            pattrs = attrs[prop_attr] or []
            for pa in pattrs:
                if not isinstance(pa, attr_cls):
                    msg = 'Invalid value "{}" for attribute "{}"; must be a {}'
                    raise ValueError(msg.format(pa, prop_attr, attr_cls))
                pa._owner = clsname
            propagated += pattrs
            should_propagate = True
        if should_propagate:
            for p in propagated:
                override = bool(getattr(p, 'override', None))
                overridden = bool(getattr(p, '_overridden', None))
                if override != overridden:
                    msg = "Overriding non existing parameter '{}' inside '{}'"
                    raise ValueError(msg.format(p.name, p._owner))
            attrs[prop_attr] = propagated
