You are not logged in Log in Join
You are here: Home » Members » Caseman » Extending Zope Dynamically

Log in
Name

Password

 

Extending Zope Dynamically

Zope's built in functionality is quite impressive. It's object model is full and there are many classes to choose from. However, many times a Zope object or management screen lacks a certain feature that would like to have. There might also be a product out there that you really like except for a few things...

Waiting for ZC or the product's author to include the feature you want is not usually a good option, since your feature is likely more important to you than to them (that is not to say you shouldn't suggest the change of course). So, you decide to take advantage of the open source nature of Zope and hack in the feature yourself.

But... You quickly come to the realization that any changes you make to Zope or the Product could be obliterated when you install a new version. And since new versions of Zope come out as often as they open a new Starbucks, this is a major problem with your plan.

So, what do you do?

Python to the Rescue

Python is a highly dynamic language as you well know if you've done much programming with it. By dynamic I mean you can put everything off until run-time. You can define classes and functions, modify existing classes, the list goes on and on. The latter is the feature explained in this how-to. How to modify existing Zope classes at run-time, without touching the code of Zope itself!

To modify Zope dynamically, we must have Zope execute some code we write when Zope is started. Luckily, this is trivial to do. Creating a simple Python Zope product is all it takes. Here are the basic steps we need to modify Zope through a monkey patch:

  1. Create a product directory under {Zope dir}/lib/python/Products
  2. Add an __init__.py file in the product directory.
  3. In the __init__ module, import the classes that you want to modify, and change away!

Obviously the last step can be as simple or complex as you like.

A Simple Example

Let's say you want to add a management tab to all DTML method objects in Zope. For our example, we will create a simple tab that displays the size of the method code in bytes. Here is the code to insert into __init__.py:

1:  """Simple Monkey Patch"""
2:  from OFS.DTMLMethod import DTMLMethod
3:
4:  def manage_showSize(self):
5:      """Show method size"""
6:      return "<p>%d bytes</p>" % self.get_size()
7:
8:  DTMLMethod.manage_showSize = manage_showSize
9:  DTMLMethod.manage_options = DTMLMethod.manage_options + \
10:                             ({"label": "Size", "action": "manage_showSize"},)

Lets take a closer look at what each line does:

2: Imports the DTMLMethod class from OFS.DTMLMethod in the Zope core.
4-6: Defines a method to display the size of the DTMLMethod. get_size is an existing method of the DTMLMethod class. (Remember that public methods called from Zope must have a doc string).
8: Adds the new method to the class dynamically. This is the magic given to us by Python.
9-10: Modifies the manage_options attribute of the DTMLMethod class which tells Zope what tabs to draw in the management interface and what method to call when someone clicks the tab.

Since we are modifying the DTMLMethod class, all existing and new instances will be affected. So, once this code is in place, and you restart Zope, all DTML methods will have your new tab! And since this code is separate from the core module, it will survive upgrading to new Zope versions and can easily be applied to several Zope installs.

Our example adds a new feature to a class, but the same technique can be used to override an existing method, such as replacing a management screen with an improved version written by you.

Other Ideas

Here are some other ideas on how you could use Monkey Patches:

  1. Add new capabilities to existing objects, such as making DTML documents and methods render themselves when they are cataloged.
  2. Modify property sheets to allow your own custom data types.
  3. Add custom options to existing dtml tags.

Obviously you must take care not to get too overzealous. You can also easily create bugs and security holes using these techniques. Remember, though that this is a perfect way to experiment, because you can simply remove your product's folder to restore Zope back to original. You never need to touch any of Zope's code!