Well, submitting what I did wednesday. No RDF yet, but I'm almost getting to that point. Tomorrow I'll meet Peter Willems from TNO (Dutch practical research outfit) who also deals with RDF in the same field. Only he uses java and jena so he won't be able to help me with this.
But: google frustrated my attempt at low-key programming and only sending around emails once I got something working. I got an email from Dave Kleinschmidt asking whether he could help out on this rope project... Great to get such an email :-) Writing the first code ======================
I started off with the list of standard imports listed in the ZDG, including them in RopeProduct:
from Acquisition import Implicit from Globals import Persistent from AccessControl.Role import RoleManager from OFS.SimpleItem import Item
Then I added the following to my RopeProduct class:
""" Rope product class. Makes rdflib available to zope. """ meta_type = 'Rope' # Required by Item baseclass def __init__(self, id): self.id = id # id needed by Item baseclass
Yep, don't forget that documentation at the beginning. The Item
baseclass needs meta_type
, which is the name under which your
product will be known to zope. A few pages later in the ZDG I decided
to add a PropertyManager
as well. That way I could add the handy
title
attribute and allow people to add their own properties
afterwards.
The next step is to add security declarations. As I haven't added any
rdflib stuff there isn't yet a thing that can be
made secure or public. So I added an index_html
method including the
declarePublic statement:
from AccessControl import ClassSecurityInfo ... security = ClassSecurityInfo() security.declarePublic('index_html') def index_html(self): """ Dummy index page. """ return """ Role product instance <p>My id is %s</p> """ % self.id
Note to self: don't forget that initial code comment next time... Methods without that comment won't be executable in zope.
Then the ZDG tells us to initialise the class. Note that I added the following on the "top level" of the file, not inside the class itself (I made that mistake the first time...):
from Globals import InitializeClass ... InitializeClass(RopeProduct)
Browsing a bit ahead in the ZDG reminded me that I needed define a method that adds the RopeProduct to a zope folder, coupled with a form to fill in the needed parameters. I'll create the form with simple html for the moment, later on I'll put in a page template:
def addForm(): """ Returns an html form used to instantiate a RopeProduct instance. """ return """ Add Rope id: <br> """ def addRope(dispatcher, id): """ Create a new Rope and add it to myself. """ rope = RopeProduct(id) dispatcher.Destination()._setObject(id,rope)
Note that both are again on the toplevel. Last thing left to do for we
can do some real testing is to add an __init__.py
file to allow zope
to auto-load this file. Well, auto isn't really the correct term, as
almost everything in zope is explicit. Zope does some real magic, but
it is all plain for all to see. So automatically adding a product to
zope means writing a function in a place where zope will find and
execute it. Here is the '__init__.py':
# Import the actual Rope product and the initialisation form+adder. from rope import RopeProduct, addForm, addRope def initialize(registrar): registrar.registerClass( RopeProduct, constructors = (addForm, addRope), )
Loading the product into zope for the first time ================================================
Well, it doesn't actually do anything, but it is time to test it in
zope for the first time. I made a symlink from my zope products
directory to the directory I put all my work in (windows users will
need to copy it). I started up zope and waited for some error
messages. They came. addForm()
needed a parameter... That's not in
the ZDG. Changing the definition to the following helped:
def addForm(unknown): # I couldn't really find what 'unknown' does...
After correcting some further small errors it seemed to work. The product seemed to exist. Headed over to the management interface for the product to get auto-refresh working. No, I'm not going to restart zope over and over again.
Ok, I now get the form. Only... I pressed submit and it didn't seem to do anything. Pressing submit again got me the error that the id I just entered. Looking in the management interface the object did exist. Clicking on it got me the security interface. Hand-editing the url to the address of the object got me the desired dummy html page. It's working!
Now to work on that management interface. It needs a view tab for
index_html
and another one for the management of the properties. I
didn't include the code for that property tab for nothing. Browsing a
bit further in the ZDG gives me the hint to add this to my
RopeProduct
class:
manage_options = ( {'label': 'Properties', 'action': 'manage_propertiesForm'}, {'label': 'View', 'action': 'index_html'}, {'label': 'Security', 'action': 'manage_access'} )
Viewing it gives me an error on the properties tab... "str
object
has no attribute 'copy'". Didn't figure it out before I went home. Let's see tomorrow.
Well, tomorrow didn't work out, spend the day arranging and giving a UML course for fourth year students. Had some problems with getting it all arranged, but the local sysadmins were great and helped out very willingly. I've never had any big problems with them, good bunch of guys.
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):