def datetime(e): if not isinstance(e, Literal): raise SPARQLError("Non-literal passed as datetime: %r" % e) if not e.datatype == XSD.dateTime: raise SPARQLError( "Literal with wrong datatype passed as datetime: %r" % e) return e.toPython()
def date(e) -> py_datetime.date: if not isinstance(e, Literal): raise SPARQLError("Non-literal passed as date: %r" % e) if e.datatype not in (XSD.date, XSD.dateTime): raise SPARQLError("Literal with wrong datatype passed as date: %r" % e) result = e.toPython() if isinstance(result, py_datetime.datetime): return result.date() return result
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: %r" % s) if s.datatype and s.datatype != XSD.string: raise SPARQLError("Non-string datatype-literal passes as string: %r" % s) return s
def Builtin_TIMEZONE(e, ctx): """ http://www.w3.org/TR/sparql11-query/#func-timezone :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: %r" % 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_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_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_DATATYPE(e, ctx): l_ = e.arg if not isinstance(l_, Literal): raise SPARQLError("Can only get datatype of literal: %r" % l_) if l_.language: return RDF_langString if not l_.datatype and not l_.language: return XSD.string return l_.datatype
def Function(e, ctx): """ Custom functions and casts """ pair = _CUSTOM_FUNCTIONS.get(e.iri) if pair is None: # no such function is registered raise SPARQLError("Unknown function %r" % e.iri) func, raw = pair if raw: # function expects expression and context return func(e, ctx) else: # function expects the argument list try: return func(*e.expr) except TypeError as ex: # wrong argument number raise SPARQLError(*ex.args)
def execute_from_sparql(self, e, ctx): if not e.expr: raise SPARQLError("Nothing given to SPARQLFunction.") params = self.get_params_in_order() num_params = len(params) if len(e.expr) > num_params: raise SPARQLError("Too many parameters passed to SPARQLFunction.") elif len(e.expr) < num_params: raise SPARQLError("Too few parameters passed to SPARQLFunction.") new_binds = ctx.ctx.initBindings.copy() new_binds.update(ctx.ctx.bindings) g = ctx.ctx.graph for i, var in enumerate(e.expr): var_val = ctx[var] bind_name = params[i].localname new_binds[bind_name] = var_val if self.ask: return self.execute_ask(g, new_binds) else: return self.execute_select(g, new_binds)
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(str(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 execute_from_sparql(self, e, ctx): if not e.expr: raise SPARQLError("Nothing given to SPARQLFunction.") params = self.get_params_in_order() num_params = len(params) if len(e.expr) > num_params: raise SPARQLError("Too many parameters passed to SPARQLFunction.") elif len(e.expr) < num_params: raise SPARQLError("Too few parameters passed to SPARQLFunction.") args_map = {str(var): val for var, val in ctx.ctx.initBindings.items()} args_map.update( {str(var): val for var, val in ctx.ctx.bindings.items()}) g = ctx.ctx.graph for i, var in enumerate(e.expr): var_val = ctx[var] param_name = params[i].localname args_map[param_name] = var_val results = self.js_exe.execute(g, args_map, mode="function", return_type=self.rtype) res = results['_result'] return res
def calculateFinalDateTime(obj1, dt1, obj2, dt2, operation): """ Calculates the final dateTime/date/time resultant after addition/ subtraction of duration/dayTimeDuration/yearMonthDuration """ # checking compatibility of datatypes (duration types and date/time/dateTime) if (isCompatibleDateTimeDatatype(obj1, dt1, obj2, dt2)): # proceed if (operation == "-"): ans = obj1 - obj2 return Literal(ans, datatype=dt1) else: ans = obj1 + obj2 return Literal(ans, datatype=dt1) else: raise SPARQLError('Incompatible Data types to DateTime Operations')
def _compatibleStrings(a, b): string(a) string(b) if b.language and a.language != b.language: raise SPARQLError("incompatible arguments to str functions")
def literal(s): if not isinstance(s, Literal): raise SPARQLError("Non-literal passed as string: %r" % s) return s
def RelationalExpression(e, ctx): expr = e.expr other = e.other op = e.op # because of the way the add-expr production handled operator precedence # we sometimes have nothing to do if other is None: return expr ops = dict([ (">", lambda x, y: x.__gt__(y)), ("<", lambda x, y: x.__lt__(y)), ("=", lambda x, y: x.eq(y)), ("!=", lambda x, y: x.neq(y)), (">=", lambda x, y: x.__ge__(y)), ("<=", lambda x, y: x.__le__(y)), ("IN", pyop.contains), ("NOT IN", lambda x, y: not pyop.contains(x, y)), ]) if op in ("IN", "NOT IN"): res = op == "NOT IN" error = False if other == RDF.nil: other = [] for x in other: try: if x == expr: return Literal(True ^ res) except SPARQLError as e: error = e if not error: return Literal(False ^ res) else: raise error if op not in ("=", "!=", "IN", "NOT IN"): if not isinstance(expr, Literal): raise SPARQLError( "Compare other than =, != of non-literals is an error: %r" % expr) if not isinstance(other, Literal): raise SPARQLError( "Compare other than =, != of non-literals is an error: %r" % other) else: if not isinstance(expr, Node): raise SPARQLError("I cannot compare this non-node: %r" % expr) if not isinstance(other, Node): raise SPARQLError("I cannot compare this non-node: %r" % other) if isinstance(expr, Literal) and isinstance(other, Literal): if (expr.datatype is not None and expr.datatype not in XSD_DTs and other.datatype is not None and other.datatype not in XSD_DTs): # in SPARQL for non-XSD DT Literals we can only do =,!= if op not in ("=", "!="): raise SPARQLError( "Can only do =,!= comparisons of non-XSD Literals") try: r = ops[op](expr, other) if r == NotImplemented: raise SPARQLError("Error when comparing") except TypeError as te: raise SPARQLError(*te.args) return Literal(r)
def AdditiveExpression(e, ctx): expr = e.expr other = e.other # because of the way the add-expr production handled operator precedence # we sometimes have nothing to do if other is None: return expr # handling arithmetic(addition/subtraction) of dateTime, date, time # and duration datatypes (if any) if hasattr(expr, 'datatype') and (expr.datatype in XSD_DateTime_DTs or expr.datatype in XSD_Duration_DTs): res = dateTimeObjects(expr) dt = expr.datatype for op, term in zip(e.op, other): # check if operation is datetime,date,time operation over # another datetime,date,time datatype if dt in XSD_DateTime_DTs and dt == term.datatype and op == '-': # checking if there are more than one datetime operands - # in that case it doesn't make sense for example # ( dateTime1 - dateTime2 - dateTime3 ) is an invalid operation if len(other) > 1: error_message = "Can't evaluate multiple %r arguments" raise SPARQLError(error_message, dt.datatype) else: n = dateTimeObjects(term) res = calculateDuration(res, n) return res # datetime,date,time +/- duration,dayTimeDuration,yearMonthDuration elif (dt in XSD_DateTime_DTs and term.datatype in XSD_Duration_DTs): n = dateTimeObjects(term) res = calculateFinalDateTime(res, dt, n, term.datatype, op) return res # duration,dayTimeDuration,yearMonthDuration + datetime,date,time elif dt in XSD_Duration_DTs and term.datatype in XSD_DateTime_DTs: if op == "+": n = dateTimeObjects(term) res = calculateFinalDateTime(res, dt, n, term.datatype, op) return res # rest are invalid types else: raise SPARQLError('Invalid DateTime Operations') # handling arithmetic(addition/subtraction) of numeric datatypes (if any) else: res = numeric(expr) dt = expr.datatype for op, term in zip(e.op, other): n = numeric(term) if isinstance(n, Decimal) and isinstance(res, float): n = float(n) if isinstance(n, float) and isinstance(res, Decimal): res = float(res) dt = type_promotion(dt, term.datatype) if op == "+": res += n else: res -= n return Literal(res, datatype=dt)
def default_cast(e, ctx): 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 %r of type %r" % (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: %r" % x.datatype) if e.iri == XSD.dateTime: if x.datatype and x.datatype not in (XSD.dateTime, XSD.string): raise SPARQLError("Cannot cast %r to XSD:dateTime" % x.datatype) try: return Literal(isodate.parse_datetime(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%r' as datetime" % x) if x.datatype == XSD.dateTime: raise SPARQLError("Cannot cast XSD.dateTime to %r" % e.iri) if e.iri in (XSD.float, XSD.double): try: return Literal(float(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%r' 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 '%r' as decimal" % x) try: return Literal(Decimal(x), datatype=e.iri) except: raise SPARQLError("Cannot interpret '%r' as decimal" % x) elif e.iri == XSD.integer: try: return Literal(int(x), datatype=XSD.integer) except: raise SPARQLError("Cannot interpret '%r' 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 '%r' as bool" % x)
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 =,!=