# Buggy code
def reduce(
    self, func, dim=None, axis=None, keep_attrs=None, allow_lazy=False, **kwargs
):
    """Reduce this array by applying `func` along some dimension(s).

    Parameters
    ----------
    func : function
        Function which can be called in the form
        `func(x, axis=axis, **kwargs)` to return the result of reducing an
        np.ndarray over an integer valued axis.
    dim : str or sequence of str, optional
        Dimension(s) over which to apply `func`.
    axis : int or sequence of int, optional
        Axis(es) over which to apply `func`. Only one of the 'dim'
        and 'axis' arguments can be supplied. If neither are supplied, then
        the reduction is calculated over the flattened array (by calling
        `func(x)` without an axis argument).
    keep_attrs : bool, optional
        If True, the variable's attributes (`attrs`) will be copied from
        the original object to the new one.  If False (default), the new
        object will be returned without attributes.
    **kwargs : dict
        Additional keyword arguments passed on to `func`.

    Returns
    -------
    reduced : Array
        Array with summarized data and the indicated dimension(s)
        removed.
    """
    if dim is common.ALL_DIMS:
        dim = None
    if dim is not None and axis is not None:
        raise ValueError("cannot supply both 'axis' and 'dim' arguments")

    if dim is not None:
        axis = self.get_axis_num(dim)
    data = func(self.data if allow_lazy else self.values, axis=axis, **kwargs)

    if getattr(data, "shape", ()) == self.shape:
        dims = self.dims
    else:
        removed_axes = (
            range(self.ndim) if axis is None else np.atleast_1d(axis) % self.ndim
        )
        dims = [adim for n, adim in enumerate(self.dims) if n not in removed_axes]

    if keep_attrs is None:
        keep_attrs = _get_keep_attrs(default=False)
    attrs = self._attrs if keep_attrs else None

    return Variable(dims, data, attrs=attrs)


# Traceback (TypeError)
Traceback (most recent call last):
File "mwe.py", line 9, in <module>
sum = da.reduce(total_sum)
File "/home/tegn500/Documents/Work/Code/xarray/xarray/core/dataarray.py", line 1605, in reduce
var = self.variable.reduce(func, dim, axis, keep_attrs, **kwargs)
File "/home/tegn500/Documents/Work/Code/xarray/xarray/core/variable.py", line 1365, in reduce
axis=axis, **kwargs)
TypeError: total_sum() got an unexpected keyword argument 'axis'

# Fixed code
def reduce(
    self, func, dim=None, axis=None, keep_attrs=None, allow_lazy=False, **kwargs
):
    """Reduce this array by applying `func` along some dimension(s).

    Parameters
    ----------
    func : function
        Function which can be called in the form
        `func(x, axis=axis, **kwargs)` to return the result of reducing an
        np.ndarray over an integer valued axis.
    dim : str or sequence of str, optional
        Dimension(s) over which to apply `func`.
    axis : int or sequence of int, optional
        Axis(es) over which to apply `func`. Only one of the 'dim'
        and 'axis' arguments can be supplied. If neither are supplied, then
        the reduction is calculated over the flattened array (by calling
        `func(x)` without an axis argument).
    keep_attrs : bool, optional
        If True, the variable's attributes (`attrs`) will be copied from
        the original object to the new one.  If False (default), the new
        object will be returned without attributes.
    **kwargs : dict
        Additional keyword arguments passed on to `func`.

    Returns
    -------
    reduced : Array
        Array with summarized data and the indicated dimension(s)
        removed.
    """
    if dim is common.ALL_DIMS:
        dim = None
    if dim is not None and axis is not None:
        raise ValueError("cannot supply both 'axis' and 'dim' arguments")

    if dim is not None:
        axis = self.get_axis_num(dim)
    input_data = self.data if allow_lazy else self.values
    if axis is not None:
        data = func(input_data, axis=axis, **kwargs)
    else:
        data = func(input_data, **kwargs)

    if getattr(data, "shape", ()) == self.shape:
        dims = self.dims
    else:
        removed_axes = (
            range(self.ndim) if axis is None else np.atleast_1d(axis) % self.ndim
        )
        dims = [adim for n, adim in enumerate(self.dims) if n not in removed_axes]

    if keep_attrs is None:
        keep_attrs = _get_keep_attrs(default=False)
    attrs = self._attrs if keep_attrs else None

    return Variable(dims, data, attrs=attrs)