From c5ae0af24d4c74cafaaa0276c81fb5b3559f2861 Mon Sep 17 00:00:00 2001 From: Krzysztof Magusiak Date: Thu, 27 Oct 2022 21:00:14 +0200 Subject: [PATCH] Add filtered, sorted and operators (#10) --- odoo_connect/explore.py | 56 ++++++++++++++++++++++++++++++++++++++++- tests/test_explore.py | 28 +++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/odoo_connect/explore.py b/odoo_connect/explore.py index 2ff8fc2..d04866e 100644 --- a/odoo_connect/explore.py +++ b/odoo_connect/explore.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Iterable, List, Union +from typing import Any, Callable, Dict, Iterable, List, Union import odoo_connect.format @@ -18,12 +18,41 @@ def __init__(self, model: odoo_rpc.OdooModel, ids: List[int]) -> None: self.__model = model self.__ids = ids + def __bool__(self) -> bool: + return bool(self.__ids) + def __len__(self): return len(self.__ids) def __dir__(self) -> Iterable[str]: return self.__model.fields().keys() + def __add__(self, other) -> "Instance": + if self.__model.model != other.__model.model or not isinstance(other, Instance): + raise ValueError('Cannot combine different models') + ids = self.__ids + other.__ids + return Instance(self.__model, ids) + + def __sub__(self, other) -> "Instance": + if self.__model.model != other.__model.model or not isinstance(other, Instance): + raise ValueError('Cannot combine different models') + otherset = set(other.__ids) + ids = [i for i in self.__ids if i not in otherset] + return Instance(self.__model, ids) + + def __or__(self, other) -> "Instance": + if self.__model.model != other.__model.model or not isinstance(other, Instance): + raise ValueError('Cannot combine different models') + ids = self.__ids + (other - self).__ids + return Instance(self.__model, ids) + + def __and__(self, other) -> "Instance": + if self.__model.model != other.__model.model or not isinstance(other, Instance): + raise ValueError('Cannot combine different models') + otherset = set(other.__ids) + ids = [i for i in self.__ids if i in otherset] + return Instance(self.__model, ids) + @property def ids(self) -> List[int]: return self.__ids @@ -196,6 +225,11 @@ def unlink(self): self.invalidate_cache(self.__ids) self.__model.unlink(self.__ids) + def copy(self): + """Copy the records in the database""" + ids = self.__model.copy(self.__ids) + return self.browse(*ids) + def __cache(self) -> Dict[int, Dict[str, Any]]: model_cache = GLOBAL_CACHE.get(self.__model) if not model_cache: @@ -213,6 +247,26 @@ def invalidate_cache(self, ids=None): for id in ids: model_cache.pop(id, None) + def filtered(self, predicate: Callable[["Instance"], bool]) -> "Instance": + """Filter the records""" + + def _predicate(i): + return predicate(self.browse(i)) + + self.cache(computed=False) + ids = list(filter(_predicate, self.__ids)) + return Instance(self.__model, ids) + + def sorted(self, order: Callable[["Instance"], Any]) -> "Instance": + """Sort the objects by a field""" + + def sorted_key(i): + return order(self.browse(i)) + + self.cache(computed=False) + ids = sorted(self.__ids, key=sorted_key) + return Instance(self.__model, ids) + def get_attachments(self) -> "Instance": """Return ir.attachment linked to this instance""" return explore(self.__model.odoo['ir.attachment']).search( diff --git a/tests/test_explore.py b/tests/test_explore.py index 9de1b39..ca246a4 100644 --- a/tests/test_explore.py +++ b/tests/test_explore.py @@ -85,6 +85,27 @@ def test_ex_cache(odoo_cli_partner: Instance): assert inst.display_name +def test_ex_exist(odoo_cli_partner: Instance): + inst = odoo_cli_partner.browse(*range(10)).exists() + assert 0 < len(inst) < 10 + + +def test_ex_combine(odoo_cli_partner: Instance): + a = odoo_cli_partner.browse(5, 6) + b = odoo_cli_partner.browse(6, 7) + assert len(a + b) == 4 + assert (a - b).ids == [5] + assert (a | b).ids == [5, 6, 7] + assert (a & b).ids == [6] + + +def test_ex_filtered(odoo_cli_partner: Instance): + inst = odoo_cli_partner.browse(1, 2) + assert len(inst) == 2 + inst = inst.filtered(lambda i: i.name == 'test') + assert len(inst) == 1 + + def test_ex_create(odoo_cli_partner: Instance): inst = odoo_cli_partner.create({'name': 'ok'}) assert inst @@ -96,3 +117,10 @@ def test_ex_write(odoo_cli_partner: Instance): assert inst.name == 'test' inst.name = 'ok' assert inst.name == 'ok' + + +def test_ex_write_format(odoo_cli_partner: Instance): + inst = odoo_cli_partner.browse(1) + assert inst.name == 'test' + inst.write({'name': ''}, format=True) + assert inst.name is False