The graphpath
package provides a python implementation
of the GraphPath little-language in which each GraphPath expression is
realized as a python object. The GraphPath operators are
implemented on these objects by overloading the python operators.
Usage follows the following pattern:
Import the GraphPath step types that will be used.
from graphpath.expr import Class, Node, Property
Import the adaption module for each RDF API that will be used with GraphPath. The import will enable (non-exclusive) GraphPath support for the objects in that API. (See the adaption section for information on using GraphPath with custom data sources.)
import graphpath.libadapt # enable use of rdflib import graphpath.redadapt # enable use of Redland
Obtain a vocabulary from somewhere using the RDF API. For
rdflib a number of rdflib.URIRef
objects would be used
representing individuals, classes and properties. For Redland, RDF.Node
objects fulfill this role.
For sake of exposition, we
will use an example vocabulary from the testcases
module called ex
with attributes for nodes and properties such as ex.julie
, ex.parent
and so on.
from graphpath.testcases import ex
Obtain data from somewhere using the RDF API. For rdflib
the graph data will be an instance of rdflib.store.AbstractTripleStore
.
For Redland, an instance of RDF.Model
is used.
We will borrow some sample data from the testcases
module
and call it graph
.
from graphpath.testcases import samples as graph
Queries against graph
can now be executed using the
terms of our vocabulary, ex
, as follows:
print "Julie's parents are:" for p in graph>>Node(ex.julie)/Property(ex.parent): print p print "Julie's male ancestors are:" for a in graph>>Node(ex.julie)//Property(ex.parent)[Class(ex.Male)]: print a
Queries for related data in graph
can be
conveniently formed using the projection operator:
for name, initial in graph>>Class(ex.Male) % \ (Property(ex.name ), Node(ex.initial)): print name, initial
Inference is used to add implied data, or entailments, to the graph based on rules. For example, if Jane is a parent of Sam then it is implied that Sam is a child of Jane. The rule in this case is the that child property is the inverse of the parent property. It would be tedious to take this into account in every expression, so we add a rule. In more complicated cases, a rule is the only way to handle entailments.
from graphpath.entail import Sandbox, RuleBase rules = RuleBase() rules[Property(ex.child)] = ~Property( ex.parent ) augmented = Sandbox( graph, rules) print "Julie's children are:" for p in augmented>>Node(ex.julie)/Property(ex.child): print p
First a RuleBase
is constructed, which acts as a dictionary of rules.
The rule relating the child property to the parent property is added to this.
The rules are evaluated in a Sandbox
. The Sandbox
instance augmented
conceptually contains all of the contents of the original
graph
plus the entailments derived from that graph and the
rules
. However, the entailments are only actually calculated if and when required.