It's very late, so I'll try to make this quick and write up more later. Today, I finally had enough free time in my coffers to download "Python" from CVS (aka - 2.3 pre-alpha) onto my old iMac, and augment that with "Zope 3" - the
ComponentArchitecture project. Then I installed the simple but usable
Job Board Example. I soon noticed that said JobBoardExample was missing out on a couple of things - an editing interface, and an XML-RPC interface.
One of the notions of Zope 3 is that it's supposed to be easier for developers to embrace and extend other components by being able to write new "views" for them. So, I decided to write a JobEditView. I made a new Product (esentially, a plain Python package) called JobBoardEditor, and filled it with a couple of files -
EditJobView.py,
edit.pt (the page template to edit a single job with), and
configure.zcml, the configuration file that ties it into the Zope system. It wasn't long until I could go to a Job object and traverse to my new edit form, and then have the submit go to my 'edit' method. But, at this point, I'm running into security issues that are beyond my measure to figure out, especially at 1:00 am with a beer headache. ";->"
My other thing to try out was putting a simple XML-RPC interface on to the JobList. This was particularly interesting to me as I've found that while traditional "Zope" method calls should - in theory - work fine with something like XML-RPC, they seldom do. Sometimes it's because too much HTML is returned from a call, but most of the time lately (for me at least), it's that I want the server to do some processing of the results before sending them out to the client, using the relatively simple data types afforded to XML-RPC. As a result, I've been adding in extra Python Scripts particularly for XML-RPC, and letting them work in the proper places either via acquisition or some other clever tricks. It's not a bad system, but it's not exactly formalized or repeatable, since it's not in a formal Product.
In Zope 3, this is different. I wrote a simple XMLRPCView class. 'View' objects in Zope 3 have two state members - 'request' (the incoming request object), and 'context' - the object the View is applied against. So, for me to add in the new functionality whereby I could just get a list of approved Job titles, I wrote the following Python file in my JobBoardEditor product:
from Zope.Publisher.XMLRPC.XMLRPCView import XMLRPCView
from ZopeProducts.JobBoardEx.IJob import JobState
class JobListXMLRPCView(XMLRPCView):
__implements__ = XMLRPCView.__implements__
def listJobTitles(self):
joblist = self.context
job_ids = joblist.query(state=JobState.Approved)
out = []
for jid in job_ids:
out.append(joblist[jid].summary)
return tuple(out)
Then, I added the following to
JobBoardEditor/configure.zcml
(after adding
xmlns:xmlrpc='http://namespaces.zope.org/xmlrpc'
to the head zopeConfigure element):
<xmlrpc:view
name="joblistmethods"
for="ZopeProducts.JobBoardEx.IJobList."
factory=".JobListXMLRPCView." />
With this configuration statement, I've added a new View to be published on the XMLRPC channel (which in Zope 3 runs on a different port than normal HTTP requests, which is probably wise) for objects that implement the IJobList interface. I was able to do all of this outside of the JobBoardEx product. I just had to ensure that the Product was added in
after JobBoardEx by using the site's
products.zcml file to affect the ordering.
After restarting Zope 3 (which is a very slow restart on this machine), I was able to do this:
Py$ s = Server('http://localhost:8281/zoo/joblistmethods')
Py$ s.listJobTitles()
['test test test']
I actually had created two jobs through the web interface, but had only approved one. So I ducked in to the web interface to approve the other job, and then made the call again:
Py$ s.listJobTitles()
['test test test', 'the other job']
So, what are some benefits of this? One that comes to mind is issue trackers. Earlier in the day, I was writing a Python script to farm through some Tracker data and format it nicely for XML-RPC, with the intent of writing a simple AppleScript Studio application to list pending/accepted Tracker issues. I did this informally, dropping a Python Script into the folder above a particular tracker. Ultimately, it didn't work - and I think a lot of the blame goes on XML-RPC's utter disregard for semi-proper security. Since Zope's always published objects on the web with regards to web security standards (or embarrasments, depending on your view) such as 'Basic Auth', it's had problems with the "security by passing in arguments" design of many XML-RPC API's. But the point I was really going for was packaging. Even if the Tracker Issue finding Python Script had worked over XML-RPC, now I have to find other places to put it by copying and pasting it, ultimately adding another name onto an ever growing namespace.
With Zope 3, however, I could write an XML-RPC view particularly for the application I was designing as a normal Python component, and install and configure it as necessary (and hopefully that configuration work will be better than copying and pasting plain Python Script code). I can name it specially, essentially adding a new namespace for my application. I can distribute it to other users fairly easily.
Another example would be implementing the Blogger API not as a new weblog product for Zope, but as a view/adapter component that publishes on the XML-RPC channel, and communicates with other Zope components, either built in ones or third party.
In summary - my first tangible Zope 3 experience in quite some time has been hopeful and helpful. There's still a long way to go, but the kernel is shaping up nicely. The pattern driven / "extreme programming" sprint driven development has yielded a decent - but still shifting - code base that should be stronger and simpler than Zope 2. Sometimes, there are enough levels of indirection in Zope 3 to make it look more complex, but so far most code has been easier to follow and trace than Zope 2 (although there are a number of empty folders/packages that probably need some brute force removing from CVS) - at least, it's usually easier to tell what's going on (and even this has an at least - at least, once you start learning the new paradigm). Zope's ancester, Bobo (the kernel on which Zope is still based), was all about abstracting the means of publishing an object on the web away from the object itself. Bobo, and then Principia / Zope 1.x, built upon this, but primarily in a single-UI / single protocol type way. It's obvious today that there are many ways of looking at things on the web, including never actually using the web itself. Zope 3 brings us back to the notion of an
object publisher being able to serve up objects on different protocols. Zope 2 offers this today, but there is great difficulty in making WebDAV, normal HTTP, FTP, and XML-RPC all live harmoniously in the current design.
And finally, Zope 3 should yield a usable scalable means of adapting the works of other developers into new solutions by providing better control of product/service/view configuration and overrides, such as adding a new XML-RPC API to someone elses bug tracking system without having to alter that bug tracking system, or use secret Python hacks to alter behaviour.