diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index 3168cba410..275a25561e 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -446,6 +446,19 @@ def __init__(self, callable, **params): def argspec(self): return util.argspec(self.callable) + + def clone(self, callable=None, **overrides): + """ + Allows making a copy of the Callable optionally overriding + the callable and other parameters. + """ + old = {k: v for k, v in self.get_param_values() + if k not in ['callable', 'name']} + params = dict(old, **overrides) + callable = self.callable if callable is None else callable + return self.__class__(callable, **params) + + def __call__(self, *args, **kwargs): inputs = [i for i in self.inputs if isinstance(i, DynamicMap)] streams = [] @@ -667,9 +680,19 @@ def clone(self, data=None, shared_data=True, new_type=None, *args, **overrides): """ if data is None and shared_data: data = self.data - return super(UniformNdMapping, self).clone(overrides.pop('callback', self.callback), - shared_data, new_type, - *(data,) + args, **overrides) + clone = super(UniformNdMapping, self).clone(overrides.pop('callback', self.callback), + shared_data, new_type, + *(data,) + args, **overrides) + + # Ensure the clone references this object to ensure + # stream sources are inherited + if clone.callback is self.callback: + clone.callback = self.callback.clone() + if self not in clone.callback.inputs: + with util.disable_constant(clone.callback): + clone.callback.inputs = clone.callback.inputs+[self] + return clone + def reset(self): """ @@ -1096,13 +1119,7 @@ def reindex(self, kdims=[], force=False): if dropped: raise ValueError("DynamicMap does not allow dropping dimensions, " "reindex may only be used to reorder dimensions.") - reindexed = super(DynamicMap, self).reindex(kdims, force) - def reindex(*args, **kwargs): - keymap = {kd.name: arg for kd, arg in zip(self.kdims, args)} - keymap.update(kwargs) - args = tuple(keymap[kd.name] for kd in kdims) - return reindexed[args] - return reindexed.clone(callback=Callable(reindex, inputs=[self])) + return super(DynamicMap, self).reindex(kdims, force) def drop_dimension(self, dimensions): diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 19055216e4..1ec9ad3ce1 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -7,6 +7,7 @@ import datetime as dt from collections import defaultdict, Counter from functools import partial +from contextlib import contextmanager import numpy as np import param @@ -982,6 +983,25 @@ def get_param_values(data): return params +@contextmanager +def disable_constant(parameterized): + """ + Temporarily set parameters on Parameterized object to + constant=False. + """ + params = parameterized.params().values() + constants = [p.constant for p in params] + for param in params: + param.constant = False + try: + yield + except: + raise + finally: + for (param, const) in zip(params, constants): + param.constant = const + + def get_ndmapping_label(ndmapping, attr): """ Function to get the first non-auxiliary object diff --git a/holoviews/streams.py b/holoviews/streams.py index 95423badba..c99a6734ce 100644 --- a/holoviews/streams.py +++ b/holoviews/streams.py @@ -32,25 +32,6 @@ def triggering_streams(streams): stream._triggering = False -@contextmanager -def disable_constant(parameterized): - """ - Temporarily set parameters on Parameterized object to - constant=False. - """ - params = parameterized.params().values() - constants = [p.constant for p in params] - for param in params: - param.constant = False - try: - yield - except: - raise - finally: - for (param, const) in zip(params, constants): - param.constant = const - - class Stream(param.Parameterized): """ A Stream is simply a parameterized object with parameters that @@ -118,7 +99,7 @@ def trigger(cls, streams): subscriber(**dict(union)) for stream in streams: - with disable_constant(stream): + with util.disable_constant(stream): if stream.transient: stream.reset() @@ -175,7 +156,7 @@ def reset(self): """ Resets stream parameters to their defaults. """ - with disable_constant(self): + with util.disable_constant(self): for k, p in self.params().items(): if k != 'name': setattr(self, k, p.default) @@ -250,7 +231,7 @@ def _set_stream_parameters(self, **kwargs): Sets the stream parameters which are expected to be declared constant. """ - with disable_constant(self) as constant: + with util.disable_constant(self) as constant: self.set_param(**kwargs)