Long time since I updated this (well, two weeks or so), but I had a short holiday of a week. And I ran into severe zope vs. rdflib biting... Back from holiday
Just got back from a one-week holiday (Texel, the Netherlands). I've kept the nagging feeling that I did something wrong with removing the actual rdflib store to a local variable instead of subclassing all the rdflib functionality.
Some research made it clear that subclassing existing classes in zope
need a few workarounds. So in the end I kept that
variable. Rdflib uses the new-style-class's
super() method a lot and
that is stopped dead in its tracks by ExtensionClass. And
ExtensionClass is deep in zope and used by acquisition... I better
just admit defeat and keep rdflib a bit apart from the zope
aparatus. Zope 3 promises to be much better in this regard, however.
Adding an icon proved to be simple. I created
www/rope.gif and added
icon = "www/rope.gif" to
__init__.py, just after the line with the
Also I added a page template. I created them in
first one is 'rope_view.pt':
I am an RDF store I am an RDF store <p> My id is Subject Predicate Object
For this to work, some things have to be added to 'rope.py':
# Import for page templates from Products.PageTemplates.PageTemplateFile import PageTemplateFile .... # Place this line just inside the class definition viewTemplateFile = PageTemplateFile('skins/default/rope_view.pt', globals()) .... # Replace index_html with the following def index_html(self, REQUEST=None): """ Default index page. """ return self.viewTemplateFile.__of__(self)(self,REQUEST) .... security.declarePublic('triples') def triples(self, tripleQuestion): for s,p,o in self.store.triples(tripleQuestion): yield s,p,o
Now index_html is rendered according to the page template, getting rid of hardcoded html in the code. Separation of logic and layout is a very good thing.
Well, in the end there was nothing to be done about it: either zope's extentionclass mechanism goes out or the new-style classes go out. As zope is much bigger than rdflib I decided to remove the new-style classes from rdflib :-)
For this I copied all imported rdflib files to the root directory of
my product, removing all
rdflib. thingies to make sure the local
version of the file is loaded instead of the installed rdflib
library. Putting everything in the product's root directory feels very
sloppy to me, but subdirectories don't work in this case. An
subdirectory.filename sends python to look for a library
subdirectory instead of having him look in the subdirectory. Ah
A small positive point in all this mess: in this way you don't need to install rdflib seperately, it's all one self-contained package.
To get meaningful error messages I added the following to the end of
rope.py. This way I could do a
python rope.py and get a few
if __name__ == '__main__': rope = RopeProduct('abc') ns = Namespace('http://vanrees.org/test#') rope.namespaces['rr'] = ns print "One namespace:" print rope.namespaces print rope.store
First I did an iterative process:
rope.pyat the beginning).
rdflib.part (and other subdirectories if present).
python rope.pyand see what it's complaining about.
There are some points at which you encounter name clashes. For
from rdflib.syntax.parser import Parser doesn't give a
from parser import Parser imports the parser from some
python or zope standard library. In a case like that I renamed the
rdflibparser.py. The same with
rdflibexceptions.py. Sometimes you need to remove all
parser.py doesn't have any visible effect on python's
parser.pyc is still available (yes, I had that
problem, it bugged me for 10 minutes).
New-style classes subclass from the
object superclass. A
*py | grep object will reveal the culprits (or at least most of
them). Next I removed that object-subclassing from the files.
At this moment I got rid of "metaclass error" messages when running
super() is used a lot by rdflib in order to coordinate the various
__init__() methods, as rdflib uses subclassing a lot. It is also
used in other places, but
__init__() is the most common here.
This was actually quite a precision job as I had to call the
__init__() manually now. This means looking very
carefully at the inheritance hierarchy and at the needed arguments.
As an example, 'loadsave.py':
class LoadSave(NTParser, Parser, Serializer): def __init__(self): super(LoadSave, self).__init__() self.location = None self.__lock = Lock()
super() first calls NTparser's, Parser's and Serializer's init
method (if available) and then does things of it's own. This is
def __init__(self): Serializer.__init__(self) self.location = None self.__lock = Lock()
Explanation: NTParser doesn't have a meaningfull init method, so that
one doesn't have to be called (I removed NTParser's
later). Parser hasn't got an init method, so only serializer is
left. That one is called.
It's an iterative process of running
python rope.py, seeing where
python complains and then correcting that
super() method. This way
you won't miss anything. My guess is that in this way you follow a
remotely useful path through the source files.
At one moment I ran out of error messages (yahoo!!!) so I added another line to the test function:
Hm. The error message I got didn't concern
super() errors. Ok. While
there are still a few
super() calls left in the software, none of
them directly interfere with the zope mechanism. Perhaps something
doesn't get stored in the zope database, but I'll worry about that
The current set of errors centers around properties. Another new
thingy with new-style classes. You say "this is a property, but use
these two methods to get/set the data". Which probably means that this
mechanism doesn't work when you just removed the subclassing of
object from the class. I printed the new-style classes
documentation. Reading fodder for the train home :-)
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
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):