Skip to content
Permalink
Browse files
Chart data files (#3130)
Fix #3129 by providing support for JSON/YAML files in chart shortcodes and directives
  • Loading branch information
ralsina committed Aug 6, 2018
1 parent 42e6fd6 commit 69ef41d1ca9498da077acf5bfcef957877e2f0a7
Showing with 52 additions and 14 deletions.
  1. +1 −0 CHANGES.txt
  2. +29 −2 docs/manual.rst
  3. +1 −0 nikola/plugins/compile/rest/chart.py
  4. +21 −12 nikola/plugins/shortcode/chart.py
@@ -6,6 +6,7 @@ Changes since Beta 2
Features
--------

* New data_file option for chart shortcode and directive (Issue #3129)
* Show the filename of the missing file when ``nikola serve`` can't
find a file (i.e. when an 404 error occurs).
* Better error messages for JSON download failures in ``nikola
@@ -1256,14 +1256,39 @@ chart

.. code:: text

{{% raw %}}{{% chart Bar title='Browser usage evolution (in %)' %}}
x_labels='["2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012"]'%}}
{{% raw %}}{{% chart Bar title='Browser usage evolution (in %)'
x_labels='["2002","2003","2004","2005","2006","2007"]' %}}
'Firefox', [None, None, 0, 16.6, 25, 31]
'Chrome', [None, None, None, None, None, None]
'IE', [85.8, 84.6, 84.7, 74.5, 66, 58.6]
'Others', [14.2, 15.4, 15.3, 8.9, 9, 10.4]
{{% /chart %}}{{% /raw %}}

Additionally, you can use a file_data argument which can point to a JSON or YAML file, and will be used for both arguments and data.
Example:

.. code:: json
{
"x_labels": ["2002","2003","2004","2005","2006","2007"],
"data": {
"Firefox": [null, null, 0, 16.6, 25, 31],
"Chrome": [null, null, null, null, null, null],
"IE": [85.8, 84.6, 84.7, 74.5, 66, 58.6],
"Others": [14.2, 15.4, 15.3, 8.9, 9, 10.4]
}
}
Which can be used like this:

.. code:: text

{{% raw %}}{{% chart Bar title='Browser usage evolution (in %)' data_file="posts/browsers.json" %}}
{{% /chart %}}
{{% /raw %}}

If the data or any option is available in both the ``data_file`` and the document, the document has priority.

doc
Will link to a document in the page, see `Doc role for details
<#doc>`__. Example:
@@ -2663,6 +2688,8 @@ You can use any option described in `the pygal docs <http://pygal.org/en/stable/
Finally, the content of the directive is the actual data, in the form of a label and
a list of values, one series per line.

You can also specify a ``:data_file:`` option as described in the documentation for the chart shortcut.

Doc
~~~

@@ -72,6 +72,7 @@ class Chart(Directive):
"classes": directives.unchanged,
"css": directives.unchanged,
"defs": directives.unchanged,
"data_file": directives.unchanged,
"disable_xml_declaration": directives.unchanged,
"dots_size": directives.unchanged,
"dynamic_print_values": directives.unchanged,
@@ -33,7 +33,7 @@
pygal = None # NOQA

from nikola.plugin_categories import ShortcodePlugin
from nikola.utils import req_missing
from nikola.utils import req_missing, load_data

_site = None

@@ -50,18 +50,30 @@ def handler(self, chart_type, **_options):
['pygal'], 'use the Chart directive', optional=True)
return '<div class="text-error">{0}</div>'.format(msg)
options = {}
data = _options.pop('data')
chart_data = []
_options.pop('post', None)
_options.pop('site')
if 'style' in _options:
style_name = _options.pop('style')
else:
style_name = 'BlueStyle'
data = _options.pop('data')

for line in data.splitlines():
line = line.strip()
if line:
chart_data.append(literal_eval('({0})'.format(line)))
if 'data_file' in _options:
options = load_data(_options['data_file'])
_options.pop('data_file')
if not chart_data: # If there is data in the document, it wins
for k, v in options.pop('data', {}).items():
chart_data.append((k, v))

options.update(_options)

style_name = options.pop('style', 'BlueStyle')
if '(' in style_name: # Parametric style
style = eval('pygal.style.' + style_name)
else:
style = getattr(pygal.style, style_name)
for k, v in _options.items():
for k, v in options.items():
try:
options[k] = literal_eval(v)
except Exception:
@@ -73,9 +85,6 @@ def handler(self, chart_type, **_options):
if _site and _site.invariant:
chart.no_prefix = True
chart.config(**options)
for line in data.splitlines():
line = line.strip()
if line:
label, series = literal_eval('({0})'.format(line))
chart.add(label, series)
for label, series in chart_data:
chart.add(label, series)
return chart.render().decode('utf8')

0 comments on commit 69ef41d

Please sign in to comment.