[Python-Dev] metaclass insanity (original) (raw)

Michael Hudson mwh@python.net
30 Oct 2002 14:36:20 +0000


Kevin Jacobs <jacobs@penguin.theopalgroup.com> writes:

On 30 Oct 2002, Michael Hudson wrote: > 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.

The mro is an internal data structure of new-style classes, so redefining mro() doesn't change the values used.

Yeah, I noticed that eventually.

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 basegetter(cls): return cls.mybases def basesetter(cls,bases): if not bases: bases = (object,) metaclass = getattr(cls, 'metaclass', type) newcls = metaclass(cls.name, bases, dict(cls.dict)) cls.class = newcls class MetaBase(type): bases = property(basegetter,basesetter) def new(cls, name, bases, ns): ns['mybases'] = 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,)

I don't think this has a hope of working does it? This approach would need to rebind "Foo" in the last line, no?

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.

I think the error message gives it away: in "cls.class = new_cls", cls.class is MetaBase, new_cls is the new Foo.

I guess one way of doing this would be to reimplement mro resolution and so on in Python, which would be annoying and inefficient. Hmm.

Cheers, M.

-- [3] Modem speeds being what they are, large .avi files were generally downloaded to the shell server instead[4]. [4] Where they were usually found by the technical staff, and burned to CD. -- Carlfish, asr