Thursday, 17 March 2005
I’m happy to announce that version 0.7 of sparta.py, a simple API for RDF, is now available. As always, feedback and suggestions are appreciated.
My goal for this release was to clean up cardinality. In particular, I wanted to make Sparta usable with the Atom OWL work that’s been going on. Unfortunately, it’s difficult to show — both because Atom is a moving target, and due to a few flaws in the stylesheet and model — but with a little tweaking, I believe it’ll be pretty straightforward once Atom settles down and they catch up.
The most obvious change in this version is in how cardinality is determined. After actually reading the OWL docs, I think I’ve done it correctly; an object will be considered unique (thereby giving you direct access to it, rather than through a ResourceSet), if:
- The predicate is an owl:FunctionalProperty, or
- The subject is subclassed to have an owl:Restriction on that property with either an owl:MaxCardinality or an owl:cardinality of “1”.
Practically speaking, this means that where you previously said that a property had owl:maxCardinality of “1” to work with Sparta, you’ll now need to say it has an rdf:type of owl:FunctionalProperty.
Also, __init__ is a little more picky about the properties that you instantiate it with; if something isn’t considered unique (as per above), you’ll need to wrap it in a list; e.g.,
bob = Thing(None, rdf_type=["people_Person"], person_age='23')
assuming that person_age is constrained in cardinality, and rdf_type isn’t.
Assignment can now copy between different stores, so if you’re jugging two rdf datastores with Sparta, you can do things like
bob = StoreOneThing("person_bob") mary = StoreTwoThing("person_mary") bob.person_wife = mary
and it will work. This involved adding the copyTo method, which supports directly copying statements from one store to the other.
You can also pass a URI string when working with attributes, which is helpful if you don’t know what prefix to use with it. Although this isn’t too useful with direct access (Python syntax doesn’t allow object properties named bob.http://example.com/person#wife), it is useful with getattr and friends (e.g., getattr(bob, “http://example.com/person#wife”)).
Rich comparison support means you can now compare objects and know if they represent the same underlying RDF node; e.g.,
if bob.wife == Thing("person_mary"): ...
Finally, one under-the-covers change that should make Sparta a lot more compatible with existing, real-world RDF is that it now does the right thing when nodes have multiple rdf:type and rdfs:range values. The currently implementation is correct if inefficient, but I expect optimisation will be fairly straightforward.
I’m not going to say that this is feature-complete, because I’ve said that too many times before. I still need to dig into RDF and OWL a bit more to see where else I can find nice things to do, and still want to think about typing list members.
After the API and functionality are stable, I’ll look at more documentation, refactoring, optimisation, and documentation, as well as a Redland back end.