Mixin a routine into the target.

        :param routine: routine to mix in target.
        :param str name: mixin name. Routine name by default.
        :param bool isbound: If True (False by default), the mixin result is a
            bound method to target.

def mixin_function_or_method(target, routine, name=None, isbound=False):
        """Mixin a routine into the target.

        :param routine: routine to mix in target.
        :param str name: mixin name. Routine name by default.
        :param bool isbound: If True (False by default), the mixin result is a
            bound method to target.
        """

        function = None

        if isfunction(routine):
            function = routine

        elif ismethod(routine):
            function = get_method_function(routine)

        else:
            raise Mixin.MixInError(
                "{0} must be a function or a method.".format(routine))

        if name is None:
            name = routine.__name__

        if not isclass(target) or isbound:
            _type = type(target)
            method_args = [function, target]

            if PY2:
                method_args += _type

            result = MethodType(*method_args)

        else:

            if PY2:
                result = MethodType(function, None, target)

            else:
                result = function

        Mixin.set_mixin(target, result, name)

        return result