Kurt B. Kaiser added the comment:

First, I'm changing my mind about Percolator inheriting from
Delegator.  A Percolator acts as a container for Delegators:
it "hasa" (chain) of them.  But it fails "isa" Delegator.
It has no use for the Delegator's caching, and chaining
Percolators doesn't make sense.  Inheriting from Delegator
just confuses things further, it seems to me.

Delegator is just a mixin implementing a node in the chain.

I do support splitting TkTextPercolator off Percolator.

> 3) make Delegator able to delegate direct calls

Except that the Delegator mixin doesn't know to what function
to delegate the call.  Delegating a function call down the nodes
doesn't do anything, except possibly error out if the bottom
object isn't callable, as in delegator.txt.

> IMO, the nice thing about the Delegator class is that you can
> use an instance just as if it were the underlying object, transparently.
> The major exception from this behavior was that calling a Delegator
> never works, even if the underlying object is callable.

But it does work, if the filter that is using the Delegator mixin has
a __call__ method.  See delegator2.txt above.  Note that the Delegator
__call__ method is removed.  You have to override the latter anyway
if you want to run some code in the filter.  Do you have some 
reason for mixing callable and non-callable filter instances in the
percolator chain?

I can see adding a __call__ method to Percolator, which would call
self.top().  Then each instance in the chain would have a __call__
to appropriate code.

We have two goals: solve your specific requirement of being able to
replace a method with a percolator, and increasing the clarity of the
existing WidgetRedirector/Delegator/Percolator code.

Yes, a Percolator already has semantic overload.  Right now, there are
two ways to access the chain:
1. Since the delegate link is exposed, filters can directly call
   specific methods further down the chain, e.g. self.delegate.index()
2. The caching and __getattr__() allows a "delegator" to call
   unimplemented methods; they will be looked up on the chain.  This
   allows ColorDelegator to access its Text instance's methods without
   having been passed a reference to the instance, as you noted.
   Whether this adds or detracts from the clarity of the code is
   debatable.  Once you understand how it works, it's not a problem,
   but it would be for people new to the code.  Further, it's fragile,
   since the first method with the correct name will be called.

Adding a __call__() method to Delegator doesn't seem to do anything
that can't be accomplished better by adding it to the class
implementing the filter.  Why add complexity prematurely?

----------
assignee:  -> kbk
priority:  -> normal
Added file: http://bugs.python.org/file8635/delegator2.txt

__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1252>
__________________________________
##################
##    def __call__(self, *args, **kw):
##        return self.delegate(*args, **kw)

class Hooker(Delegator):

    def __init__(self, name):
        Delegator.__init__(self)
        self.name = name

    def my_fcn(self, caller):
        print "Hooker %s called via %s" % (self.name, caller)

    def __call__(self, *args, **kw):
        self.my_fcn(*args)
        self.delegate(*args, **kw)


class Interceptor(Delegator):
    
    def __init__(self, name):
        Delegator.__init__(self)
        self.name = name

    def my_fcn(self, caller):
        print "Interceptor %s called via %s" % (self.name, caller)
        
    def __call__(self, *args, **kw):
        self.my_fcn(*args)
        #self.delegate(*args, **kw) # uncomment to propagate

def fcn(caller):
    print "Fcn at base called via %s" % caller

if __name__ == "__main__":
    bottom = Hooker("bottom")
    bottom.setdelegate(fcn)
    middle = Hooker("middle")
    middle.setdelegate(bottom)
    top = Interceptor("top")
    top.setdelegate(middle)
    print "top: ", top
    print "top.delegate: ", top.delegate
    print "calling top()... "
    top("top()")
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to