[pypy-commit] pypy mapdict-interp: A test, and fix.
arigo
noreply at buildbot.pypy.org
Tue May 17 15:45:52 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: mapdict-interp
Changeset: r44247:924fc7a7a0f4
Date: 2011-05-17 15:51 +0200
http://bitbucket.org/pypy/pypy/changeset/924fc7a7a0f4/
Log: A test, and fix.
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -754,24 +754,32 @@
w_descr = w_type.getattribute_if_not_from_object()
if w_descr is not None:
return space._handle_getattribute(w_descr, w_obj, w_name)
-
version_tag = w_type.version_tag()
if version_tag is not None:
name = space.str_w(w_name)
- w_descr = w_type.lookup(name)
+ # We need to care for obscure cases in which the w_descr is
+ # a TypeCell, which may change without changing the version_tag
+ assert space.config.objspace.std.withmethodcache
+ _, w_descr = w_type._pure_lookup_where_with_method_cache(
+ name, version_tag)
selector = ("", INVALID)
- if w_descr is not None and space.is_data_descr(w_descr):
- from pypy.interpreter.typedef import Member
- descr = space.interpclass_w(w_descr)
- if isinstance(descr, Member):
- selector = ("slot", SLOTS_STARTING_FROM + descr.index)
+ if w_descr is None:
+ selector = (name, DICT) # common case: not shadowing anything
+ elif isinstance(w_descr, TypeCell):
+ pass # shadowing a TypeCell: give up
else:
- selector = (name, DICT)
+ if space.is_data_descr(w_descr):
+ from pypy.interpreter.typedef import Member
+ descr = space.interpclass_w(w_descr)
+ if isinstance(descr, Member): # a slot
+ selector = ("slot", SLOTS_STARTING_FROM + descr.index)
+ else:
+ selector = (name, DICT) # shadowing a non-data descr
if selector[1] != INVALID:
index = map.index(selector)
if index >= 0:
- # note that if map.terminator is a DevolvedDictTerminator,
- # map.index() will always return -1 if selector[1]==DICT
+ # Note that if map.terminator is a DevolvedDictTerminator,
+ # map.index() will always return -1 if selector[1]==DICT.
_fill_cache(pycode, nameindex, map, version_tag, index)
return w_obj._mapdict_read_storage(index)
if space.config.objspace.std.withmethodcachecounter:
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -930,6 +930,26 @@
got = a.method()
assert got == 44
+ def test_bug_slot_via_changing_member_descr(self):
+ class A(object):
+ __slots__ = ['a', 'b', 'c', 'd']
+ x = A()
+ x.a = 'a'
+ x.b = 'b'
+ x.c = 'c'
+ x.d = 'd'
+ got = x.a
+ assert got == 'a'
+ A.a = A.b
+ got = x.a
+ assert got == 'b'
+ A.a = A.c
+ got = x.a
+ assert got == 'c'
+ A.a = A.d
+ got = x.a
+ assert got == 'd'
+
class AppTestGlobalCaching(AppTestWithMapDict):
def setup_class(cls):
cls.space = gettestobjspace(
More information about the pypy-commit
mailing list