Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r78547:2f052c461fca Date: 2015-07-13 17:41 +0200 http://bitbucket.org/pypy/pypy/changeset/2f052c461fca/
Log: Issue #2079: missed another obscure condition in type object creation 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 @@ -1031,6 +1031,48 @@ A.__dict__['x'] = 5 assert A.x == 5 + def test_we_already_got_one_1(self): + # Issue #2079: highly obscure: CPython complains if we say + # ``__slots__="__dict__"`` and there is already a __dict__... + # but from the "best base" only. If the __dict__ comes from + # another base, it doesn't complain. Shrug and copy the logic. + class A(object): + __slots__ = () + class B(object): + pass + class C(A, B): # "best base" is A + __slots__ = ("__dict__",) + class D(A, B): # "best base" is A + __slots__ = ("__weakref__",) + try: + class E(B, A): # "best base" is B + __slots__ = ("__dict__",) + except TypeError, e: + assert 'we already got one' in str(e) + else: + raise AssertionError("TypeError not raised") + try: + class F(B, A): # "best base" is B + __slots__ = ("__weakref__",) + except TypeError, e: + assert 'we already got one' in str(e) + else: + raise AssertionError("TypeError not raised") + + def test_we_already_got_one_2(self): + class A(object): + __slots__ = () + class B: + pass + class C(A, B): # "best base" is A + __slots__ = ("__dict__",) + class D(A, B): # "best base" is A + __slots__ = ("__weakref__",) + class C(B, A): # "best base" is A + __slots__ = ("__dict__",) + class D(B, A): # "best base" is A + __slots__ = ("__weakref__",) + class AppTestWithMethodCacheCounter: spaceconfig = {"objspace.std.withmethodcachecounter": True} diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -1022,7 +1022,7 @@ w_self.nslots = w_bestbase.nslots return hasoldstylebase -def create_all_slots(w_self, hasoldstylebase): +def create_all_slots(w_self, hasoldstylebase, w_bestbase): space = w_self.space dict_w = w_self.dict_w if '__slots__' not in dict_w: @@ -1040,12 +1040,12 @@ for w_slot_name in slot_names_w: slot_name = space.str_w(w_slot_name) if slot_name == '__dict__': - if wantdict or w_self.hasdict: + if wantdict or w_bestbase.hasdict: raise oefmt(space.w_TypeError, "__dict__ slot disallowed: we already got one") wantdict = True elif slot_name == '__weakref__': - if wantweakref or w_self.weakrefable: + if wantweakref or w_bestbase.weakrefable: raise oefmt(space.w_TypeError, "__weakref__ slot disallowed: we already got one") wantweakref = True @@ -1106,7 +1106,7 @@ w_self.flag_abstract |= w_base.flag_abstract hasoldstylebase = copy_flags_from_bases(w_self, w_bestbase) - create_all_slots(w_self, hasoldstylebase) + create_all_slots(w_self, hasoldstylebase, w_bestbase) ensure_common_attributes(w_self) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit