Skip to content

Commit

Permalink
Add n-triples tests and update triples function.
Browse files Browse the repository at this point in the history
- triples() now returns an iterator instead of a list
- a bit of cleanup
- added docs for triples
  • Loading branch information
davidlehn committed Sep 20, 2011
1 parent 2870283 commit 32a3d43
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 47 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -20,6 +20,7 @@ API Reference
.. autofunction:: expand
.. autofunction:: frame
.. autofunction:: normalize
.. autofunction:: triples

Indices and tables
------------------
Expand Down
68 changes: 40 additions & 28 deletions lib/pyld/jsonld.py
Expand Up @@ -15,7 +15,7 @@
__copyright__ = "Copyright (c) 2011 Digital Bazaar, Inc."
__license__ = "New BSD licence"

__all__ = ["compact", "expand", "frame", "normalize"]
__all__ = ["compact", "expand", "frame", "normalize", "triples"]

import copy

Expand Down Expand Up @@ -1738,33 +1738,6 @@ def _compareSerializations(s1, s2):
rval = _compare(s1, s2[0:len(s1)])
return rval


def triples(input, callback=None):
normalized = normalize(input)
rval = None

# normalize input
if (callback == None):
rval = []
def callback(s,p,o):
rval.append({'s':s, 'p':p, 'o':o })
return True

quit = False
for e in normalized:
s = e['@subject']['@iri']
for p, obj in e.iteritems():
if p == '@subject': continue
if not isinstance(obj, list):
obj = [obj]
for o2 in obj:
quit = callback(s, p, o2)==False
if quit: break
if quit: break
if quit: break

return rval

def normalize(input):
"""
Normalizes a JSON-LD object.
Expand Down Expand Up @@ -1954,3 +1927,42 @@ def frame(input, frame, options=None):
:return: the framed output.
"""
return Processor().frame(input, frame, options)

def _defaultTriplesCallback(s, p, o):
return {'s':s, 'p':p, 'o':o}

def triples(input, callback=_defaultTriplesCallback):
"""
Generates triples given a JSON-LD input. Each triple that is generated
results in a call to the given callback. The callback takes 3 parameters:
subject, property, and object. If the callback returns False then this
method will stop generating triples and return. If the callback is null,
then triple objects containing "s", "p", "o" properties will be generated.
The object or "o" property will be a JSON-LD formatted object.
:param input: the JSON-LD input.
:param callback: the triple callback.
:param options: framing options to use.
:return: an iterator of triples.
"""
normalized = normalize(input)

quit = False
for e in normalized:
s = e['@subject']['@iri']
for p, obj in e.iteritems():
if p == '@subject': continue
if not isinstance(obj, list):
obj = [obj]
for o2 in obj:
triple = callback(s, p, o2)
quit = (triple == False)
if quit:
break
else:
yield triple
if quit: break
if quit: break

77 changes: 58 additions & 19 deletions tests/TestRunner.py
Expand Up @@ -13,6 +13,20 @@
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'lib'))
from pyld import jsonld

##
# jsonld.triples callback to create ntriples lines
def _ntriple(s, p, o):
if isinstance(o, basestring):
# simple literal
return "<%s> <%s> \"%s\" ." % (s, p, o)
elif "@iri" in o:
# object is an IRI
return "<%s> <%s> <%s> ." % (s, p, o["@iri"])
else:
# object is a literal
return "<%s> <%s> \"%s\"^^<%s> ." % \
(s, p, o["@literal"], o["@datatype"])

##
# TestRunner unit testing class.
# Loads test files and runs groups of tests.
Expand Down Expand Up @@ -106,41 +120,66 @@ def main(self):
count += 1

# open the input and expected result json files
inputFd = open(join(self.testdir, test['input']))
expectFd = open(join(self.testdir, test['expect']))
inputJson = json.load(inputFd)
expectJson = json.load(expectFd)

resultJson = None
inputFile = open(join(self.testdir, test['input']))
expectFile = open(join(self.testdir, test['expect']))
inputJson = json.load(inputFile)
expectType = os.path.splitext(test['expect'])[1][1:]
if expectType == 'json':
expect = json.load(expectFile)
elif expectType == 'nt':
# read, strip non-data lines, stripe front/back whitespace, and sort
# FIXME: only handling strict nt format here
expectLines = []
for line in expectFile.readlines():
line = line.strip()
if len(line) == 0 or line[0] == '#':
continue
expectLines.append(line)
expect = '\n'.join(sorted(expectLines))

result = None

testType = test['type']
if testType == 'normalize':
resultJson = jsonld.normalize(inputJson)
result = jsonld.normalize(inputJson)
elif testType == 'expand':
resultJson = jsonld.expand(inputJson)
result = jsonld.expand(inputJson)
elif testType == 'compact':
contextFd = open(join(self.testdir, test['context']))
contextJson = json.load(contextFd)
resultJson = jsonld.compact(contextJson, inputJson)
contextFile = open(join(self.testdir, test['context']))
contextJson = json.load(contextFile)
result = jsonld.compact(contextJson, inputJson)
elif testType == 'frame':
frameFd = open(join(self.testdir, test['frame']))
frameJson = json.load(frameFd)
resultJson = jsonld.frame(inputJson, frameJson)
frameFile = open(join(self.testdir, test['frame']))
frameJson = json.load(frameFile)
result = jsonld.frame(inputJson, frameJson)
elif testType == 'triples':
result = '\n'.join(
sorted(jsonld.triples(inputJson, callback=_ntriple)))
else:
print "Unknown test type."

# check the expected value against the test result
if expectJson == resultJson:
if expect == result:
passed += 1
print 'PASS'
if self.options.verbose:
print 'Expect:', json.dumps(expectJson, indent=4)
print 'Result:', json.dumps(resultJson, indent=4)
print 'Expect:', json.dumps(expect, indent=4)
print 'Result:',
if expectType == 'json':
print json.dumps(result, indent=4)
else:
print
print result
else:
failed += 1
print 'FAIL'
print 'Expect:', json.dumps(expectJson, indent=4)
print 'Result:', json.dumps(resultJson, indent=4)
print 'Expect:', json.dumps(expect, indent=4)
print 'Result:',
if expectType == 'json':
print json.dumps(result, indent=4)
else:
print
print result

print "Tests run: %d, Tests passed: %d, Tests Failed: %d" % (run, passed, failed)

Expand Down

0 comments on commit 32a3d43

Please sign in to comment.