inamidst.com sw trio doc
You can import all of Trio...
>>> import trio
Though quite often you'll just want to use Graph and n3:
>>> from trio import Graph, n3
These make working with RDF pretty simple. The normal "Hello, world!" example with RDF is printing out a list of people in some FOAF file, so here's how to handle that in Trio:
>>> G = Graph('http://inamidst.com/sbp/foaf.rdf') >>> Q = n3('[ foaf:knows [ foaf:name ?name ] ]') >>> for name in G.query(Q, 'name'): ... print name "Aaron Swartz" "Al Gilman" ...
Graphs have all the usual kind of methods you'd expect:
>>> G = Graph('http://inamidst.com/sbp/foaf.rdf') >>> len(G) 135
That tells you how many triples there are.
>>> H = Graph('http://inamidst.com/sbp/foaf.rdf') >>> G == H True
You can get triples from a Graph too, in arbitrary order:
>>> homepage = n3['foaf:homepage'] >>> for triple in G.triples(predicate=homepage): ... print triple.object <http://www.aaronsw.com/> <http://inamidst.com/sbp/> ...
Graph takes a URI that can return RDF/XML, N3, Turtle, N-Triples, or GRDDL. Here's an example of GRDDL:
>>> G = Graph('http://www.w3.org/2004/lambda/Sites/index.html')
And we can query it for Joe Lambda's workplace homepage:
>>> Q = n3('[ foaf:workplaceHomepage ?homepage ]') >>> for homepage in G.query(Q, 'homepage'): ... print homepage ... break <http://www.acme.com>
The nodes
method returns all the nodes from a Graph instance,
which you can then sort—URIs sort before Literals, which sort before
BlankNodes and Variables:
>>> print sorted(G.nodes())[0] <http://creativecommons.org/licenses/by-nd/1.0/>
Trio passes all of the NTC test cases:
>>> for index, expected in enumerate('ynynnnnyynyyn'): ... case = '%02i' % (index + 1) ... A = Graph('http://inamidst.com/sw/test/ntc/' + case + 'a.nt') ... B = Graph('http://inamidst.com/sw/test/ntc/' + case + 'b.nt') ... ... if expected == 'y': ... assert A == B, ValueError('Expected equal graphs') ... else: assert A != B, ValueError('Expected unequal graphs')
Of course isomorphism testing is just a restricted kind of query, so this should also work though it doesn't do isomorphism testing strictly:
... def empty(results): ... try: results.next() ... except StopIteration: ... return True ... return False ... ... if expected == 'y': ... assert not empty(A.query(B)) ... else: assert empty(A.query(B))
Here's the difference:
>>> n3('?p ?q ?r') == n3('_:p _:q _:r') False >>> len(list(n3('?p ?q ?r').query(n3('_:p _:q _:r')))) 1
So, how about an actual application? One thing that I use Trio for is to work the hTurtle service, which goes a bit like this:
>>> import re, urllib >>> r_comment = re.compile(r'<!--\{((?:[^-]|(?:-[^-]))*)\}-->') >>> >>> G = trio.Graph(baseURI='http://inamidst.com/sw/hturtle/') >>> u = urllib.urlopen('http://inamidst.com/sw/hturtle/') >>> bytes = u.read() >>> u.close() >>> >>> bindings = """\ ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . ... @prefix owl: <http://www.w3.org/2002/07/owl#> . ... @prefix dc: <http://purl.org/dc/elements/1.1/> . ... @prefix foaf: <http://xmlns.com/foaf/0.1/> . ... @prefix doap: <http://usefulinc.com/ns/doap#> . ... @prefix skos: <http://www.w3.org/2004/02/skos/core#> . ... """ >>> >>> turtle = bindings + '\n'.join(r_comment.findall(bytes)) + '\n' >>> turtle = turtle.decode('utf-8') >>> G.parseText(turtle, 'turtle')
That should parse the hTurtle documentation in G and give one triple:
>>> len(G) 1 >>> for o in G.query(n3('?s ?p ?o'), 'o'): ... print o "The hTurtle Microformat"
In the application itself we want to print it out as RDF/XML:
>>> for line in G.serialiseToLines('rdfxml'): ... print line <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="http://inamidst.com/sw/hturtle/"> <e xmlns="http://purl.org/dc/elements/1.1/titl" >The hTurtle Microformat</e> </rdf:Description> </rdf:RDF>
>>> n3.prefix('', 'http://purl.org/ns/meteo#') >>> G = Graph('http://inamidst.com/sw/meteo/rdf/London') >>> Q = n3("""[ :time ?time; :cloudCover [ :percent ?cloud ]; ... :temperature [ :celsius ?temperature ]; ... :precipitation [ :inches ?precipitation ] ] .""") >>> forecasts = len(list(G.query(Q))) >>> assert 50 < forecasts < 70
There is very weak but burgeoning SPARQL support:
>>> manifest = ( ... ('algebra/data-1.ttl', ... 'algebra/filter-nested-1.rq', ... 'algebra/filter-nested-1.srx'), ... ) >>> >>> tests = 'http://www.w3.org/2001/sw/DataAccess/tests/data-r2/' >>> for data, query, expected in manifest: ... G = Graph(tests + data, format='turtle') ... R = G.sparqlURI(tests + query, 'SELECT').graph() ... E = Graph(tests + expected, format='sparql-results') ... assert R == E, '%s failed' % query
And some actual queries:
>>> manifest = ( ... ('data-01.ttl', 'dawg-tp-01.rq', 'result-tp-01.ttl'), ... ('data-01.ttl', 'dawg-tp-02.rq', 'result-tp-02.ttl'), ... ('data-02.ttl', 'dawg-tp-03.rq', 'result-tp-03.ttl'), ... ('dawg-data-01.ttl', 'dawg-tp-04.rq', 'result-tp-04.ttl'), ... ) >>> >>> tests = 'http://www.w3.org/2001/sw/DataAccess/tests/data-r2/triple-match/' >>> for data, query, expected in manifest: ... G = Graph(tests + data, format='turtle') ... R = G.sparqlURI(tests + query, 'SELECT').graph() ... E = Graph(tests + expected, format='turtle') ... assert R == E, '%s failed' % query
>>> assert trio.turtle.__file__ == trio.rdf.turtle.__file__ >>> assert trio.rdf.turtle.__file__.startswith('./trio/turtle.py')
All of the examples in this document, incidentally, form a part of the actual test suite for Trio. (The details are that this document is a GRDDL document, so then we slurp the test triples from this document and run them using Python's doctest module.) So they should always be up to date!
Sean B. Palmer, inamidst.com