Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve palettes docs and docs automation #5619

Merged
merged 2 commits into from Dec 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2,179 changes: 880 additions & 1,299 deletions bokeh/palettes.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bokeh/sphinxext/_templates/enum_detail.rst
@@ -1,6 +1,7 @@
.. data:: {{ name }}
:module: {{ module }}
:annotation: = {{ shortrepr }}
{% if noindex %}:noindex:{% endif %}

{% for line in content %}
{{ line }}
Expand Down
24 changes: 5 additions & 19 deletions bokeh/sphinxext/_templates/palette_detail.html
@@ -1,19 +1,5 @@
<div class="col-md-4" style="min-height: 230px;">
<table>
<tr>
<th colspan="2"> {{ name }} </th>
</tr>

{% for number in numbers %}
<tr>

<td height='20px' width='30px'> {{ number }} </td>

{% for color in palette[number] %}
<td height="20px" width="20px" style="background-color: {{ color }};"/>
{% endfor %}

</tr>
{% endfor %}
</table>
</div>
<span style="line-height: 0; display: inline-block; border: 1px solid black;">
{%- for color in palette -%}
<span style="width: {{ width }}px; height: 20px; background-color: {{ color }}; display: inline-block;"></span>
{%- endfor -%}
</span>
19 changes: 19 additions & 0 deletions bokeh/sphinxext/_templates/palette_group_detail.html
@@ -0,0 +1,19 @@
<div class="row-eq-height col-md-6" style="min-height: 300px;">
<table>
<tr>
<th colspan="8"> <h2>{{ name }}</h2> </th>
</tr>

{% for number in numbers %}
<tr>

<td height='20px' width='30px'> {{ number }} </td>

{% for color in palettes[number] %}
<td height="20px" width="20px" style="background-color: {{ color }};border: #444444 thin solid;"/>
{% endfor %}

</tr>
{% endfor %}
</table>
</div>
4 changes: 3 additions & 1 deletion bokeh/sphinxext/bokeh_enum.py
Expand Up @@ -45,7 +45,8 @@ class BokehEnumDirective(BokehDirective):
optional_arguments = 2

option_spec = {
'module': unchanged
'module': unchanged,
'noindex': lambda x: True, # directives.flag weirdly returns None
}

def run(self):
Expand All @@ -70,6 +71,7 @@ def run(self):
rst_text = ENUM_DETAIL.render(
name=name,
module=self.options['module'],
noindex=self.options.get('noindex', False),
content=self.content,
shortrepr=shortrepr,
fullrepr=fullrepr,
Expand Down
107 changes: 69 additions & 38 deletions bokeh/sphinxext/bokeh_palette.py
@@ -1,55 +1,86 @@
""" Generate color representations of all known Bokeh palettes.
''' Generate an inline visual representations of a single color palette.

This directive takes no arguments.
The ``:bokeh-palette:`` role can be used with by providing any of the
following:

"""
from __future__ import absolute_import
* a palette name from ``bokeh.palettes``, e.g. ``Spectral9``

from docutils import nodes
* a palette function from ``bokeh.palettes`` called with argument, e.g. ``viridis(12)``

from sphinx.util.compat import Directive
* An explicit list of colors: ``['#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff']``

from ..palettes import small_palettes
from .templates import PALETTE_DETAIL
The following usage of the the directive:

.. code-block:: rest

* by name: :bokeh-palette:`Spectral9`

* by function: :bokeh-palette:`viridis(12)`

* by list: :bokeh-palette:`['#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff']`

Generates the output:

* by name: :bokeh-palette:`Spectral9`

* by function: :bokeh-palette:`viridis(12)`

CSS = """
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
"""
* by list: :bokeh-palette:`['#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff']`

JS = """
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
"""
Palette swatches are 20 pixels in height. For palettes short than 20 colors,
the default width for the swatches is 20 pixels. If larger palettes are given,
the width of the HTML spans is progressively reduced, down to a minimum of one
pixel. For instance displaying the full Viridis palette with the expression

.. code-block:: rest

class bokeh_palette(nodes.General, nodes.Element):
pass
:bokeh-palette:`viridis(256)`

Will generate the output:

class BokehPaletteDirective(Directive):
:bokeh-palette:`viridis(256)`

has_content = False
required_arguments = 1
'''
from __future__ import absolute_import

from docutils import nodes
from sphinx.errors import SphinxError

from .templates import PALETTE_DETAIL

def run(self):
node = bokeh_palette()
node['module'] = self.arguments[0]
return [node]
_globals = {}
exec("from bokeh.palettes import *", _globals)

def html_visit_bokeh_palette(self, node):
names = sorted(small_palettes)
self.body.append(CSS)
self.body.append('<div class="container-fluid"><div class="row">"')
for name in names:
palette = small_palettes[name]
numbers = sorted(palette)
def bokeh_palette(name, rawtext, text, lineno, inliner, options=None, content=None):
''' Generate an inline visual representations of a single color palette.

html = PALETTE_DETAIL.render(name=name, numbers=numbers, palette=palette)
self.body.append(html)
self.body.append('</div></div>')
self.body.append(JS)
raise nodes.SkipNode
This function evaluates the expression ``"palette = %s" % text``, in the
context of a ``globals`` namespace that has previously imported all of
``bokeh.plotting``. The resulting value for ``palette`` is used to
construct a sequence of HTML ``<span>`` elements for each color.

If evaluating the palette expression fails or does not produce a list or
tuple of all strings, then a SphinxError is raised to terminate the build.

For details on the arguments to this function, consult the Docutils docs:

http://docutils.sourceforge.net/docs/howto/rst-roles.html#define-the-role-function

'''
try:
exec("palette = %s" % text, _globals)
except Exception as e:
raise SphinxError("cannot evaluate palette expression '%r', reason: %s" % (text, e))
p = _globals.get('palette', None)
if not isinstance(p, (list, tuple)) or not all(isinstance(x, str) for x in p):
raise SphinxError("palette expression '%r' generated invalid or no output: %s" % (text, p))
w = 20 if len(p) < 15 else 10 if len(p) < 32 else 5 if len(p) < 64 else 2 if len(p) < 128 else 1
html = PALETTE_DETAIL.render(palette=p, width=w)
node = nodes.raw('', html, format="html")
return [node], []

def setup(app):
app.add_node(bokeh_palette, html=(html_visit_bokeh_palette, None))
app.add_directive('bokeh-palette', BokehPaletteDirective)
''' Required setup function for Sphinx extensions.

'''
app.add_role('bokeh-palette', bokeh_palette)
72 changes: 72 additions & 0 deletions bokeh/sphinxext/bokeh_palette_group.py
@@ -0,0 +1,72 @@
""" Generate visual representations of palettes in Bokeh palette groups.

The ``bokeh.palettes`` modules expose attributes such as ``mpl``, ``brewer``,
and ``d3`` that provide groups of palettes. The ``bokeh-palette-group``
directive accepts the name of one of these groups, and generates a visual
matrix of colors for every palette in the group.

As an example, the following usage of the the directive:

.. code-block:: rest

.. bokeh-palette-group:: mpl

Generates the output:

.. bokeh-palette-group:: mpl

"""
from __future__ import absolute_import

from docutils import nodes

from sphinx.errors import SphinxError
from sphinx.util.compat import Directive

from .. import palettes as bp
from .templates import PALETTE_GROUP_DETAIL

CSS = """
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
"""

JS = """
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
"""


class bokeh_palette_group(nodes.General, nodes.Element):
pass


class BokehPaletteGroupDirective(Directive):

has_content = False
required_arguments = 1

def run(self):
node = bokeh_palette_group()
node['group'] = self.arguments[0]
return [node]

def html_visit_bokeh_palette_group(self, node):
self.body.append(CSS)
self.body.append('<div class="container-fluid"><div class="row">"')
group = getattr(bp, node['group'], None)
if not isinstance(group, dict):
raise SphinxError("invalid palette group name %r" % node['group'])
names = sorted(group)
for name in names:
palettes = group[name]
# arbitrary cuttoff here, idea is to not show large (e.g 256 length) palettes
numbers = [x for x in sorted(palettes) if x < 30]
html = PALETTE_GROUP_DETAIL.render(name=name, numbers=numbers, palettes=palettes)
self.body.append(html)
self.body.append('</div></div>')
self.body.append(JS)
raise nodes.SkipNode

def setup(app):
app.add_node(bokeh_palette_group, html=(html_visit_bokeh_palette_group, None))
app.add_directive('bokeh-palette-group', BokehPaletteGroupDirective)
2 changes: 2 additions & 0 deletions bokeh/sphinxext/templates.py
Expand Up @@ -19,6 +19,8 @@

PALETTE_DETAIL = _env.get_template("palette_detail.html")

PALETTE_GROUP_DETAIL = _env.get_template("palette_group_detail.html")

PLOT_PAGE = _env.get_template("plot_page.rst")

PROP_DETAIL = _env.get_template("prop_detail.rst")
2 changes: 1 addition & 1 deletion setup.cfg
Expand Up @@ -13,7 +13,7 @@
exclude = __init__.py
ignore = E,W
select = F,E101,E111,E501
max-line-length = 160
max-line-length = 165

[tool:pytest]
norecursedirs = build _build node_modules
Expand Down
1 change: 1 addition & 0 deletions sphinx/source/conf.py
Expand Up @@ -42,6 +42,7 @@
'bokeh.sphinxext.bokeh_model',
'bokeh.sphinxext.bokeh_options',
'bokeh.sphinxext.bokeh_palette',
'bokeh.sphinxext.bokeh_palette_group',
'bokeh.sphinxext.bokeh_plot',
'bokeh.sphinxext.bokeh_prop',
'bokeh.sphinxext.bokeh_sitemap',
Expand Down
1 change: 0 additions & 1 deletion sphinx/source/docs/installation.rst
Expand Up @@ -177,4 +177,3 @@ and
.. _anaconda.org: http://anaconda.org
.. _Continuum Analytics: http://continuum.io
.. _npmjs.org: https://www.npmjs.org/package/bokehjs
.. _redis: http://redis.io
7 changes: 7 additions & 0 deletions sphinx/source/docs/reference/sphinxext.rst
Expand Up @@ -51,6 +51,13 @@ bokeh_palette

.. automodule:: bokeh.sphinxext.bokeh_palette

.. _bokeh.sphinxext.bokeh_palette_group:

bokeh_palette_group
-------------------

.. automodule:: bokeh.sphinxext.bokeh_palette_group

.. _bokeh.sphinxext.bokeh_plot:

bokeh_plot
Expand Down