Skip to content

Commit

Permalink
Add support for passing in parameter instances as streams (#3616)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored and jlstevens committed Apr 10, 2019
1 parent 1af2264 commit 02308a8
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 19 deletions.
42 changes: 27 additions & 15 deletions holoviews/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,30 +166,42 @@ def trigger(cls, streams):
def _on_trigger(self):
"""Called when a stream has been triggered"""


@classmethod
def _process_streams(cls, streams):
"""
Processes a list of streams promoting Parameterized objects and
methods to Param based streams.
"""
param_watch_support = util.param_version >= '1.8.0'
parameterizeds = [s.parameterized for s in streams if isinstance(s, Params)]
parameterizeds = defaultdict(set)
valid, invalid = [], []
for s in streams:
if not isinstance(s, Stream):
if isinstance(s, param.Parameterized) and param_watch_support:
if s not in parameterizeds:
s = Params(s)
else:
continue
elif util.is_param_method(s) and param_watch_support:
if not hasattr(s, "_dinfo") or util.get_method_owner(s) in parameterizeds:
continue
else:
s = ParamMethod(s)
else:
invalid.append(s)
if isinstance(s, Stream):
pass
elif isinstance(s, param.Parameter):
s = Params(s.owner, [s.name])
elif isinstance(s, param.Parameterized):
s = Params(s)
elif util.is_param_method(s):
if not hasattr(s, "_dinfo"):
continue
s = ParamMethod(s)
else:
invalid.append(s)
continue
if isinstance(s, Params):
pid = id(s.parameterized)
overlap = (set(s.parameters) & parameterizeds[pid])
if overlap:
pname = type(s.parameterized).__name__
param.main.param.warning(
'The %s parameter(s) on the %s object have '
'already been supplied in another stream. '
'Ensure that the supplied streams only specify '
'each parameter once, otherwise multiple '
'events will be triggered when the parameter '
'changes.' % (sorted(overlap), pname))
parameterizeds[pid] |= set(s.parameters)
valid.append(s)
return valid, invalid

Expand Down
43 changes: 39 additions & 4 deletions holoviews/tests/teststreams.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
from holoviews.streams import * # noqa (Test all available streams)
from holoviews.util import Dynamic

from .utils import LoggingComparisonTestCase


def test_all_stream_parameters_constant():
all_stream_cls = [v for v in globals().values() if
isinstance(v, type) and issubclass(v, Stream)]
Expand Down Expand Up @@ -178,12 +181,9 @@ def test_class_value_update(self):



class TestParamsStream(ComparisonTestCase):
class TestParamsStream(LoggingComparisonTestCase):

def setUp(self):
if LooseVersion(param.__version__) < '1.8.0':
raise SkipTest('Params stream requires param >= 1.8.0')

class Inner(param.Parameterized):

x = param.Number(default = 0)
Expand Down Expand Up @@ -223,6 +223,41 @@ def subscriber(**kwargs):
inner.y = 2
self.assertEqual(values, [{'x': 2, 'y': 2}])

def test_param_stream_instance_separate_parameters(self):
inner = self.inner()

xparam = Params(inner, ['x'])
yparam = Params(inner, ['y'])

valid, invalid = Stream._process_streams([xparam, yparam])
self.assertEqual(len(valid), 2)
self.assertEqual(len(invalid), 0)

def test_param_stream_instance_overlapping_parameters(self):
inner = self.inner()

params1 = Params(inner)
params2 = Params(inner)

Stream._process_streams([params1, params2])
self.log_handler.assertContains('WARNING', "['x', 'y']")

def test_param_parameter_instance_separate_parameters(self):
inner = self.inner()

valid, invalid = Stream._process_streams([inner.param.x, inner.param.y])
xparam, yparam = valid

self.assertIs(xparam.parameterized, inner)
self.assertEqual(xparam.parameters, ['x'])
self.assertIs(yparam.parameterized, inner)
self.assertEqual(yparam.parameters, ['y'])

def test_param_parameter_instance_overlapping_parameters(self):
inner = self.inner()
Stream._process_streams([inner.param.x, inner.param.x])
self.log_handler.assertContains('WARNING', "['x']")

def test_param_stream_parameter_override(self):
inner = self.inner(x=2)
stream = Params(inner, parameters=['x'])
Expand Down

0 comments on commit 02308a8

Please sign in to comment.