From 52069b7bb3daa9c969a43a0912dbeef587d064c4 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 14 Sep 2022 23:01:52 +0200 Subject: [PATCH] Improved Sequences --- src/cpl_query/base/queryable_abc.py | 22 ++++++++--------- src/cpl_query/base/sequence_abc.py | 3 --- src/cpl_query/base/sequence_values.py | 16 +++++++------ src/cpl_query/enumerable/enumerable.py | 18 ++++---------- src/cpl_query/iterable/iterable_abc.py | 24 +++++++++---------- .../unittests_query/iterable_test_case.py | 14 +++++++++++ 6 files changed, 50 insertions(+), 47 deletions(-) diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 382d8ef6..976c9ab4 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -5,7 +5,7 @@ from typing import Optional, Callable, Union class QueryableABC(ABC): @abstractmethod - def all(self, _func: Callable) -> bool: + def all(self, _func: Callable = None) -> bool: r"""Checks if every element of list equals result found by function Parameter @@ -20,7 +20,7 @@ class QueryableABC(ABC): pass @abstractmethod - def any(self, _func: Callable) -> bool: + def any(self, _func: Callable = None) -> bool: r"""Checks if list contains result found by function Parameter @@ -35,7 +35,7 @@ class QueryableABC(ABC): pass @abstractmethod - def average(self, _func: Callable) -> Union[int, float, complex]: + def average(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns average value of list Parameter @@ -145,7 +145,7 @@ class QueryableABC(ABC): pass @abstractmethod - def for_each(self, _func: Callable): + def for_each(self, _func: Callable = None): r"""Runs given function for each element of list Parameter @@ -174,8 +174,9 @@ class QueryableABC(ABC): Last element of list: Optional[any] """ pass + @abstractmethod - def max(self, _func: Callable) -> Union[int, float, complex]: + def max(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns the highest value Parameter @@ -199,9 +200,8 @@ class QueryableABC(ABC): """ pass - @abstractmethod - def min(self, _func: Callable) -> Union[int, float, complex]: + def min(self, _func: Callable = None) -> Union[int, float, complex]: r"""Returns the lowest value Parameter @@ -216,7 +216,7 @@ class QueryableABC(ABC): pass @abstractmethod - def order_by(self, _func: Callable) -> 'QueryableABC': + def order_by(self, _func: Callable = None) -> 'QueryableABC': r"""Sorts elements by function in ascending order Parameter @@ -231,7 +231,7 @@ class QueryableABC(ABC): pass @abstractmethod - def order_by_descending(self, _func: Callable) -> 'QueryableABC': + def order_by_descending(self, _func: Callable = None) -> 'QueryableABC': r"""Sorts elements by function in descending order Parameter @@ -331,7 +331,7 @@ class QueryableABC(ABC): pass @abstractmethod - def sum(self, _func: Callable) -> Union[int, float, complex]: + def sum(self, _func: Callable = None) -> Union[int, float, complex]: r"""Sum of all values Parameter @@ -376,7 +376,7 @@ class QueryableABC(ABC): pass @abstractmethod - def where(self, _func: Callable) -> 'QueryableABC': + def where(self, _func: Callable = None) -> 'QueryableABC': r"""Select element by function Parameter diff --git a/src/cpl_query/base/sequence_abc.py b/src/cpl_query/base/sequence_abc.py index 15b665d7..23bbf592 100644 --- a/src/cpl_query/base/sequence_abc.py +++ b/src/cpl_query/base/sequence_abc.py @@ -37,9 +37,6 @@ class SequenceABC(ABC): def type(self) -> type: return self._type - def reset(self): - self._values.reset() - def to_list(self) -> list: r"""Converts :class: `cpl_query.base.sequence_abc.SequenceABC` to :class: `list` diff --git a/src/cpl_query/base/sequence_values.py b/src/cpl_query/base/sequence_values.py index 79d7937c..c0a70526 100644 --- a/src/cpl_query/base/sequence_values.py +++ b/src/cpl_query/base/sequence_values.py @@ -19,20 +19,22 @@ class SequenceValues: if data is None: data = [] + if len(data) > 0: + def type_check(_t: type, _l: list): + return all(isinstance(x, _t) for x in _l) + + if not type_check(_t, data): + raise Exception(f'Unexpected type\nExpected type: {_t}') + if not hasattr(data, '__iter__'): raise TypeError(f'{type(self).__name__} must be instantiated with an iterable object') - self._data = [] - for element in data: - if _t is not None and type(element) != _t and not isinstance(type(element), _t) and not issubclass(type(element), _t): - raise Exception(f'Unexpected type: {type(element)}\nExpected type: {_t}') - self._data.append(element) + self._data = data self._index = 0 - self._len = sum(1 for item in self._data) self._cycle = itertools.cycle(self._data) def __len__(self): - return self._len + return sum(1 for item in self._data) def __iter__(self): i = 0 diff --git a/src/cpl_query/enumerable/enumerable.py b/src/cpl_query/enumerable/enumerable.py index 0b252c9c..10a528ce 100644 --- a/src/cpl_query/enumerable/enumerable.py +++ b/src/cpl_query/enumerable/enumerable.py @@ -1,7 +1,6 @@ -from typing import Union, Callable, Optional, Iterable +from typing import Union, Callable, Optional from cpl_query._helper import is_number -from cpl_query.base.sequence_values import SequenceValues from cpl_query.enumerable.enumerable_abc import EnumerableABC from cpl_query.enumerable.ordered_enumerable_abc import OrderedEnumerableABC from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException, IndexOutOfRangeException @@ -88,7 +87,7 @@ class Enumerable(EnumerableABC): return result def element_at(self, _index: int) -> any: - self.reset() + self._values.reset() while _index >= 0: current = self.next() if _index == 0: @@ -195,7 +194,7 @@ class Enumerable(EnumerableABC): @staticmethod def range(start: int, length: int) -> 'EnumerableABC': - return Enumerable(int, range(start, start + length, 1)) + return Enumerable(int, range(start, length)) def reverse(self: EnumerableABC) -> EnumerableABC: if self is None: @@ -295,7 +294,6 @@ class Enumerable(EnumerableABC): raise ArgumentNoneException(ExceptionArgument.index) _list = self.to_list() - index = len(_list) - _index if index >= len(_list) or index < 0: @@ -322,12 +320,4 @@ class Enumerable(EnumerableABC): if _func is None: raise ArgumentNoneException(ExceptionArgument.func) - if _func is None: - _func = _default_lambda - - result = Enumerable(self.type) - for element in self: - if _func(element): - result.add(element) - - return result + return Enumerable(self.type, [x for x in self if _func(x)]) diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index e844ec2a..7b32ea90 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -15,21 +15,21 @@ class IterableABC(SequenceABC, QueryableABC): SequenceABC.__init__(self, t, values) def __getitem__(self, n) -> object: - r"""Gets item in enumerable at specified zero-based index + return self.to_list().__getitem__(n) - Parameter - -------- - n: the index of the item to get + def __delitem__(self, i: int): + """Delete an item""" + _l = self.to_list() + del _l[i] + self._values = SequenceValues(_l, self._type) - Returns - ------- - The element at the specified index. + def __setitem__(self, i: int, value): + _l = self.to_list() + _l.__setitem__(i, value) + self._values = SequenceValues(_l, self._type) - Raises - ------ - IndexError if n > number of elements in the iterable - """ - return list.__getitem__(self.to_list(), n) + def __str__(self): + return str(self.to_list()) def append(self, __object: object) -> None: r"""Adds element to list diff --git a/unittests/unittests_query/iterable_test_case.py b/unittests/unittests_query/iterable_test_case.py index 1c7b6ca8..0185ec92 100644 --- a/unittests/unittests_query/iterable_test_case.py +++ b/unittests/unittests_query/iterable_test_case.py @@ -19,3 +19,17 @@ class IterableTestCase(unittest.TestCase): self.assertEqual(self._list.to_list(), [1, 2, 3]) self.assertRaises(Exception, lambda v: self._list.append(v), '3') + + def test_assign(self): + self._list.append(1) + self._list.append(2) + self._list.append(3) + self._list[0] = 42 + self.assertEqual(self._list[0], 42) + self._list[0] = 1 + self._list.append(42) + self.assertEqual(self._list[3], 42) + del self._list[3] + + self.assertEqual(self._list.to_list(), [1, 2, 3]) + self.assertRaises(Exception, lambda v: self._list.append(v), '3')