Rope part 2ΒΆ

Tags: plone

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.

 
vanrees.org logo

Reinout van Rees

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.

Weblog feeds

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):