Return a color palette object with color definition and handling.

    Calling this function with ``palette=None`` will return the current
    matplotlib color cycle.

    This function can also be used in a ``with`` statement to temporarily
    set the color cycle for a plot or set of plots.

    Parameters
    ----------

    palette : None or str or sequence
        Name of a palette or ``None`` to return the current palette. If a
        sequence the input colors are used but possibly cycled.

        Available palette names from :py:mod:`yellowbrick.colors.palettes` are:

        .. hlist::
            :columns: 3

            * :py:const:`accent`
            * :py:const:`dark`
            * :py:const:`paired`
            * :py:const:`pastel`
            * :py:const:`bold`
            * :py:const:`muted`
            * :py:const:`colorblind`
            * :py:const:`sns_colorblind`
            * :py:const:`sns_deep`
            * :py:const:`sns_muted`
            * :py:const:`sns_pastel`
            * :py:const:`sns_bright`
            * :py:const:`sns_dark`
            * :py:const:`flatui`
            * :py:const:`neural_paint`

    n_colors : None or int
        Number of colors in the palette. If ``None``, the default will depend
        on how ``palette`` is specified. Named palettes default to 6 colors
        which allow the use of the names "bgrmyck", though others do have more
        or less colors; therefore reducing the size of the list can only be
        done by specifying this parameter. Asking for more colors than exist
        in the palette will cause it to cycle.

    Returns
    -------
    list(tuple)
        Returns a ColorPalette object, which behaves like a list, but can be
        used as a context manager and possesses functions to convert colors.

    .. seealso::

        :func:`.set_palette`
            Set the default color cycle for all plots.
        :func:`.set_color_codes`
            Reassign color codes like ``"b"``, ``"g"``, etc. to
            colors from one of the yellowbrick palettes.
        :func:`..colors.resolve_colors`
            Resolve a color map or listed sequence of colors.

def color_palette(palette=None, n_colors=None):
    """
    Return a color palette object with color definition and handling.

    Calling this function with ``palette=None`` will return the current
    matplotlib color cycle.

    This function can also be used in a ``with`` statement to temporarily
    set the color cycle for a plot or set of plots.

    Parameters
    ----------

    palette : None or str or sequence
        Name of a palette or ``None`` to return the current palette. If a
        sequence the input colors are used but possibly cycled.

        Available palette names from :py:mod:`yellowbrick.colors.palettes` are:

        .. hlist::
            :columns: 3

            * :py:const:`accent`
            * :py:const:`dark`
            * :py:const:`paired`
            * :py:const:`pastel`
            * :py:const:`bold`
            * :py:const:`muted`
            * :py:const:`colorblind`
            * :py:const:`sns_colorblind`
            * :py:const:`sns_deep`
            * :py:const:`sns_muted`
            * :py:const:`sns_pastel`
            * :py:const:`sns_bright`
            * :py:const:`sns_dark`
            * :py:const:`flatui`
            * :py:const:`neural_paint`

    n_colors : None or int
        Number of colors in the palette. If ``None``, the default will depend
        on how ``palette`` is specified. Named palettes default to 6 colors
        which allow the use of the names "bgrmyck", though others do have more
        or less colors; therefore reducing the size of the list can only be
        done by specifying this parameter. Asking for more colors than exist
        in the palette will cause it to cycle.

    Returns
    -------
    list(tuple)
        Returns a ColorPalette object, which behaves like a list, but can be
        used as a context manager and possesses functions to convert colors.

    .. seealso::

        :func:`.set_palette`
            Set the default color cycle for all plots.
        :func:`.set_color_codes`
            Reassign color codes like ``"b"``, ``"g"``, etc. to
            colors from one of the yellowbrick palettes.
        :func:`..colors.resolve_colors`
            Resolve a color map or listed sequence of colors.

    """
    if palette is None:
        palette = get_color_cycle()
        if n_colors is None:
            n_colors = len(palette)

    elif not isinstance(palette, str):
        if n_colors is None:
            n_colors = len(palette)

    else:
        if palette.lower() not in PALETTES:
            raise YellowbrickValueError(
                "'{}' is not a recognized palette!".format(palette)
            )

        palette = PALETTES[palette.lower()]
        if n_colors is None:
            n_colors = len(palette)

    # Always return as many colors as we asked for
    pal_cycle = cycle(palette)
    palette = [next(pal_cycle) for _ in range(n_colors)]

    # Always return in RGB tuple format
    try:
        palette = map(mpl.colors.colorConverter.to_rgb, palette)
        palette = ColorPalette(palette)
    except ValueError:
        raise YellowbrickValueError(
            "Could not generate a palette for %s" % str(palette)
        )

    return palette