[Zope] publish() hook

Paul Winkler pw_lists@slinkp.com
Tue, 23 Apr 2002 14:57:20 -0700


On Tue, Apr 23, 2002 at 09:58:30PM +0200, Dieter Maurer wrote:
> The "user" probably does
> 
>     from ZPublisher.Publish import publish
> 
> Then, later changes to "ZPublisher.Publish" do not affect the imported
> "publish".

python cookbook to the rescue!
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/92823

Ignore the specifics, just notice the principle. 
Here's a simple example:

$ python
Python 1.5.2 (#1, Aug 25 2000, 09:33:37)  [GCC 2.96 20000731 (experimental)] on linux-i386
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> class Foo:
...   def bar(self, arg):
...     print arg 
... 
>>> def newbar(self, arg, oldbar=Foo.bar):  # have to pass in the old method
...   print "Now in newbar, and calling the old one"
...   oldbar(self, arg)
... 
>>> x = Foo()
>>> x.bar(1)
1
>>> Foo.bar=newbar  # substitute the new method
>>> x.bar(1)   
Now in newbar, and calling the old one
1


So you can redefine a method and see the effect in all existing
(and future) instances. AFAIKT this should work regardless of how the 
class gets imported anywhere else.
 
When I first heard this idea, I mistakenly thought it was just the Decorator
design pattern, but clearly it's much more wide-reaching...

Decorator, for any readers who don't know, shows how to change the behavior
of a *single instance* of a class and leave all other instances alone.
Probably not what you want in this case, but a very powerful tool anyway,
and very easy in python.

Here's an example, continuing from the above python session:

>>> class Decorator:
...    def __init__(self, original):
...        self.original=original
...    def bar(self, arg):
...        print "This is the decorated version..."
...        self.original.bar(arg)
...        print "we now return to your regularly scheduled programming."
... 
>>> 
>>> y = Foo()
>>> x = Decorator(x)
>>> x.bar("blah")
This is the decorated version...
Now in newbar, and calling the old one
blah
we now return to your regularly scheduled programming.
>>> y.bar("bleah")
Now in newbar, and calling the old one
bleah
>>> x = x.original    
>>> x.bar("wheeee")
Now in newbar, and calling the old one
wheeee


Now back to my C++ homework. It's not nearly this much fun. :(

--PW