|
Saturday, January 11, 2003
|
|
|
Friday, January 3, 2003
|
|
Big Alpha Releases for Zope and Python
Two big alpha releases were made for the new year: Python 2.3a1 and Zope 3X a1.
Python 2.3 doesn't make any major changes to the language (unlike previous Python 2 series releases, which brought things like list comprehensions, generators, nested scopes, iterators, etc). Andrew Kuchling, as always, covers the changes extensively. Of interest are - ability to import from .zip files, universal newline support!, a new logging package, a new Set datatype and default Boolean datatype.
Zope 3X (x for "experimental" - a final Zope 3 release without the 'X' is expected to have some Zope 2 migration features) is a completely different beast from its ancestors. Its primary focus is still the Object Publishing mission that's been in place since the days of Bobo, but beneath the covers it is shockingly different from Zope's 1 and 2 before it.
Zope 3 is also dubbed the component architecture project. Its design focuses on many interacting components with well-defined interfaces. It's an aggregation heavy design, as opposed to the inheritance heavy design of Zope 2. Adapters exist to take the burden off of objects for out-of-scope elements such as text indexing or sorting-by-size. As the author of a particular object, you can implement those interfaces (ISearchableText, ISized) on the class itself, or as separate classes. Code that requires searchable text or sizing information asks for an ISearchableText implementation for your class, and since that's the only interface that it's expecting to use, it doesn't matter if it gets an adapter or your class - it only matters that the ISearchableText interface is implemented correctly. Design by Contract finally makes a strong appearance in the Zope world.
Zope 3 should also score big on the packaging and deployment front. Zope 3 uses a new configuration language called ZCML. ZCML is used to register new components at load time, and to load in still further components. It wrests control away from Python's import statements and need for special functions in __init__.py such as the common Zope 2 initialize(context). As such, it can be not only more expressive, but allows control over the order in which items get initialized. Under the mantra of explicit is better than implicit, all new components have to be explicitly added (usually in the products.zcml file). A side effect of this is that heavily customized Zope distributions can be made. Some such distributions exist now with Plone installers and BizarShop. Zope 3's customization and configuration capabilities should allow similar distributions to be made that don't look like Zope at all, while still tying in to all of the available features of Zope.
The combination of heavy Interface use combined with rich configuration options should mean that any part of the system could be kicked out in place of a new one, as long as the expected interfaces are implemented. This is a fundamental feature of component systems, and Zope 3 looks like it will live up to this feature.
Another big feature of Zope 3 is the proliferation of View Components. Views can be individual ZPT pages, attached to a particular content interface via ZCML. But they can also be full-on components in their own right, usually as Python classes. And they're not limited to HTML. Other views may be written to correspond with the other publishing channels (ftp, xml-rpc, and others in the future). I wrote a post back in September about my early experiments augmenting other Zope 3 components, in which I include some example code making an XML-RPC view onto a Job Board component written by someone else. My final paragraph in that post reads:
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.
A few other positive notes about Zope 3X a1. The "grand renaming" went into effect during the final weeks of the beta. This involved cleaning up the Python package hierarchy. It also involved case-normalization of package and module names. They are now all lowercase, like most other well-written Python packages/frameworks (distutils, docutils, etc), which makes it easy to distinguish classes and other module exports from the modules themselves. Zope 3 also uses Python 2.2 "new-style-classes" and gets rid of ExtensionClasses, since now you can write new extension types for Python in C and subclass them (which was the big point of ExtensionClasses). Zope 3 also (finally) makes use of other long-standing Python technologies such as distutils.
Now for the negative aspects. Since this is an alpha of the Zope 3 "experimental" line, it's not surprising that there is little or no documentation. The code structure is significantly different from that of Zope 2. It takes some time to find ones way around the code layout. Most things are pretty clear though (a benefit of having Interfaces) when you do find them, but there's so much new technology and terminology here that even when you grasp the terminology, it's not obvious to an outsider how to put it all to work.
Zope 3 is heavily reliant on Services, which is a good thing. Services are like Tools in the CMF - well known objects that provide a service to a global or local region. Examples of services are Event Channels (yay! Events!), or something like the Error Log that showed up in Zope 2.6. Other examples of Services are Database Adapters. In Zope 2, most service objects existed in the same namespace as all other objects. Zope 3 manages them in special namespaces. This allows content objects to be managed separately from service objects while still retaining placefulness. There are numerous upsides to a service based architecture. What's the downside? The downside is there's significant "what the...?!" effect when first encountering Services and Configuration objects. I'm sure it will all make more sense as future Zope 3X development releases are made, but right now it's a proverbial kick in the head.
There are some other aspects of Zope 3 that I'm likewarm to right now, mostly because they're difficult to fully comprehend how/when/where to use at the moment. Zope 3 allows for automatic user interface generation to occur. This was a feature of OS/2 (2.0+), and the defining motive of Naked Objects. Zope 2 has a subset of this feature in its use of properties. What Zope 3 seems to have done is to marry Interfaces (software, not user) and Formulator together. In essence, this allows easy edit forms to be generated off of the objects interface description. From the 'src/zope/app/browser/content/configure.zcml' file, here's an example of how an editform is configured for a ZPT Page:
<browser:editform
schema="zope.app.content.zpt.IZPTPage"
name="edit.html"
menu="zmi_views"
label="Edit a ZPT page"
permission="zope.ManageContent"
/>
And from the IZPTPage interface:
source = zope.schema.Text(
title=u"Source",
description=u"""The source of the page template.""",
required=True)
expand = zope.schema.Bool(
title=u"Expand macros",
)
Whew! That's about all I can cover for right now. If I have time this weekend, I intend to write a new Content Component (probably a reStructuredText Document) to see how different it really is from developing a similar product for Zope 2 or the CMF. I have no promises right now that it will get done this weekend, but it is something I've been wanting to do. Now that Zope 3X is at alpha1 stage, the fundamental structure should be fairly stable.
3:22:33 PM
|
|
|
Wednesday, November 13, 2002
|
|
Problems with StructuredText
I was going to write up my own list of issues I've had with Zope's StructuredText (Classic and NG) implementation, but this document sums it up nicely.
My expectation of software is, to quote Radiohead, "No alarms and no surprises." Zope Page Templates live up to that mantra, as does reStructuredText, so far.
9:50:10 AM
|
|
|
Wednesday, October 30, 2002
|
|
reStructuredText First Impressions
Today I started writing up user documentation for the project I'm wrapping up. It's the first time I've used reStructuredText, and I must say that I'm liking it. As far as structured text markup languages go, it's pretty comprehensive and not *too* obtrusive. It's definitely good enough for most technical documentation needs, and is in fact a PEP Formatting Standard (see also PEP 12 Source). Other items of interest, particularly to Python programmers, are:
I include the source links to show the relative cleanliness of the markup, which is the point of all Structured Text formats.
sigh I thought I'd have more to say, but I'm really too tired. So - quick wrap up: I was pretty productive with this stuff right off the bat. Nice.
For Zope, there is a proposal to integrate reStructuredText into Zope, hopefully for 2.7.
10:10:23 PM
|
|
|
Tuesday, October 8, 2002
|
|
Looking ahead to Python 2.3
I was trying to ascertain the state of Python 2.3 today, and PEP 283 offered up an interesting list of what is already in for 2.3, and a fairly long list of "planned features". What's in? Two new types - booleans and sets!. A fundamental datetime type or interface may make the release as well. A planned possible feature is an Iterator Tools module featuring "goodies from SML and Haskell".
I've been using Python for over six years now (it's hard to believe it's been that long!), and it's been interesting to watch the language grow since 1.3. A nice thing about Python's growth is that it's been fairly smart - as it picks up new features, it also simplifies itself. A lot of the old confusions / problems are gone or going away, and helpful features have popped up -- the type/class dichotomy is on its way out (it's interesting to see the prototype 'bool' type written up in Python by subclassing from 'int' - see PEP 285); booleans are coming in (I've always liked the way Python has treated true/false values, but it's nice to have actual 'True' and 'False' objects, and the built in 'bool' constructor); much of the old 'string' module has become methods on the 'string' type, removing the oddities of having a bunch of procedures to operate on a very common object in an object-oriented language; there are more unifications in expressions (the 'in' operator can now be used to search for substrings in a string: if 'this' in 'there was this thing..': in place of if 'there was this thing..'.find('this') > -1:; this also applies for dictionary keys: 'somekey' in mydict in place of mydict.has_key('somekey')); iterators are offered throughout the language now, sometimes offering shortcuts for common operations (such as reading individual lines from a file), and keeping resource use down for others; and we finally have nested scopes. Not to mention the little delights like Generators and List Comprehensions.
12:26:29 PM
|
|
|
Monday, September 2, 2002
|
|
A Zope 3 story - augmenting other components
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.
1:47:43 AM
|
|
|
Wednesday, July 17, 2002
|
|
Aha! (Python Patch)
So, the mysterious core dumps seem to be over, thanks to this patch on SourceForge.net regarding pthreads and stack sizes on BSD. I reverted back from the Tracker changes I made last night, and nothing crashed.
I did have to make one small patch to Tracker though, introducing a fun filled positive lookahead assertion to a regular expression used to generate HREF's.
7:19:05 PM
|
|
|
| January 2003 |
| Sun |
Mon |
Tue |
Wed |
Thu |
Fri |
Sat |
| |
|
|
1 |
2 |
3 |
4 |
| 5 |
6 |
7 |
8 |
9 |
10 |
11 |
| 12 |
13 |
14 |
15 |
16 |
17 |
18 |
| 19 |
20 |
21 |
22 |
23 |
24 |
25 |
| 26 |
27 |
28 |
29 |
30 |
31 |
|
| Nov Feb |
|
Navigation
Blogroll
|