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)