Convert valid colormap specifications to a list of colors.

def process_cmap(cmap, ncolors=None, provider=None, categorical=False):
    """
    Convert valid colormap specifications to a list of colors.
    """
    providers_checked="matplotlib, bokeh, or colorcet" if provider is None else provider

    if isinstance(cmap, Cycle):
        palette = [rgb2hex(c) if isinstance(c, tuple) else c for c in cmap.values]
    elif isinstance(cmap, list):
        palette = cmap
    elif isinstance(cmap, basestring):
        mpl_cmaps = _list_cmaps('matplotlib')
        bk_cmaps = _list_cmaps('bokeh')
        cet_cmaps = _list_cmaps('colorcet')
        if provider=='matplotlib' or (provider is None and (cmap in mpl_cmaps or cmap.lower() in mpl_cmaps)):
            palette = mplcmap_to_palette(cmap, ncolors, categorical)
        elif provider=='bokeh' or (provider is None and (cmap in bk_cmaps or cmap.capitalize() in bk_cmaps)):
            palette = bokeh_palette_to_palette(cmap, ncolors, categorical)
        elif provider=='colorcet' or (provider is None and cmap in cet_cmaps):
            from colorcet import palette
            if cmap.endswith('_r'):
                palette = list(reversed(palette[cmap[:-2]]))
            else:
                palette = palette[cmap]
        else:
            raise ValueError("Supplied cmap %s not found among %s colormaps." %
                             (cmap,providers_checked))
    else:
        try:
            # Try processing as matplotlib colormap
            palette = mplcmap_to_palette(cmap, ncolors)
        except:
            palette = None
    if not isinstance(palette, list):
        raise TypeError("cmap argument %s expects a list, Cycle or valid %s colormap or palette."
                        % (cmap,providers_checked))
    if ncolors and len(palette) != ncolors:
        return [palette[i%len(palette)] for i in range(ncolors)]
    return palette