Remove a mixin with name (and reference) from targetand returns the
        replaced one or None.

        :param mixedin: a mixedin value or the last defined mixedin if is None
            (by default).
        :param bool replace: If True (default), the removed mixedin replaces
            the current mixin.

def remove_mixin(target, name, mixedin=None, replace=True):
        """Remove a mixin with name (and reference) from targetand returns the
        replaced one or None.

        :param mixedin: a mixedin value or the last defined mixedin if is None
            (by default).
        :param bool replace: If True (default), the removed mixedin replaces
            the current mixin.
        """

        try:
            result = getattr(target, name)

        except AttributeError:
            raise Mixin.MixInError(
                "No mixin {0} exists in {1}".format(name, target)
            )

        mixedins_by_name = Mixin.get_mixedins_by_name(target)

        mixedins = mixedins_by_name.get(name)

        if mixedins:

            if mixedin is None:
                mixedin = mixedins[-1]
                mixedins = mixedins[:-2]

            else:

                try:
                    index = mixedins.index(mixedin)

                except ValueError:
                    raise Mixin.MixInError(
                        "Mixedin {0} with name {1} does not exist \
                        in target {2}"
                        .format(mixedin, name, target)
                    )

                mixedins = mixedins[0:index] + mixedins[index + 1:]

            if len(mixedins) == 0:
                # force to replace/delete the mixin even if replace is False
                # in order to stay in a consistent state
                if mixedin != Mixin.__NEW_CONTENT_KEY__:
                    setattr(target, name, mixedin)

                else:
                    delattr(target, name)

                del mixedins_by_name[name]

            else:
                if replace:
                    setattr(target, name, mixedin)

                mixedins_by_name[name] = mixedins

        else:
            # shouldn't be raised except if removing has been done
            # manually
            raise Mixin.MixInError(
                "No mixin {0} exists in {1}".format(name, target))

        # clean mixedins if no one exists
        if len(mixedins_by_name) == 0:
            delattr(target, Mixin.__MIXEDIN_KEY__)

        return result