def Builtin_BOUND(e, ctx):
"""
http://www.w3.org/TR/sparql11-query/#func-bound
"""
n = e.get('arg', variables=True)
return Literal(not isinstance(n, Variable))
python类Variable()的实例源码
def evalQuery(graph, query, initBindings, base=None):
ctx = QueryContext(graph)
ctx.prologue = query.prologue
if initBindings:
for k, v in initBindings.iteritems():
if not isinstance(k, Variable):
k = Variable(k)
ctx[k] = v
# ctx.push() # nescessary?
main = query.algebra
# import pdb; pdb.set_trace()
if main.datasetClause:
if ctx.dataset is None:
raise Exception(
"Non-conjunctive-graph doesn't know about " +
"graphs! Try a query without FROM (NAMED).")
ctx = ctx.clone() # or push/pop?
firstDefault = False
for d in main.datasetClause:
if d.default:
if firstDefault:
# replace current default graph
dg = ctx.dataset.get_context(BNode())
ctx = ctx.pushGraph(dg)
firstDefault = True
ctx.load(d.default, default=True)
elif d.named:
g = d.named
ctx.load(g, default=False)
return evalPart(ctx, main)
def _knownTerms(triple, varsknown, varscount):
return (len(filter(None, (x not in varsknown and
isinstance(
x, (Variable, BNode)) for x in triple))),
-sum(varscount.get(x, 0) for x in triple),
not isinstance(triple[2], Literal),
)
def _aggs(e, A):
"""
Collect Aggregates in A
replaces aggregates with variable references
"""
# TODO: nested Aggregates?
if isinstance(e, CompValue) and e.name.startswith('Aggregate_'):
A.append(e)
aggvar = Variable('__agg_%d__' % len(A))
e["res"] = aggvar
return aggvar
def _findVars(x, res):
"""
Find all variables in a tree
"""
if isinstance(x, Variable):
res.add(x)
if isinstance(x, CompValue):
if x.name == "Bind":
res.add(x.var)
return x # stop recursion and finding vars in the expr
elif x.name == 'SubSelect':
if x.projection:
res.update(v.var or v.evar for v in x.projection)
return x
def _sample(e, v=None):
"""
For each unaggregated variable V in expr
Replace V with Sample(V)
"""
if isinstance(e, CompValue) and e.name.startswith("Aggregate_"):
return e # do not replace vars in aggregates
if isinstance(e, Variable) and v != e:
return CompValue('Aggregate_Sample', vars=e)
def translateAggregates(q, M):
E = []
A = []
# collect/replace aggs in :
# select expr as ?var
if q.projection:
for v in q.projection:
if v.evar:
v.expr = traverse(v.expr, functools.partial(_sample, v=v.evar))
v.expr = traverse(v.expr, functools.partial(_aggs, A=A))
# having clause
if traverse(q.having, _hasAggregate, complete=False):
q.having = traverse(q.having, _sample)
traverse(q.having, functools.partial(_aggs, A=A))
# order by
if traverse(q.orderby, _hasAggregate, complete=False):
q.orderby = traverse(q.orderby, _sample)
traverse(q.orderby, functools.partial(_aggs, A=A))
# sample all other select vars
# TODO: only allowed for vars in group-by?
if q.projection:
for v in q.projection:
if v.var:
rv = Variable('__agg_%d__' % (len(A) + 1))
A.append(CompValue('Aggregate_Sample', vars=v.var, res=rv))
E.append((rv, v.var))
return CompValue('AggregateJoin', A=A, p=M), E
def _get_bindings(self):
ret = []
for row in self.json['results']['bindings']:
outRow = {}
for k, v in row.items():
outRow[Variable(k)] = parseJsonTerm(v)
ret.append(outRow)
return ret
def __getitem__(self, key):
# in SPARQL BNodes are just labels
if not type(key) in (BNode, Variable):
return key
try:
return self.bindings[key]
except KeyError:
return None
def value(ctx, val, variables=False, errors=False):
"""
utility function for evaluating something...
Variables will be looked up in the context
Normally, non-bound vars is an error,
set variables=True to return unbound vars
Normally, an error raises the error,
set errors=True to return error
"""
if isinstance(val, Expr):
return val.eval(ctx) # recurse?
elif isinstance(val, CompValue):
raise Exception("What do I do with this CompValue? %s" % val)
elif isinstance(val, list):
return [value(ctx, x, variables, errors) for x in val]
elif isinstance(val, (BNode, Variable)):
r = ctx.get(val)
if isinstance(r, SPARQLError) and not errors:
raise r
if r is not None:
return r
# not bound
if variables:
return val
else:
raise NotBoundError
elif isinstance(val, ParseResults) and len(val) == 1:
return value(ctx, val[0], variables, errors)
else:
return val
def _traverse_sparql_result_dom(
doc, as_dictionary=False, node_from_result=_node_from_result):
"""
Returns a generator over tuples of results
"""
# namespace handling in elementtree xpath sub-set is not pretty :(
vars_ = [
Variable(v.attrib["name"])
for v in doc.findall(
'./{http://www.w3.org/2005/sparql-results#}head/'
'{http://www.w3.org/2005/sparql-results#}variable'
)
]
for result in doc.findall(
'./{http://www.w3.org/2005/sparql-results#}results/'
'{http://www.w3.org/2005/sparql-results#}result'):
curr_bind = {}
values = []
for binding in result.findall(
'{http://www.w3.org/2005/sparql-results#}binding'):
var_val = binding.attrib["name"]
var = Variable(var_val)
term = node_from_result(binding.findall('*')[0])
values.append(term)
curr_bind[var] = term
if as_dictionary:
yield curr_bind, vars_
else:
def __locproc(values_):
if len(values_) == 1:
return values_[0]
else:
return tuple(values_)
yield __locproc(values), vars_
def contexts(self, triple=None):
"""
Iterates over results to "SELECT ?NAME { GRAPH ?NAME { ?s ?p ?o } }"
or "SELECT ?NAME { GRAPH ?NAME {} }" if triple is `None`.
Returns instances of this store with the SPARQL wrapper
object updated via addNamedGraph(?NAME).
This causes a named-graph-uri key / value pair to be sent over
the protocol.
Please note that some SPARQL endpoints are not able to find empty named
graphs.
"""
self.resetQuery()
if triple:
s, p, o = triple
params = ((s if s else Variable('s')).n3(),
(p if p else Variable('p')).n3(),
(o if o else Variable('o')).n3())
self.setQuery('SELECT ?name WHERE { GRAPH ?name { %s %s %s }}' % params)
else:
self.setQuery('SELECT ?name WHERE { GRAPH ?name {} }')
doc = ElementTree.parse(SPARQLWrapper.query(self).response)
return (
rt.get(Variable("name"))
for rt, vars in _traverse_sparql_result_dom(
doc, as_dictionary=True, node_from_result=self.node_from_result)
)
# Namespace persistence interface implementation
def test_query_no_vars(self):
triples = [(rdflib.URIRef('http://dbpedia.org/resource/Helmut_Kohl'),
rdflib.URIRef('http://dbpedia.org/property/deputy'),
rdflib.URIRef('http://dbpedia.org/resource/Klaus_Kinkel'))]
algebra = CompValue ('SelectQuery', p = CompValue('BGP', triples=triples, _vars=set()),
datasetClause = None, PV = [], _vars = set())
res = self.sas.query_algebra(algebra)
self.assertEqual(len(res), 1)
for row in res:
s = ''
for v in res.vars:
s += ' %s=%s' % (v, row[v])
logging.debug('algebra result row: %s' % s)
# # @unittest.skip("temporarily disabled")
# def test_query_none(self):
# vx = rdflib.Variable('X')
# triples = [(vx,
# rdflib.URIRef('http://dbpedia.org/property/office'),
# rdflib.URIRef('http://dbpedia.org/resource/Chancellor_of_Germany')),
# (vx,
# rdflib.URIRef('http://dbpedia.org/property/termEnd'),
# None) ]
# algebra = CompValue ('SelectQuery', p = CompValue('BGP', triples=triples, _vars=set([vx])),
# datasetClause = None, PV = [vx], _vars = set([vx]))
# res = self.sas.query_algebra(algebra)
# self.assertEqual(len(res), 1)
# for row in res:
# s = ''
# for v in res.vars:
# s += ' %s=%s' % (v, row[v])
# logging.debug('algebra result row: %s' % s)
def __init__(self, source):
xmlstring = source.read()
if isinstance(xmlstring, unicode):
xmlstring = xmlstring.encode('utf-8')
try:
tree = ElementTree.fromstring(xmlstring)
except Exception, e:
try:
raise e.__class__("error parsing %r: %s" % (xmlstring, e))
except:
raise e
boolean = tree.find(RESULTS_NS_ET + 'boolean')
results = tree.find(RESULTS_NS_ET + 'results')
if boolean is not None:
type_ = 'ASK'
elif results is not None:
type_ = 'SELECT'
else:
g = Graph()
try:
g.parse(data=xmlstring)
if len(g) == 0:
raise
type_ = 'CONSTRUCT'
except:
raise ResultException(
"No RDF Graph, result-bindings or boolean answer found!")
Result.__init__(self, type_)
if type_ == 'SELECT':
self.bindings = []
for result in results:
r = {}
for binding in result:
r[Variable(binding.get('name'))] = parseTerm(binding[0])
self.bindings.append(r)
self.vars = [Variable(x.get("name"))
for x in tree.findall(
'./%shead/%svariable' % (
RESULTS_NS_ET, RESULTS_NS_ET))]
elif type_ == 'ASK':
self.askAnswer = boolean.text.lower().strip() == "true"
elif type_ == 'CONSTRUCT':
self.graph = g
def __init__(self, source, **kwargs):
if not isinstance(source, Graph):
graph = Graph()
graph.load(source, **kwargs)
else:
graph = source
rs = graph.value(predicate=RDF.type, object=RS.ResultSet)
# there better be only one :)
if rs is None:
type_ = 'CONSTRUCT'
# use a new graph
g = Graph()
g += graph
else:
askAnswer = graph.value(rs, RS.boolean)
if askAnswer is not None:
type_ = 'ASK'
else:
type_ = 'SELECT'
Result.__init__(self, type_)
if type_ == 'SELECT':
self.vars = [Variable(v) for v in graph.objects(rs,
RS.resultVariable)]
self.bindings = []
for s in graph.objects(rs, RS.solution):
sol = {}
for b in graph.objects(s, RS.binding):
sol[Variable(graph.value(
b, RS.variable))] = graph.value(b, RS.value)
self.bindings.append(sol)
elif type_ == 'ASK':
self.askAnswer = askAnswer.value
if askAnswer.value == None:
raise Exception('Malformed boolean in ask answer!')
elif type_ == 'CONSTRUCT':
self.graph = g
def evalUpdate(graph, update, initBindings=None):
"""
http://www.w3.org/TR/sparql11-update/#updateLanguage
'A request is a sequence of operations [...] Implementations MUST
ensure that operations of a single request are executed in a
fashion that guarantees the same effects as executing them in
lexical order.
Operations all result either in success or failure.
If multiple operations are present in a single request, then a
result of failure from any operation MUST abort the sequence of
operations, causing the subsequent operations to be ignored.'
This will return None on success and raise Exceptions on error
"""
for u in update:
ctx = QueryContext(graph)
ctx.prologue = u.prologue
if initBindings:
for k, v in initBindings.iteritems():
if not isinstance(k, Variable):
k = Variable(k)
ctx[k] = v
# ctx.push() # nescessary?
try:
if u.name == 'Load':
evalLoad(ctx, u)
elif u.name == 'Clear':
evalClear(ctx, u)
elif u.name == 'Drop':
evalDrop(ctx, u)
elif u.name == 'Create':
evalCreate(ctx, u)
elif u.name == 'Add':
evalAdd(ctx, u)
elif u.name == 'Move':
evalMove(ctx, u)
elif u.name == 'Copy':
evalCopy(ctx, u)
elif u.name == 'InsertData':
evalInsertData(ctx, u)
elif u.name == 'DeleteData':
evalDeleteData(ctx, u)
elif u.name == 'DeleteWhere':
evalDeleteWhere(ctx, u)
elif u.name == 'Modify':
evalModify(ctx, u)
else:
raise Exception('Unknown update operation: %s' % (u,))
except:
if not u.silent:
raise
def __init__(self, source, **kwargs):
if not isinstance(source, Graph):
graph = Graph()
graph.load(source, **kwargs)
else:
graph = source
rs = graph.value(predicate=RDF.type, object=RS.ResultSet)
# there better be only one :)
if rs is None:
type_ = 'CONSTRUCT'
# use a new graph
g = Graph()
g += graph
else:
askAnswer = graph.value(rs, RS.boolean)
if askAnswer is not None:
type_ = 'ASK'
else:
type_ = 'SELECT'
Result.__init__(self, type_)
if type_ == 'SELECT':
self.vars = [Variable(v) for v in graph.objects(rs,
RS.resultVariable)]
self.bindings = []
for s in graph.objects(rs, RS.solution):
sol = {}
for b in graph.objects(s, RS.binding):
sol[Variable(graph.value(
b, RS.variable))] = graph.value(b, RS.value)
self.bindings.append(sol)
elif type_ == 'ASK':
self.askAnswer = askAnswer.value
if askAnswer.value == None:
raise Exception('Malformed boolean in ask answer!')
elif type_ == 'CONSTRUCT':
self.graph = g
def evalUpdate(graph, update, initBindings=None):
"""
http://www.w3.org/TR/sparql11-update/#updateLanguage
'A request is a sequence of operations [...] Implementations MUST
ensure that operations of a single request are executed in a
fashion that guarantees the same effects as executing them in
lexical order.
Operations all result either in success or failure.
If multiple operations are present in a single request, then a
result of failure from any operation MUST abort the sequence of
operations, causing the subsequent operations to be ignored.'
This will return None on success and raise Exceptions on error
"""
for u in update:
ctx = QueryContext(graph)
ctx.prologue = u.prologue
if initBindings:
for k, v in initBindings.iteritems():
if not isinstance(k, Variable):
k = Variable(k)
ctx[k] = v
# ctx.push() # nescessary?
try:
if u.name == 'Load':
evalLoad(ctx, u)
elif u.name == 'Clear':
evalClear(ctx, u)
elif u.name == 'Drop':
evalDrop(ctx, u)
elif u.name == 'Create':
evalCreate(ctx, u)
elif u.name == 'Add':
evalAdd(ctx, u)
elif u.name == 'Move':
evalMove(ctx, u)
elif u.name == 'Copy':
evalCopy(ctx, u)
elif u.name == 'InsertData':
evalInsertData(ctx, u)
elif u.name == 'DeleteData':
evalDeleteData(ctx, u)
elif u.name == 'DeleteWhere':
evalDeleteWhere(ctx, u)
elif u.name == 'Modify':
evalModify(ctx, u)
else:
raise Exception('Unknown update operation: %s' % (u,))
except:
if not u.silent:
raise