changeset a86dba790821 in trytond:5.6
details: https://hg.tryton.org/trytond?cmd=changeset;node=a86dba790821
description:
        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
        (grafted from 84244f5b76418f093ce6212653ddd365259818ea)
diffstat:

 trytond/model/tree.py      |  56 ++++++++++++++++++++++--------------------
 trytond/tests/test_tree.py |  60 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 27 deletions(-)

diffs (149 lines):

diff -r b88a0fa56278 -r a86dba790821 trytond/model/tree.py
--- a/trytond/model/tree.py     Sat Oct 24 23:17:19 2020 +0200
+++ b/trytond/model/tree.py     Mon Oct 26 21:27:13 2020 +0100
@@ -38,39 +38,41 @@
 
             @classmethod
             def search_rec_name(cls, _, clause):
+                domain = []
                 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:
-                    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 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
diff -r b88a0fa56278 -r a86dba790821 trytond/tests/test_tree.py
--- a/trytond/tests/test_tree.py        Sat Oct 24 23:17:19 2020 +0200
+++ b/trytond/tests/test_tree.py        Mon Oct 26 21:27:13 2020 +0100
@@ -70,6 +70,21 @@
         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"
         pool = Pool()
@@ -100,6 +115,51 @@
         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"
         pool = Pool()

Reply via email to