
For moderately nefarious reasons[1] I've being trying to write a metaclass whose instances have writable __bases__. This in itself isn't so hard, but having assigments to __bases__ "do the right thing" has eluded me, basically because I can't seem to affect the mro. Here's what I have so far: def base_getter(klass): return klass.__priv_bases__ def base_setter(klass, v): klass.__priv_bases__ = v class MetaMutableBases(type): def __new__(self, name, bases, ns): t = type.__new__(self, name, bases, ns) t.__priv_bases__ = type.__dict__["__bases__"].__get__(self) return t __bases__ = property(base_getter, base_setter) def mro(self): if hasattr(self, "__priv_bases__"): return type("noname", self.__priv_bases__, {}).__mro__ else: return type.mro(self) I've tried variations on the same, but haven't got anything working yet. Anyone have any ideas? I think my brain's exploded. And I realise this is in some sense more appropriate for c.l.py, but I think my odds of a good answer are vastly higher here. Cheers, M. [1] in http://groups.google.com/groups?selm=m2r8e99l0b.fsf%40python.net I posted a metaclass that attempts to automatically upgrade instances of its instances on redefinition. Ideally, this would also frob its subclasses so they now inherited from redefined class. I'm aware this can go wrong in various ways, but I think it would be pretty handy in a large range of situations. -- This is not to say C++ = bad, Lisp = good. It's to say C++ = bad irrespective of everything else. -- Alain Picard, comp.lang.lisp

On 30 Oct 2002, Michael Hudson wrote:
The mro is an internal data structure of new-style classes, so redefining mro() doesn't change the values used. Here is my (non-working version) that attempts to re-assign the class of an object, although it fails on a layout violation with Python 2.2.2. def base_getter(cls): return cls.__my_bases__ def base_setter(cls,bases): if not bases: bases = (object,) metaclass = getattr(cls, '__metaclass__', type) new_cls = metaclass(cls.__name__, bases, dict(cls.__dict__)) cls.__class__ = new_cls class MetaBase(type): __bases__ = property(base_getter,base_setter) def __new__(cls, name, bases, ns): ns['__my_bases__'] = tuple(bases) return super(MetaBase, cls).__new__(cls, name, bases, ns) class Foo(object): __metaclass__ = MetaBase class Baz(object): pass Foo.__bases__ = Foo.__bases__ + (Baz,) Which results in: TypeError: __class__ assignment: 'Foo' object layout differs from 'MetaBase' I haven't looked into why this is being flagged as a layout error, though my first instinct is to say that the check is too conservative in this case. I'll think about it more and dig into the code. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

On 30 Oct 2002, Michael Hudson wrote:
The mro is an internal data structure of new-style classes, so redefining mro() doesn't change the values used. Here is my (non-working version) that attempts to re-assign the class of an object, although it fails on a layout violation with Python 2.2.2. def base_getter(cls): return cls.__my_bases__ def base_setter(cls,bases): if not bases: bases = (object,) metaclass = getattr(cls, '__metaclass__', type) new_cls = metaclass(cls.__name__, bases, dict(cls.__dict__)) cls.__class__ = new_cls class MetaBase(type): __bases__ = property(base_getter,base_setter) def __new__(cls, name, bases, ns): ns['__my_bases__'] = tuple(bases) return super(MetaBase, cls).__new__(cls, name, bases, ns) class Foo(object): __metaclass__ = MetaBase class Baz(object): pass Foo.__bases__ = Foo.__bases__ + (Baz,) Which results in: TypeError: __class__ assignment: 'Foo' object layout differs from 'MetaBase' I haven't looked into why this is being flagged as a layout error, though my first instinct is to say that the check is too conservative in this case. I'll think about it more and dig into the code. -Kevin -- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com
participants (2)
-
Kevin Jacobs
-
Michael Hudson