def slice_to_range(sl: slice, n):
    """
    Turn a slice into a range
    :param sl: slice object
    :param n: total number of items
    :return: range object, if the slice is not supported an exception is raised
    """
    if sl.start is None and sl.step is None and sl.start is None:  # (:)
        return range(n)

    elif sl.start is not None and sl.step is None and sl.start is None:  # (a:)
        return range(sl.start, n)

    elif sl.start is not None and sl.step is not None and sl.start is None:  # (?)
        raise Exception('Invalid slice')
    elif sl.start is not None and sl.step is None and sl.start is not None:  # (a:b)
        return range(sl.start, sl.stop)

    elif sl.start is not None and sl.step is not None and sl.start is not None:  # (a:s:b)
        return range(sl.start, sl.stop, sl.step)

    elif sl.start is None and sl.step is None and sl.start is not None:  # (:b)
        return range(sl.stop)

    else:
        raise Exception('Invalid slice')