Python param.Parameter() Examples

The following are 30 code examples of param.Parameter(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module param , or try the search function .
Example #1
Source File: util.py    From hvplot with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def process_dynamic_args(x, y, kind, **kwds):
    dynamic = {}
    arg_deps = []
    arg_names = []

    for k, v in list(kwds.items()) + [('x', x), ('y', y), ('kind', kind)]:
        if isinstance(v, param.Parameter):
            dynamic[k] = v
        elif panel_available and isinstance(v, pn.widgets.Widget):
            if LooseVersion(pn.__version__) < '0.6.4':
                dynamic[k] = v.param.value
            else:
                dynamic[k] = v

    for k, v in kwds.items():
        if k not in dynamic and isinstance(v, FunctionType) and hasattr(v, '_dinfo'):
            deps = v._dinfo['dependencies']
            arg_deps += list(deps)
            arg_names += list(k) * len(deps)

    return dynamic, arg_deps, arg_names 
Example #2
Source File: test_reactive.py    From panel with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def test_param_rename():
    "Test that Reactive renames params and properties"

    class ReactiveRename(Reactive):

        a = param.Parameter()
    
        _rename = {'a': 'b'}

    obj = ReactiveRename()

    params = obj._process_property_change({'b': 1})
    assert params == {'a': 1}

    properties = obj._process_param_change({'a': 1})
    assert properties == {'b': 1} 
Example #3
Source File: test_param.py    From panel with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def test_param_subobject_expand_no_toggle(document, comm):
    class Test(param.Parameterized):
        a = param.Parameter()

    test = Test(a=Test(name='Nested'))
    test_pane = Pane(test, expand=True,
                     expand_button=False)
    model = test_pane.get_root(document, comm=comm)

    # Assert no toggle was added
    assert len(model.children) == 3

    # Expand subpane
    _, _, subpanel = test_pane.layout.objects
    div, widget = model.children[2].children
    assert div.text == '<b>Nested</b>'
    assert isinstance(widget, BkTextInput) 
Example #4
Source File: param.py    From panel with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def _validate_object(self):
        dependencies = getattr(self.object, '_dinfo', None)
        if not dependencies or not dependencies.get('watch'):
            return
        fn_type = 'method' if type(self) is ParamMethod else 'function'
        self.param.warning(f"The {fn_type} supplied for Panel to display "
                           "was declared with `watch=True`, which will "
                           f"cause the {fn_type} to be called twice for "
                           "any change in a dependent Parameter. "
                           "`watch` should be False when Panel is "
                           "responsible for displaying the result "
                           f"of the {fn_type} call, while `watch=True` "
                           f"should be reserved for {fn_type}s that work "
                           "via side-effects, e.g. by modifying internal  "
                           "state of a class or global state in an "
                           "application's namespace.")

    #----------------------------------------------------------------
    # Callback API
    #---------------------------------------------------------------- 
Example #5
Source File: operation.py    From holoviews with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def __call__(self, element, **kwargs):
        params = dict(kwargs)
        for k, v in kwargs.items():
            if util.is_param_method(v, has_deps=True):
                params[k] = v()
            elif isinstance(v, param.Parameter) and isinstance(v.owner, param.Parameterized):
                params[k] = getattr(v.owner, v.name)
        self.p = param.ParamOverrides(self, params,
                                      allow_extra_keywords=self._allow_extra_keywords)
        if not self.p.dynamic:
            kwargs['dynamic'] = False
            if isinstance(element, HoloMap):
                # Backwards compatibility for key argument
                return element.clone([(k, self._apply(el, key=k))
                                      for k, el in element.items()])
            elif ((self._per_element and isinstance(element, Element)) or
                  (not self._per_element and isinstance(element, ViewableElement))):
                return self._apply(element)
        elif 'streams' not in kwargs:
            kwargs['streams'] = self.p.streams
        kwargs['per_element'] = self._per_element
        kwargs['link_dataset'] = self._propagate_dataset
        return element.apply(self, **kwargs) 
Example #6
Source File: depends.py    From panel with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def param_value_if_widget(arg):
    if isinstance(arg, Widget):
        return arg.param.value

    from .pane.ipywidget import IPyWidget
    if IPyWidget.applies(arg) and hasattr(arg, 'value'):
        name = type(arg).__name__
        if name in ipywidget_classes:
            ipy_param = ipywidget_classes[name]
        else:
            ipy_param = param.parameterized_class(name, {'value': param.Parameter()})
        ipywidget_classes[name] = ipy_param
        ipy_inst = ipy_param(value=arg.value)
        arg.observe(lambda event: ipy_inst.set_param(value=event['new']), 'value')
        return ipy_inst.param.value
    return arg 
Example #7
Source File: interact.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def _yield_abbreviations_for_parameter(parameter, kwargs):
    """Get an abbreviation for a function parameter."""
    name = parameter.name
    kind = parameter.kind
    ann = parameter.annotation
    default = parameter.default
    not_found = (name, empty, empty)
    if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
        if name in kwargs:
            value = kwargs.pop(name)
        elif ann is not empty:
            param.main.warning("Using function annotations to implicitly specify interactive controls is deprecated. "
                               "Use an explicit keyword argument for the parameter instead.", DeprecationWarning)
            value = ann
        elif default is not empty:
            value = default
            if isinstance(value, (Iterable, Mapping)):
                value = fixed(value)
        else:
            yield not_found
        yield (name, value, default)
    elif kind == Parameter.VAR_KEYWORD:
        # In this case name=kwargs and we yield the items in kwargs with their keys.
        for k, v in kwargs.copy().items():
            kwargs.pop(k)
            yield k, v, empty 
Example #8
Source File: test_reactive.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_link():
    "Link two Reactive objects"

    class ReactiveLink(Reactive):

        a = param.Parameter()

    obj = ReactiveLink()
    obj2 = ReactiveLink()
    obj.link(obj2, a='a')
    obj.a = 1

    assert obj.a == 1
    assert obj2.a == 1 
Example #9
Source File: test_param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_expand_param_subobject_tabs(document, comm):
    class Test(param.Parameterized):
        abc = param.Parameter()

    test = Test(abc=Test(name='Nested'), name='A')
    test_pane = Pane(test, expand_layout=Tabs)
    model = test_pane.get_root(document, comm=comm)

    toggle = model.tabs[0].child.children[0].children[1]
    assert isinstance(toggle, Toggle)

    # Expand subpanel
    test_pane._widgets['abc'][1].value = True
    assert len(model.tabs) == 2
    _, subpanel = test_pane.layout.objects
    subtabs = model.tabs[1].child
    assert model.tabs[1].title == 'Abc'
    assert isinstance(subtabs, BkTabs)
    assert len(subtabs.tabs) == 1
    assert subtabs.tabs[0].title == 'Nested'

    box = subtabs.tabs[0].child
    assert isinstance(box, BkColumn)
    assert len(box.children) == 1
    widget = box.children[0]
    assert isinstance(widget, BkTextInput)

    # Collapse subpanel
    test_pane._widgets['abc'][1].value = False
    assert len(model.tabs) == 1 
Example #10
Source File: test_param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_expand_param_subobject_into_row(document, comm):
    class Test(param.Parameterized):
        a = param.Parameter()

    test = Test(a=Test(name='Nested'))
    row = Row()
    test_pane = Pane(test, expand_layout=row)
    layout = Row(test_pane, row)
    model = layout.get_root(document, comm=comm)

    toggle = model.children[0].children[1].children[1]
    assert isinstance(toggle, Toggle)

    # Expand subpane
    test_pane._widgets['a'][1].value = True
    assert len(model.children) == 2
    subpanel = row.objects[0]
    row = model.children[1]
    assert isinstance(row, BkRow)
    assert len(row.children) == 1
    box = row.children[0]
    assert isinstance(box, BkColumn)
    assert len(box.children) == 2
    div, widget = box.children
    assert div.text == '<b>Nested</b>'
    assert isinstance(widget, BkTextInput)

    # Collapse subpanel
    test_pane._widgets['a'][1].value = False
    assert len(row.children) == 0
    assert subpanel._models == {} 
Example #11
Source File: test_param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_expand_param_subobject(document, comm):
    class Test(param.Parameterized):
        a = param.Parameter()

    test = Test(a=Test(name='Nested'))
    test_pane = Pane(test)
    model = test_pane.get_root(document, comm=comm)

    toggle = model.children[1].children[1]
    assert isinstance(toggle, Toggle)

    # Expand subpane
    test_pane._widgets['a'][1].value = True
    assert len(model.children) == 3
    _, _, subpanel = test_pane.layout.objects
    col = model.children[2]
    assert isinstance(col, BkColumn)
    assert isinstance(col, BkColumn)
    assert len(col.children) == 2
    div, widget = col.children
    assert div.text == '<b>Nested</b>'
    assert isinstance(widget, BkTextInput)

    # Collapse subpanel
    test_pane._widgets['a'][1].value = False
    assert len(model.children) == 2 
Example #12
Source File: test_param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_single_param(document, comm):

    class Test(param.Parameterized):
        a = param.Parameter(default=0)

    test = Test()
    test_pane = Pane(test.param.a)
    model = test_pane.get_root(document, comm=comm)

    assert isinstance(model, BkColumn)
    assert len(model.children) == 1

    widget = model.children[0]
    assert isinstance(widget, TextInput)
    assert widget.value == '0' 
Example #13
Source File: test_base.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_widget_from_param_instance():
    class Test(param.Parameterized):

        a = param.Parameter()

    test = Test()
    widget = TextInput.from_param(test.param.a)
    assert isinstance(widget, TextInput)
    assert widget.name == 'A'

    test.a = 'abc'
    assert widget.value == 'abc'

    widget.value = 'def'
    assert test.a == 'def' 
Example #14
Source File: test_base.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_widget_from_param_cls():
    class Test(param.Parameterized):

        a = param.Parameter()

    widget = TextInput.from_param(Test.param.a)
    assert isinstance(widget, TextInput)
    assert widget.name == 'A'

    Test.a = 'abc'
    assert widget.value == 'abc'

    widget.value = 'def'
    assert Test.a == 'def' 
Example #15
Source File: param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def eval(self, function):
        args, kwargs = (), {}
        if hasattr(function, '_dinfo'):
            arg_deps = function._dinfo['dependencies']
            kw_deps = function._dinfo.get('kw', {})
            if kw_deps or any(isinstance(d, param.Parameter) for d in arg_deps):
                args = (getattr(dep.owner, dep.name) for dep in arg_deps)
                kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw_deps.items()}
        return function(*args, **kwargs) 
Example #16
Source File: param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def applies(cls, obj):
        return (is_parameterized(obj) or
                isinstance(obj, param.parameterized.Parameters) or
                (isinstance(obj, param.Parameter) and obj.owner is not None)) 
Example #17
Source File: param.py    From panel with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __init__(self, object=None, **params):
        if isinstance(object, param.Parameter):
            if not 'show_name' in params:
                params['show_name'] = False
            params['parameters'] = [object.name]
            object = object.owner
        if isinstance(object, param.parameterized.Parameters):
            object = object.cls if object.self is None else object.self
        if 'parameters' not in params and object is not None:
            params['parameters'] = [p for p in object.param if p != 'name']
        if object and 'name' not in params:
            params['name'] = param_name(object.name)
        super(Param, self).__init__(object, **params)
        self._updating = []

        # Construct Layout
        kwargs = {p: v for p, v in self.param.get_param_values()
                  if p in Layoutable.param and v is not None}
        self._widget_box = self.default_layout(**kwargs)

        layout = self.expand_layout
        if isinstance(layout, Panel):
            self._expand_layout = layout
            self.layout = self._widget_box
        elif isinstance(self._widget_box, layout):
            self.layout = self._expand_layout = self._widget_box
        elif isinstance(layout, type) and issubclass(layout, Panel):
            self.layout = self._expand_layout = layout(self._widget_box, **kwargs)
        else:
            raise ValueError('expand_layout expected to be a panel.layout.Panel'
                             'type or instance, found %s type.' %
                             type(layout).__name__)
        self.param.watch(self._update_widgets, [
            'object', 'parameters', 'name', 'display_threshold', 'expand_button',
            'expand', 'expand_layout', 'widgets', 'show_labels', 'show_name'])
        self._update_widgets() 
Example #18
Source File: boundingregion.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __set__(self, obj, val):
        """
        Set a non default bounding box, use the installed set hook to
        apply any conversion or transformation on the coordinates and
        create a new bounding box with the converted coordinate set.
        """
        coords = [self.set_hook(obj, point) for point in val.lbrt()]
        if coords != val.lbrt():
            val = BoundingBox(
                points=[(coords[0], coords[1]), (coords[2], coords[3])])

        if not isinstance(val, BoundingRegion):
            raise ValueError("Parameter must be a BoundingRegion.")
        else:
            super(BoundingRegionParameter, self).__set__(obj, val) 
Example #19
Source File: util.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def resolve_dependent_value(value):
    """Resolves parameter dependencies on the supplied value

    Resolves parameter values, Parameterized instance methods and
    parameterized functions with dependencies on the supplied value.

    Args:
       value: A value which will be resolved

    Returns:
       A new dictionary where any parameter dependencies have been
       resolved.
    """
    if 'panel' in sys.modules:
        from panel.widgets.base import Widget
        if isinstance(value, Widget):
            value = value.param.value
    if is_param_method(value, has_deps=True):
        value = value()
    elif isinstance(value, param.Parameter) and isinstance(value.owner, param.Parameterized):
        value = getattr(value.owner, value.name)
    elif isinstance(value, FunctionType) and hasattr(value, '_dinfo'):
        deps = value._dinfo
        args = (getattr(p.owner, p.name) for p in deps.get('dependencies', []))
        kwargs = {k: getattr(p.owner, p.name) for k, p in deps.get('kw', {}).items()}
        value = value(*args, **kwargs)
    return value 
Example #20
Source File: __init__.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def _update_backend(cls, backend):

        if cls.__original_docstring__ is None:
            cls.__original_docstring__ = cls.__doc__

        all_keywords = set()
        element_keywords = cls._element_keywords(backend)
        for element, keywords in element_keywords.items():
            with param.logging_level('CRITICAL'):
                all_keywords |= set(keywords)
                setattr(cls, element,
                        cls._create_builder(element, keywords))

        filtered_keywords = [k for k in all_keywords if k not in cls._no_completion]
        sorted_kw_set = sorted(set(filtered_keywords))
        if sys.version_info.major == 2:
            kws = ', '.join('{opt}=None'.format(opt=opt) for opt in sorted_kw_set)
            old_doc = cls.__original_docstring__.replace(
                'params(strict=Boolean, name=String)','')
            cls.__doc__ = '\n    opts({kws})'.format(kws=kws) + old_doc
        else:
            from inspect import Parameter, Signature
            signature = Signature([Parameter('args', Parameter.VAR_POSITIONAL)]
                                  + [Parameter(kw, Parameter.KEYWORD_ONLY)
                                     for kw in sorted_kw_set])
            cls.__init__.__signature__ = signature 
Example #21
Source File: transform.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def params(self):
        params = {}
        for op in self.ops:
            op_args = list(op['args'])+list(op['kwargs'].values())
            for op_arg in op_args:
                if 'panel' in sys.modules:
                    from panel.widgets.base import Widget
                    if isinstance(op_arg, Widget):
                        op_arg = op_arg.param.value
                if (isinstance(op_arg, param.Parameter) and
                    isinstance(op_arg.owner, param.Parameterized)):
                    params[op_arg.name+str(id(op))] = op_arg
        return params

    # Namespace properties 
Example #22
Source File: teststreams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_XY_set_invalid_instance_y(self):
        xy = self.XY(x=1,y=2)
        regexp = "Parameter 'y' only takes numeric values"
        with self.assertRaisesRegexp(ValueError, regexp):
            xy.y = 'string' 
Example #23
Source File: teststreams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_XY_set_invalid_instance_x(self):
        xy = self.XY(x=1,y=2)
        regexp = "Parameter 'x' only takes numeric values"
        with self.assertRaisesRegexp(ValueError, regexp):
            xy.x = 'string' 
Example #24
Source File: teststreams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_XY_set_invalid_class_y(self):
        regexp = "Parameter 'y' only takes numeric values"
        with self.assertRaisesRegexp(ValueError, regexp):
            self.XY.y = 'string' 
Example #25
Source File: teststreams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_all_stream_parameters_constant():
    all_stream_cls = [v for v in globals().values() if
                      isinstance(v, type) and issubclass(v, Stream)]
    for stream_cls in all_stream_cls:
        for name, p in stream_cls.param.params().items():
            if name == 'name': continue
            if p.constant != True:
                raise TypeError('Parameter %s of stream %s not declared constant'
                                % (name, stream_cls.__name__)) 
Example #26
Source File: streams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __init__(self, parameterized=None, parameters=None, watch=True, watch_only=False, **params):
        if util.param_version < '1.8.0' and watch:
            raise RuntimeError('Params stream requires param version >= 1.8.0, '
                               'to support watching parameters.')
        if parameters is None:
            parameters = [parameterized.param[p] for p in parameterized.param if p != 'name']
        else:
            parameters = [p if isinstance(p, param.Parameter) else parameterized.param[p]
                          for p in parameters]

        if 'rename' in params:
            rename = {}
            owners = [p.owner for p in parameters]
            for k, v in params['rename'].items():
                if isinstance(k, tuple):
                    rename[k] = v
                else:
                    rename.update({(o, k): v for o in owners})
            params['rename'] = rename

        self._watch_only = watch_only
        super(Params, self).__init__(parameterized=parameterized, parameters=parameters, **params)
        self._memoize_counter = 0
        self._events = []
        self._watchers = []
        if watch:
            # Subscribe to parameters
            keyfn = lambda x: id(x.owner)
            for _, group in groupby(sorted(parameters, key=keyfn)):
                group = list(group)
                watcher = group[0].owner.param.watch(self._watcher, [p.name for p in group])
                self._watchers.append(watcher) 
Example #27
Source File: streams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def define(cls, name, **kwargs):
        """
        Utility to quickly and easily declare Stream classes. Designed
        for interactive use such as notebooks and shouldn't replace
        parameterized class definitions in source code that is imported.

        Takes a stream class name and a set of keywords where each
        keyword becomes a parameter. If the value is already a
        parameter, it is simply used otherwise the appropriate parameter
        type is inferred and declared, using the value as the default.

        Supported types: bool, int, float, str, dict, tuple and list
        """
        params = {'name': param.String(default=name)}
        for k, v in kwargs.items():
            kws = dict(default=v, constant=True)
            if isinstance(v, param.Parameter):
                params[k] = v
            elif isinstance(v, bool):
                params[k] = param.Boolean(**kws)
            elif isinstance(v, int):
                params[k] = param.Integer(**kws)
            elif isinstance(v, float):
                params[k] = param.Number(**kws)
            elif isinstance(v, str):
                params[k] = param.String(**kws)
            elif isinstance(v, dict):
                params[k] = param.Dict(**kws)
            elif isinstance(v, tuple):
                params[k] = param.Tuple(**kws)
            elif isinstance(v, list):
                params[k] = param.List(**kws)
            elif isinstance(v, np.ndarray):
                params[k] = param.Array(**kws)
            else:
                params[k] = param.Parameter(**kws)

        # Dynamic class creation using type
        return type(name, (Stream,), params) 
Example #28
Source File: teststreams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def setUp(self):
        if LooseVersion(param.__version__) < '1.8.0':
            raise SkipTest('Params stream requires param >= 1.8.0')

        class Inner(param.Parameterized):

            action = param.Action(lambda o: o.param.trigger('action'))
            x = param.Number(default = 0)
            y = param.Number(default = 0)
            count = param.Integer(default=0)

            @param.depends('x')
            def method(self):
                self.count += 1
                return Points([])

            @param.depends('action')
            def action_method(self):
                pass

            @param.depends('action', 'x')
            def action_number_method(self):
                self.count += 1
                return Points([])

            @param.depends('y')
            def op_method(self, obj):
                pass

            def method_no_deps(self):
                pass

        class InnerSubObj(Inner):

            sub = param.Parameter()

            @param.depends('sub.x')
            def subobj_method(self):
                pass

        self.inner = Inner
        self.innersubobj = InnerSubObj 
Example #29
Source File: streams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def _process_streams(cls, streams):
        """
        Processes a list of streams promoting Parameterized objects and
        methods to Param based streams.
        """
        parameterizeds = defaultdict(set)
        valid, invalid = [], []
        for s in streams:
            if isinstance(s, partial):
                s = s.func
            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)
            elif isinstance(s, FunctionType) and hasattr(s, "_dinfo"):
                deps = s._dinfo
                dep_params = list(deps['dependencies']) + list(deps.get('kw', {}).values())
                rename = {(p.owner, p.name): k for k, p in deps.get('kw', {}).items()}
                s = Params(parameters=dep_params, rename=rename)
            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([p.name for p in overlap]), pname))
                parameterizeds[pid] |= set(s.parameters)
            valid.append(s)
        return valid, invalid 
Example #30
Source File: streams.py    From holoviews with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def trigger(cls, streams):
        """
        Given a list of streams, collect all the stream parameters into
        a dictionary and pass it to the union set of subscribers.

        Passing multiple streams at once to trigger can be useful when a
        subscriber may be set multiple times across streams but only
        needs to be called once.
        """
        # Union of stream contents
        items = [stream.contents.items() for stream in set(streams)]
        union = [kv for kvs in items for kv in kvs]
        klist = [k for k, _ in union]
        key_clashes = []
        for k, v in union:
            key_count = klist.count(k)
            try:
                value_count = union.count((k, v))
            except Exception:
                # If we can't compare values we assume they are not equal
                value_count = 1
            if key_count > 1 and key_count > value_count and k not in key_clashes:
                key_clashes.append(k)
        if key_clashes:
            print('Parameter name clashes for keys %r' % key_clashes)

        # Group subscribers by precedence while keeping the ordering
        # within each group
        subscriber_precedence = defaultdict(list)
        for stream in streams:
            stream._on_trigger()
            for precedence, subscriber in stream._subscribers:
                subscriber_precedence[precedence].append(subscriber)
        sorted_subscribers = sorted(subscriber_precedence.items(), key=lambda x: x[0])
        subscribers = util.unique_iterator([s for _, subscribers in sorted_subscribers
                                            for s in subscribers])

        with triggering_streams(streams):
            for subscriber in subscribers:
                subscriber(**dict(union))

        for stream in streams:
            with util.disable_constant(stream):
                if stream.transient:
                    stream.reset()