diff --git a/src/cpl_query/base/queryable_abc.py b/src/cpl_query/base/queryable_abc.py index 2a058959..e7d8f5ec 100644 --- a/src/cpl_query/base/queryable_abc.py +++ b/src/cpl_query/base/queryable_abc.py @@ -1,17 +1,17 @@ -from typing import Optional, Callable, Union +from typing import Optional, Callable, Union, Iterable from cpl_query._helper import is_number from cpl_query.base.sequence import Sequence from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException -def _default_lambda(x: object): +def _default_lambda(x: object) -> object: return x class QueryableABC(Sequence): - def __init__(self, t: type = None, values: list = None): + def __init__(self, t: type, values: Iterable = None): Sequence.__init__(self, t, values) def all(self, _func: Callable = None) -> bool: @@ -97,7 +97,7 @@ class QueryableABC(Sequence): if _func is None: return self.__len__() - return self.where(_func).__len__() + return self.where(_func).count() def distinct(self, _func: Callable = None) -> 'QueryableABC': r"""Returns list without redundancies @@ -144,7 +144,7 @@ class QueryableABC(Sequence): if _index < 0 or _index >= self.count(): raise IndexOutOfRangeException - result = self[_index] + result = self._values[_index] if result is None: raise IndexOutOfRangeException @@ -166,7 +166,7 @@ class QueryableABC(Sequence): raise ArgumentNoneException(ExceptionArgument.index) try: - return self[_index] + return self._values[_index] except IndexError: return None @@ -177,10 +177,10 @@ class QueryableABC(Sequence): ------- First element of list: any """ - if len(self) == 0: + if self.count() == 0: raise IndexOutOfRangeException() - return self[0] + return self._values[0] def first_or_default(self) -> any: r"""Returns first element or None @@ -189,10 +189,10 @@ class QueryableABC(Sequence): ------- First element of list: Optional[any] """ - if len(self) == 0: + if self.count() == 0: return None - return self[0] + return self._values[0] def for_each(self, _func: Callable = None): r"""Runs given function for each element of list @@ -221,14 +221,14 @@ class QueryableABC(Sequence): for v in self: value = _func(v) - if value not in groups: + if v not in groups: groups[value] = [] groups[value].append(v) v = [] for g in groups.values(): - v.append(type(self)(None, g)) + v.append(type(self)(object, g)) x = type(self)(type(self), v) return x @@ -239,10 +239,10 @@ class QueryableABC(Sequence): ------- Last element of list: any """ - if len(self) == 0: + if self.count() == 0: raise IndexOutOfRangeException() - return self[len(self) - 1] + return self._values[self.count() - 1] def last_or_default(self) -> any: r"""Returns last element or None @@ -251,12 +251,12 @@ class QueryableABC(Sequence): ------- Last element of list: Optional[any] """ - if len(self) == 0: + if self.count() == 0: return None - return self[len(self) - 1] + return self._values[self.count() - 1] - def max(self, _func: Callable = None) -> Union[int, float, complex]: + def max(self, _func: Callable = None) -> object: r"""Returns the highest value Parameter @@ -266,7 +266,7 @@ class QueryableABC(Sequence): Returns ------- - Union[int, float, complex] + object """ if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -295,7 +295,7 @@ class QueryableABC(Sequence): else (float(result[i - 1]) + float(result[i])) / float(2) ) - def min(self, _func: Callable = None) -> Union[int, float, complex]: + def min(self, _func: Callable = None) -> object: r"""Returns the lowest value Parameter @@ -305,7 +305,7 @@ class QueryableABC(Sequence): Returns ------- - Union[int, float, complex] + object """ if _func is None and not is_number(self.type): raise InvalidTypeException() @@ -358,7 +358,7 @@ class QueryableABC(Sequence): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - return type(self)(self._type, list(reversed(self))) + return type(self)(self._type, reversed(self._values)) def select(self, _func: Callable) -> 'QueryableABC': r"""Formats each element of list to a given format @@ -370,7 +370,7 @@ class QueryableABC(Sequence): if _func is None: _func = _default_lambda - return type(self)(any, [_func(_o) for _o in self]) + return type(self)(object, [_func(_o) for _o in self]) def select_many(self, _func: Callable) -> 'QueryableABC': r"""Flattens resulting lists to one @@ -381,7 +381,7 @@ class QueryableABC(Sequence): """ # The line below is pain. I don't understand anything of it... # written on 09.11.2022 by Sven Heidemann - return type(self)(any, [_a for _o in self for _a in _func(_o)]) + return type(self)(object, [_a for _o in self for _a in _func(_o)]) def single(self) -> any: r"""Returns one single element of list @@ -395,12 +395,12 @@ class QueryableABC(Sequence): ArgumentNoneException: when argument is None Exception: when argument is None or found more than one element """ - if len(self) > 1: + if self.count() > 1: raise Exception('Found more than one element') - elif len(self) == 0: + elif self.count() == 0: raise Exception('Found no element') - return self[0] + return self._values[0] def single_or_default(self) -> Optional[any]: r"""Returns one single element of list @@ -409,12 +409,12 @@ class QueryableABC(Sequence): ------- Found value: Optional[any] """ - if len(self) > 1: + if self.count() > 1: raise Exception('Index out of range') - elif len(self) == 0: + elif self.count() == 0: return None - return self[0] + return self._values[0] def skip(self, _index: int) -> 'QueryableABC': r"""Skips all elements from index @@ -431,7 +431,7 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - return type(self)(self.type, self[_index:]) + return type(self)(self.type, self._values[_index:]) def skip_last(self, _index: int) -> 'QueryableABC': r"""Skips all elements after index @@ -448,8 +448,8 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - index = len(self) - _index - return type(self)(self._type, self[:index]) + index = self.count() - _index + return type(self)(self._type, self._values[:index]) def sum(self, _func: Callable = None) -> Union[int, float, complex]: r"""Sum of all values @@ -523,7 +523,7 @@ class QueryableABC(Sequence): if _index is None: raise ArgumentNoneException(ExceptionArgument.index) - return type(self)(self._type, self[:_index]) + return type(self)(self._type, self._values[:_index]) def take_last(self, _index: int) -> 'QueryableABC': r"""Takes all elements after index @@ -537,12 +537,12 @@ class QueryableABC(Sequence): ------- :class: `cpl_query.base.queryable_abc.QueryableABC` """ - index = len(self) - _index + index = self.count() - _index - if index >= len(self) or index < 0: + if index >= self.count() or index < 0: raise IndexOutOfRangeException() - return type(self)(self._type, self[index:]) + return type(self)(self._type, self._values[index:]) def where(self, _func: Callable = None) -> 'QueryableABC': r"""Select element by function @@ -562,9 +562,4 @@ class QueryableABC(Sequence): if _func is None: _func = _default_lambda - result = [] - for element in self: - if _func(element): - result.append(element) - - return type(self)(self.type, result) + return type(self)(self.type, filter(_func, self)) diff --git a/src/cpl_query/base/sequence.py b/src/cpl_query/base/sequence.py index 15f7fc4a..cb97b1b3 100644 --- a/src/cpl_query/base/sequence.py +++ b/src/cpl_query/base/sequence.py @@ -1,29 +1,36 @@ -from abc import ABC, abstractmethod +from abc import abstractmethod, ABC +from typing import Iterable -class Sequence(list): +class Sequence(ABC): @abstractmethod - def __init__(self, t: type = None, values: list = None): - list.__init__(self) - ABC.__init__(self) - values = [] if values is None else values - list.__init__(self, values) + def __init__(self, t: type, values: Iterable = None): + if values is None: + values = [] - if t is None and len(values) > 0: - t = type(values[0]) + self._values = list(values) if t is None: - t = any + t = object self._type = t + def __iter__(self): + return iter(self._values) + + def __next__(self): + return next(iter(self._values)) + + def __len__(self): + return self.to_list().__len__() + @classmethod def __class_getitem__(cls, _t: type): return _t def __repr__(self): - return f'<{type(self).__name__} {list(self).__repr__()}>' + return f'<{type(self).__name__} {self.to_list().__repr__()}>' @property def type(self) -> type: @@ -43,7 +50,7 @@ class Sequence(list): ------- :class: `list` """ - return [x for x in self] + return [x for x in self._values] def copy(self) -> 'Sequence': r"""Creates a copy of sequence @@ -62,7 +69,7 @@ class Sequence(list): ------- Sequence object that contains no elements """ - return cls() + return cls(object, []) def index_of(self, _object: object) -> int: r"""Returns the index of given element @@ -83,4 +90,4 @@ class Sequence(list): @classmethod def range(cls, start: int, length: int) -> 'Sequence': - return cls(int, list(range(start, length))) + return cls(int, range(start, length)) diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index 04d3236a..48aede0d 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -4,7 +4,7 @@ "Version": { "Major": "2022", "Minor": "12", - "Micro": "1.post3" + "Micro": "2" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index 62e0d5b4..30722127 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -1,4 +1,4 @@ -from typing import Iterable as IterableType +from typing import Iterator from cpl_query.iterable.iterable import Iterable @@ -7,9 +7,18 @@ class List(Iterable): r"""Implementation of :class: `cpl_query.extension.iterable.Iterable` """ - def __init__(self, t: type = None, values: IterableType = None): + def __init__(self, t: type = None, values: Iterator = None): Iterable.__init__(self, t, values) + def __getitem__(self, *args): + return self._values.__getitem__(*args) + + def __setitem__(self, *args): + self._values.__setitem__(*args) + + def __delitem__(self, *args): + self._values.__delitem__(*args) + def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/src/cpl_query/iterable/iterable.py b/src/cpl_query/iterable/iterable.py index 38367269..07ec5b8d 100644 --- a/src/cpl_query/iterable/iterable.py +++ b/src/cpl_query/iterable/iterable.py @@ -1,4 +1,4 @@ -from typing import Iterable as IterableType +from typing import Iterable as TIterable from cpl_query.iterable.iterable_abc import IterableABC @@ -9,5 +9,5 @@ def _default_lambda(x: object): class Iterable(IterableABC): - def __init__(self, t: type = None, values: IterableType = None): + def __init__(self, t: type = None, values: TIterable = None): IterableABC.__init__(self, t, values) diff --git a/src/cpl_query/iterable/iterable_abc.py b/src/cpl_query/iterable/iterable_abc.py index 571a61e1..5640230b 100644 --- a/src/cpl_query/iterable/iterable_abc.py +++ b/src/cpl_query/iterable/iterable_abc.py @@ -12,10 +12,6 @@ class IterableABC(QueryableABC): def __init__(self, t: type = None, values: Iterable = None): QueryableABC.__init__(self, t, values) - @property - def type(self) -> type: - return self._type - def __str__(self): return str(self.to_list()) @@ -30,7 +26,7 @@ class IterableABC(QueryableABC): value """ self._check_type(_object) - super().append(_object) + self._values.append(_object) def extend(self, __iterable: Iterable) -> 'IterableABC': r"""Adds elements of given list to list @@ -54,7 +50,7 @@ class IterableABC(QueryableABC): if _object not in self: raise ValueError - super().remove(_object) + self._values.remove(_object) def remove_at(self, _index: int): r"""Removes element from list @@ -63,7 +59,7 @@ class IterableABC(QueryableABC): _object: :class:`object` value """ - self.pop(_index) + self._values.pop(_index) def to_enumerable(self) -> 'EnumerableABC': r"""Converts :class: `cpl_query.iterable.iterable_abc.IterableABC` to :class: `cpl_query.enumerable.enumerable_abc.EnumerableABC` diff --git a/unittests/unittests_query/enumerable_query_test_case.py b/unittests/unittests_query/enumerable_query_test_case.py index ffe71576..89db64d1 100644 --- a/unittests/unittests_query/enumerable_query_test_case.py +++ b/unittests/unittests_query/enumerable_query_test_case.py @@ -183,7 +183,7 @@ class EnumerableQueryTestCase(unittest.TestCase): res = self._tests.max(lambda u: u.address.nr) self.assertEqual(res, self._t_user.address.nr) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(99, tests.max()) def invalid(): @@ -196,7 +196,7 @@ class EnumerableQueryTestCase(unittest.TestCase): res = self._tests.min(lambda u: u.address.nr) self.assertEqual(1, res) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid(): @@ -319,7 +319,7 @@ class EnumerableQueryTestCase(unittest.TestCase): self.assertEqual(s_res, res) - tests = Enumerable(values=list(range(0, 100))) + tests = Enumerable(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid(): diff --git a/unittests/unittests_query/iterable_query_test_case.py b/unittests/unittests_query/iterable_query_test_case.py index 6dfa36f0..0e64ecbb 100644 --- a/unittests/unittests_query/iterable_query_test_case.py +++ b/unittests/unittests_query/iterable_query_test_case.py @@ -351,7 +351,7 @@ class IterableQueryTestCase(unittest.TestCase): self.assertEqual(s_res, res) - tests = List(values=list(range(0, 100))) + tests = List(int, list(range(0, 100))) self.assertEqual(0, tests.min()) def invalid():