I've been in MiddleKit.Design, adding support for PostgreSQL and Samples.csv, when I got sidetracked with a mix-in issue.
According to a few of Chuck's comments sprinkled throughout the source, "invoking super is the only awkward aspect of mix-ins that hasn't been solved". But invoking super is what I needed to do. So I started looking more closely at MiscUtils.MixIn, and started making changes (patch attached). I added a parameter called mixInSuperMethods (defaults to false), which, when true, binds the original methods in the class to specially-derived names in the mix-in class (the naming scheme is 'mixInSuper' + OriginalMethodName). Doing this means that the superclass methods are only available from that mix-in class, but I think this makes sense, since that's the only place you'd ever want them. I grappled with the problem for a while before making this realization, after which the solution seemed obvious. The semantics for multiple mixins are what you'd expect, but the order of the calls depends on the order in which the classes were originally mixed. Here's an example: from MiscUtils.MixIn import MixIn class Foo: def bar(self): return 'Foo' class FooMixIn: def bar(self): value = FooMixIn.mixInSuperBar(self) return value + ", FooMixIn" class FooMixIn2: def bar(self): value = FooMixIn2.mixInSuperBar(self) return value + ", FooMixIn2" MixIn(Foo, FooMixIn, mixInSuperMethods=1) MixIn(Foo, FooMixIn2, mixInSuperMethods=1) f = Foo() print f.bar() # prints 'Foo, FooMixIn, FooMixIn2' I think being able to invoke super from mix-ins will allow us to avoid some awkwardness in the code, and use mix-ins a bit more naturally, so I'm interested in committing this change, and starting to make use of it in MiddleKit. Comments? Suggestions for a better naming scheme? Does anyone (hi, Chuck!) see any potential pitfalls? -- Jason D. Hildebrand [EMAIL PROTECTED]
Index: MixIn.py =================================================================== RCS file: /cvsroot/webware/Webware/MiscUtils/MixIn.py,v retrieving revision 1.2 diff -u -r1.2 MixIn.py --- MixIn.py 20 Jun 2002 17:47:59 -0000 1.2 +++ MixIn.py 12 Apr 2003 19:16:09 -0000 @@ -2,7 +2,7 @@ import sys if hasattr(sys, 'version_info') and sys.version_info[0]>=2: - def MixIn(pyClass, mixInClass, makeAncestor=0): + def MixIn(pyClass, mixInClass, makeAncestor=0, mixInSuperMethods=0): """ Mixes in the attributes of the mixInClass into the pyClass. These attributes are typically methods (but don't have to be). Note that private attributes, denoted by a double underscore, are not mixed in. Collisions are resolved by the mixInClass' attribute overwriting the pyClass'. This gives mix-ins the power to override the behavior of the pyClass. @@ -52,6 +52,11 @@ for name in dir(mixInClass): if not name.startswith('__'): # skip private members member = getattr(mixInClass, name) + + if type(member) is MethodType and mixInSuperMethods: + if hasattr(pyClass, name): + origmember = getattr(pyClass, name) + setattr(mixInClass, 'mixInSuper' + name.capitalize(), origmember) if type(member) is MethodType: member = member.im_func setattr(pyClass, name, member)