Construct recursively Tree search_rec_name with 'in' operators

Each value of the 'in' operators must be processed as a '=' clause.
The None values must be supported just in case it set in the 'in' values
because the mixin does not allow empty name.

issue9354
review304601002
This commit is contained in:
Cédric Krier committed 2020-10-26 21:27:13 +01:00
1 parent fc9aefe104
commit 0a2cc7162d
2 files changed
+91 -29

No files matched your search

+31 -29
View File
@@ -38,39 +38,41 @@ def tree(parent='parent', name='name', separator=None):
@classmethod
def search_rec_name(cls, _, clause):
if isinstance(clause[2], str):
values = list(reversed(clause[2].split(separator)))
else:
values = [[]]
for value in clause[2]:
if value is None:
values[0].append(value)
continue
for i, v in range(reversed(value.split(separator))):
while len(values) <= i:
values.append([])
values[i].append(v)
domain = []
field = name
for value in values:
domain.append((field, clause[1], value.strip()))
field = parent + '.' + field
if ((
clause[1].endswith('like')
and not clause[2].replace(
'%%', '__').startswith('%'))
or not clause[1].endswith('like')):
if clause[1].startswith('not') or clause[1] == '!=':
if isinstance(clause[2], str):
field = name
values = list(reversed(clause[2].split(separator)))
for value in values:
domain.append((field, clause[1], value.strip()))
field = parent + '.' + field
if ((
clause[1].endswith('like')
and not clause[2].replace(
'%%', '__').startswith('%'))
or not clause[1].endswith('like')):
if clause[1].startswith('not') or clause[1] == '!=':
operator = '!='
domain.insert(0, 'OR')
else:
operator = '='
top_parent = '.'.join((parent,) * len(values))
domain.append((top_parent, operator, None))
if (clause[1].endswith('like')
and clause[2].replace('%%', '__').endswith('%')):
ids = list(map(int, cls.search(domain, order=[])))
domain = [(parent, 'child_of', ids)]
elif clause[2] is None:
domain.append((name, clause[1], clause[2]))
else:
if clause[1].startswith('not'):
operator = '!='
domain.insert(0, 'OR')
domain.append('AND')
else:
operator = '='
top_parent = '.'.join((parent,) * len(values))
domain.append((top_parent, operator, None))
if (clause[1].endswith('like')
and clause[2].replace('%%', '__').endswith('%')):
ids = list(map(int, cls.search(domain, order=[])))
domain = [(parent, 'child_of', ids)]
domain.append('OR')
for value in clause[2]:
domain.append(cls.search_rec_name(
name, (clause[0], operator, value)))
return domain
@classmethod
+60
View File
@@ -69,6 +69,21 @@ class TreeMixinTestCase(unittest.TestCase):
self.assertEqual(records, [parent])
@with_transaction()
def test_search_rec_name_equals_none(self):
"Test search_rec_name equals"
pool = Pool()
Tree = pool.get('test.tree')
parent = Tree(name="parent")
parent.save()
record = Tree(name="record", parent=parent)
record.save()
records = Tree.search([('rec_name', '=', None)])
self.assertEqual(records, [])
@with_transaction()
def test_search_rec_name_non_equals(self):
"Test search_rec_name non equals"
@@ -99,6 +114,51 @@ class TreeMixinTestCase(unittest.TestCase):
self.assertEqual(records, [record])
@with_transaction()
def test_search_rec_name_non_equals_none(self):
"Test search_rec_name equals"
pool = Pool()
Tree = pool.get('test.tree')
parent = Tree(name="parent")
parent.save()
record = Tree(name="record", parent=parent)
record.save()
records = Tree.search([('rec_name', '!=', None)])
self.assertEqual(records, [parent, record])
@with_transaction()
def test_search_rec_name_in(self):
"Test search_rec_name in"
pool = Pool()
Tree = pool.get('test.tree')
parent = Tree(name="parent")
parent.save()
record = Tree(name="record", parent=parent)
record.save()
records = Tree.search([('rec_name', 'in', ['parent / record'])])
self.assertEqual(records, [record])
@with_transaction()
def test_search_rec_name_in_toplevel(self):
"Test search_rec_name in top-level"
pool = Pool()
Tree = pool.get('test.tree')
parent = Tree(name="parent")
parent.save()
record = Tree(name="record", parent=parent)
record.save()
records = Tree.search([('rec_name', 'in', ['parent'])])
self.assertEqual(records, [parent])
@with_transaction()
def test_search_rec_name_like(self):
"Test search_rec_name like"