changeset 1fe05701cda8 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=1fe05701cda8
description:
        Use simplified parser for get_eval_fields

        Instead of using the PYSONEncoder we can just iterate over the basic 
JSON types
        and use the pyson method to retrieve nested PYSON instances.

        issue11164
        review376551002
diffstat:

 trytond/model/fields/field.py       |  30 +++++++++++++++---------------
 trytond/pyson.py                    |   9 +++++++++
 trytond/tests/test_field_depends.py |  18 +++++++++++++++++-
 3 files changed, 41 insertions(+), 16 deletions(-)

diffs (96 lines):

diff -r 65e6c8a59986 -r 1fe05701cda8 trytond/model/fields/field.py
--- a/trytond/model/fields/field.py     Sun Jan 30 12:58:51 2022 +0100
+++ b/trytond/model/fields/field.py     Sun Jan 30 13:10:57 2022 +0100
@@ -125,23 +125,23 @@
     return decorator
 
 
+def _iter_eval_fields(value):
+    "Iterate over evaluated fields"
+    if isinstance(value, Eval):
+        yield value.basename
+    elif isinstance(value, PYSON):
+        yield from _iter_eval_fields(value.pyson())
+    elif isinstance(value, (list, tuple)):
+        for val in value:
+            yield from _iter_eval_fields(val)
+    elif isinstance(value, dict):
+        for val in value.values():
+            yield from _iter_eval_fields(val)
+
+
 def get_eval_fields(value):
     "Return fields evaluated"
-    class Encoder(PYSONEncoder):
-        def __init__(self, *args, **kwargs):
-            super(Encoder, self).__init__(*args, **kwargs)
-            self.fields = set()
-
-        def default(self, obj):
-            if isinstance(obj, Eval):
-                fname = obj._value
-                if not fname.startswith('_parent_'):
-                    self.fields.add(fname)
-            return super(Encoder, self).default(obj)
-
-    encoder = Encoder()
-    encoder.encode(value)
-    return encoder.fields
+    return set(_iter_eval_fields(value))
 
 
 def instanciate_values(Target, value, **extra):
diff -r 65e6c8a59986 -r 1fe05701cda8 trytond/pyson.py
--- a/trytond/pyson.py  Sun Jan 30 12:58:51 2022 +0100
+++ b/trytond/pyson.py  Sun Jan 30 13:10:57 2022 +0100
@@ -162,6 +162,15 @@
                     }, context.get(base) or {})
         return context.get(dct['v'], dct['d'])
 
+    @property
+    def basename(self):
+        name = self._value
+        if name.startswith('_parent_'):
+            name = name[len('_parent_'):]
+        if '.' in name:
+            name = name.split('.', 1)[0]
+        return name
+
 
 class Not(PYSON):
 
diff -r 65e6c8a59986 -r 1fe05701cda8 trytond/tests/test_field_depends.py
--- a/trytond/tests/test_field_depends.py       Sun Jan 30 12:58:51 2022 +0100
+++ b/trytond/tests/test_field_depends.py       Sun Jan 30 13:10:57 2022 +0100
@@ -3,7 +3,7 @@
 import unittest
 
 from trytond.model import ModelView, fields
-from trytond.pyson import Eval
+from trytond.pyson import Eval, If
 from trytond.tests.test_tryton import activate_module, with_transaction
 
 
@@ -248,6 +248,22 @@
 
         self.assertEqual(Model.bar.on_change, {'foo', 'bar'})
 
+    def test_get_eval_fields(self):
+        "Test get_eval_fields"
+        for value, result in [
+                ('test', set()),
+                (Eval('foo'), {'foo'}),
+                (Eval('_parent_foo'), {'foo'}),
+                (Eval('foo.bar'), {'foo'}),
+                ([Eval('foo'), Eval('bar')], {'foo', 'bar'}),
+                ((Eval('foo'), Eval('bar')), {'foo', 'bar'}),
+                ({'foo': Eval('bar')}, {'bar'}),
+                (If(Eval('foo'), Eval('bar'), Eval('baz')),
+                    {'foo', 'bar', 'baz'}),
+                ]:
+            with self.subTest(value=value):
+                self.assertEqual(fields.get_eval_fields(value), result)
+
 
 def suite():
     return unittest.TestLoader().loadTestsFromTestCase(FieldDependsTestCase)

Reply via email to