def datetime(e): if not isinstance(e, Literal): raise SPARQLError("Non-literal passed as datetime: %s" % e) if not e.datatype == XSD.dateTime: raise SPARQLError( "Literal with wrong datatype passed as datetime: %s" % e) return e.toPython()
def string(s): """ Make sure the passed thing is a string literal i.e. plain literal, xsd:string literal or lang-tagged literal """ if not isinstance(s, Literal): raise SPARQLError("Non-literal passes as string: %s" % s) if s.datatype and s.datatype != XSD.string: raise SPARQLError( "Non-string datatype-literal passes as string: %s" % s) return s
def Builtin_TIMEZONE(e, ctx): """ Returns the timezone part of arg as an xsd:dayTimeDuration. Raises an error if there is no timezone. """ dt = datetime(e.arg) if not dt.tzinfo: raise SPARQLError('datatime has no timezone: %s' % dt) delta = dt.tzinfo.utcoffset(ctx.now) d = delta.days s = delta.seconds neg = "" if d < 0: s = -24 * 60 * 60 * d - s d = 0 neg = "-" h = s / (60 * 60) m = (s - h * 60 * 60) / 60 s = s - h * 60 * 60 - m * 60 tzdelta = "%sP%sT%s%s%s" % (neg, "%dD" % d if d else "", "%dH" % h if h else "", "%dM" % m if m else "", "%dS" % s if not d and not h and not m else "") return Literal(tzdelta, datatype=XSD.dayTimeDuration)
def MultiplicativeExpression(e, ctx): expr = e.expr other = e.other # because of the way the mul-expr production handled operator precedence # we sometimes have nothing to do if other is None: return expr try: res = Decimal(numeric(expr)) for op, f in zip(e.op, other): f = numeric(f) if type(f) == float: res = float(res) if op == '*': res *= f else: res /= f except (InvalidOperation, ZeroDivisionError): raise SPARQLError('divide by 0') return Literal(res)
def Builtin_DATATYPE(e, ctx): l = e.arg if not isinstance(l, Literal): raise SPARQLError('Can only get datatype of literal: %s' % l) if l.language: return RDF_langString if not l.datatype and not l.language: return XSD.string return l.datatype
def Builtin_COALESCE(expr, ctx): """ http://www.w3.org/TR/sparql11-query/#func-coalesce """ for x in expr.get('arg', variables=True): if x is not None and not isinstance(x, (SPARQLError, Variable)): return x raise SPARQLError( "COALESCE got no arguments that did not evaluate to an error")
def Builtin_STRLANG(expr, ctx): """ http://www.w3.org/TR/sparql11-query/#func-strlang """ s = string(expr.arg1) if s.language or s.datatype: raise SPARQLError('STRLANG expects a simple literal') # TODO: normalisation of lang tag to lower-case # should probably happen in literal __init__ return Literal(unicode(s), lang=str(expr.arg2).lower())
def Builtin_IRI(expr, ctx): """ http://www.w3.org/TR/sparql11-query/#func-iri """ a = expr.arg if isinstance(a, URIRef): return a if isinstance(a, Literal): return ctx.prologue.absolutize(URIRef(a)) raise SPARQLError('IRI function only accepts URIRefs or Literals/Strings!')
def Builtin_BNODE(expr, ctx): """ http://www.w3.org/TR/sparql11-query/#func-bnode """ a = expr.arg if a is None: return BNode() if isinstance(a, Literal): return ctx.bnodes[a] # defaultdict does the right thing raise SPARQLError( 'BNode function only accepts no argument or literal/string')
def literal(s): if not isinstance(s, Literal): raise SPARQLError("Non-literal passed as string: %s" % s) return s
def Function(e, ctx): """ Custom functions (and casts!) """ if e.iri in XSD_DTs: # a cast if not e.expr: raise SPARQLError("Nothing given to cast.") if len(e.expr) > 1: raise SPARQLError("Cannot cast more than one thing!") x = e.expr[0] if e.iri == XSD.string: if isinstance(x, (URIRef, Literal)): return Literal(x, datatype=XSD.string) else: raise SPARQLError( "Cannot cast term %s of type %s" % (x, type(x))) if not isinstance(x, Literal): raise SPARQLError( "Can only cast Literals to non-string data-types") if x.datatype and not x.datatype in XSD_DTs: raise SPARQLError( "Cannot cast literal with unknown datatype: %s" % x.datatype) if e.iri == XSD.dateTime: if x.datatype and x.datatype not in (XSD.dateTime, XSD.string): raise SPARQLError( "Cannot cast %s to XSD:dateTime" % x.datatype) try: return Literal(isodate.parse_datetime(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%s' as datetime" % x) if x.datatype == XSD.dateTime: raise SPARQLError("Cannot cast XSD.dateTime to %s" % e.iri) if e.iri in (XSD.float, XSD.double): try: return Literal(float(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%s' as float" % x) elif e.iri == XSD.decimal: if "e" in x or "E" in x: # SPARQL/XSD does not allow exponents in decimals raise SPARQLError("Cannot interpret '%s' as decimal" % x) try: return Literal(Decimal(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%s' as decimal" % x) elif e.iri == XSD.integer: try: return Literal(int(x), datatype=XSD.integer) except: raise SPARQLError("Cannot interpret '%s' as int" % x) elif e.iri == XSD.boolean: # # I would argue that any number is True... # try: # return Literal(bool(int(x)), datatype=XSD.boolean) # except: if x.lower() in ("1", "true"): return Literal(True) if x.lower() in ("0", "false"): return Literal(False) raise SPARQLError("Cannot interpret '%s' as bool" % x) else: raise Exception("I do not know how to cast to %s" % e.iri) else: raise SPARQLError('Unknown function %s"%e.iri')
def _compatibleStrings(a, b): string(a) string(b) if b.language and a.language != b.language: raise SPARQLError('incompatible arguments to str functions')
for x in other: try: if x == expr: return Literal(True ^ res) except SPARQLError, e: error = e if not error: return Literal(False ^ res) else: raise error if not op in ('=', '!=', 'IN', 'NOT IN'): if not isinstance(expr, Literal): raise SPARQLError( "Compare other than =, != of non-literals is an error: %s" % expr) if not isinstance(other, Literal): raise SPARQLError( "Compare other than =, != of non-literals is an error: %s" % other) else: if not isinstance(expr, Node): raise SPARQLError('I cannot compare this non-node: %s' % expr) if not isinstance(other, Node): raise SPARQLError('I cannot compare this non-node: %s' % other) if isinstance(expr, Literal) and isinstance(other, Literal): if expr.datatype != None and expr.datatype not in XSD_DTs and other.datatype != None and other.datatype not in XSD_DTs: # in SPARQL for non-XSD DT Literals we can only do =,!=