def _getusercls(cls, reallywantdict=False): from rpython.rlib import objectmodel from pypy.objspace.std.objectobject import W_ObjectObject from pypy.module.__builtin__.interp_classobj import W_InstanceObject from pypy.objspace.std.mapdict import (BaseUserClassMapdict, MapdictDictSupport, MapdictWeakrefSupport, _make_storage_mixin_size_n, MapdictStorageMixin) typedef = cls.typedef name = cls.__name__ + "User" if cls is W_ObjectObject or cls is W_InstanceObject: base_mixin = _make_storage_mixin_size_n() else: base_mixin = MapdictStorageMixin copy_methods = [BaseUserClassMapdict] if reallywantdict or not typedef.hasdict: # the type has no dict, mapdict to provide the dict copy_methods.append(MapdictDictSupport) name += "Dict" if not typedef.weakrefable: # the type does not support weakrefs yet, mapdict to provide weakref # support copy_methods.append(MapdictWeakrefSupport) name += "Weakrefable" class subcls(cls): user_overridden_class = True objectmodel.import_from_mixin(base_mixin) for copycls in copy_methods: _copy_methods(copycls, subcls) subcls.__name__ = name return subcls
def test_specialized_class(): from pypy.objspace.std.mapdict import _make_storage_mixin_size_n from pypy.objspace.std.objectobject import W_ObjectObject classes = [_make_storage_mixin_size_n(i) for i in range(2, 10)] w1 = W_Root() w2 = W_Root() w3 = W_Root() w4 = W_Root() w5 = W_Root() w6 = W_Root() for mixin in classes: class objectcls(W_ObjectObject): objectmodel.import_from_mixin(BaseUserClassMapdict) objectmodel.import_from_mixin(MapdictDictSupport) objectmodel.import_from_mixin(mixin) cls = Class() obj = objectcls() obj.user_setup(space, cls) obj.setdictvalue(space, "a", w1) assert obj._value0 is w1 assert obj.getdictvalue(space, "a") is w1 assert obj.getdictvalue(space, "b") is None assert obj.getdictvalue(space, "c") is None obj.setdictvalue(space, "a", w2) assert obj._value0 is w2 assert obj.getdictvalue(space, "a") == w2 assert obj.getdictvalue(space, "b") is None assert obj.getdictvalue(space, "c") is None obj.setdictvalue(space, "b", w3) #== [20, 30] assert obj.getdictvalue(space, "a") is w2 assert obj.getdictvalue(space, "b") is w3 assert obj.getdictvalue(space, "c") is None obj.setdictvalue(space, "b", w4) assert obj.getdictvalue(space, "a") is w2 assert obj.getdictvalue(space, "b") is w4 assert obj.getdictvalue(space, "c") is None abmap = obj.map res = obj.deldictvalue(space, "a") assert res assert obj._value0 is w4 assert obj.getdictvalue(space, "a") is None assert obj.getdictvalue(space, "b") is w4 assert obj.getdictvalue(space, "c") is None obj2 = objectcls() obj2.user_setup(space, cls) obj2.setdictvalue(space, "a", w5) obj2.setdictvalue(space, "b", w6) assert obj2.getdictvalue(space, "a") is w5 assert obj2.getdictvalue(space, "b") is w6 assert obj2.map is abmap
def _getusercls(cls, reallywantdict=False): from rpython.rlib import objectmodel from pypy.objspace.std.objectobject import W_ObjectObject from pypy.module.__builtin__.interp_classobj import W_InstanceObject from pypy.objspace.std.mapdict import (BaseUserClassMapdict, MapdictDictSupport, MapdictWeakrefSupport, _make_storage_mixin_size_n, MapdictStorageMixin) # some subtleties here: We want w_obj.getclass to be a small func # set, ie less than 5 different implementations. That way, it can be # inlined into its callers. This means we cannot give every single # user-defined subclass its own getclass, instead we use the same function # for all of them. This has the effect that the call to # w_obj._get_mapdict_map() in BaseUserClassMapdict.getclass is an # *indirect* call. That's fine, however, we want the object subclasses to # work somewhat better than the rest, so W_ObjectObjectUserDictWeakrefable # should have a *copy* of getclass. This is all achieved by using # _share_methods (which shares functions, does not create copies) instead of # import_from_mixin, which *does* copy functions. There is a test for all # of this in test_mapdict.py, test_correct_method_sharing typedef = cls.typedef name = cls.__name__ + "User" isobjectsubclass = cls is W_ObjectObject if isobjectsubclass or cls is W_InstanceObject: base_mixin = _make_storage_mixin_size_n() else: base_mixin = MapdictStorageMixin if not isobjectsubclass: shared_methods = [BaseUserClassMapdict] else: shared_methods = [] if reallywantdict or not typedef.hasdict: # the type has no dict, mapdict to provide the dict shared_methods.append(MapdictDictSupport) name += "Dict" if not typedef.weakrefable: # the type does not support weakrefs yet, mapdict to provide weakref # support shared_methods.append(MapdictWeakrefSupport) name += "Weakrefable" class subcls(cls): user_overridden_class = True objectmodel.import_from_mixin(base_mixin) if isobjectsubclass: objectmodel.import_from_mixin(BaseUserClassMapdict) for _, shortcut_name, meth, _ in SHORTCUTS: setattr(subcls, shortcut_name, meth) for copycls in shared_methods: _share_methods(copycls, subcls) subcls.__name__ = name return subcls