From 5c80cf222235efdc1fafa9f56a35e854da8f7f7b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 25 Jul 2021 12:24:58 +0200 Subject: [PATCH 01/31] Added CPL Query --- cpl-workspace.json | 5 ++--- src/cpl_query/__init__.py | 25 +++++++++++++++++++++ src/cpl_query/cpl_query.json | 43 ++++++++++++++++++++++++++++++++++++ src/cpl_query/main.py | 9 ++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/cpl_query/__init__.py create mode 100644 src/cpl_query/cpl_query.json create mode 100644 src/cpl_query/main.py diff --git a/cpl-workspace.json b/cpl-workspace.json index 5ac236f3..73799eaa 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -3,9 +3,8 @@ "DefaultProject": "cpl_cli", "Projects": { "cpl": "src/cpl/cpl.json", - "cpl_cli": "src/cpl_cli/cpl_cli.json" - }, - "Scripts": { + "cpl_cli": "src/cpl_cli/cpl_cli.json", + "cpl_query": "src/cpl_query/cpl_query.json" } } } \ No newline at end of file diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py new file mode 100644 index 00000000..bf37461c --- /dev/null +++ b/src/cpl_query/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +cpl_query +~~~~~~~~~~~~~~~~~~~ + + + +:copyright: (c) +:license: + +""" + +__title__ = 'cpl_query' +__author__ = '' +__license__ = '' +__copyright__ = 'Copyright (c) ' +__version__ = '0.0.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='0', micro='0') diff --git a/src/cpl_query/cpl_query.json b/src/cpl_query/cpl_query.json new file mode 100644 index 00000000..1603c0c7 --- /dev/null +++ b/src/cpl_query/cpl_query.json @@ -0,0 +1,43 @@ +{ + "ProjectSettings": { + "Name": "cpl_query", + "Version": { + "Major": "2021", + "Minor": "10", + "Micro": "3" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Common Python library Query", + "LongDescription": "sh-edraft Common Python library Python integrated Queries", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2020 - 2021", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl==2021.4.0.post1" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../cpl-env/bin/python3.9" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "cpl_query.main", + "EntryPoint": "cpl_query", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/cpl_query/main.py b/src/cpl_query/main.py new file mode 100644 index 00000000..42e34771 --- /dev/null +++ b/src/cpl_query/main.py @@ -0,0 +1,9 @@ +from cpl.console import Console + + +def main(): + Console.write_line('Hello World') + + +if __name__ == '__main__': + main() -- 2.45.1 From 4e78b9c12b059890ba1e6d644ecdae4344ee9975 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 25 Jul 2021 19:15:02 +0200 Subject: [PATCH 02/31] Added different queries & unittests --- src/cpl_query/_query/__init__.py | 0 src/cpl_query/_query/any_query.py | 7 ++ src/cpl_query/_query/first_query.py | 17 ++++ src/cpl_query/_query/for_each_query.py | 8 ++ src/cpl_query/_query/single_query.py | 21 +++++ src/cpl_query/_query/where_query.py | 13 +++ src/cpl_query/cpl_query.json | 2 +- src/cpl_query/extension/__init__.py | 0 src/cpl_query/extension/iterable_abc.py | 30 +++++++ src/cpl_query/extension/list.py | 40 +++++++++ src/cpl_query/main.py | 9 -- src/cpl_query/tests/__init__.py | 0 src/cpl_query/tests/models.py | 12 +++ src/cpl_query/tests/query_test.py | 111 ++++++++++++++++++++++++ src/cpl_query/tests/tester.py | 23 +++++ 15 files changed, 283 insertions(+), 10 deletions(-) create mode 100644 src/cpl_query/_query/__init__.py create mode 100644 src/cpl_query/_query/any_query.py create mode 100644 src/cpl_query/_query/first_query.py create mode 100644 src/cpl_query/_query/for_each_query.py create mode 100644 src/cpl_query/_query/single_query.py create mode 100644 src/cpl_query/_query/where_query.py create mode 100644 src/cpl_query/extension/__init__.py create mode 100644 src/cpl_query/extension/iterable_abc.py create mode 100644 src/cpl_query/extension/list.py delete mode 100644 src/cpl_query/main.py create mode 100644 src/cpl_query/tests/__init__.py create mode 100644 src/cpl_query/tests/models.py create mode 100644 src/cpl_query/tests/query_test.py create mode 100644 src/cpl_query/tests/tester.py diff --git a/src/cpl_query/_query/__init__.py b/src/cpl_query/_query/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_query/_query/any_query.py b/src/cpl_query/_query/any_query.py new file mode 100644 index 00000000..8ff9456e --- /dev/null +++ b/src/cpl_query/_query/any_query.py @@ -0,0 +1,7 @@ +from cpl_query._query.where_query import where_query +from cpl_query.extension.iterable_abc import IterableABC + + +def any_query(_list: IterableABC, _func: str) -> bool: + result = where_query(_list, _func) + return len(result) > 0 diff --git a/src/cpl_query/_query/first_query.py b/src/cpl_query/_query/first_query.py new file mode 100644 index 00000000..d0917117 --- /dev/null +++ b/src/cpl_query/_query/first_query.py @@ -0,0 +1,17 @@ +from typing import Optional + +from cpl_query.extension.iterable_abc import IterableABC + + +def first_query(_list: IterableABC) -> any: + if len(_list) == 0: + raise Exception('Index out of range') + + return _list[0] + + +def first_or_default_query(_list: IterableABC) -> Optional[any]: + if len(_list) == 0: + return None + + return _list[0] diff --git a/src/cpl_query/_query/for_each_query.py b/src/cpl_query/_query/for_each_query.py new file mode 100644 index 00000000..6681bd0f --- /dev/null +++ b/src/cpl_query/_query/for_each_query.py @@ -0,0 +1,8 @@ +from collections import Callable + +from cpl_query.extension.iterable_abc import IterableABC + + +def for_each_query(_list: IterableABC, func: Callable): + for element in _list: + func(element) diff --git a/src/cpl_query/_query/single_query.py b/src/cpl_query/_query/single_query.py new file mode 100644 index 00000000..8ad30cef --- /dev/null +++ b/src/cpl_query/_query/single_query.py @@ -0,0 +1,21 @@ +from typing import Optional + +from cpl_query.extension.iterable_abc import IterableABC + + +def single_query(_list: IterableABC) -> any: + if len(_list) > 1: + raise Exception('Found more than one element') + elif len(_list) == 0: + raise Exception('Found no element') + + return _list[0] + + +def single_or_default_query(_list: IterableABC) -> Optional[any]: + if len(_list) > 1: + raise Exception('Index out of range') + elif len(_list) == 0: + return None + + return _list[0] diff --git a/src/cpl_query/_query/where_query.py b/src/cpl_query/_query/where_query.py new file mode 100644 index 00000000..97e3eefc --- /dev/null +++ b/src/cpl_query/_query/where_query.py @@ -0,0 +1,13 @@ +from cpl_query.extension.iterable_abc import IterableABC + + +def where_query(_list: IterableABC, _func: str) -> IterableABC: + result = IterableABC() + for element in _list: + element_type = type(element).__name__ + if element_type in _func: + func = _func.replace(element_type, 'element') + if eval(func): + result.append(element) + + return result diff --git a/src/cpl_query/cpl_query.json b/src/cpl_query/cpl_query.json index 1603c0c7..85334a56 100644 --- a/src/cpl_query/cpl_query.json +++ b/src/cpl_query/cpl_query.json @@ -20,7 +20,7 @@ ], "PythonVersion": ">=3.9.2", "PythonPath": { - "linux": "../../cpl-env/bin/python3.9" + "linux": "../cpl-env/bin/python3.9" }, "Classifiers": [] }, diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py new file mode 100644 index 00000000..0aceedf1 --- /dev/null +++ b/src/cpl_query/extension/iterable_abc.py @@ -0,0 +1,30 @@ +from abc import ABC, abstractmethod +from typing import Optional, Callable + + +class IterableABC(ABC, list): + + @abstractmethod + def __init__(self): + list.__init__(self) + + @abstractmethod + def any(self, func: str) -> bool: pass + + @abstractmethod + def first(self) -> any: pass + + @abstractmethod + def first_or_default(self) -> any: pass + + @abstractmethod + def for_each(self, func: Callable): pass + + @abstractmethod + def single(self): pass + + @abstractmethod + def single_or_default(self) -> Optional[any]: pass + + @abstractmethod + def where(self, func: str) -> 'IterableABC': pass diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py new file mode 100644 index 00000000..b8eebcf3 --- /dev/null +++ b/src/cpl_query/extension/list.py @@ -0,0 +1,40 @@ +from typing import Optional, Callable + +from .._query.any_query import any_query +from .._query.first_query import first_or_default_query, first_query +from .._query.for_each_query import for_each_query +from .._query.single_query import single_query, single_or_default_query +from .._query.where_query import where_query +from cpl_query.extension.iterable_abc import IterableABC + + +class List(IterableABC): + + def __init__(self): + IterableABC.__init__(self) + + def any(self, func: str) -> bool: + return any_query(self, func) + + def first(self) -> any: + return first_query(self) + + def first_or_default(self) -> Optional[any]: + return first_or_default_query(self) + + def for_each(self, func: Callable): + for_each_query(self, func) + + def single(self) -> any: + return single_query(self) + + def single_or_default(self) -> Optional[any]: + return single_or_default_query(self) + + def where(self, func: str) -> IterableABC: + res = where_query(self, func) + res.__class__ = List + return res + + def to_list(self) -> list: + return list(self) diff --git a/src/cpl_query/main.py b/src/cpl_query/main.py deleted file mode 100644 index 42e34771..00000000 --- a/src/cpl_query/main.py +++ /dev/null @@ -1,9 +0,0 @@ -from cpl.console import Console - - -def main(): - Console.write_line('Hello World') - - -if __name__ == '__main__': - main() diff --git a/src/cpl_query/tests/__init__.py b/src/cpl_query/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_query/tests/models.py b/src/cpl_query/tests/models.py new file mode 100644 index 00000000..d3b147dd --- /dev/null +++ b/src/cpl_query/tests/models.py @@ -0,0 +1,12 @@ +class User: + + def __init__(self, name, address): + self.name = name + self.address = address + + +class Address: + + def __init__(self, street, nr): + self.street = street + self.nr = nr \ No newline at end of file diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py new file mode 100644 index 00000000..c85c2dec --- /dev/null +++ b/src/cpl_query/tests/query_test.py @@ -0,0 +1,111 @@ +import string +import unittest +from random import randint + +from cpl.utils import String +from cpl_query.extension.list import List +from cpl_query.tests.models import User, Address + + +class QueryTest(unittest.TestCase): + + def setUp(self) -> None: + self._tests = List() + self._t_user = User( + 'Test user', + Address( + 'teststr.', + 15 + ) + ) + + self._generate_test_data() + + def _generate_test_data(self): + for i in range(0, 100): + user = User( + String.random_string(string.ascii_letters, 8), + Address( + String.random_string(string.ascii_letters, 10), + randint(0, 10) + ) + ) + + self._tests.append(user) + + self._tests.append(self._t_user) + + def test_any(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.any(f'User.address.nr == 10') + n_res = self._tests.any(f'User.address.nr == 100') + + self.assertTrue(res) + self.assertFalse(n_res) + + def test_first(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.where(f'User.address.nr == 10') + s_res = self._tests.where(f'User.address.nr == 10').first() + + self.assertEqual(len(res), len(results)) + self.assertIsNotNone(s_res) + + def test_first_or_default(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.where(f'User.address.nr == 10') + s_res = self._tests.where(f'User.address.nr == 10').first_or_default() + sn_res = self._tests.where(f'User.address.nr == 11').first_or_default() + + self.assertEqual(len(res), len(results)) + self.assertIsNotNone(s_res) + self.assertIsNone(sn_res) + + def test_for_each(self): + users = [] + self._tests.for_each( + lambda user: ( + # Console.write_line(f'User: {user.name} | '), + # Console.write(f'Address: {user.address.street}'), + users.append(user) + ) + ) + + self.assertEqual(len(users), len(self._tests)) + + def test_single(self): + res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}') + s_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}').single() + + self.assertEqual(len(res), 1) + self.assertEqual(self._t_user, s_res) + + def test_single_or_default(self): + res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}') + s_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}').single_or_default() + sn_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr + 1}').single_or_default() + + self.assertEqual(len(res), 1) + self.assertEqual(self._t_user, s_res) + self.assertIsNone(sn_res) + + def test_where(self): + results = [] + for user in self._tests: + if user.address.nr == 5: + results.append(user) + + res = self._tests.where('User.address.nr == 5') + self.assertEqual(len(results), len(res)) diff --git a/src/cpl_query/tests/tester.py b/src/cpl_query/tests/tester.py new file mode 100644 index 00000000..98b10ebb --- /dev/null +++ b/src/cpl_query/tests/tester.py @@ -0,0 +1,23 @@ +import unittest + +from cpl_query.tests.query_test import QueryTest + + +class Tester: + + def __init__(self): + self._suite = unittest.TestSuite() + + def create(self): + loader = unittest.TestLoader() + self._suite.addTests(loader.loadTestsFromTestCase(QueryTest)) + + def start(self): + runner = unittest.TextTestRunner() + runner.run(self._suite) + + +if __name__ == '__main__': + tester = Tester() + tester.create() + tester.start() -- 2.45.1 From cc7755bafcc689f94697c80f9c58c312ef40ac98 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Sun, 25 Jul 2021 19:18:06 +0200 Subject: [PATCH 03/31] Improved cli project builders --- cpl-workspace.json | 3 ++- src/cpl_cli/source_creator/console_builder.py | 3 ++- src/cpl_cli/source_creator/library_builder.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cpl-workspace.json b/cpl-workspace.json index 73799eaa..a8752234 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -5,6 +5,7 @@ "cpl": "src/cpl/cpl.json", "cpl_cli": "src/cpl_cli/cpl_cli.json", "cpl_query": "src/cpl_query/cpl_query.json" - } + }, + "Scripts": {} } } \ No newline at end of file diff --git a/src/cpl_cli/source_creator/console_builder.py b/src/cpl_cli/source_creator/console_builder.py index 2e321b37..a48d0d0b 100644 --- a/src/cpl_cli/source_creator/console_builder.py +++ b/src/cpl_cli/source_creator/console_builder.py @@ -43,7 +43,8 @@ class ConsoleBuilder: ws_dict = { WorkspaceSettings.__name__: { WorkspaceSettingsNameEnum.default_project.value: project_name, - WorkspaceSettingsNameEnum.projects.value: projects + WorkspaceSettingsNameEnum.projects.value: projects, + WorkspaceSettingsNameEnum.scripts: {} } } diff --git a/src/cpl_cli/source_creator/library_builder.py b/src/cpl_cli/source_creator/library_builder.py index 2f410dcb..78f18908 100644 --- a/src/cpl_cli/source_creator/library_builder.py +++ b/src/cpl_cli/source_creator/library_builder.py @@ -43,7 +43,8 @@ class LibraryBuilder: ws_dict = { WorkspaceSettings.__name__: { WorkspaceSettingsNameEnum.default_project.value: project_name, - WorkspaceSettingsNameEnum.projects.value: projects + WorkspaceSettingsNameEnum.projects.value: projects, + WorkspaceSettingsNameEnum.scripts: {} } } -- 2.45.1 From 0cae3428b9b636a2dcb026356cb8bbe592727ce8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 26 Jul 2021 15:21:57 +0200 Subject: [PATCH 04/31] Added order by functions --- src/cpl_query/_query/order_by.py | 28 ++++++++++ src/cpl_query/extension/iterable.py | 53 +++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 6 +++ src/cpl_query/extension/list.py | 42 +++------------ src/cpl_query/extension/ordered_iterable.py | 19 +++++++ .../extension/ordered_iterable_abc.py | 20 +++++++ src/cpl_query/tests/query_test.py | 42 +++++++++++++-- 7 files changed, 172 insertions(+), 38 deletions(-) create mode 100644 src/cpl_query/_query/order_by.py create mode 100644 src/cpl_query/extension/iterable.py create mode 100644 src/cpl_query/extension/ordered_iterable.py create mode 100644 src/cpl_query/extension/ordered_iterable_abc.py diff --git a/src/cpl_query/_query/order_by.py b/src/cpl_query/_query/order_by.py new file mode 100644 index 00000000..12cea7b3 --- /dev/null +++ b/src/cpl_query/_query/order_by.py @@ -0,0 +1,28 @@ +from collections import Callable + +from cpl_query.extension.iterable_abc import IterableABC +from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC + + +def order_by_query(_list: IterableABC, _func: Callable) -> OrderedIterableABC: + result = OrderedIterableABC(_func) + _list.sort(key=_func) + result.extend(_list) + return result + + +def order_by_descending_query(_list: IterableABC, _func: Callable) -> OrderedIterableABC: + result = OrderedIterableABC(_func) + _list.sort(key=_func, reverse=True) + result.extend(_list) + return result + + +def then_by_query(_list: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: + _list.sort(key=_func) + return _list + + +def then_by_descending_query(_list: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: + _list.sort(key=_func, reverse=True) + return _list diff --git a/src/cpl_query/extension/iterable.py b/src/cpl_query/extension/iterable.py new file mode 100644 index 00000000..50926fa6 --- /dev/null +++ b/src/cpl_query/extension/iterable.py @@ -0,0 +1,53 @@ +from typing import Optional, Callable + +from .ordered_iterable import OrderedIterable +from .ordered_iterable_abc import OrderedIterableABC +from .._query.any_query import any_query +from .._query.first_query import first_or_default_query, first_query +from .._query.for_each_query import for_each_query +from .._query.order_by import order_by_query, order_by_descending_query +from .._query.single_query import single_query, single_or_default_query +from .._query.where_query import where_query +from cpl_query.extension.iterable_abc import IterableABC + + +class Iterable(IterableABC): + + def __init__(self): + IterableABC.__init__(self) + + def any(self, func: str) -> bool: + return any_query(self, func) + + def first(self) -> any: + return first_query(self) + + def first_or_default(self) -> Optional[any]: + return first_or_default_query(self) + + def for_each(self, func: Callable): + for_each_query(self, func) + + def order_by(self, func: Callable) -> OrderedIterableABC: + res = order_by_query(self, func) + res.__class__ = OrderedIterable + return res + + def order_by_descending(self, func: Callable) -> OrderedIterableABC: + res = order_by_descending_query(self, func) + res.__class__ = OrderedIterable + return res + + def single(self) -> any: + return single_query(self) + + def single_or_default(self) -> Optional[any]: + return single_or_default_query(self) + + def where(self, func: str) -> IterableABC: + res = where_query(self, func) + res.__class__ = Iterable + return res + + def to_list(self) -> list: + return list(self) diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 0aceedf1..e4bf8f80 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -20,6 +20,12 @@ class IterableABC(ABC, list): @abstractmethod def for_each(self, func: Callable): pass + @abstractmethod + def order_by(self, func: Callable): pass + + @abstractmethod + def order_by_descending(self, func: Callable): pass + @abstractmethod def single(self): pass diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index b8eebcf3..b216b18f 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -1,40 +1,12 @@ -from typing import Optional, Callable - -from .._query.any_query import any_query -from .._query.first_query import first_or_default_query, first_query -from .._query.for_each_query import for_each_query -from .._query.single_query import single_query, single_or_default_query -from .._query.where_query import where_query -from cpl_query.extension.iterable_abc import IterableABC +from cpl_query.extension.iterable import Iterable -class List(IterableABC): +class List(Iterable): - def __init__(self): - IterableABC.__init__(self) + def __init__(self, t: type = None, values: list = None): + Iterable.__init__(self) - def any(self, func: str) -> bool: - return any_query(self, func) + self._type = t - def first(self) -> any: - return first_query(self) - - def first_or_default(self) -> Optional[any]: - return first_or_default_query(self) - - def for_each(self, func: Callable): - for_each_query(self, func) - - def single(self) -> any: - return single_query(self) - - def single_or_default(self) -> Optional[any]: - return single_or_default_query(self) - - def where(self, func: str) -> IterableABC: - res = where_query(self, func) - res.__class__ = List - return res - - def to_list(self) -> list: - return list(self) + if values is not None: + self.extend(values) diff --git a/src/cpl_query/extension/ordered_iterable.py b/src/cpl_query/extension/ordered_iterable.py new file mode 100644 index 00000000..d7c168e9 --- /dev/null +++ b/src/cpl_query/extension/ordered_iterable.py @@ -0,0 +1,19 @@ +from abc import ABC +from collections import Callable + +from .._query.order_by import then_by_query, then_by_descending_query +from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC + + +class OrderedIterable(OrderedIterableABC, ABC): + + def __init__(self): + OrderedIterableABC.__init__(self) + + def then_by(self, _func: Callable) -> OrderedIterableABC: + self._funcs.append(_func) + return then_by_query(self, lambda *args: [f(*args) for f in self._funcs]) + + def then_by_descending(self, _func: Callable) -> OrderedIterableABC: + self._funcs.append(_func) + return then_by_descending_query(self, lambda *args: [f(*args) for f in self._funcs]) diff --git a/src/cpl_query/extension/ordered_iterable_abc.py b/src/cpl_query/extension/ordered_iterable_abc.py new file mode 100644 index 00000000..f64e15bd --- /dev/null +++ b/src/cpl_query/extension/ordered_iterable_abc.py @@ -0,0 +1,20 @@ +from abc import abstractmethod +from collections import Callable + +from cpl_query.extension.iterable_abc import IterableABC + + +class OrderedIterableABC(IterableABC): + + @abstractmethod + def __init__(self, _func: Callable = None): + IterableABC.__init__(self) + self._funcs: list[Callable] = [] + if _func is not None: + self._funcs.append(_func) + + @abstractmethod + def then_by(self, func: Callable) -> 'OrderedIterableABC': pass + + @abstractmethod + def then_by_descending(self, func: Callable) -> 'OrderedIterableABC': pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index c85c2dec..4c9ca6dc 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -10,7 +10,7 @@ from cpl_query.tests.models import User, Address class QueryTest(unittest.TestCase): def setUp(self) -> None: - self._tests = List() + self._tests = List(User) self._t_user = User( 'Test user', Address( @@ -24,9 +24,9 @@ class QueryTest(unittest.TestCase): def _generate_test_data(self): for i in range(0, 100): user = User( - String.random_string(string.ascii_letters, 8), + String.random_string(string.ascii_letters, 8).lower(), Address( - String.random_string(string.ascii_letters, 10), + String.random_string(string.ascii_letters, 10).lower(), randint(0, 10) ) ) @@ -85,6 +85,42 @@ class QueryTest(unittest.TestCase): self.assertEqual(len(users), len(self._tests)) + def test_order_by(self): + res = self._tests.order_by(lambda user: user.address.street) + res2 = self._tests.order_by(lambda user: user.address.nr) + s_res = self._tests + s_res.sort(key=lambda user: user.address.street) + + self.assertEqual(res, s_res) + s_res.sort(key=lambda user: user.address.nr) + self.assertEqual(res2, s_res) + + def test_order_by_descending(self): + res = self._tests.order_by_descending(lambda user: user.address.street) + res2 = self._tests.order_by_descending(lambda user: user.address.nr) + s_res = self._tests + s_res.sort(key=lambda user: user.address.street, reverse=True) + + self.assertEqual(res, s_res) + s_res.sort(key=lambda user: user.address.nr, reverse=True) + self.assertEqual(res2, s_res) + + def test_then_by(self): + res = self._tests.order_by(lambda user: user.address.street[0]).then_by(lambda user: user.address.nr) + + s_res = self._tests + s_res.sort(key=lambda user: (user.address.street[0], user.address.nr)) + + self.assertEqual(res, s_res) + + def test_then_by_descending(self): + res = self._tests.order_by_descending(lambda user: user.address.street[0]).then_by_descending(lambda user: user.address.nr) + + s_res = self._tests + s_res.sort(key=lambda user: (user.address.street[0], user.address.nr), reverse=True) + + self.assertEqual(res, s_res) + def test_single(self): res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}') s_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}').single() -- 2.45.1 From b7be43938149f1aa8ff7ddf1e28d57a31e1bdbd8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 26 Jul 2021 15:32:28 +0200 Subject: [PATCH 05/31] Changed func type from str to Callable --- src/cpl_query/_query/any_query.py | 4 +++- src/cpl_query/_query/where_query.py | 14 +++++++---- src/cpl_query/extension/iterable.py | 4 ++-- src/cpl_query/extension/iterable_abc.py | 4 ++-- src/cpl_query/tests/query_test.py | 32 ++++++++++++------------- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/cpl_query/_query/any_query.py b/src/cpl_query/_query/any_query.py index 8ff9456e..ff85fa98 100644 --- a/src/cpl_query/_query/any_query.py +++ b/src/cpl_query/_query/any_query.py @@ -1,7 +1,9 @@ +from collections import Callable + from cpl_query._query.where_query import where_query from cpl_query.extension.iterable_abc import IterableABC -def any_query(_list: IterableABC, _func: str) -> bool: +def any_query(_list: IterableABC, _func: Callable) -> bool: result = where_query(_list, _func) return len(result) > 0 diff --git a/src/cpl_query/_query/where_query.py b/src/cpl_query/_query/where_query.py index 97e3eefc..3c73b5b2 100644 --- a/src/cpl_query/_query/where_query.py +++ b/src/cpl_query/_query/where_query.py @@ -1,13 +1,17 @@ +from collections import Callable + from cpl_query.extension.iterable_abc import IterableABC -def where_query(_list: IterableABC, _func: str) -> IterableABC: +def where_query(_list: IterableABC, _func: Callable) -> IterableABC: result = IterableABC() for element in _list: element_type = type(element).__name__ - if element_type in _func: - func = _func.replace(element_type, 'element') - if eval(func): - result.append(element) + if _func(element): + result.append(element) + # if element_type in _func: + # func = _func.replace(element_type, 'element') + # if eval(func): + # result.append(element) return result diff --git a/src/cpl_query/extension/iterable.py b/src/cpl_query/extension/iterable.py index 50926fa6..d5844620 100644 --- a/src/cpl_query/extension/iterable.py +++ b/src/cpl_query/extension/iterable.py @@ -16,7 +16,7 @@ class Iterable(IterableABC): def __init__(self): IterableABC.__init__(self) - def any(self, func: str) -> bool: + def any(self, func: Callable) -> bool: return any_query(self, func) def first(self) -> any: @@ -44,7 +44,7 @@ class Iterable(IterableABC): def single_or_default(self) -> Optional[any]: return single_or_default_query(self) - def where(self, func: str) -> IterableABC: + def where(self, func: Callable) -> IterableABC: res = where_query(self, func) res.__class__ = Iterable return res diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index e4bf8f80..63d5d97b 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -9,7 +9,7 @@ class IterableABC(ABC, list): list.__init__(self) @abstractmethod - def any(self, func: str) -> bool: pass + def any(self, func: Callable) -> bool: pass @abstractmethod def first(self) -> any: pass @@ -33,4 +33,4 @@ class IterableABC(ABC, list): def single_or_default(self) -> Optional[any]: pass @abstractmethod - def where(self, func: str) -> 'IterableABC': pass + def where(self, func: Callable) -> 'IterableABC': pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 4c9ca6dc..2d0e8784 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -41,8 +41,8 @@ class QueryTest(unittest.TestCase): if user.address.nr == 10: results.append(user) - res = self._tests.any(f'User.address.nr == 10') - n_res = self._tests.any(f'User.address.nr == 100') + res = self._tests.any(lambda u: u.address.nr == 10) + n_res = self._tests.any(lambda u: u.address.nr == 100) self.assertTrue(res) self.assertFalse(n_res) @@ -53,8 +53,8 @@ class QueryTest(unittest.TestCase): if user.address.nr == 10: results.append(user) - res = self._tests.where(f'User.address.nr == 10') - s_res = self._tests.where(f'User.address.nr == 10').first() + res = self._tests.where(lambda u: u.address.nr == 10) + s_res = self._tests.where(lambda u: u.address.nr == 10).first() self.assertEqual(len(res), len(results)) self.assertIsNotNone(s_res) @@ -65,9 +65,9 @@ class QueryTest(unittest.TestCase): if user.address.nr == 10: results.append(user) - res = self._tests.where(f'User.address.nr == 10') - s_res = self._tests.where(f'User.address.nr == 10').first_or_default() - sn_res = self._tests.where(f'User.address.nr == 11').first_or_default() + res = self._tests.where(lambda u: u.address.nr == 10) + s_res = self._tests.where(lambda u: u.address.nr == 10).first_or_default() + sn_res = self._tests.where(lambda u: u.address.nr == 11).first_or_default() self.assertEqual(len(res), len(results)) self.assertIsNotNone(s_res) @@ -77,8 +77,6 @@ class QueryTest(unittest.TestCase): users = [] self._tests.for_each( lambda user: ( - # Console.write_line(f'User: {user.name} | '), - # Console.write(f'Address: {user.address.street}'), users.append(user) ) ) @@ -114,7 +112,8 @@ class QueryTest(unittest.TestCase): self.assertEqual(res, s_res) def test_then_by_descending(self): - res = self._tests.order_by_descending(lambda user: user.address.street[0]).then_by_descending(lambda user: user.address.nr) + res = self._tests.order_by_descending(lambda user: user.address.street[0]).then_by_descending( + lambda user: user.address.nr) s_res = self._tests s_res.sort(key=lambda user: (user.address.street[0], user.address.nr), reverse=True) @@ -122,16 +121,16 @@ class QueryTest(unittest.TestCase): self.assertEqual(res, s_res) def test_single(self): - res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}') - s_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}').single() + res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr) + s_res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr).single() self.assertEqual(len(res), 1) self.assertEqual(self._t_user, s_res) def test_single_or_default(self): - res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}') - s_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr}').single_or_default() - sn_res = self._tests.where(f'User.address.nr == {self._t_user.address.nr + 1}').single_or_default() + res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr) + s_res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr).single_or_default() + sn_res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr + 1).single_or_default() self.assertEqual(len(res), 1) self.assertEqual(self._t_user, s_res) @@ -143,5 +142,6 @@ class QueryTest(unittest.TestCase): if user.address.nr == 5: results.append(user) - res = self._tests.where('User.address.nr == 5') + res = self._tests.where(lambda u: u.address.nr == 5) + # res = self._tests.where('User.address.nr == 5') self.assertEqual(len(results), len(res)) -- 2.45.1 From 94949394de58545ca50bafc20462ae39236e5aea Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 26 Jul 2021 15:48:42 +0200 Subject: [PATCH 06/31] Improved list to handle typing --- src/cpl_query/extension/list.py | 6 ++++++ src/cpl_query/tests/iterable_test.py | 28 ++++++++++++++++++++++++++++ src/cpl_query/tests/query_test.py | 1 - src/cpl_query/tests/tester.py | 2 ++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/cpl_query/tests/iterable_test.py diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index b216b18f..7496d43c 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -10,3 +10,9 @@ class List(Iterable): if values is not None: self.extend(values) + + def append(self, __object: object) -> None: + 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)}') + + super().append(__object) diff --git a/src/cpl_query/tests/iterable_test.py b/src/cpl_query/tests/iterable_test.py new file mode 100644 index 00000000..9b12b28e --- /dev/null +++ b/src/cpl_query/tests/iterable_test.py @@ -0,0 +1,28 @@ +import unittest + +from cpl_query.extension.list import List + + +class IterableTest(unittest.TestCase): + + def setUp(self) -> None: + self._list = List(int) + + def _clear(self): + self._list.clear() + self.assertEqual(self._list, []) + + def test_append(self): + self._list.append(1) + self._list.append(2) + self._list.append(3) + + self.assertEqual(self._list, [1, 2, 3]) + self._clear() + + def test_append_wrong_type(self): + self._list.append(1) + self._list.append(2) + + self.assertRaises(Exception, lambda v: self._list.append(v), '3') + self._clear() diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 2d0e8784..9135c434 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -143,5 +143,4 @@ class QueryTest(unittest.TestCase): results.append(user) res = self._tests.where(lambda u: u.address.nr == 5) - # res = self._tests.where('User.address.nr == 5') self.assertEqual(len(results), len(res)) diff --git a/src/cpl_query/tests/tester.py b/src/cpl_query/tests/tester.py index 98b10ebb..084071c3 100644 --- a/src/cpl_query/tests/tester.py +++ b/src/cpl_query/tests/tester.py @@ -1,5 +1,6 @@ import unittest +from cpl_query.tests.iterable_test import IterableTest from cpl_query.tests.query_test import QueryTest @@ -11,6 +12,7 @@ class Tester: def create(self): loader = unittest.TestLoader() self._suite.addTests(loader.loadTestsFromTestCase(QueryTest)) + self._suite.addTests(loader.loadTestsFromTestCase(IterableTest)) def start(self): runner = unittest.TextTestRunner() -- 2.45.1 From 8dcf3a67681c4f86aa6ffbb182b7cae85ae5f323 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 26 Jul 2021 15:52:27 +0200 Subject: [PATCH 07/31] Refactoring --- src/cpl_query/_extension/__init__.py | 0 src/cpl_query/{extension => _extension}/iterable.py | 4 ++-- src/cpl_query/{extension => _extension}/ordered_iterable.py | 0 src/cpl_query/extension/list.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 src/cpl_query/_extension/__init__.py rename src/cpl_query/{extension => _extension}/iterable.py (91%) rename src/cpl_query/{extension => _extension}/ordered_iterable.py (100%) diff --git a/src/cpl_query/_extension/__init__.py b/src/cpl_query/_extension/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cpl_query/extension/iterable.py b/src/cpl_query/_extension/iterable.py similarity index 91% rename from src/cpl_query/extension/iterable.py rename to src/cpl_query/_extension/iterable.py index d5844620..690a8cd3 100644 --- a/src/cpl_query/extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -1,7 +1,7 @@ from typing import Optional, Callable -from .ordered_iterable import OrderedIterable -from .ordered_iterable_abc import OrderedIterableABC +from cpl_query._extension.ordered_iterable import OrderedIterable +from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC from .._query.any_query import any_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query diff --git a/src/cpl_query/extension/ordered_iterable.py b/src/cpl_query/_extension/ordered_iterable.py similarity index 100% rename from src/cpl_query/extension/ordered_iterable.py rename to src/cpl_query/_extension/ordered_iterable.py diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index 7496d43c..94eeeb09 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -1,4 +1,4 @@ -from cpl_query.extension.iterable import Iterable +from .._extension.iterable import Iterable class List(Iterable): -- 2.45.1 From a3fff9c7d7d12039414b21012733c42cc5178676 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 26 Jul 2021 15:55:08 +0200 Subject: [PATCH 08/31] Build package --- src/cpl_query/__init__.py | 18 +++++++++--------- src/cpl_query/_extension/__init__.py | 25 +++++++++++++++++++++++++ src/cpl_query/_query/__init__.py | 25 +++++++++++++++++++++++++ src/cpl_query/cpl_query.json | 4 +--- src/cpl_query/extension/__init__.py | 25 +++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index bf37461c..4c2a8ace 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -1,25 +1,25 @@ # -*- coding: utf-8 -*- """ -cpl_query +cpl_query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ +sh-edraft Common Python library Python integrated Queries - -:copyright: (c) -:license: +:copyright: (c) 2020 - 2021 sh-edraft.de +:license: MIT, see LICENSE for more details. """ __title__ = 'cpl_query' -__author__ = '' -__license__ = '' -__copyright__ = 'Copyright (c) ' -__version__ = '0.0.0' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' +__version__ = '2021.10.3' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='0', micro='0') +version_info = VersionInfo(major='2021', minor='10', micro='3') diff --git a/src/cpl_query/_extension/__init__.py b/src/cpl_query/_extension/__init__.py index e69de29b..be7ebebb 100644 --- a/src/cpl_query/_extension/__init__.py +++ b/src/cpl_query/_extension/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +cpl_query sh-edraft Common Python library Query +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Python integrated Queries + +:copyright: (c) 2020 - 2021 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'cpl_query._extension' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' +__version__ = '2021.10.3' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='10', micro='3') diff --git a/src/cpl_query/_query/__init__.py b/src/cpl_query/_query/__init__.py index e69de29b..d9873974 100644 --- a/src/cpl_query/_query/__init__.py +++ b/src/cpl_query/_query/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +cpl_query sh-edraft Common Python library Query +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Python integrated Queries + +:copyright: (c) 2020 - 2021 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'cpl_query._query' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' +__version__ = '2021.10.3' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='10', micro='3') diff --git a/src/cpl_query/cpl_query.json b/src/cpl_query/cpl_query.json index 85334a56..c2d0a970 100644 --- a/src/cpl_query/cpl_query.json +++ b/src/cpl_query/cpl_query.json @@ -19,9 +19,7 @@ "sh_cpl==2021.4.0.post1" ], "PythonVersion": ">=3.9.2", - "PythonPath": { - "linux": "../cpl-env/bin/python3.9" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index e69de29b..22693b99 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +cpl_query sh-edraft Common Python library Query +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Common Python library Python integrated Queries + +:copyright: (c) 2020 - 2021 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'cpl_query.extension' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' +__version__ = '2021.10.3' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='2021', minor='10', micro='3') -- 2.45.1 From 0f85d4b9bce9019abe2897b646243c1ad512b33e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 09:15:19 +0200 Subject: [PATCH 09/31] Refactoring & added all query --- src/cpl_query/_extension/iterable.py | 4 ++++ src/cpl_query/_query/all_query.py | 9 +++++++++ src/cpl_query/_query/where_query.py | 5 ----- src/cpl_query/extension/iterable_abc.py | 3 +++ src/cpl_query/tests/query_test.py | 12 ++++++++++++ 5 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 src/cpl_query/_query/all_query.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 690a8cd3..2db2c507 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -2,6 +2,7 @@ from typing import Optional, Callable from cpl_query._extension.ordered_iterable import OrderedIterable from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC +from .._query.all_query import all_query from .._query.any_query import any_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query @@ -19,6 +20,9 @@ class Iterable(IterableABC): def any(self, func: Callable) -> bool: return any_query(self, func) + def all(self, func: Callable) -> bool: + return all_query(self, func) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/all_query.py b/src/cpl_query/_query/all_query.py new file mode 100644 index 00000000..33c9e4c6 --- /dev/null +++ b/src/cpl_query/_query/all_query.py @@ -0,0 +1,9 @@ +from collections import Callable + +from cpl_query._query.where_query import where_query +from cpl_query.extension.iterable_abc import IterableABC + + +def all_query(_list: IterableABC, _func: Callable) -> bool: + result = where_query(_list, _func) + return len(result) == len(_list) diff --git a/src/cpl_query/_query/where_query.py b/src/cpl_query/_query/where_query.py index 3c73b5b2..92593fdd 100644 --- a/src/cpl_query/_query/where_query.py +++ b/src/cpl_query/_query/where_query.py @@ -6,12 +6,7 @@ from cpl_query.extension.iterable_abc import IterableABC def where_query(_list: IterableABC, _func: Callable) -> IterableABC: result = IterableABC() for element in _list: - element_type = type(element).__name__ if _func(element): result.append(element) - # if element_type in _func: - # func = _func.replace(element_type, 'element') - # if eval(func): - # result.append(element) return result diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 63d5d97b..b4ce047d 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -11,6 +11,9 @@ class IterableABC(ABC, list): @abstractmethod def any(self, func: Callable) -> bool: pass + @abstractmethod + def all(self, func: Callable) -> bool: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 9135c434..5020183f 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -47,6 +47,18 @@ class QueryTest(unittest.TestCase): self.assertTrue(res) self.assertFalse(n_res) + def test_all(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.all(lambda u: u.address is not None) + n_res = self._tests.all(lambda u: u.address.nr == 100) + + self.assertTrue(res) + self.assertFalse(n_res) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From e0b77287192c3d0f2224d2236928f8327fc18f3e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 09:26:30 +0200 Subject: [PATCH 10/31] Added avg query --- src/cpl_query/_extension/iterable.py | 6 +++++- src/cpl_query/_query/avg_query.py | 22 ++++++++++++++++++++++ src/cpl_query/exceptions.py | 6 ++++++ src/cpl_query/extension/iterable_abc.py | 5 ++++- src/cpl_query/tests/query_test.py | 23 +++++++++++++++++++++++ 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/cpl_query/_query/avg_query.py create mode 100644 src/cpl_query/exceptions.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 2db2c507..14f681a8 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -1,9 +1,10 @@ -from typing import Optional, Callable +from typing import Optional, Callable, Union from cpl_query._extension.ordered_iterable import OrderedIterable from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC from .._query.all_query import all_query from .._query.any_query import any_query +from .._query.avg_query import avg_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -23,6 +24,9 @@ class Iterable(IterableABC): def all(self, func: Callable) -> bool: return all_query(self, func) + def average(self, t: type, func: Callable) -> Union[int, float, complex]: + return avg_query(self, t, func) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/avg_query.py b/src/cpl_query/_query/avg_query.py new file mode 100644 index 00000000..bd884893 --- /dev/null +++ b/src/cpl_query/_query/avg_query.py @@ -0,0 +1,22 @@ +from typing import Callable, Union + +from cpl_query.exceptions import InvalidTypeException, WrongTypeException +from cpl_query.extension.iterable_abc import IterableABC + + +def avg_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: + average = 0 + count = len(_list) + + if _t != int and _t != float and _t != complex: + raise InvalidTypeException() + + for element in _list: + value = _func(element) + if type(value) != _t: + raise WrongTypeException() + + average += value + + return average / count + diff --git a/src/cpl_query/exceptions.py b/src/cpl_query/exceptions.py new file mode 100644 index 00000000..1bf256e9 --- /dev/null +++ b/src/cpl_query/exceptions.py @@ -0,0 +1,6 @@ +class InvalidTypeException(Exception): + pass + + +class WrongTypeException(Exception): + pass diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index b4ce047d..85aaf734 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Optional, Callable +from typing import Optional, Callable, Union class IterableABC(ABC, list): @@ -14,6 +14,9 @@ class IterableABC(ABC, list): @abstractmethod def all(self, func: Callable) -> bool: pass + @abstractmethod + def average(self, t: type, func: Callable) -> Union[int, float, complex]: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 5020183f..0af4dbaa 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -3,6 +3,7 @@ import unittest from random import randint from cpl.utils import String +from cpl_query.exceptions import InvalidTypeException, WrongTypeException from cpl_query.extension.list import List from cpl_query.tests.models import User, Address @@ -59,6 +60,28 @@ class QueryTest(unittest.TestCase): self.assertTrue(res) self.assertFalse(n_res) + def test_avg(self): + avg = 0 + for user in self._tests: + avg += user.address.nr + + avg = avg / len(self._tests) + res = self._tests.average(int, lambda u: u.address.nr) + + self.assertEqual(res, avg) + + def test_avg_invalid(self): + def _(): + res = self._tests.average(str, lambda u: u.address.nr) + + self.assertRaises(InvalidTypeException, _) + + def test_avg_wrong(self): + def _(): + res = self._tests.average(int, lambda u: u.address.street) + + self.assertRaises(WrongTypeException, _) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From 5e5d86cf9486362a3928b52b6bef196456848ba4 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 09:41:51 +0200 Subject: [PATCH 11/31] Added better exceptions --- src/cpl_query/_query/all_query.py | 7 +++++++ src/cpl_query/_query/any_query.py | 7 +++++++ src/cpl_query/_query/avg_query.py | 8 +++++++- src/cpl_query/_query/first_query.py | 7 +++++++ src/cpl_query/_query/for_each_query.py | 11 +++++++++-- src/cpl_query/_query/order_by.py | 19 +++++++++++++++++++ src/cpl_query/_query/single_query.py | 7 +++++++ src/cpl_query/_query/where_query.py | 7 +++++++ src/cpl_query/exceptions.py | 17 +++++++++++++++++ src/cpl_query/tests/iterable_test.py | 7 ------- src/cpl_query/tests/query_test.py | 22 ++++++++++++---------- 11 files changed, 99 insertions(+), 20 deletions(-) diff --git a/src/cpl_query/_query/all_query.py b/src/cpl_query/_query/all_query.py index 33c9e4c6..07c40a51 100644 --- a/src/cpl_query/_query/all_query.py +++ b/src/cpl_query/_query/all_query.py @@ -1,9 +1,16 @@ from collections import Callable from cpl_query._query.where_query import where_query +from cpl_query.exceptions import ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC def all_query(_list: IterableABC, _func: Callable) -> bool: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + result = where_query(_list, _func) return len(result) == len(_list) diff --git a/src/cpl_query/_query/any_query.py b/src/cpl_query/_query/any_query.py index ff85fa98..ede1c0d8 100644 --- a/src/cpl_query/_query/any_query.py +++ b/src/cpl_query/_query/any_query.py @@ -1,9 +1,16 @@ from collections import Callable from cpl_query._query.where_query import where_query +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC def any_query(_list: IterableABC, _func: Callable) -> bool: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + result = where_query(_list, _func) return len(result) > 0 diff --git a/src/cpl_query/_query/avg_query.py b/src/cpl_query/_query/avg_query.py index bd884893..6d140da8 100644 --- a/src/cpl_query/_query/avg_query.py +++ b/src/cpl_query/_query/avg_query.py @@ -1,6 +1,6 @@ from typing import Callable, Union -from cpl_query.exceptions import InvalidTypeException, WrongTypeException +from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC @@ -8,6 +8,12 @@ def avg_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float average = 0 count = len(_list) + 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() diff --git a/src/cpl_query/_query/first_query.py b/src/cpl_query/_query/first_query.py index d0917117..6f3859ae 100644 --- a/src/cpl_query/_query/first_query.py +++ b/src/cpl_query/_query/first_query.py @@ -1,9 +1,13 @@ from typing import Optional +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC def first_query(_list: IterableABC) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + if len(_list) == 0: raise Exception('Index out of range') @@ -11,6 +15,9 @@ def first_query(_list: IterableABC) -> any: def first_or_default_query(_list: IterableABC) -> Optional[any]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + if len(_list) == 0: return None diff --git a/src/cpl_query/_query/for_each_query.py b/src/cpl_query/_query/for_each_query.py index 6681bd0f..62411c4d 100644 --- a/src/cpl_query/_query/for_each_query.py +++ b/src/cpl_query/_query/for_each_query.py @@ -1,8 +1,15 @@ from collections import Callable +from cpl_query.exceptions import ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC -def for_each_query(_list: IterableABC, func: Callable): +def for_each_query(_list: IterableABC, _func: Callable): + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + for element in _list: - func(element) + _func(element) diff --git a/src/cpl_query/_query/order_by.py b/src/cpl_query/_query/order_by.py index 12cea7b3..2012486c 100644 --- a/src/cpl_query/_query/order_by.py +++ b/src/cpl_query/_query/order_by.py @@ -1,5 +1,6 @@ from collections import Callable +from cpl_query.exceptions import ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC @@ -12,6 +13,12 @@ def order_by_query(_list: IterableABC, _func: Callable) -> OrderedIterableABC: def order_by_descending_query(_list: IterableABC, _func: Callable) -> OrderedIterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + result = OrderedIterableABC(_func) _list.sort(key=_func, reverse=True) result.extend(_list) @@ -19,10 +26,22 @@ def order_by_descending_query(_list: IterableABC, _func: Callable) -> OrderedIte def then_by_query(_list: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + _list.sort(key=_func) return _list def then_by_descending_query(_list: OrderedIterableABC, _func: Callable) -> OrderedIterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + _list.sort(key=_func, reverse=True) return _list diff --git a/src/cpl_query/_query/single_query.py b/src/cpl_query/_query/single_query.py index 8ad30cef..7112a2c8 100644 --- a/src/cpl_query/_query/single_query.py +++ b/src/cpl_query/_query/single_query.py @@ -1,9 +1,13 @@ from typing import Optional +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC def single_query(_list: IterableABC) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + if len(_list) > 1: raise Exception('Found more than one element') elif len(_list) == 0: @@ -13,6 +17,9 @@ def single_query(_list: IterableABC) -> any: def single_or_default_query(_list: IterableABC) -> Optional[any]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + if len(_list) > 1: raise Exception('Index out of range') elif len(_list) == 0: diff --git a/src/cpl_query/_query/where_query.py b/src/cpl_query/_query/where_query.py index 92593fdd..94d555fe 100644 --- a/src/cpl_query/_query/where_query.py +++ b/src/cpl_query/_query/where_query.py @@ -1,9 +1,16 @@ from collections import Callable +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC def where_query(_list: IterableABC, _func: Callable) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + result = IterableABC() for element in _list: if _func(element): diff --git a/src/cpl_query/exceptions.py b/src/cpl_query/exceptions.py index 1bf256e9..b0a320ea 100644 --- a/src/cpl_query/exceptions.py +++ b/src/cpl_query/exceptions.py @@ -1,3 +1,20 @@ +from enum import Enum + + +# models +class ExceptionArgument(Enum): + list = 'list' + func = 'func' + type = 'type' + + +# exceptions +class ArgumentNoneException(Exception): + + def __init__(self, arg: ExceptionArgument): + Exception.__init__(self, f'Argument {arg} is None') + + class InvalidTypeException(Exception): pass diff --git a/src/cpl_query/tests/iterable_test.py b/src/cpl_query/tests/iterable_test.py index 9b12b28e..a8936a88 100644 --- a/src/cpl_query/tests/iterable_test.py +++ b/src/cpl_query/tests/iterable_test.py @@ -18,11 +18,4 @@ class IterableTest(unittest.TestCase): self._list.append(3) self.assertEqual(self._list, [1, 2, 3]) - self._clear() - - def test_append_wrong_type(self): - self._list.append(1) - self._list.append(2) - self.assertRaises(Exception, lambda v: self._list.append(v), '3') - self._clear() diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 0af4dbaa..d26f2f88 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -3,7 +3,7 @@ import unittest from random import randint from cpl.utils import String -from cpl_query.exceptions import InvalidTypeException, WrongTypeException +from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ArgumentNoneException from cpl_query.extension.list import List from cpl_query.tests.models import User, Address @@ -70,17 +70,14 @@ class QueryTest(unittest.TestCase): self.assertEqual(res, avg) - def test_avg_invalid(self): - def _(): - res = self._tests.average(str, lambda u: u.address.nr) + def invalid(): + e_res = self._tests.average(str, lambda u: u.address.nr) - self.assertRaises(InvalidTypeException, _) + def wrong(): + e_res = self._tests.average(int, lambda u: u.address.street) - def test_avg_wrong(self): - def _(): - res = self._tests.average(int, lambda u: u.address.street) - - self.assertRaises(WrongTypeException, _) + self.assertRaises(InvalidTypeException, invalid) + self.assertRaises(WrongTypeException, wrong) def test_first(self): results = [] @@ -179,3 +176,8 @@ class QueryTest(unittest.TestCase): res = self._tests.where(lambda u: u.address.nr == 5) self.assertEqual(len(results), len(res)) + + def ex(): + e_res = self._tests.where(None) + + self.assertRaises(ArgumentNoneException, ex) -- 2.45.1 From f8bd86692e78a4c45f3db0d765a27bf4f77d4158 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 10:55:23 +0200 Subject: [PATCH 12/31] Added contains query --- src/cpl_query/_extension/iterable.py | 4 ++++ src/cpl_query/_query/contains_query.py | 5 +++++ src/cpl_query/extension/iterable_abc.py | 3 +++ src/cpl_query/tests/query_test.py | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/cpl_query/_query/contains_query.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 14f681a8..28f9bcfc 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -5,6 +5,7 @@ from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC from .._query.all_query import all_query from .._query.any_query import any_query from .._query.avg_query import avg_query +from .._query.contains_query import contains_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -27,6 +28,9 @@ class Iterable(IterableABC): def average(self, t: type, func: Callable) -> Union[int, float, complex]: return avg_query(self, t, func) + def contains(self, value: object) -> bool: + return contains_query(self, value) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/contains_query.py b/src/cpl_query/_query/contains_query.py new file mode 100644 index 00000000..e235c65d --- /dev/null +++ b/src/cpl_query/_query/contains_query.py @@ -0,0 +1,5 @@ +from cpl_query.extension.iterable_abc import IterableABC + + +def contains_query(_list: IterableABC, value: object) -> bool: + return value in _list diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 85aaf734..ba80b979 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -17,6 +17,9 @@ class IterableABC(ABC, list): @abstractmethod def average(self, t: type, func: Callable) -> Union[int, float, complex]: pass + @abstractmethod + def contains(self, value: object) -> bool: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index d26f2f88..b836bb6c 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -79,6 +79,10 @@ class QueryTest(unittest.TestCase): self.assertRaises(InvalidTypeException, invalid) self.assertRaises(WrongTypeException, wrong) + def test_contains(self): + self.assertTrue(self._tests.contains(self._t_user)) + self.assertFalse(self._tests.contains(User("Test", None))) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From 45733b30ef8e3fcc7c814fa53cdd392f7cacf50a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 10:59:24 +0200 Subject: [PATCH 13/31] Improved error handling --- src/cpl_query/_query/contains_query.py | 11 +++++++++-- src/cpl_query/exceptions.py | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cpl_query/_query/contains_query.py b/src/cpl_query/_query/contains_query.py index e235c65d..47d29dc8 100644 --- a/src/cpl_query/_query/contains_query.py +++ b/src/cpl_query/_query/contains_query.py @@ -1,5 +1,12 @@ +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC -def contains_query(_list: IterableABC, value: object) -> bool: - return value in _list +def contains_query(_list: IterableABC, _value: object) -> bool: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _value is None: + raise ArgumentNoneException(ExceptionArgument.value) + + return _value in _list diff --git a/src/cpl_query/exceptions.py b/src/cpl_query/exceptions.py index b0a320ea..c9694221 100644 --- a/src/cpl_query/exceptions.py +++ b/src/cpl_query/exceptions.py @@ -6,6 +6,7 @@ class ExceptionArgument(Enum): list = 'list' func = 'func' type = 'type' + value = 'value' # exceptions -- 2.45.1 From c60598b3f61f5a1a76ea01910d76cb07fd0af00d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:01:43 +0200 Subject: [PATCH 14/31] Added count query --- src/cpl_query/_extension/iterable.py | 4 ++++ src/cpl_query/_query/count_query.py | 15 +++++++++++++++ src/cpl_query/extension/iterable_abc.py | 3 +++ src/cpl_query/tests/query_test.py | 4 ++++ 4 files changed, 26 insertions(+) create mode 100644 src/cpl_query/_query/count_query.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 28f9bcfc..f925851e 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -6,6 +6,7 @@ from .._query.all_query import all_query from .._query.any_query import any_query from .._query.avg_query import avg_query from .._query.contains_query import contains_query +from .._query.count_query import count_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -31,6 +32,9 @@ class Iterable(IterableABC): def contains(self, value: object) -> bool: return contains_query(self, value) + def count(self, func: Callable = None) -> int: + return count_query(self, func) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/count_query.py b/src/cpl_query/_query/count_query.py new file mode 100644 index 00000000..246feee1 --- /dev/null +++ b/src/cpl_query/_query/count_query.py @@ -0,0 +1,15 @@ +from collections import Callable + +from cpl_query._query.where_query import where_query +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.extension.iterable_abc import IterableABC + + +def count_query(_list: IterableABC, _func: Callable = None) -> int: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + return len(_list) + + return len(where_query(_list, _func)) diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index ba80b979..6a85d604 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -20,6 +20,9 @@ class IterableABC(ABC, list): @abstractmethod def contains(self, value: object) -> bool: pass + @abstractmethod + def count(self, func: Callable) -> int: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index b836bb6c..cb7a42a4 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -83,6 +83,10 @@ class QueryTest(unittest.TestCase): self.assertTrue(self._tests.contains(self._t_user)) self.assertFalse(self._tests.contains(User("Test", None))) + def test_count(self): + self.assertEqual(len(self._tests), self._tests.count()) + self.assertEqual(1, self._tests.count(lambda u: u == self._t_user)) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From 669133d4919cfc4f16c3187006baa5332728294c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:20:35 +0200 Subject: [PATCH 15/31] Added distinct query --- src/cpl_query/_extension/iterable.py | 6 ++++++ src/cpl_query/_query/distinct_query.py | 24 ++++++++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 9 ++++++--- src/cpl_query/tests/query_test.py | 4 ++++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/cpl_query/_query/distinct_query.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index f925851e..60f1b94d 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -7,6 +7,7 @@ from .._query.any_query import any_query from .._query.avg_query import avg_query from .._query.contains_query import contains_query from .._query.count_query import count_query +from .._query.distinct_query import distinct_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -35,6 +36,11 @@ class Iterable(IterableABC): def count(self, func: Callable = None) -> int: return count_query(self, func) + def distinct(self, func: Callable) -> IterableABC: + res = distinct_query(self, func) + res.__class__ = Iterable + return res + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/distinct_query.py b/src/cpl_query/_query/distinct_query.py new file mode 100644 index 00000000..791ef7c7 --- /dev/null +++ b/src/cpl_query/_query/distinct_query.py @@ -0,0 +1,24 @@ +from collections import Callable + +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.extension.iterable_abc import IterableABC + + +def distinct_query(_list: IterableABC, _func: Callable) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + result = IterableABC() + known_values = [] + for element in _list: + value = _func(element) + if value in known_values: + continue + + known_values.append(value) + result.append(element) + + return result diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 6a85d604..bd031833 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -23,6 +23,9 @@ class IterableABC(ABC, list): @abstractmethod def count(self, func: Callable) -> int: pass + @abstractmethod + def distinct(self, func: Callable) -> 'IterableABC': pass + @abstractmethod def first(self) -> any: pass @@ -33,13 +36,13 @@ class IterableABC(ABC, list): def for_each(self, func: Callable): pass @abstractmethod - def order_by(self, func: Callable): pass + def order_by(self, func: Callable) -> 'IterableABC': pass @abstractmethod - def order_by_descending(self, func: Callable): pass + def order_by_descending(self, func: Callable) -> 'IterableABC': pass @abstractmethod - def single(self): pass + def single(self) -> any: pass @abstractmethod def single_or_default(self) -> Optional[any]: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index cb7a42a4..9a187f3e 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -87,6 +87,10 @@ class QueryTest(unittest.TestCase): self.assertEqual(len(self._tests), self._tests.count()) self.assertEqual(1, self._tests.count(lambda u: u == self._t_user)) + def test_distinct(self): + res = self._tests.distinct(lambda u: u.address.nr).where(lambda u: u.address.nr == 5) + self.assertEqual(1, len(res)) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From 6951a19670e315e64a30704752563fc041dd6ad6 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:22:29 +0200 Subject: [PATCH 16/31] Renamed files --- src/cpl_query/_extension/iterable.py | 20 +++++++++---------- src/cpl_query/_query/{all_query.py => all.py} | 2 +- src/cpl_query/_query/{any_query.py => any.py} | 2 +- src/cpl_query/_query/{avg_query.py => avg.py} | 0 .../_query/{contains_query.py => contains.py} | 0 .../_query/{count_query.py => count.py} | 2 +- .../_query/{distinct_query.py => distinct.py} | 0 .../_query/{first_query.py => first.py} | 0 .../_query/{for_each_query.py => for_each.py} | 0 .../_query/{single_query.py => single.py} | 0 .../_query/{where_query.py => where.py} | 0 11 files changed, 13 insertions(+), 13 deletions(-) rename src/cpl_query/_query/{all_query.py => all.py} (89%) rename src/cpl_query/_query/{any_query.py => any.py} (89%) rename src/cpl_query/_query/{avg_query.py => avg.py} (100%) rename src/cpl_query/_query/{contains_query.py => contains.py} (100%) rename src/cpl_query/_query/{count_query.py => count.py} (88%) rename src/cpl_query/_query/{distinct_query.py => distinct.py} (100%) rename src/cpl_query/_query/{first_query.py => first.py} (100%) rename src/cpl_query/_query/{for_each_query.py => for_each.py} (100%) rename src/cpl_query/_query/{single_query.py => single.py} (100%) rename src/cpl_query/_query/{where_query.py => where.py} (100%) diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 60f1b94d..2361fe67 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -2,17 +2,17 @@ from typing import Optional, Callable, Union from cpl_query._extension.ordered_iterable import OrderedIterable from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC -from .._query.all_query import all_query -from .._query.any_query import any_query -from .._query.avg_query import avg_query -from .._query.contains_query import contains_query -from .._query.count_query import count_query -from .._query.distinct_query import distinct_query -from .._query.first_query import first_or_default_query, first_query -from .._query.for_each_query import for_each_query +from .._query.all import all_query +from .._query.any import any_query +from .._query.avg import avg_query +from .._query.contains import contains_query +from .._query.count import count_query +from .._query.distinct import distinct_query +from .._query.first import first_or_default_query, first_query +from .._query.for_each import for_each_query from .._query.order_by import order_by_query, order_by_descending_query -from .._query.single_query import single_query, single_or_default_query -from .._query.where_query import where_query +from .._query.single import single_query, single_or_default_query +from .._query.where import where_query from cpl_query.extension.iterable_abc import IterableABC diff --git a/src/cpl_query/_query/all_query.py b/src/cpl_query/_query/all.py similarity index 89% rename from src/cpl_query/_query/all_query.py rename to src/cpl_query/_query/all.py index 07c40a51..76aa2fb0 100644 --- a/src/cpl_query/_query/all_query.py +++ b/src/cpl_query/_query/all.py @@ -1,6 +1,6 @@ from collections import Callable -from cpl_query._query.where_query import where_query +from cpl_query._query.where import where_query from cpl_query.exceptions import ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC diff --git a/src/cpl_query/_query/any_query.py b/src/cpl_query/_query/any.py similarity index 89% rename from src/cpl_query/_query/any_query.py rename to src/cpl_query/_query/any.py index ede1c0d8..ab63c154 100644 --- a/src/cpl_query/_query/any_query.py +++ b/src/cpl_query/_query/any.py @@ -1,6 +1,6 @@ from collections import Callable -from cpl_query._query.where_query import where_query +from cpl_query._query.where import where_query from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC diff --git a/src/cpl_query/_query/avg_query.py b/src/cpl_query/_query/avg.py similarity index 100% rename from src/cpl_query/_query/avg_query.py rename to src/cpl_query/_query/avg.py diff --git a/src/cpl_query/_query/contains_query.py b/src/cpl_query/_query/contains.py similarity index 100% rename from src/cpl_query/_query/contains_query.py rename to src/cpl_query/_query/contains.py diff --git a/src/cpl_query/_query/count_query.py b/src/cpl_query/_query/count.py similarity index 88% rename from src/cpl_query/_query/count_query.py rename to src/cpl_query/_query/count.py index 246feee1..a4a87096 100644 --- a/src/cpl_query/_query/count_query.py +++ b/src/cpl_query/_query/count.py @@ -1,6 +1,6 @@ from collections import Callable -from cpl_query._query.where_query import where_query +from cpl_query._query.where import where_query from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument from cpl_query.extension.iterable_abc import IterableABC diff --git a/src/cpl_query/_query/distinct_query.py b/src/cpl_query/_query/distinct.py similarity index 100% rename from src/cpl_query/_query/distinct_query.py rename to src/cpl_query/_query/distinct.py diff --git a/src/cpl_query/_query/first_query.py b/src/cpl_query/_query/first.py similarity index 100% rename from src/cpl_query/_query/first_query.py rename to src/cpl_query/_query/first.py diff --git a/src/cpl_query/_query/for_each_query.py b/src/cpl_query/_query/for_each.py similarity index 100% rename from src/cpl_query/_query/for_each_query.py rename to src/cpl_query/_query/for_each.py diff --git a/src/cpl_query/_query/single_query.py b/src/cpl_query/_query/single.py similarity index 100% rename from src/cpl_query/_query/single_query.py rename to src/cpl_query/_query/single.py diff --git a/src/cpl_query/_query/where_query.py b/src/cpl_query/_query/where.py similarity index 100% rename from src/cpl_query/_query/where_query.py rename to src/cpl_query/_query/where.py -- 2.45.1 From a3a0a150a8440393e40b1518ee4d8a02aeb7ac5f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:29:52 +0200 Subject: [PATCH 17/31] Added element at query --- src/cpl_query/_extension/iterable.py | 7 +++++++ src/cpl_query/_query/element_at.py | 25 +++++++++++++++++++++++++ src/cpl_query/exceptions.py | 1 + src/cpl_query/extension/iterable_abc.py | 6 ++++++ src/cpl_query/tests/query_test.py | 9 +++++++++ 5 files changed, 48 insertions(+) create mode 100644 src/cpl_query/_query/element_at.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 2361fe67..cb0f868e 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -8,6 +8,7 @@ from .._query.avg import avg_query from .._query.contains import contains_query from .._query.count import count_query from .._query.distinct import distinct_query +from .._query.element_at import element_at_query, element_at_or_default_query from .._query.first import first_or_default_query, first_query from .._query.for_each import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -41,6 +42,12 @@ class Iterable(IterableABC): res.__class__ = Iterable return res + def element_at(self, index: int) -> any: + return element_at_query(self, index) + + def element_at_or_default(self, index: int) -> Optional[any]: + return element_at_or_default_query(self, index) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/element_at.py b/src/cpl_query/_query/element_at.py new file mode 100644 index 00000000..67bd514c --- /dev/null +++ b/src/cpl_query/_query/element_at.py @@ -0,0 +1,25 @@ +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.extension.iterable_abc import IterableABC + + +def element_at_query(_list: IterableABC, _index: int) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + return _list[_index] + + +def element_at_or_default_query(_list: IterableABC, _index: int) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + try: + return _list[_index] + except IndexError: + return None diff --git a/src/cpl_query/exceptions.py b/src/cpl_query/exceptions.py index c9694221..1b6e550d 100644 --- a/src/cpl_query/exceptions.py +++ b/src/cpl_query/exceptions.py @@ -7,6 +7,7 @@ class ExceptionArgument(Enum): func = 'func' type = 'type' value = 'value' + index = 'index' # exceptions diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index bd031833..28cb188b 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -26,6 +26,12 @@ class IterableABC(ABC, list): @abstractmethod def distinct(self, func: Callable) -> 'IterableABC': pass + @abstractmethod + def element_at(self, index: int) -> any: pass + + @abstractmethod + def element_at_or_default(self, index: int) -> Optional[any]: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 9a187f3e..2481f60e 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -91,6 +91,15 @@ class QueryTest(unittest.TestCase): res = self._tests.distinct(lambda u: u.address.nr).where(lambda u: u.address.nr == 5) self.assertEqual(1, len(res)) + def test_element_at(self): + index = randint(0, len(self._tests) - 1) + self.assertEqual(self._tests[index], self._tests.element_at(index)) + + def test_element_at_or_default(self): + index = randint(0, len(self._tests) - 1) + self.assertEqual(self._tests[index], self._tests.element_at_or_default(index)) + self.assertIsNone(self._tests.element_at_or_default(len(self._tests))) + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From 82a9e3a23a23f1287116226787edaa44001256e7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:40:24 +0200 Subject: [PATCH 18/31] Improved index out of range exception --- src/cpl_query/_query/first.py | 4 ++-- src/cpl_query/exceptions.py | 8 +++++++- src/cpl_query/tests/query_test.py | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cpl_query/_query/first.py b/src/cpl_query/_query/first.py index 6f3859ae..0eb98924 100644 --- a/src/cpl_query/_query/first.py +++ b/src/cpl_query/_query/first.py @@ -1,6 +1,6 @@ from typing import Optional -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException from cpl_query.extension.iterable_abc import IterableABC @@ -9,7 +9,7 @@ def first_query(_list: IterableABC) -> any: raise ArgumentNoneException(ExceptionArgument.list) if len(_list) == 0: - raise Exception('Index out of range') + raise IndexOutOfRangeException() return _list[0] diff --git a/src/cpl_query/exceptions.py b/src/cpl_query/exceptions.py index 1b6e550d..7fc33909 100644 --- a/src/cpl_query/exceptions.py +++ b/src/cpl_query/exceptions.py @@ -14,7 +14,13 @@ class ExceptionArgument(Enum): class ArgumentNoneException(Exception): def __init__(self, arg: ExceptionArgument): - Exception.__init__(self, f'Argument {arg} is None') + Exception.__init__(self, f'argument {arg} is None') + + +class IndexOutOfRangeException(Exception): + + def __init__(self): + Exception.__init__(self, f'List index out of range') class InvalidTypeException(Exception): diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 2481f60e..0f6b3e17 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -100,6 +100,9 @@ class QueryTest(unittest.TestCase): self.assertEqual(self._tests[index], self._tests.element_at_or_default(index)) self.assertIsNone(self._tests.element_at_or_default(len(self._tests))) + test = [1, 2, 3] + t = test[100] + def test_first(self): results = [] for user in self._tests: -- 2.45.1 From e7863a92e002205dffd481b73c4e22e4d63d1bd8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:43:45 +0200 Subject: [PATCH 19/31] Added last query --- src/cpl_query/_extension/iterable.py | 7 ++++++ src/cpl_query/_query/last.py | 24 +++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 6 +++++ src/cpl_query/tests/query_test.py | 31 +++++++++++++++++++++---- 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 src/cpl_query/_query/last.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index cb0f868e..091eae1a 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -11,6 +11,7 @@ from .._query.distinct import distinct_query from .._query.element_at import element_at_query, element_at_or_default_query from .._query.first import first_or_default_query, first_query from .._query.for_each import for_each_query +from .._query.last import last_query, last_or_default_query from .._query.order_by import order_by_query, order_by_descending_query from .._query.single import single_query, single_or_default_query from .._query.where import where_query @@ -48,6 +49,12 @@ class Iterable(IterableABC): def element_at_or_default(self, index: int) -> Optional[any]: return element_at_or_default_query(self, index) + def last(self) -> any: + return last_query(self) + + def last_or_default(self) -> Optional[any]: + return last_or_default_query(self) + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/last.py b/src/cpl_query/_query/last.py new file mode 100644 index 00000000..20ff901a --- /dev/null +++ b/src/cpl_query/_query/last.py @@ -0,0 +1,24 @@ +from typing import Optional + +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException +from cpl_query.extension.iterable_abc import IterableABC + + +def last_query(_list: IterableABC) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if len(_list) == 0: + raise IndexOutOfRangeException() + + return _list[len(_list) - 1] + + +def last_or_default_query(_list: IterableABC) -> Optional[any]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if len(_list) == 0: + return None + + return _list[len(_list) - 1] diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 28cb188b..c9d0105b 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -32,6 +32,12 @@ class IterableABC(ABC, list): @abstractmethod def element_at_or_default(self, index: int) -> Optional[any]: pass + @abstractmethod + def last(self) -> any: pass + + @abstractmethod + def last_or_default(self) -> any: pass + @abstractmethod def first(self) -> any: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 0f6b3e17..64f5f23c 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -100,8 +100,31 @@ class QueryTest(unittest.TestCase): self.assertEqual(self._tests[index], self._tests.element_at_or_default(index)) self.assertIsNone(self._tests.element_at_or_default(len(self._tests))) - test = [1, 2, 3] - t = test[100] + def test_last(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.where(lambda u: u.address.nr == 10) + s_res = self._tests.where(lambda u: u.address.nr == 10).last() + + self.assertEqual(len(res), len(results)) + self.assertEqual(res[len(res) - 1], s_res) + + def test_last_or_default(self): + results = [] + for user in self._tests: + if user.address.nr == 10: + results.append(user) + + res = self._tests.where(lambda u: u.address.nr == 10) + s_res = self._tests.where(lambda u: u.address.nr == 10).last_or_default() + sn_res = self._tests.where(lambda u: u.address.nr == 11).last_or_default() + + self.assertEqual(len(res), len(results)) + self.assertEqual(res[len(res) - 1], s_res) + self.assertIsNone(sn_res) def test_first(self): results = [] @@ -113,7 +136,7 @@ class QueryTest(unittest.TestCase): s_res = self._tests.where(lambda u: u.address.nr == 10).first() self.assertEqual(len(res), len(results)) - self.assertIsNotNone(s_res) + self.assertEqual(res[0], s_res) def test_first_or_default(self): results = [] @@ -126,7 +149,7 @@ class QueryTest(unittest.TestCase): sn_res = self._tests.where(lambda u: u.address.nr == 11).first_or_default() self.assertEqual(len(res), len(results)) - self.assertIsNotNone(s_res) + self.assertEqual(res[0], s_res) self.assertIsNone(sn_res) def test_for_each(self): -- 2.45.1 From c115afd7368351dc562657c0c7d6d4be5fdffd91 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:47:13 +0200 Subject: [PATCH 20/31] Moved last queries --- src/cpl_query/_extension/iterable.py | 3 +-- src/cpl_query/_query/first.py | 24 ------------------- .../_query/{last.py => first_last.py} | 20 ++++++++++++++++ 3 files changed, 21 insertions(+), 26 deletions(-) delete mode 100644 src/cpl_query/_query/first.py rename src/cpl_query/_query/{last.py => first_last.py} (59%) diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 091eae1a..45180a9c 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -9,9 +9,8 @@ from .._query.contains import contains_query from .._query.count import count_query from .._query.distinct import distinct_query from .._query.element_at import element_at_query, element_at_or_default_query -from .._query.first import first_or_default_query, first_query +from .._query.first_last import first_or_default_query, first_query, last_or_default_query, last_query from .._query.for_each import for_each_query -from .._query.last import last_query, last_or_default_query from .._query.order_by import order_by_query, order_by_descending_query from .._query.single import single_query, single_or_default_query from .._query.where import where_query diff --git a/src/cpl_query/_query/first.py b/src/cpl_query/_query/first.py deleted file mode 100644 index 0eb98924..00000000 --- a/src/cpl_query/_query/first.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Optional - -from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException -from cpl_query.extension.iterable_abc import IterableABC - - -def first_query(_list: IterableABC) -> any: - if _list is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(_list) == 0: - raise IndexOutOfRangeException() - - return _list[0] - - -def first_or_default_query(_list: IterableABC) -> Optional[any]: - if _list is None: - raise ArgumentNoneException(ExceptionArgument.list) - - if len(_list) == 0: - return None - - return _list[0] diff --git a/src/cpl_query/_query/last.py b/src/cpl_query/_query/first_last.py similarity index 59% rename from src/cpl_query/_query/last.py rename to src/cpl_query/_query/first_last.py index 20ff901a..9008300a 100644 --- a/src/cpl_query/_query/last.py +++ b/src/cpl_query/_query/first_last.py @@ -4,6 +4,26 @@ from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, Index from cpl_query.extension.iterable_abc import IterableABC +def first_query(_list: IterableABC) -> any: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if len(_list) == 0: + raise IndexOutOfRangeException() + + return _list[0] + + +def first_or_default_query(_list: IterableABC) -> Optional[any]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if len(_list) == 0: + return None + + return _list[0] + + def last_query(_list: IterableABC) -> any: if _list is None: raise ArgumentNoneException(ExceptionArgument.list) -- 2.45.1 From d4b5c32a2112bb248720706d2295008bd2d68585 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:57:42 +0200 Subject: [PATCH 21/31] Added min and max queries --- src/cpl_query/_extension/iterable.py | 7 ++++ src/cpl_query/_query/max_min.py | 48 +++++++++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 5 ++- src/cpl_query/tests/query_test.py | 10 +++++- 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/cpl_query/_query/max_min.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 45180a9c..15037603 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -11,6 +11,7 @@ from .._query.distinct import distinct_query from .._query.element_at import element_at_query, element_at_or_default_query from .._query.first_last import first_or_default_query, first_query, last_or_default_query, last_query from .._query.for_each import for_each_query +from .._query.max_min import max_query, min_query from .._query.order_by import order_by_query, order_by_descending_query from .._query.single import single_query, single_or_default_query from .._query.where import where_query @@ -63,6 +64,12 @@ 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 min(self, t: type, func: Callable) -> Union[int, float, complex]: + return min_query(self, t, func) + def order_by(self, func: Callable) -> OrderedIterableABC: res = order_by_query(self, func) res.__class__ = OrderedIterable diff --git a/src/cpl_query/_query/max_min.py b/src/cpl_query/_query/max_min.py new file mode 100644 index 00000000..82dc01c0 --- /dev/null +++ b/src/cpl_query/_query/max_min.py @@ -0,0 +1,48 @@ +from collections import Callable +from typing import Union + +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException +from cpl_query.extension.iterable_abc import IterableABC + + +def max_query(_list: IterableABC, _t: type, _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() + for element in _list: + value = _func(element) + if value > max_value: + max_value = value + + return max_value + + +def min_query(_list: IterableABC, _t: type, _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() + is_first = True + for element in _list: + value = _func(element) + if is_first: + min_value = value + is_first = False + + if value < min_value: + min_value = value + + return min_value diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index c9d0105b..6a94c8c3 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -45,7 +45,10 @@ class IterableABC(ABC, list): def first_or_default(self) -> any: pass @abstractmethod - def for_each(self, func: Callable): pass + def for_each(self, func: Callable) -> Union[int, float, complex]: pass + + @abstractmethod + def max(self, t: type, 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 64f5f23c..c5522813 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -28,7 +28,7 @@ class QueryTest(unittest.TestCase): String.random_string(string.ascii_letters, 8).lower(), Address( String.random_string(string.ascii_letters, 10).lower(), - randint(0, 10) + randint(1, 10) ) ) @@ -162,6 +162,14 @@ 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) + self.assertEqual(self._t_user.address.nr, res) + + def test_min(self): + res = self._tests.min(int, lambda u: u.address.nr) + self.assertEqual(1, res) + def test_order_by(self): res = self._tests.order_by(lambda user: user.address.street) res2 = self._tests.order_by(lambda user: user.address.nr) -- 2.45.1 From daac14e0997faac9d157317f19fc01828ff86f0a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 12:35:14 +0200 Subject: [PATCH 22/31] Improved avg query --- src/cpl_query/_extension/iterable.py | 8 ++++---- src/cpl_query/_helper.py | 2 ++ src/cpl_query/_query/avg.py | 23 +++++++++++------------ src/cpl_query/extension/iterable_abc.py | 22 ++++++++++++++++++++-- src/cpl_query/extension/list.py | 13 +------------ src/cpl_query/tests/query_test.py | 19 ++++++++++++------- 6 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 src/cpl_query/_helper.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 15037603..d2a9fb4e 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -20,8 +20,8 @@ from cpl_query.extension.iterable_abc import IterableABC class Iterable(IterableABC): - def __init__(self): - IterableABC.__init__(self) + def __init__(self, t: type = None, values: list = None): + IterableABC.__init__(self, t, values) def any(self, func: Callable) -> bool: return any_query(self, func) @@ -29,8 +29,8 @@ class Iterable(IterableABC): def all(self, func: Callable) -> bool: return all_query(self, func) - def average(self, t: type, func: Callable) -> Union[int, float, complex]: - return avg_query(self, t, func) + def average(self, func: Callable = None) -> Union[int, float, complex]: + return avg_query(self, func) def contains(self, value: object) -> bool: return contains_query(self, value) diff --git a/src/cpl_query/_helper.py b/src/cpl_query/_helper.py new file mode 100644 index 00000000..6f92e585 --- /dev/null +++ b/src/cpl_query/_helper.py @@ -0,0 +1,2 @@ +def is_number(t: type) -> bool: + return issubclass(t, int) or issubclass(t, float) or issubclass(t, complex) diff --git a/src/cpl_query/_query/avg.py b/src/cpl_query/_query/avg.py index 6d140da8..cf8d354a 100644 --- a/src/cpl_query/_query/avg.py +++ b/src/cpl_query/_query/avg.py @@ -1,28 +1,27 @@ from typing import Callable, Union +from cpl_query._helper import is_number from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ExceptionArgument, ArgumentNoneException from cpl_query.extension.iterable_abc import IterableABC -def avg_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: - average = 0 - count = len(_list) - +def avg_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() + average = 0 + count = len(_list) for element in _list: - value = _func(element) - if type(value) != _t: + if _func is not None: + value = _func(element) + + else: + value = element + + if _list.type is not None and type(element) != _list.type or not is_number(type(value)): raise WrongTypeException() average += value return average / count - diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 6a94c8c3..76a61f72 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -5,17 +5,35 @@ from typing import Optional, Callable, Union class IterableABC(ABC, list): @abstractmethod - def __init__(self): + def __init__(self, t: type = None, values: list = None): list.__init__(self) + if t == any: + t = None + self._type = t + + if values is not None: + for value in values: + self.append(value) + + @property + def type(self) -> type: + return self._type + @abstractmethod def any(self, func: Callable) -> bool: pass @abstractmethod def all(self, func: Callable) -> bool: pass + def append(self, __object: object) -> None: + 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)}') + + super().append(__object) + @abstractmethod - def average(self, t: type, func: Callable) -> Union[int, float, complex]: pass + def average(self, func: Callable = None) -> Union[int, float, complex]: pass @abstractmethod def contains(self, value: object) -> bool: pass diff --git a/src/cpl_query/extension/list.py b/src/cpl_query/extension/list.py index 94eeeb09..c642f0be 100644 --- a/src/cpl_query/extension/list.py +++ b/src/cpl_query/extension/list.py @@ -4,15 +4,4 @@ from .._extension.iterable import Iterable class List(Iterable): def __init__(self, t: type = None, values: list = None): - Iterable.__init__(self) - - self._type = t - - if values is not None: - self.extend(values) - - def append(self, __object: object) -> None: - 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)}') - - super().append(__object) + Iterable.__init__(self, t, values) diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index c5522813..e1d0b417 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -66,19 +66,24 @@ class QueryTest(unittest.TestCase): avg += user.address.nr avg = avg / len(self._tests) - res = self._tests.average(int, lambda u: u.address.nr) + res = self._tests.average(lambda u: u.address.nr) - self.assertEqual(res, avg) - - def invalid(): - e_res = self._tests.average(str, lambda u: u.address.nr) + self.assertEqual(avg, res) def wrong(): - e_res = self._tests.average(int, lambda u: u.address.street) + e_res = self._tests.average(lambda u: u.address.street) - self.assertRaises(InvalidTypeException, invalid) self.assertRaises(WrongTypeException, wrong) + tests = List(int, list(range(0, 100))) + self.assertEqual(sum(tests) / len(tests), tests.average()) + + def wrong2(): + tests2 = List(int, values=list(range(0, 100))) + e_res = tests2.average(lambda u: u.address.nr) + + self.assertRaises(AttributeError, wrong2) + def test_contains(self): self.assertTrue(self._tests.contains(self._t_user)) self.assertFalse(self._tests.contains(User("Test", None))) -- 2.45.1 From a26c6f1bd910850a643e54e2c42dc6885ec74bac Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 12:42:33 +0200 Subject: [PATCH 23/31] 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): -- 2.45.1 From a080119c449e15addcb5dc0c457342cdee874176 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 12:48:22 +0200 Subject: [PATCH 24/31] Improved unittests --- src/cpl_query/_extension/iterable.py | 4 ++-- src/cpl_query/extension/iterable_abc.py | 4 ++-- src/cpl_query/tests/query_test.py | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index abd06a14..44793b87 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -64,10 +64,10 @@ class Iterable(IterableABC): def for_each(self, func: Callable): for_each_query(self, func) - def max(self, func: Callable) -> Union[int, float, complex]: + def max(self, func: Callable = None) -> Union[int, float, complex]: return max_query(self, func) - def min(self, func: Callable) -> Union[int, float, complex]: + def min(self, func: Callable = None) -> Union[int, float, complex]: return min_query(self, func) def order_by(self, func: Callable) -> OrderedIterableABC: diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index e8b8c8a9..d21cb116 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -69,10 +69,10 @@ class IterableABC(ABC, list): def for_each(self, func: Callable) -> Union[int, float, complex]: pass @abstractmethod - def max(self, func: Callable) -> Union[int, float, complex]: pass + def max(self, func: Callable = None) -> Union[int, float, complex]: pass @abstractmethod - def min(self, func: Callable) -> Union[int, float, complex]: pass + def min(self, func: Callable = None) -> 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 f150f56b..cc850237 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -171,10 +171,26 @@ class QueryTest(unittest.TestCase): res = self._tests.max(lambda u: u.address.nr) self.assertEqual(self._t_user.address.nr, res) + tests = List(values=list(range(0, 100))) + self.assertEqual(99, tests.max()) + + def wrong(): + e_res = List(str, list([str(v) for v in range(0, 100)])).max() + + self.assertRaises(WrongTypeException, wrong) + def test_min(self): res = self._tests.min(lambda u: u.address.nr) self.assertEqual(1, res) + tests = List(values=list(range(0, 100))) + self.assertEqual(0, tests.min()) + + def wrong(): + e_res = List(str, list([str(v) for v in range(0, 100)])).min() + + self.assertRaises(WrongTypeException, wrong) + def test_order_by(self): res = self._tests.order_by(lambda user: user.address.street) res2 = self._tests.order_by(lambda user: user.address.nr) -- 2.45.1 From 62c8b9c68d461380c018e0a1d6349d2c218f447d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 12:54:49 +0200 Subject: [PATCH 25/31] Added reverse query --- src/cpl_query/_extension/iterable.py | 7 ++++--- src/cpl_query/_query/reverse.py | 15 +++++++++++++++ src/cpl_query/extension/iterable_abc.py | 6 ++++++ src/cpl_query/tests/query_test.py | 7 +++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 src/cpl_query/_query/reverse.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 44793b87..d480af94 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -13,6 +13,7 @@ from .._query.first_last import first_or_default_query, first_query, last_or_def from .._query.for_each import for_each_query from .._query.max_min import max_query, min_query from .._query.order_by import order_by_query, order_by_descending_query +from .._query.reverse import reverse_query from .._query.single import single_query, single_or_default_query from .._query.where import where_query from cpl_query.extension.iterable_abc import IterableABC @@ -80,6 +81,9 @@ class Iterable(IterableABC): res.__class__ = OrderedIterable return res + def reverse(self) -> IterableABC: + return reverse_query(self) + def single(self) -> any: return single_query(self) @@ -90,6 +94,3 @@ class Iterable(IterableABC): res = where_query(self, func) res.__class__ = Iterable return res - - def to_list(self) -> list: - return list(self) diff --git a/src/cpl_query/_query/reverse.py b/src/cpl_query/_query/reverse.py new file mode 100644 index 00000000..404d7bd1 --- /dev/null +++ b/src/cpl_query/_query/reverse.py @@ -0,0 +1,15 @@ +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.extension.iterable_abc import IterableABC + + +def reverse_query(_list: IterableABC) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + result = IterableABC() + _copied_list = _list.to_list() + _copied_list.reverse() + for element in _copied_list: + result.append(element) + + return result diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index d21cb116..4b8d65f1 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -80,9 +80,15 @@ class IterableABC(ABC, list): @abstractmethod def order_by_descending(self, func: Callable) -> 'IterableABC': pass + @abstractmethod + def reverse(self) -> 'IterableABC': pass + @abstractmethod def single(self) -> any: pass + def to_list(self) -> list: + return list(self) + @abstractmethod def single_or_default(self) -> Optional[any]: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index cc850237..7426bd5f 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -228,6 +228,13 @@ class QueryTest(unittest.TestCase): self.assertEqual(res, s_res) + def test_reverse(self): + res = self._tests.reverse() + l_res = self._tests.to_list() + l_res.reverse() + + self.assertEqual(l_res, res) + def test_single(self): res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr) s_res = self._tests.where(lambda u: u.address.nr == self._t_user.address.nr).single() -- 2.45.1 From 2b5831c5fe6b3b2946edd68e08fc567a4e64e4c4 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 13:00:06 +0200 Subject: [PATCH 26/31] Improved numbered queries --- src/cpl_query/_query/avg.py | 6 +++--- src/cpl_query/_query/max_min.py | 12 ++++++------ src/cpl_query/tests/query_test.py | 21 ++++++++++++--------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/cpl_query/_query/avg.py b/src/cpl_query/_query/avg.py index ff299a3d..09fbbcc4 100644 --- a/src/cpl_query/_query/avg.py +++ b/src/cpl_query/_query/avg.py @@ -9,6 +9,9 @@ def avg_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] if _list is None: raise ArgumentNoneException(ExceptionArgument.list) + if _func is None and not is_number(_list.type): + raise InvalidTypeException() + average = 0 count = len(_list) @@ -19,9 +22,6 @@ def avg_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] else: value = element - if _func is None and type(element) != _list.type or not is_number(type(value)): - raise WrongTypeException() - average += value return average / count diff --git a/src/cpl_query/_query/max_min.py b/src/cpl_query/_query/max_min.py index a6cae896..d9c2c6a5 100644 --- a/src/cpl_query/_query/max_min.py +++ b/src/cpl_query/_query/max_min.py @@ -10,6 +10,9 @@ def max_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] if _list is None: raise ArgumentNoneException(ExceptionArgument.list) + if _func is None and not is_number(_list.type): + raise InvalidTypeException() + max_value = 0 for element in _list: if _func is not None: @@ -17,9 +20,6 @@ def max_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] 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 @@ -30,6 +30,9 @@ def min_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] if _list is None: raise ArgumentNoneException(ExceptionArgument.list) + if _func is None and not is_number(_list.type): + raise InvalidTypeException() + min_value = 0 is_first = True for element in _list: @@ -38,9 +41,6 @@ def min_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex] 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/tests/query_test.py b/src/cpl_query/tests/query_test.py index 7426bd5f..61cd1de9 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -70,10 +70,11 @@ class QueryTest(unittest.TestCase): self.assertEqual(avg, res) - def wrong(): - e_res = self._tests.average(lambda u: u.address.street) + def invalid(): + tests = List(str, ['hello', 'world']) + e_res = tests.average() - self.assertRaises(WrongTypeException, wrong) + self.assertRaises(InvalidTypeException, invalid) tests = List(int, list(range(0, 100))) self.assertEqual(sum(tests) / len(tests), tests.average()) @@ -174,10 +175,11 @@ class QueryTest(unittest.TestCase): tests = List(values=list(range(0, 100))) self.assertEqual(99, tests.max()) - def wrong(): - e_res = List(str, list([str(v) for v in range(0, 100)])).max() + def invalid(): + tests = List(str, ['hello', 'world']) + e_res = tests.average() - self.assertRaises(WrongTypeException, wrong) + self.assertRaises(InvalidTypeException, invalid) def test_min(self): res = self._tests.min(lambda u: u.address.nr) @@ -186,10 +188,11 @@ class QueryTest(unittest.TestCase): tests = List(values=list(range(0, 100))) self.assertEqual(0, tests.min()) - def wrong(): - e_res = List(str, list([str(v) for v in range(0, 100)])).min() + def invalid(): + tests = List(str, ['hello', 'world']) + e_res = tests.average() - self.assertRaises(WrongTypeException, wrong) + self.assertRaises(InvalidTypeException, invalid) def test_order_by(self): res = self._tests.order_by(lambda user: user.address.street) -- 2.45.1 From 37175b722753bbd60a1a982eadf8281aa3b17f33 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 13:57:42 +0200 Subject: [PATCH 27/31] Added queries sum, skip & take --- src/cpl_query/_extension/iterable.py | 33 +++++++--- src/cpl_query/_extension/ordered_iterable.py | 5 +- src/cpl_query/_query/skip_take.py | 66 ++++++++++++++++++++ src/cpl_query/_query/sum.py | 25 ++++++++ src/cpl_query/extension/iterable_abc.py | 27 ++++++-- src/cpl_query/tests/query_test.py | 46 ++++++++++++++ 6 files changed, 189 insertions(+), 13 deletions(-) create mode 100644 src/cpl_query/_query/skip_take.py create mode 100644 src/cpl_query/_query/sum.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index d480af94..524d5164 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -1,6 +1,5 @@ from typing import Optional, Callable, Union -from cpl_query._extension.ordered_iterable import OrderedIterable from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC from .._query.all import all_query from .._query.any import any_query @@ -15,6 +14,8 @@ from .._query.max_min import max_query, min_query from .._query.order_by import order_by_query, order_by_descending_query from .._query.reverse import reverse_query from .._query.single import single_query, single_or_default_query +from .._query.skip_take import skip_query, skip_last_query, take_query, take_last_query +from .._query.sum import sum_query from .._query.where import where_query from cpl_query.extension.iterable_abc import IterableABC @@ -40,9 +41,7 @@ class Iterable(IterableABC): return count_query(self, func) def distinct(self, func: Callable) -> IterableABC: - res = distinct_query(self, func) - res.__class__ = Iterable - return res + return self.__to_self(distinct_query(self, func)) def element_at(self, index: int) -> any: return element_at_query(self, index) @@ -73,11 +72,13 @@ class Iterable(IterableABC): def order_by(self, func: Callable) -> OrderedIterableABC: res = order_by_query(self, func) + from cpl_query._extension.ordered_iterable import OrderedIterable res.__class__ = OrderedIterable return res def order_by_descending(self, func: Callable) -> OrderedIterableABC: res = order_by_descending_query(self, func) + from cpl_query._extension.ordered_iterable import OrderedIterable res.__class__ = OrderedIterable return res @@ -90,7 +91,25 @@ class Iterable(IterableABC): def single_or_default(self) -> Optional[any]: return single_or_default_query(self) + def skip(self, index: int) -> IterableABC: + return self.__to_self(skip_query(self, index)) + + def skip_last(self, index: int) -> IterableABC: + return self.__to_self(skip_last_query(self, index)) + + def sum(self, func: Callable = None) -> Union[int, float, complex]: + return sum_query(self, func) + + def take(self, index: int) -> IterableABC: + return self.__to_self(take_query(self, index)) + + def take_last(self, index: int) -> IterableABC: + return self.__to_self(take_last_query(self, index)) + def where(self, func: Callable) -> IterableABC: - res = where_query(self, func) - res.__class__ = Iterable - return res + return self.__to_self(where_query(self, func)) + + @staticmethod + def __to_self(obj: IterableABC) -> IterableABC: + obj.__class__ = Iterable + return obj diff --git a/src/cpl_query/_extension/ordered_iterable.py b/src/cpl_query/_extension/ordered_iterable.py index d7c168e9..e711c7f4 100644 --- a/src/cpl_query/_extension/ordered_iterable.py +++ b/src/cpl_query/_extension/ordered_iterable.py @@ -1,13 +1,14 @@ -from abc import ABC from collections import Callable +from .iterable import Iterable from .._query.order_by import then_by_query, then_by_descending_query from cpl_query.extension.ordered_iterable_abc import OrderedIterableABC -class OrderedIterable(OrderedIterableABC, ABC): +class OrderedIterable(Iterable, OrderedIterableABC): def __init__(self): + Iterable.__init__(self) OrderedIterableABC.__init__(self) def then_by(self, _func: Callable) -> OrderedIterableABC: diff --git a/src/cpl_query/_query/skip_take.py b/src/cpl_query/_query/skip_take.py new file mode 100644 index 00000000..ba5972ef --- /dev/null +++ b/src/cpl_query/_query/skip_take.py @@ -0,0 +1,66 @@ +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, IndexOutOfRangeException +from cpl_query.extension.iterable_abc import IterableABC + + +def skip_query(_list: IterableABC, _index: int) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + if _index >= len(_list): + raise IndexOutOfRangeException() + + result = IterableABC() + result.extend(_list[_index:]) + return result + + +def skip_last_query(_list: IterableABC, _index: int) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + index = len(_list) - _index + + if index >= len(_list) or index < 0: + raise IndexOutOfRangeException() + + result = IterableABC() + result.extend(_list[:index]) + return result + + +def take_query(_list: IterableABC, _index: int) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + if _index >= len(_list): + raise IndexOutOfRangeException() + + result = IterableABC() + result.extend(_list[:_index]) + return result + + +def take_last_query(_list: IterableABC, _index: int) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _index is None: + raise ArgumentNoneException(ExceptionArgument.index) + + index = len(_list) - _index + + if index >= len(_list) or index < 0: + raise IndexOutOfRangeException() + + result = IterableABC() + result.extend(_list[index:]) + return result diff --git a/src/cpl_query/_query/sum.py b/src/cpl_query/_query/sum.py new file mode 100644 index 00000000..f8829dad --- /dev/null +++ b/src/cpl_query/_query/sum.py @@ -0,0 +1,25 @@ +from collections import Callable +from typing import Union + +from cpl_query._helper import is_number +from cpl_query.exceptions import ExceptionArgument, ArgumentNoneException, InvalidTypeException +from cpl_query.extension.iterable_abc import IterableABC + + +def sum_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None and not is_number(_list.type): + raise InvalidTypeException() + + result = 0 + for element in _list: + if _func is not None: + value = _func(element) + else: + value = element + + result += value + + return result diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 4b8d65f1..673f6167 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Optional, Callable, Union +from typing import Optional, Callable, Union, Iterable class IterableABC(ABC, list): @@ -53,6 +53,10 @@ class IterableABC(ABC, list): @abstractmethod def element_at_or_default(self, index: int) -> Optional[any]: pass + def extend(self, __iterable: Iterable) -> None: + for value in __iterable: + self.append(value) + @abstractmethod def last(self) -> any: pass @@ -86,11 +90,26 @@ class IterableABC(ABC, list): @abstractmethod def single(self) -> any: pass - def to_list(self) -> list: - return list(self) - @abstractmethod def single_or_default(self) -> Optional[any]: pass + @abstractmethod + def skip(self, index: int) -> 'IterableABC': pass + + @abstractmethod + def skip_last(self, index: int) -> 'IterableABC': pass + + @abstractmethod + def sum(self, func: Callable = None) -> Union[int, float, complex]: pass + + @abstractmethod + def take(self, index: int) -> 'IterableABC': pass + + @abstractmethod + def take_last(self, index: int) -> 'IterableABC': pass + + def to_list(self) -> list: + return list(self) + @abstractmethod def where(self, func: Callable) -> 'IterableABC': pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 61cd1de9..aee2cf2b 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -204,6 +204,8 @@ class QueryTest(unittest.TestCase): s_res.sort(key=lambda user: user.address.nr) self.assertEqual(res2, s_res) + self.assertEqual(self._t_user, res.where(lambda u: u.address.nr == self._t_user.address.nr).single()) + def test_order_by_descending(self): res = self._tests.order_by_descending(lambda user: user.address.street) res2 = self._tests.order_by_descending(lambda user: user.address.nr) @@ -254,6 +256,50 @@ class QueryTest(unittest.TestCase): self.assertEqual(self._t_user, s_res) self.assertIsNone(sn_res) + def test_skip(self): + skipped = self._tests.skip(5) + + self.assertEqual(len(self._tests) - 5, len(skipped)) + self.assertEqual(self._tests[5:], skipped) + + def test_skip_last(self): + skipped = self._tests.skip_last(5) + + self.assertEqual(len(self._tests) - 5, len(skipped)) + self.assertEqual(self._tests[:-5], skipped) + self.assertEqual(self._tests[:-5][len(self._tests[:-5]) - 1], skipped.last()) + + def test_sum(self): + res = self._tests.sum(lambda u: u.address.nr) + + s_res = 0 + for user in self._tests: + s_res += user.address.nr + + self.assertEqual(s_res, res) + + tests = List(values=list(range(0, 100))) + self.assertEqual(0, tests.min()) + + def invalid(): + tests2 = List(str, ['hello', 'world']) + e_res = tests2.average() + + self.assertRaises(InvalidTypeException, invalid) + + def test_take(self): + skipped = self._tests.take(5) + + self.assertEqual(5, len(skipped)) + self.assertEqual(self._tests[:5], skipped) + + def test_take_last(self): + skipped = self._tests.take_last(5) + + self.assertEqual(5, len(skipped)) + self.assertEqual(self._tests[-5:], skipped) + self.assertEqual(self._tests[len(self._tests) - 1], skipped.last()) + def test_where(self): results = [] for user in self._tests: -- 2.45.1 From b9499108d81272774ba8b8a984a0996e08bd02e3 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 2 Aug 2021 14:03:51 +0200 Subject: [PATCH 28/31] Build cpl_query --- src/cpl_query/__init__.py | 2 +- src/cpl_query/_extension/__init__.py | 2 +- src/cpl_query/_query/__init__.py | 2 +- src/cpl_query/cpl_query.json | 2 +- src/cpl_query/extension/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 4c2a8ace..2d8f31b2 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -cpl_query sh-edraft Common Python library Query +sh_cpl_query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries diff --git a/src/cpl_query/_extension/__init__.py b/src/cpl_query/_extension/__init__.py index be7ebebb..8afe588d 100644 --- a/src/cpl_query/_extension/__init__.py +++ b/src/cpl_query/_extension/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -cpl_query sh-edraft Common Python library Query +sh_cpl_query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries diff --git a/src/cpl_query/_query/__init__.py b/src/cpl_query/_query/__init__.py index d9873974..508ccbc1 100644 --- a/src/cpl_query/_query/__init__.py +++ b/src/cpl_query/_query/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -cpl_query sh-edraft Common Python library Query +sh_cpl_query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries diff --git a/src/cpl_query/cpl_query.json b/src/cpl_query/cpl_query.json index c2d0a970..906af43b 100644 --- a/src/cpl_query/cpl_query.json +++ b/src/cpl_query/cpl_query.json @@ -1,6 +1,6 @@ { "ProjectSettings": { - "Name": "cpl_query", + "Name": "sh_cpl_query", "Version": { "Major": "2021", "Minor": "10", diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 22693b99..8f1999c8 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -cpl_query sh-edraft Common Python library Query +sh_cpl_query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries -- 2.45.1 From ffaa5c4a2bfdf56513ea3d867f0621e29191df4f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 2 Aug 2021 14:09:42 +0200 Subject: [PATCH 29/31] Refactoring --- src/cpl_query/tests/query_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index aee2cf2b..9efe8310 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -3,7 +3,7 @@ import unittest from random import randint from cpl.utils import String -from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ArgumentNoneException +from cpl_query.exceptions import InvalidTypeException, ArgumentNoneException from cpl_query.extension.list import List from cpl_query.tests.models import User, Address @@ -160,8 +160,7 @@ class QueryTest(unittest.TestCase): def test_for_each(self): users = [] - self._tests.for_each( - lambda user: ( + self._tests.for_each(lambda user: ( users.append(user) ) ) -- 2.45.1 From 6867eb0e65cd9bf5d3e9c786ee3c097f278e7cde Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 2 Aug 2021 14:14:50 +0200 Subject: [PATCH 30/31] Improved scripts --- scripts/build.sh | 12 ++++++++---- scripts/publish.sh | 14 +++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index bccdac52..78e1e24c 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -2,10 +2,14 @@ # activate venv source /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/cpl-env/bin/activate -# CLI -cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/ -cpl build - # CPL cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl +cpl build + +# CLI +cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl_cli +cpl build + +# CPL Query +cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl_query cpl build \ No newline at end of file diff --git a/scripts/publish.sh b/scripts/publish.sh index 341a279c..428a540f 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -2,10 +2,14 @@ # activate venv source /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/cpl-env/bin/activate -# CLI -cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/ -cpl publish - # CPL cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl -cpl publish \ No newline at end of file +cpl publish + +# CLI +cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl_cli +cpl publish + +# CPL Query +cd /home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cpl/src/cpl_query +cpl \ No newline at end of file -- 2.45.1 From e09a4402b3a449e4ed7c0df336dea0390bb7b670 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 2 Aug 2021 14:36:00 +0200 Subject: [PATCH 31/31] Published sh_cpl-query to version 2021.10.0rc1 --- notices/pip.txt | 15 +++++++++++++++ src/cpl_query/__init__.py | 6 +++--- src/cpl_query/_extension/__init__.py | 6 +++--- src/cpl_query/_query/__init__.py | 6 +++--- src/cpl_query/cpl_query.json | 10 +++++----- src/cpl_query/extension/__init__.py | 6 +++--- 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/notices/pip.txt b/notices/pip.txt index fddb0076..6e6e9ab7 100644 --- a/notices/pip.txt +++ b/notices/pip.txt @@ -7,6 +7,10 @@ upload: twine upload --repository-url https://pip.sh-edraft.de dist/sh_cpl-cli/publish/setup/* twine upload -r pip.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + query: + twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl-query/publish/setup/* + twine upload -r pip-dev.sh-edraft.de dist/sh_cpl-query/publish/setup/* + exp: cpl: twine upload --repository-url https://pip-exp.sh-edraft.de dist/sh_cpl/publish/setup/* @@ -16,6 +20,10 @@ upload: twine upload --repository-url https://pip-exp.sh-edraft.de dist/sh_cpl-cli/publish/setup/* twine upload -r pip-exp.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + query: + twine upload --repository-url https://pip-exp.sh-edraft.de dist/sh_cpl-query/publish/setup/* + twine upload -r pip-exp.sh-edraft.de dist/sh_cpl-query/publish/setup/* + dev: cpl: twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl/publish/setup/* @@ -25,15 +33,22 @@ upload: twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl-cli/publish/setup/* twine upload -r pip-dev.sh-edraft.de dist/sh_cpl-cli/publish/setup/* + query: + twine upload --repository-url https://pip-dev.sh-edraft.de dist/sh_cpl-query/publish/setup/* + twine upload -r pip-dev.sh-edraft.de dist/sh_cpl-query/publish/setup/* + install: prod: pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl-cli + pip install --extra-index-url https://pip.sh-edraft.de/ sh_cpl-query exp: pip install --extra-index-url https://pip-exp.sh-edraft.de/ sh_cpl pip install --extra-index-url https://pip-exp.sh-edraft.de/ sh_cpl-cli + pip install --extra-index-url https://pip-exp.sh-edraft.de/ sh_cpl-query dev: pip install --extra-index-url https://pip-dev.sh-edraft.de/ sh_cpl pip install --extra-index-url https://pip-dev.sh-edraft.de/ sh_cpl-cli + pip install --extra-index-url https://pip-dev.sh-edraft.de/ sh_cpl-query diff --git a/src/cpl_query/__init__.py b/src/cpl_query/__init__.py index 2d8f31b2..c4bb6465 100644 --- a/src/cpl_query/__init__.py +++ b/src/cpl_query/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -sh_cpl_query sh-edraft Common Python library Query +sh_cpl-query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries @@ -15,11 +15,11 @@ __title__ = 'cpl_query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.10.3' +__version__ = '2021.10.0rc1' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='10', micro='3') +version_info = VersionInfo(major='2021', minor='10', micro='0.rc1') diff --git a/src/cpl_query/_extension/__init__.py b/src/cpl_query/_extension/__init__.py index 8afe588d..20b5dd05 100644 --- a/src/cpl_query/_extension/__init__.py +++ b/src/cpl_query/_extension/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -sh_cpl_query sh-edraft Common Python library Query +sh_cpl-query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries @@ -15,11 +15,11 @@ __title__ = 'cpl_query._extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.10.3' +__version__ = '2021.10.0rc1' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='10', micro='3') +version_info = VersionInfo(major='2021', minor='10', micro='0.rc1') diff --git a/src/cpl_query/_query/__init__.py b/src/cpl_query/_query/__init__.py index 508ccbc1..4eb1e489 100644 --- a/src/cpl_query/_query/__init__.py +++ b/src/cpl_query/_query/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -sh_cpl_query sh-edraft Common Python library Query +sh_cpl-query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries @@ -15,11 +15,11 @@ __title__ = 'cpl_query._query' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.10.3' +__version__ = '2021.10.0rc1' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='10', micro='3') +version_info = VersionInfo(major='2021', minor='10', micro='0.rc1') diff --git a/src/cpl_query/cpl_query.json b/src/cpl_query/cpl_query.json index 906af43b..042aa616 100644 --- a/src/cpl_query/cpl_query.json +++ b/src/cpl_query/cpl_query.json @@ -1,10 +1,10 @@ { "ProjectSettings": { - "Name": "sh_cpl_query", + "Name": "sh_cpl-query", "Version": { "Major": "2021", "Minor": "10", - "Micro": "3" + "Micro": "0.rc1" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", @@ -26,9 +26,9 @@ "ProjectType": "library", "SourcePath": "", "OutputPath": "../../dist", - "Main": "cpl_query.main", - "EntryPoint": "cpl_query", - "IncludePackageData": false, + "Main": "", + "EntryPoint": "", + "IncludePackageData": true, "Included": [], "Excluded": [ "*/__pycache__", diff --git a/src/cpl_query/extension/__init__.py b/src/cpl_query/extension/__init__.py index 8f1999c8..21af0cd0 100644 --- a/src/cpl_query/extension/__init__.py +++ b/src/cpl_query/extension/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -sh_cpl_query sh-edraft Common Python library Query +sh_cpl-query sh-edraft Common Python library Query ~~~~~~~~~~~~~~~~~~~ sh-edraft Common Python library Python integrated Queries @@ -15,11 +15,11 @@ __title__ = 'cpl_query.extension' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2020 - 2021 sh-edraft.de' -__version__ = '2021.10.3' +__version__ = '2021.10.0rc1' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='2021', minor='10', micro='3') +version_info = VersionInfo(major='2021', minor='10', micro='0.rc1') -- 2.45.1