This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author taleinat
Recipients kbk, taleinat
Date 2007-10-25.19:32:51
SpamBayes Score 0.0024937969
Marked as misclassified No
Message-id <1193340774.34.0.512157048606.issue1252@psf.upfronthosting.co.za>
In-reply-to
Content
I understand your argument, but am not convinced. I'll try to explain
how I see this and how I came to this view.


I wished to wrap a specific method (or function) instead of wrapping the
father object with a Delegator and implementing a single method. But I
needed more than simple function wrapping - I wanted a chain of
functions where each wraps the next, and the ability to change the order
of links in this chain. So what I really wanted was a Percolator, but
instead of having it wrap an object and delegate methods, I wanted it to
delegate direct calls.

My first idea was to implement a FunctionDelegator class. But I realized
I would have to implement a FunctionPercolator class, which would be
indentical to the existing Percolator class except that it would inherit
from FunctionDelegator instead of Delegator.

From there I had three choices:

1) create a second pair of delegator/percolator classes which are nearly
identical (much code ducplication)

2) make a Percolator generator function, which accepts a Delegator
class, and returns a Percolator class/object which uses it (possibly
inheriting from it)

3) make Delegator able to delegate direct calls

The third option is obviously the simplest to implement, requiring the
least code without any code duplication.

After some thought, I came to the point-of-view described below, and
realized that the third option is actually what I would expect if I were
thinking about delegators and percolators as transparent proxies.


> Delegates are not intended to be callable.

Why not? 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. From this point
of view, my patch makes the Delegator concept complete, while before it
was broken.

> I think this patch increases the complexity and obscurity of the
> Delegator/Percolator/WidgetRedirector code, rather than improving
> it.  Apparently you want to sometimes call a chain of methods (as
> in current usage) and sometimes call a chain of functions. The
> semantic overload, which was bad enough already, is too great.

You describe method calls and direct calls as though they were
fundamentally different. Therefore you find that delegating both is too
much semantic overloading. However, if one views direct calling of an
object as a special case of calling a method (since functions are also
objects) -- the __call__ method -- then delegating both method calls and
direct calls is The Right Thing.

> Also, this __call__ method, if actually used, propagates to the
> end of the Delegator chain and calls the function at the end,
> (assuming it is a function).  Or it will skip non-callable
> Delegators and stop at the first callable one.

True, since this is precisely what Delegators do for any method call --
this is the expected behavior.


> If Squeezer and ShellLogger require this change, then I'd
> suggest changing them to match current Percolator usage, instead.
> Currently I don't see a Delegator being used in Squeezer.  Could
> you be more specific about why the change is needed for those
> two extensions?

Squeezer currently replaces PyShell's write method with a method of its
own. ShellLogger also needs to hook onto the write method, but
ShellLogger's function must be called before Squeezer's method, since
Squeezer can insert a button without calling the underlying write
method. But extensions must replace the write method in their
constructor, and the order of their construction is "random". In other
words, a rudimentary form of constraint enforcement is required, which
can be achieved using a Percolator.

Without the suggested change to Delegator, this can be accomplished by
wrapping EditorWindow with a Percolator, and having extensions insert
Delegators (filters) as appropriate. However, this is a much larger
change to the code -- for example, this breaks type checks, e.g. assert
isinstance(editwin, EditorWindow)). This would also add overhead to
every method call done on EditorWindow, with this overhead growing
linearly with the number of Delegators inserted. I find wrapping
specific methods to be more straightforward and therefore simpler, but
this can be argued.
History
Date User Action Args
2007-10-25 19:32:54taleinatsetspambayes_score: 0.0024938 -> 0.0024937969
recipients: + taleinat, kbk
2007-10-25 19:32:54taleinatsetspambayes_score: 0.0024938 -> 0.0024938
messageid: <1193340774.34.0.512157048606.issue1252@psf.upfronthosting.co.za>
2007-10-25 19:32:54taleinatlinkissue1252 messages
2007-10-25 19:32:52taleinatcreate