[FIX] unsafe listification of weakref in Python < 2.7.4
Fixes #966 * As a preallocation optimization, ``list()`` calls ``__len__`` on its parameter if it's available * Before Python 2.7.4, WeakSet has a bug[0] where ``len()`` is unsafe: it is done by iteration and weakrefs may be removed from the underlying set during the iteration As a result, the safety feature of listifying a WeakSet to ensure we have strong refs on all items during iteration may blow up. Wrapping the weakset in a ``iter()`` makes ``__len__()`` invisible and ensures we're within the IterationGuard[1]. Which now that I think about it means we *should* be able to safely iterate weaksets in the first place and may not have needed to listify them... [0] http://bugs.python.org/issue14159 [1] http://hg.python.org/cpython/file/b6acfbe2bdbe/Lib/_weakrefset.py#l58
This commit is contained in:
parent
cd7e9a98d4
commit
ac282e0294
|
@ -756,7 +756,7 @@ class Environment(object):
|
|||
"""
|
||||
if not spec:
|
||||
return
|
||||
for env in list(self.all):
|
||||
for env in list(iter(self.all)):
|
||||
c = env.cache
|
||||
for field, ids in spec:
|
||||
if ids is None:
|
||||
|
@ -769,7 +769,7 @@ class Environment(object):
|
|||
|
||||
def invalidate_all(self):
|
||||
""" Clear the cache of all environments. """
|
||||
for env in list(self.all):
|
||||
for env in list(iter(self.all)):
|
||||
env.cache.clear()
|
||||
env.prefetch.clear()
|
||||
env.computed.clear()
|
||||
|
|
|
@ -5415,7 +5415,7 @@ class BaseModel(object):
|
|||
""" If `field` must be recomputed on some record in `self`, return the
|
||||
corresponding records that must be recomputed.
|
||||
"""
|
||||
for env in [self.env] + list(self.env.all):
|
||||
for env in [self.env] + list(iter(self.env.all)):
|
||||
if env.todo.get(field) and env.todo[field] & self:
|
||||
return env.todo[field]
|
||||
|
||||
|
@ -5437,7 +5437,7 @@ class BaseModel(object):
|
|||
""" Recompute stored function fields. The fields and records to
|
||||
recompute have been determined by method :meth:`modified`.
|
||||
"""
|
||||
for env in list(self.env.all):
|
||||
for env in list(iter(self.env.all)):
|
||||
while env.todo:
|
||||
field, recs = next(env.todo.iteritems())
|
||||
# evaluate the fields to recompute, and save them to database
|
||||
|
|
Loading…
Reference in New Issue