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)

Reply via email to