[FIX] fields: make `copy_cache` use a todo list instead of recursion

The recursion was based on an incorrect assumption: the cache of the target
environment is initially empty.  If another computation left some value there,
the copying is incomplete, and that causes bugs in onchanges.
This commit is contained in:
Raphael Collet 2016-02-04 13:48:28 +01:00
parent 67a63e2cc9
commit 0f2e7d783e
1 changed files with 9 additions and 6 deletions

View File

@ -61,14 +61,17 @@ def _check_value(value):
def copy_cache(records, env):
""" Recursively copy the cache of ``records`` to the environment ``env``. """
for record, target in zip(records, records.with_env(env)):
if not target._cache:
todo, done = set(records), set()
while todo:
record = todo.pop()
if record not in done:
done.add(record)
target = record.with_env(env)
for name, value in record._cache.iteritems():
if isinstance(value, BaseModel):
target._cache[name] = value.with_env(env)
copy_cache(value, env)
else:
target._cache[name] = value
todo.add(value)
value = value.with_env(env)
target._cache[name] = value
def resolve_all_mro(cls, name, reverse=False):