def sanitize_axis(shape, axis):
    """
    Checks conformity of an axis with respect to a given shape. The axis will be converted to its positive equivalent
    and is checked to be within bounds

    Parameters
    ----------
    shape : tuple of ints
        shape of an array
    axis : ints or tuple of ints
        the axis to be sanitized

    Returns
    -------
    sane_axis : int or tuple of ints
        the sane axis

    Raises
    -------
    ValueError
        if the axis cannot be sanitized, i.e. out of bounds.
    TypeError
        if the the axis is not integral.

    Examples
    -------
    >>> sanitize_axis((5,4,4),1)
    1

    >>> sanitize_axis((5,4,4),-1)
    2

    >>> sanitize_axis((5, 4), (1,))
    (1,)

    >>> sanitize_axis((5, 4), 1.0)
    TypeError
    """
    # scalars are handled like unsplit matrices
    if len(shape) == 0:
        axis = None

    if axis is not None:
        if not isinstance(axis, int) and not isinstance(axis, tuple):
            raise TypeError("axis must be None or int or tuple, but was {}".format(type(axis)))
    if isinstance(axis, tuple):
        axis = tuple(dim + len(shape) if dim < 0 else dim for dim in axis)
        for dim in axis:
            if dim < 0 or dim >= len(shape):
                raise ValueError("axis {} is out of bounds for shape {}".format(axis, shape))
        return axis

    if axis is None or 0 <= axis < len(shape):
        return axis
    elif axis < 0:
        axis += len(shape)

    if axis < 0 or axis >= len(shape):
        raise ValueError("axis {} is out of bounds for shape {}".format(axis, shape))

    return axis