From a26c6f1bd910850a643e54e2c42dc6885ec74bac Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 12:42:33 +0200 Subject: [PATCH] Improved avg, max and min queries type handling --- src/cpl_query/_extension/iterable.py | 8 ++--- src/cpl_query/_query/avg.py | 2 +- src/cpl_query/_query/max_min.py | 41 +++++++++++++------------ src/cpl_query/extension/iterable_abc.py | 8 ++++- src/cpl_query/tests/query_test.py | 4 +-- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index d2a9fb4e..abd06a14 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -64,11 +64,11 @@ class Iterable(IterableABC): def for_each(self, func: Callable): for_each_query(self, func) - def max(self, t: type, func: Callable) -> Union[int, float, complex]: - return max_query(self, t, func) + def max(self, func: Callable) -> Union[int, float, complex]: + return max_query(self, func) - def min(self, t: type, func: Callable) -> Union[int, float, complex]: - return min_query(self, t, func) + def min(self, func: Callable) -> Union[int, float, complex]: + return min_query(self, func) def order_by(self, func: Callable) -> OrderedIterableABC: res = order_by_query(self, func) diff --git a/src/cpl_query/_query/avg.py b/src/cpl_query/_query/avg.py index cf8d354a..ff299a3d 100644 --- a/src/cpl_query/_query/avg.py +++ b/src/cpl_query/_query/avg.py @@ -19,7 +19,7 @@ def avg_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] else: value = element - if _list.type is not None and type(element) != _list.type or not is_number(type(value)): + if _func is None and type(element) != _list.type or not is_number(type(value)): raise WrongTypeException() average += value diff --git a/src/cpl_query/_query/max_min.py b/src/cpl_query/_query/max_min.py index 82dc01c0..a6cae896 100644 --- a/src/cpl_query/_query/max_min.py +++ b/src/cpl_query/_query/max_min.py @@ -1,43 +1,46 @@ from collections import Callable from typing import Union -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException +from cpl_query._helper import is_number +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException, WrongTypeException from cpl_query.extension.iterable_abc import IterableABC -def max_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: +def max_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex]: if _list is None: raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - if _t != int and _t != float and _t != complex: - raise InvalidTypeException() - - max_value = _t() + max_value = 0 for element in _list: - value = _func(element) + if _func is not None: + value = _func(element) + else: + value = element + + if _func is None and type(value) != _list.type or not is_number(type(value)): + raise WrongTypeException() + if value > max_value: max_value = value return max_value -def min_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: +def min_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex]: if _list is None: raise ArgumentNoneException(ExceptionArgument.list) - if _func is None: - raise ArgumentNoneException(ExceptionArgument.func) - - if _t != int and _t != float and _t != complex: - raise InvalidTypeException() - - min_value = _t() + min_value = 0 is_first = True for element in _list: - value = _func(element) + if _func is not None: + value = _func(element) + else: + value = element + + if _func is None and type(value) != _list.type or not is_number(type(value)): + raise WrongTypeException() + if is_first: min_value = value is_first = False diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 76a61f72..e8b8c8a9 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -30,6 +30,9 @@ class IterableABC(ABC, list): if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type): raise Exception(f'Unexpected type: {type(__object)}') + if len(self) == 0 and self._type is None: + self._type = type(__object) + super().append(__object) @abstractmethod @@ -66,7 +69,10 @@ class IterableABC(ABC, list): def for_each(self, func: Callable) -> Union[int, float, complex]: pass @abstractmethod - def max(self, t: type, func: Callable) -> Union[int, float, complex]: pass + def max(self, func: Callable) -> Union[int, float, complex]: pass + + @abstractmethod + def min(self, func: Callable) -> Union[int, float, complex]: pass @abstractmethod def order_by(self, func: Callable) -> 'IterableABC': pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index e1d0b417..f150f56b 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -168,11 +168,11 @@ class QueryTest(unittest.TestCase): self.assertEqual(len(users), len(self._tests)) def test_max(self): - res = self._tests.max(int, lambda u: u.address.nr) + res = self._tests.max(lambda u: u.address.nr) self.assertEqual(self._t_user.address.nr, res) def test_min(self): - res = self._tests.min(int, lambda u: u.address.nr) + res = self._tests.min(lambda u: u.address.nr) self.assertEqual(1, res) def test_order_by(self):