Forum OpenACS Q&A: Response to Article on ACS x Zope

Posted by Chris McDonough on
yep... I'll bust my message up into a few pieces, then. """ RELATIVELY? Care to define that term? """

OK, now we're getting somewhere. Here's a snippet of Python that sits in a configuration file on disk that creates a FileStorage instance (from memory, the spelling might be wrong, the thrust is not):

import ZODB
db = ZODB.FileStorage('/tmp/Data.fs')

Here's a snippet of Python that does the same with a relational storage:

import InterbaseStorage
db = InterbaseStorage('/tmp/zope_storage.gdb', 'localhost', 'user', 'password')

These are the only configuration differences, it is only configured once, and the remainder of the code in Zope is the same and is 100% transparent to the end user. The same operational rules apply when using either storage. One storage is hosted on the filesystem, the other is hosted in an Interbase database. A particular storage format/table structure is defined for either.

The rest is common between storages. For the most part, any valid Python statement can act against the ZODB (doesn't matter which storage type its hosted by). Objects that are not Python builtins must subclass from a Persistence class to participate in the ZODB. There is one other unobvious deviation from the norm that Python programmers need to understand, which is that they must treat mutable attributes of builtin objects immutably (ie. you need to notify the storage separately if you use methods of built-in objects (arrays, hashes, etc) that modify them "in-place", as opposed to using assignment).

Most storages support "versions" and "undo". Undo works on a per-transaction basis, and all transactions are undoable unless objects referenced in the transaction are modified by a subsequent transaction. Versions are long-running transactions used mostly for site "staging", where you can modify objects without having your changes show up in production until an explicit commit (handy for HTML developers) reducing the need for a separate staging server.

Recently, we've added support for Mountable Storages, which means that a single application namespace can host different storages simultaneously. This is desirable in cases that you want to make use of BerekelyStorage (a storage using BerkelelyDB) in situations where undo and versions are not necessary and the "all-writes-are-appends" properties of undoable storages lead to unwanted file growth. You can think of mountable storages somewhat like Unix mounted filesystems, where the application namespace is the root of the filesystem.

Users create objects, whether through the web interface, through DTML, or through Python within either storage. You interact with the ZODB in a manner consistent across them. Transactions begun by a web request or via DTML are automatically committed or aborted at the end of a request. Transactions begun within Python code must be committed explicitly.