Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: Changeset: r52670:4b254e123047 Date: 2012-02-20 12:17 +0100 http://bitbucket.org/pypy/pypy/changeset/4b254e123047/
Log: issue1059 testing make the .__dict__.clear method of builtin types raise an error. Fix popitem on dict proxies (builtin types raise an error, normal types work normally). diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -142,6 +142,13 @@ else: return result + def popitem(self, w_dict): + space = self.space + iterator = self.iter(w_dict) + w_key, w_value = iterator.next() + self.delitem(w_dict, w_key) + return (w_key, w_value) + def clear(self, w_dict): strategy = self.space.fromcache(EmptyDictStrategy) storage = strategy.get_empty_storage() diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py --- a/pypy/objspace/std/dictproxyobject.py +++ b/pypy/objspace/std/dictproxyobject.py @@ -3,7 +3,7 @@ from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation from pypy.objspace.std.dictmultiobject import DictStrategy from pypy.objspace.std.typeobject import unwrap_cell -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError, operationerrfmt from pypy.rlib import rerased @@ -44,7 +44,8 @@ raise if not w_type.is_cpytype(): raise - # xxx obscure workaround: allow cpyext to write to type->tp_dict. + # xxx obscure workaround: allow cpyext to write to type->tp_dict + # xxx even in the case of a builtin type. # xxx like CPython, we assume that this is only done early after # xxx the type is created, and we don't invalidate any cache. w_type.dict_w[key] = w_value @@ -86,8 +87,14 @@ for (key, w_value) in self.unerase(w_dict.dstorage).dict_w.iteritems()] def clear(self, w_dict): - self.unerase(w_dict.dstorage).dict_w.clear() - self.unerase(w_dict.dstorage).mutated(None) + space = self.space + w_type = self.unerase(w_dict.dstorage) + if (not space.config.objspace.std.mutable_builtintypes + and not w_type.is_heaptype()): + msg = "can't clear dictionary of type '%s'" + raise operationerrfmt(space.w_TypeError, msg, w_type.name) + w_type.dict_w.clear() + w_type.mutated(None) class DictProxyIteratorImplementation(IteratorImplementation): def __init__(self, space, strategy, dictimplementation): diff --git a/pypy/objspace/std/test/test_dictproxy.py b/pypy/objspace/std/test/test_dictproxy.py --- a/pypy/objspace/std/test/test_dictproxy.py +++ b/pypy/objspace/std/test/test_dictproxy.py @@ -22,6 +22,9 @@ assert NotEmpty.string == 1 raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)') + key, value = NotEmpty.__dict__.popitem() + assert (key == 'a' and value == 1) or (key == 'b' and value == 4) + def test_dictproxyeq(self): class a(object): pass @@ -43,6 +46,11 @@ assert s1 == s2 assert s1.startswith('{') and s1.endswith('}') + def test_immutable_dict_on_builtin_type(self): + raises(TypeError, "int.__dict__['a'] = 1") + raises(TypeError, int.__dict__.popitem) + raises(TypeError, int.__dict__.clear) + class AppTestUserObjectMethodCache(AppTestUserObject): def setup_class(cls): cls.space = gettestobjspace( diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py --- a/pypy/objspace/std/test/test_typeobject.py +++ b/pypy/objspace/std/test/test_typeobject.py @@ -993,7 +993,9 @@ raises(TypeError, setattr, list, 'append', 42) raises(TypeError, setattr, list, 'foobar', 42) raises(TypeError, delattr, dict, 'keys') - + raises(TypeError, 'int.__dict__["a"] = 1') + raises(TypeError, 'int.__dict__.clear()') + def test_nontype_in_mro(self): class OldStyle: pass _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit