[FIX] tools: serialize lazy to json

This commit is contained in:
Raphael Collet
2018-08-16 16:39:20 +02:00
parent 49fb7a4682
commit 2a2ff6eb5c
2 changed files with 34 additions and 18 deletions
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
import json
from odoo.tests.common import TransactionCase, users, warmup
from odoo.tools import pycompat
@@ -138,3 +139,6 @@ class TestPerformance(TransactionCase):
self.assertEqual(res['partner_id'][0], exp['partner_id'][0])
self.assertEqual(res['partner_id_count'], exp['partner_id_count'])
self.assertEqual(res['value'], exp['value'])
# now serialize to json, which should force evaluation
with self.assertQueryCount(admin=1, demo=1):
json.dumps(result)
+30 -18
View File
@@ -4,8 +4,9 @@
__all__ = ['synchronized', 'lazy_classproperty', 'lazy_property',
'classproperty', 'conditional', 'lazy']
from functools import wraps, partial
from functools import wraps
from inspect import getsourcefile
from json import JSONEncoder
class lazy_property(object):
@@ -122,27 +123,27 @@ class lazy(object):
baz = foo + 2 # use result of func(arg) and add 2
"""
__slots__ = ['_func', '_value']
__slots__ = ['_func', '_args', '_kwargs', '_cached_value']
def __init__(self, func, *args, **kwargs):
self._func = partial(func, *args, **kwargs)
# bypass own __setattr__
object.__setattr__(self, '_func', func)
object.__setattr__(self, '_args', args)
object.__setattr__(self, '_kwargs', kwargs)
def __getattr__(self, name):
if name == '_value':
self._value = value = self._func()
self._func = None
return value
return getattr(self._value, name)
@property
def _value(self):
if self._func is not None:
value = self._func(*self._args, **self._kwargs)
object.__setattr__(self, '_func', None)
object.__setattr__(self, '_args', None)
object.__setattr__(self, '_kwargs', None)
object.__setattr__(self, '_cached_value', value)
return self._cached_value
def __setattr__(self, name, value):
if name in ('_func', '_value'):
return object.__setattr__(self, name, value)
return setattr(self._value, name, value)
def __delattr__(self, name):
if name in ('_func', '_value'):
return object.__delattr__(self, name)
return delattr(self._value, name)
def __getattr__(self, name): return getattr(self._value, name)
def __setattr__(self, name, value): return setattr(self._value, name, value)
def __delattr__(self, name): return delattr(self._value, name)
def __repr__(self):
return repr(self._value) if self._func is None else object.__repr__(self)
@@ -241,3 +242,14 @@ class lazy(object):
def __aenter__(self): return self._value.__aenter__()
def __aexit__(self, exc_type, exc_value, traceback):
return self._value.__aexit__(exc_type, exc_value, traceback)
# patch serialization of lazy
def default(self, o):
if isinstance(o, lazy):
return o._value
return json_encoder_default(self, o)
json_encoder_default = JSONEncoder.default
JSONEncoder.default = default