From 9a2d3e8afbe3cdb411caedf2540e5cad9dfaf1ec Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sat, 10 Dec 2016 18:45:45 +0000
Subject: [PATCH 1/3] Fixed FuncTickFormater with py2js_tickformatter util and
tests
---
holoviews/plotting/bokeh/element.py | 16 +++--------
holoviews/plotting/bokeh/util.py | 30 ++++++++++++++++++++-
tests/testplotutils.py | 42 +++++++++++++++++++++++++++++
3 files changed, 75 insertions(+), 13 deletions(-)
create mode 100644 tests/testplotutils.py
diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py
index f3f36165c1..4d2d2a2860 100644
--- a/holoviews/plotting/bokeh/element.py
+++ b/holoviews/plotting/bokeh/element.py
@@ -34,7 +34,7 @@
from ..util import dynamic_update, get_sources
from .plot import BokehPlot
from .util import (mpl_to_bokeh, convert_datetime, update_plot,
- bokeh_version, mplcmap_to_palette)
+ bokeh_version, mplcmap_to_palette, py2js_tickformatter)
if bokeh_version >= '0.12':
from bokeh.models import FuncTickFormatter
@@ -450,17 +450,9 @@ def _axis_properties(self, axis, key, plot, dimension,
if formatter:
msg = ('%s dimension formatter could not be '
'converted to tick formatter. ' % dimension.name)
- try:
- formatter = FuncTickFormatter.from_py_func(formatter)
- except RuntimeError:
- self.warning(msg+'Ensure Flexx is installed '
- '("conda install -c bokeh flexx" or '
- '"pip install flexx")')
- except Exception as e:
- error = 'Pyscript raised an error: {0}'.format(e)
- error = error.replace('%', '%%')
- self.warning(msg+error)
- else:
+ jsfunc = py2js_tickformatter(formatter, msg)
+ if jsfunc:
+ formatter = FuncTickFormatter(code=jsfunc)
axis_props['formatter'] = formatter
return axis_props
diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py
index cad1752ffe..67b5b3bc6f 100644
--- a/holoviews/plotting/bokeh/util.py
+++ b/holoviews/plotting/bokeh/util.py
@@ -1,4 +1,4 @@
-import itertools
+import itertools, inspect, re
from distutils.version import LooseVersion
from collections import defaultdict
@@ -372,3 +372,31 @@ def pad_plots(plots, padding=0.85):
for p, w in zip(row, ws)] for row, ws in zip(plots, widths)]
total_width = np.max([np.sum(row) for row in widths])
return plots, total_width
+
+
+def py2js_tickformatter(formatter, msg=''):
+ """
+ Uses flexx.pyscript to compile a python tick formatter to JS code
+ """
+ try:
+ from flexx.pyscript import py2js
+ except ImportError:
+ self.warning(msg+'Ensure Flexx is installed '
+ '("conda install -c bokeh flexx" or '
+ '"pip install flexx")')
+ return
+ try:
+ jscode = py2js(formatter, 'formatter')
+ except Exception as e:
+ error = 'Pyscript raised an error: {0}'.format(e)
+ error = error.replace('%', '%%')
+ self.warning(msg+error)
+ return
+
+ args = inspect.getargspec(formatter).args
+ arg_define = 'var %s = tick;' % args[0] if args else ''
+ return_js = 'return formatter();\n'
+ jsfunc = '\n'.join([arg_define, jscode, return_js])
+ match = re.search('(function \(.*\))', jsfunc )
+ return jsfunc[:match.start()] + 'function ()' + jsfunc[match.end():]
+
diff --git a/tests/testplotutils.py b/tests/testplotutils.py
new file mode 100644
index 0000000000..fe170ff489
--- /dev/null
+++ b/tests/testplotutils.py
@@ -0,0 +1,42 @@
+from unittest import SkipTest
+
+from holoviews.core.options import Store
+from holoviews.element.comparison import ComparisonTestCase
+
+try:
+ from holoviews.plotting.bokeh import util
+ bokeh_renderer = Store.renderers['bokeh']
+except:
+ bokeh_renderer = None
+
+
+class TestBokehUtils(ComparisonTestCase):
+
+ def setUp(self):
+ if not bokeh_renderer:
+ raise SkipTest("Bokeh required to test bokeh plot utils.")
+
+
+ def test_py2js_funcformatter_single_arg(self):
+ def test(x): return '%s$' % x
+ jsfunc = util.py2js_tickformatter(test)
+ js_func = ('var x = tick;\nvar formatter;\nformatter = function () {\n'
+ ' return "" + x + "$";\n};\n\nreturn formatter();\n')
+ self.assertEqual(jsfunc, js_func)
+
+
+ def test_py2js_funcformatter_two_args(self):
+ def test(x, pos): return '%s$' % x
+ jsfunc = util.py2js_tickformatter(test)
+ js_func = ('var x = tick;\nvar formatter;\nformatter = function () {\n'
+ ' return "" + x + "$";\n};\n\nreturn formatter();\n')
+ self.assertEqual(jsfunc, js_func)
+
+
+ def test_py2js_funcformatter_arg_and_kwarg(self):
+ def test(x, pos=None): return '%s$' % x
+ jsfunc = util.py2js_tickformatter(test)
+ js_func = ('var x = tick;\nvar formatter;\nformatter = function () {\n'
+ ' pos = (pos === undefined) ? null: pos;\n return "" '
+ '+ x + "$";\n};\n\nreturn formatter();\n')
+ self.assertEqual(jsfunc, js_func)
From 30b0d254424588b2b00865f129a9a02a40191831 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sat, 10 Dec 2016 19:06:43 +0000
Subject: [PATCH 2/3] Fixed warnings
---
holoviews/plotting/bokeh/util.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py
index 67b5b3bc6f..bfaad130a8 100644
--- a/holoviews/plotting/bokeh/util.py
+++ b/holoviews/plotting/bokeh/util.py
@@ -10,6 +10,7 @@
except ImportError:
cm, colors = None, None
+import param
import bokeh
bokeh_version = LooseVersion(bokeh.__version__)
from bokeh.core.enums import Palette
@@ -381,16 +382,16 @@ def py2js_tickformatter(formatter, msg=''):
try:
from flexx.pyscript import py2js
except ImportError:
- self.warning(msg+'Ensure Flexx is installed '
- '("conda install -c bokeh flexx" or '
- '"pip install flexx")')
+ param.main.warning(msg+'Ensure Flexx is installed '
+ '("conda install -c bokeh flexx" or '
+ '"pip install flexx")')
return
try:
jscode = py2js(formatter, 'formatter')
except Exception as e:
error = 'Pyscript raised an error: {0}'.format(e)
error = error.replace('%', '%%')
- self.warning(msg+error)
+ param.main.warning(msg+error)
return
args = inspect.getargspec(formatter).args
From a1dd750c4c72c02907f234a5c21fe00eba1e4ee4 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Sat, 10 Dec 2016 19:08:37 +0000
Subject: [PATCH 3/3] Install flexx on travis
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index c7264fc11b..9e95612cc3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,7 +26,7 @@ install:
- conda info -a
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION scipy numpy freetype nose bokeh pandas jupyter ipython=4.2.0 param pyqt=4 matplotlib=1.5.1 xarray datashader
- source activate test-environment
- - conda install -c conda-forge -c scitools iris sip=4.18 plotly
+ - conda install -c conda-forge -c scitools iris sip=4.18 plotly flexx
- if [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
conda install python=3.4.3;
fi