From cb8021607419ad767a1c6997248000b3ea19238b Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 28 Jul 2023 13:53:30 +0200 Subject: [PATCH] Implement more functions --- param/reactive.py | 42 +++++++++++++++++++++++++++++++++++++++++- tests/testreactive.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/param/reactive.py b/param/reactive.py index 1aebcf92d..a58844745 100644 --- a/param/reactive.py +++ b/param/reactive.py @@ -84,6 +84,7 @@ import math import operator +from collections.abc import Iterable, Iterator from types import FunctionType, MethodType from typing import Any, Callable, Optional @@ -589,12 +590,51 @@ def __rxor__(self, other): def __getitem__(self, other): return self._apply_operator(operator.getitem, other) + def bool_(self): + """ + __bool__ cannot be implemented so it is provided as a method. + """ + return self._apply_operator(bool) + def len(self): """ - __len__ cannot be implemented so we alternative helper. + __len__ cannot be implemented so it is provided as a method. """ return self._apply_operator(len) + def is_(self, other): + """ + Replacement for the ``is`` statement. + """ + return self._apply_operator(operator.is_, other) + + def __iter__(self): + if isinstance(self._current, Iterator): + while True: + try: + new = self._apply_operator(next) + new.eval() + except RuntimeError: + break + yield new + return + elif not isinstance(self._current, Iterable): + raise TypeError('cannot unpack non-iterable {type(self._current).__name__} object.') + iterator = [] + def iterate(value): + if iterator: + iterate = iterator[0] + else: + iterate = iter(value) + iterator.append(iterate) + try: + yield next(iterate) + except StopIteration as e: + iterator.clear() + raise e + for item in self._apply_operator(iterate): + yield item + def pipe(self, func, *args, **kwargs): """ Apply chainable functions. diff --git a/tests/testreactive.py b/tests/testreactive.py index 4b4246411..3b978bd12 100644 --- a/tests/testreactive.py +++ b/tests/testreactive.py @@ -188,3 +188,33 @@ def test_reactive_dataframe_param_value_method_chain(dataframe): pd.testing.assert_frame_equal(dfi.eval(), dataframe.groupby('str')[['float']].mean().reset_index()) P.string = 'int' pd.testing.assert_frame_equal(dfi.eval(), dataframe.groupby('int')[['float']].mean().reset_index()) + +def test_reactive_len(): + i = reactive([1, 2, 3]) + l = i.len() + assert l.eval() == 3 + i.set([1, 2]) + assert l == 2 + +def test_reactive_bool(): + i = reactive(1) + b = i.bool_() + assert b.eval() is True + i.set(0) + assert b.eval() is False + +def test_reactive_iter(): + i = reactive(('a', 'b')) + a, b = i + assert a.eval() == 'a' + assert b.eval() == 'b' + i.set(('b', 'a')) + assert a.eval() == 'b' + assert b.eval() == 'a' + +def test_reactive_is(): + i = reactive(None) + is_ = i.is_(None) + assert is_.eval() + i.set(False) + assert not is_.eval()