Skip to content

Commit

Permalink
Add filtered, sorted and operators (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
kmagusiak authored Oct 27, 2022
1 parent cab0d21 commit c5ae0af
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
56 changes: 55 additions & 1 deletion odoo_connect/explore.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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(
Expand Down
28 changes: 28 additions & 0 deletions tests/test_explore.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

0 comments on commit c5ae0af

Please sign in to comment.