Function fields broken by migration from 3.0 to 3.4

50 views
Skip to first unread message

Jon Levy

unread,
Apr 2, 2016, 4:40:04 AM4/2/16
to tryton
I am working to migrate my 3.0 installation to 3.4, but I've run into problems with
function fields.  I can't find any relevant changes in the documentation or
notes in the wiki.

Two fields, so far, crash in tests that passed in 3.0.

(1)  
Behavior:
    Given an instance of MyClass, attempts to access
    the_instance.current result in: "RuntimeError: maximum recursion depth exceeded"

Code (simplified):
    class MyClass(ModelSQL, ModelView):
      association = fields.Many2One('my_module.association', 'Association',
 required=True, select=True, ondelete='CASCADE”
      )
      current = fields.Function(fields.Boolean('Current'), 'get_current')

      def get_current(self, name):
 "Get current"
 return self.association.is_current

 # same error also results when replacing the code with
 #    self.association
 #    return True
          # Ie, the error is simply from accessing the Many2One field
          # of the instance.

(2)
Tests that attempt to access this function field report the following
traceback:
    Traceback (most recent call last):
      File ..., line 2432, in test0130
self.assertEqual(log1.calculable_dh_chain_end, log3)
      File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/field.py",
              line 213, in __get__
 return inst.__getattr__(self.name)
      File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelstorage.py",
              line 1332, in __getattr__
 fvalue = instantiate(field, data[fname], data)
      File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelstorage.py",
              line 1303, in instantiate
 return Model(value, _ids=ids, _local_cache=local_cache)
      File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelstorage.py",
              line 1157, in __init__
 assert id in _ids
    AssertionError

However, it works fine when directly call the getter of the instance.  Ie:
    an_instance.get_calculable_dh_chain_end(None)  # the function doesn't use name
This returns as expected (in the case of the test, log3).

All advice and suggestions are welcome.  Thank you in advance for your attention!

Cédric Krier

unread,
Apr 2, 2016, 4:53:49 AM4/2/16
to tryton
I guess it is because the value in the database of the column
'association' is not an id but something that int() can convert (maybe a
float).
Maybe we should change the test that convert to int() by an isinstance
test.

--
Cédric Krier - B2CK SPRL
Email/Jabber: cedric...@b2ck.com
Tel: +32 472 54 46 59
Website: http://www.b2ck.com/

Cédric Krier

unread,
Apr 2, 2016, 5:05:03 AM4/2/16
to tryton

Jon Levy

unread,
Apr 3, 2016, 5:35:05 PM4/3/16
to tryton
Here is the traceback for errors in the first category:

[Loop occurs lots of times]
[Start of loop]
  File "/usr/local/lib/python2.7/dist-packages/trytond/modules/advocatetax/log.py", line 4367, in get_entity
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/field.py", line 213, in __get__
    return inst.__getattr__(self.name)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelstorage.py", line 1326, in __getattr__
    read_data = self.read(list(ids), ffields.keys())
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelsql.py", line 645, in read
    getter_results = field.get(ids, cls, field_list, values=result)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/function.py", line 91, in get
    return dict((name, call(name)) for name in names)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/function.py", line 91, in <genexpr>
    return dict((name, call(name)) for name in names)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/function.py", line 85, in call
    return dict((r.id, method(r, name)) for r in records)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/function.py", line 85, in <genexpr>
    return dict((r.id, method(r, name)) for r in records)
[End of loop]
  File "/usr/local/lib/python2.7/dist-packages/trytond/modules/advocatetax/log.py", line 4367, in get_entity
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/fields/field.py", line 213, in __get__
    return inst.__getattr__(self.name)
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelstorage.py", line 1326, in __getattr__
    read_data = self.read(list(ids), ffields.keys())
[Breaks out of loop, throwing error]
  File "/usr/local/lib/python2.7/dist-packages/trytond/model/modelsql.py", line 576, in read
    order_by=history_order, limit=history_limit))
  File "/usr/local/lib/python2.7/dist-packages/sql/__init__.py", line 192, in __iter__
    yield str(self)
  File "/usr/local/lib/python2.7/dist-packages/sql/__init__.py", line 538, in __str__
    where = ' WHERE ' + str(self.where)
  File "/usr/local/lib/python2.7/dist-packages/sql/operators.py", line 148, in __str__
    return '(' + (' %s ' % self._operator).join(map(str, self)) + ')'
  File "/usr/local/lib/python2.7/dist-packages/sql/operators.py", line 132, in __str__
    return '(%s %s %s)' % (self._format(left), self._operator,
  File "/usr/local/lib/python2.7/dist-packages/sql/operators.py", line 76, in _format
    return str(operand)
  File "/usr/local/lib/python2.7/dist-packages/sql/__init__.py", line 1267, in __str__
    alias = self._from.alias
  File "/usr/local/lib/python2.7/dist-packages/sql/__init__.py", line 249, in alias
    return AliasManager.get(self)

Cédric Krier

unread,
Apr 3, 2016, 6:00:05 PM4/3/16
to tryton
Looking at https://codereview.tryton.org/24111002, it seems that you
have a Function field for Many2One (or xxx2Many) for which the getter
returns a (list of) instances instead of a (list of) ids.

Jon Levy

unread,
Apr 5, 2016, 5:34:16 PM4/5/16
to tryton


On Sunday, April 3, 2016 at 6:00:05 PM UTC-4, Cédric Krier wrote:
it seems that you
have a Function field for Many2One (or xxx2Many) for which the getter
returns a (list of) instances instead of a (list of) ids.

Bingo, that was it!  Thank you.

I'm still working on the recursion-limit error, but this was a huge help. 

Jon Levy

unread,
Apr 7, 2016, 7:31:33 PM4/7/16
to tryton


On Tuesday, April 5, 2016 at 5:34:16 PM UTC-4, Jon Levy wrote:
I'm still working on the recursion-limit error, but this was a huge help. 

For anyone else encountering this problem, it was caused in my case by using a function field in the context of another field.  This is apparently not allowed anymore, as evidenced by the addition to 3.4's documentation that "The context could only depend on direct field of the record and without context."[1]

The resultant error is: RuntimeError: maximum recursion depth exceeded.

Reply all
Reply to author
Forward
0 new messages