[pypy-svn] r37808 - in pypy/dist/pypy/objspace/std: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri Feb 2 15:22:32 CET 2007
Author: cfbolz
Date: Fri Feb 2 15:22:31 2007
New Revision: 37808
Modified:
pypy/dist/pypy/objspace/std/listobject.py
pypy/dist/pypy/objspace/std/test/test_listobject.py
Log:
make list.remove safe against list elements with an __eq__ that mutate the
list. Before, you could get an interp-level exception :-(.
Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py (original)
+++ pypy/dist/pypy/objspace/std/listobject.py Fri Feb 2 15:22:31 2007
@@ -376,11 +376,13 @@
def list_remove__List_ANY(space, w_list, w_any):
# needs to be safe against eq_w() mutating the w_list behind our back
items = w_list.wrappeditems
- length = len(items)
- for i in range(length):
+ i = 0
+ while i < len(items):
if space.eq_w(items[i], w_any):
- del items[i]
+ if i < len(items): # if this is wrong the list was changed
+ del items[i]
return space.w_None
+ i += 1
raise OperationError(space.w_ValueError,
space.wrap("list.remove(x): x not in list"))
Modified: pypy/dist/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_listobject.py (original)
+++ pypy/dist/pypy/objspace/std/test/test_listobject.py Fri Feb 2 15:22:31 2007
@@ -1,4 +1,3 @@
-#from __future__ import nested_scopes
import autopath, random
from pypy.objspace.std.listobject import W_ListObject
from pypy.interpreter.error import OperationError
@@ -553,3 +552,28 @@
def test_reversed(self):
assert list(list('hello').__reversed__()) == ['o', 'l', 'l', 'e', 'h']
assert list(reversed(list('hello'))) == ['o', 'l', 'l', 'e', 'h']
+
+ def test_mutate_while_remove(self):
+ class Mean(object):
+ def __init__(self, i):
+ self.i = i
+ def __eq__(self, other):
+ if self.i == 9:
+ del l[i - 1]
+ return True
+ else:
+ return False
+ l = [Mean(i) for i in range(10)]
+ # does not crash
+ l.remove(None)
+ class Mean2(object):
+ def __init__(self, i):
+ self.i = i
+ def __eq__(self, other):
+ l.append(self.i)
+ return False
+ l = [Mean2(i) for i in range(10)]
+ # does not crash
+ l.remove(5)
+ print l
+ assert l[10:] == [0, 1, 2, 3, 4, 6, 7, 8, 9]
More information about the pypy-svn
mailing list