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
isn't that
easy. You
need a few workarounds. So in the end I kept that store
local
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
constructors.
Also I added a page template. I created them in skins/default
. The
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 import
subdirectory.filename
sends python to look for a library
subdirectory
instead of having him look in the subdirectory. Ah
well.
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
errors:
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.py
at the beginning).rdflib.
part
(and other subdirectories if present).python rope.py
and see what it's complaining about. There are some points at which you encounter name clashes. For
instance from rdflib.syntax.parser import Parser
doesn't give a
problem, but from parser import Parser
imports the parser from some
python or zope standard library. In a case like that I renamed the
file from parser.py
to rdflibparser.py
. The same with
rdflibexceptions.py
. Sometimes you need to remove all *.pyc
files
also. Renaming parser.py
doesn't have any visible effect on python's
complaining when 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 grep class
*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
python rope.py
!
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
superclasses' __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()
Here super()
first calls NTparser's, Parser's and Serializer's init
method (if available) and then does things of it's own. This is
changed to:
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 __init__()
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:
rope.store.add((ns['a'],ns['b'],ns['c']))
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
later.
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 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):