def void_dataset(graph_name): """Describe one RDF dataset""" try: logger.debug( '[/void/] Loading VoID descriptions for dataset {}'.format( graph_name)) graph = dataset.get_graph(graph_name) if graph is None: abort(404) logger.debug('[/void/] Corresponding dataset found') mimetype = request.accept_mimetypes.best_match([ "application/n-triples", "text/turtle", "application/xml", "application/n-quads", "application/trig", "application/json", "application/json+ld" ]) url = secure_url(request.url_root) if url.endswith('/'): url = url[0:len(url) - 1] descriptor = VoidDescriptor(url, graph) format, mimetype = choose_format(mimetype) return Response(descriptor.describe(format), content_type=mimetype) except Exception as e: logger.error(e) abort(500)
def index(): try: url = secure_url(request.url) dinfos = [dinfo for dinfo in dataset.describe(url)] long_description = Markup(markdown(dataset.long_description)) return render_template("index_sage.html", dataset=dinfos, server_public_url=dataset.public_url, default_query=dataset.default_query, long_description=long_description) except Exception as e: gunicorn_logger.error(e) abort(500)
def void_all(): """Describe all RDF datasets hosted by the Sage endpoint""" try: mimetype = request.accept_mimetypes.best_match([ "application/n-triples", "text/turtle", "application/xml", "application/n-quads", "application/trig", "application/json", "application/json+ld" ]) url = secure_url(request.url_root) if url.endswith('/'): url = url[0:len(url) - 1] format, mimetype = choose_format(mimetype) description = many_void(url, datasets, format) return Response(description, content_type=mimetype) except Exception: abort(500)
def index(): try: datasets_infos = datasets._config["datasets"] url = secure_url(request.url) api_doc = { "@context": "http://www.w3.org/ns/hydra/context.jsonld", "@id": url, "@type": "ApiDocumentation", "title": "SaGe SPARQL API", "description": "A SaGe interface which allow evaluation of SPARQL queries over RDF datasets", "entrypoint": "{}sparql".format(url), "supportedClass": [] } for dinfo in datasets.describe(url): api_doc["supportedClass"].append(dinfo) long_description = Markup(markdown(datasets.long_description)) return render_template("index_sage.html", datasets=datasets_infos, api=api_doc, server_public_url=datasets.public_url, default_query=datasets.default_query, long_description=long_description) except Exception as e: print(e) abort(500)
def sparql_index(): mimetype = request.accept_mimetypes.best_match([ "application/json", "application/xml", "application/sparql-results+json", "application/sparql-results+xml", "text/html" ]) try: url = secure_url(request.base_url) # parse arguments if request.method == "GET": query = request.args.get("query") or None default_graph_uri = request.args.get( "default-graph-uri") or None next_link = request.args.get("next") or None # ensure that both the query and default-graph-uri params are set if (query is None or default_graph_uri is None) and ( next_link is None or default_graph_uri is None): return sage_http_error( "Invalid request sent to server: a GET request must contains both parameters 'query' and 'default-graph-uri'. See <a href='http://sage.univ-nantes.fr/documentation'>the API documentation</a> for reference." ) elif request.method == "POST" and request.is_json: # POST query post_query, err = SageSparqlQuery().load(request.get_json()) if err is not None and len(err) > 0: # TODO better formatting return Response(format_marshmallow_errors(err), status=400) query = post_query["query"] default_graph_uri = post_query["defaultGraph"] next_link = post_query["next"] if 'next' in post_query else None else: return sage_http_error( "Invalid request sent to server: a GET request must contains both parameters 'query' and 'default-graph-uri'. See <a href='http://sage.univ-nantes.fr/documentation'>the API documentation</a> for reference." ) # execute query return execute_query(query, default_graph_uri, next_link, dataset, mimetype, url) except Exception as e: logger.error(e) abort(500)
def sparql_index(): try: mimetype = request.accept_mimetypes.best_match( ["application/json", "text/html"]) url = secure_url(request.url) api_doc = { "@context": "http://www.w3.org/ns/hydra/context.jsonld", "@id": url, "@type": "ApiDocumentation", "title": "SaGe SPARQL API", "description": "A SaGe interface which allow evaluation of SPARQL queries over RDF datasets", "entrypoint": "{}sparql".format(url), "supportedClass": [] } for dinfo in datasets.describe(url): api_doc["supportedClass"].append(dinfo) if mimetype is "text/html": return render_template("interfaces.html", api=api_doc) return json.jsonify(api_doc) except Exception: abort(500)
def sparql_query(graph_name): """WARNING: old API, deprecated""" graph = dataset.get_graph(graph_name) if graph is None: abort(404) logger.debug('[/sparql/] Corresponding dataset found') mimetype = request.accept_mimetypes.best_match([ "application/json", "application/xml", "application/sparql-results+json", "application/sparql-results+xml" ]) url = secure_url(request.url) try: # A GET request always returns the homepage of the dataset if request.method == "GET" or (not request.is_json): dinfo = graph.describe(url) dinfo['@id'] = url void_desc = { "nt": VoidDescriptor(url, graph).describe("ntriples"), "ttl": VoidDescriptor(url, graph).describe("turtle"), "xml": VoidDescriptor(url, graph).describe("xml") } return render_template("website/sage_dataset.html", dataset_info=dinfo, void_desc=void_desc) engine = SageEngine() post_query, err = QueryRequest().load(request.get_json()) if err is not None and len(err) > 0: return Response(format_marshmallow_errors(err), status=400) quota = graph.quota / 1000 max_results = graph.max_results # Load next link next_link = None if 'next' in post_query: next_link = decode_saved_plan(post_query["next"]) # build physical query plan, then execute it with the given quota start = time() plan, cardinalities = build_query_plan(post_query["query"], dataset, graph_name, next_link) loading_time = (time() - start) * 1000 # convert in milliseconds bindings, saved_plan, is_done = engine.execute( plan, quota, max_results) # compute controls for the next page start = time() next_page = None if not is_done: next_page = encode_saved_plan(saved_plan) exportTime = (time() - start) * 1000 # convert in milliseconds stats = { "cardinalities": cardinalities, "import": loading_time, "export": exportTime } if mimetype == "application/sparql-results+json": res = Response(responses.w3c_json_streaming( bindings, next_page, stats, url), content_type='application/json') if mimetype == "application/xml" or mimetype == "application/sparql-results+xml": res = Response(responses.w3c_xml(bindings, next_page, stats), content_type="application/xml") else: res = Response(responses.raw_json_streaming( bindings, next_page, stats, url), content_type='application/json') # set deprecation warning in headers res.headers.add( "Warning", "199 SaGe/2.0 \"You are using a deprecated API. Consider uppgrading to the SaGe SPARQL query API. See http://sage.univ-nantes.fr/documentation fore more details.\"" ) return res except Exception as e: logger.error(e) abort(500)
def lookup_entity(graph_name, entity): """Evaluates a DESCRIBE query over a RDF dataset""" logger.debug('[IP: {}] [/lookup/] Querying {}'.format( request.environ['REMOTE_ADDR'], graph_name)) graph = dataset.get_graph(graph_name) if graph is None: abort(404) url = secure_url(request.url) try: engine = SageEngine() # Get entity and possible next link entity_uri = secure_url(request.base_url) next_link = request.args.get("next", default=None) post_query = build_describe_query(entity_uri) logger.debug('[IP: {}] [/lookup/] Entity={}'.format( request.environ['REMOTE_ADDR'], entity_uri)) quota = graph.quota / 1000 max_results = graph.max_results # Load next link if next_link is not None: logger.debug( '[/lookup/{}] Saved plan found, decoding "next" link'. format(graph_name)) next_link = decode_saved_plan(next_link) else: logger.debug('[/lookup/{}] Query to evaluate: {}'.format( graph_name, post_query)) # build physical query plan, then execute it with the given quota logger.debug( '[/lookup/{}] Starting query evaluation...'.format(graph_name)) # start = time() plan, cardinalities = build_query_plan(post_query, dataset, graph_name, next_link) # loading_time = (time() - start) * 1000 bindings, saved_plan, is_done = engine.execute( plan, quota, max_results) logger.debug( '[/lookup/{}] Query evaluation completed'.format(graph_name)) # compute controls for the next page # start = time() next_page = None if is_done: logger.debug( '[/lookup/{}] Query completed under the time quota'.format( graph_name)) else: logger.debug( '[/lookup/{}] The query was not completed under the time quota...' .format(graph_name)) logger.debug( '[/lookup/{}] Saving the execution to plan to generate a "next" link' .format(graph_name)) next_page = encode_saved_plan(saved_plan) logger.debug( '[/lookup/{}] "next" link successfully generated'.format( graph_name)) # exportTime = (time() - start) * 1000 # stats = {"import": loading_time, "export": exportTime} triples = bindings_to_triple(entity_uri, bindings, url) headers = dict() if next_page is not None: headers["X-Sage-Next"] = "{}?next={}".format( entity_uri, next_page) headers[ "Link"] = "<{}?next={}>; rel=\"next\"; title=\"Next page\"".format( entity_uri, next_page) return Response(responses.ntriples_streaming(triples), content_type="application/ntriples", headers=headers) except Exception as e: logger.error(e) abort(500)
def sparql_query(dataset_name): logger.info('[IP: {}] [/sparql/] Querying {}'.format( request.environ['REMOTE_ADDR'], dataset_name)) dataset = datasets.get_dataset(dataset_name) if dataset is None: abort(404) logger.debug('[/sparql/] Corresponding dataset found') mimetype = request.accept_mimetypes.best_match([ "application/json", "application/xml", "application/sparql-results+json", "application/sparql-results+xml" ]) url = secure_url(request.url) try: # A GET request always returns the homepage of the dataset if request.method == "GET" or (not request.is_json): dinfo = dataset.describe(url) dinfo['@id'] = url void_desc = { "nt": VoidDescriptor(url, dataset).describe("ntriples"), "ttl": VoidDescriptor(url, dataset).describe("turtle"), "xml": VoidDescriptor(url, dataset).describe("xml") } return render_template("sage.html", dataset_info=dinfo, void_desc=void_desc) engine = SageEngine() post_query, err = QueryRequest().load(request.get_json()) if err is not None and len(err) > 0: return Response(format_marshmallow_errors(err), status=400) logger.info('[IP: {}] [/sparql/] Query={}'.format( request.environ['REMOTE_ADDR'], post_query)) quota = dataset.quota / 1000 max_results = dataset.max_results # Load next link next_link = None if 'next' in post_query: logger.debug( '[/sparql/{}] Saved plan found, decoding "next" link'. format(dataset_name)) next_link = decode_saved_plan(post_query["next"]) else: logger.debug('[/sparql/{}] Query to evaluate: {}'.format( dataset_name, post_query)) # build physical query plan, then execute it with the given quota logger.debug('[/sparql/{}] Starting query evaluation...'.format( dataset_name)) start = time() plan, cardinalities = build_query_plan(post_query["query"], dataset, next_link) loading_time = (time() - start) * 1000 bindings, saved_plan, is_done = engine.execute( plan, quota, max_results) logger.debug( '[/sparql/{}] Query evaluation completed'.format(dataset_name)) # compute controls for the next page start = time() next_page = None if is_done: logger.debug( '[/sparql/{}] Query completed under the time quota'.format( dataset_name)) else: logger.debug( '[/sparql/{}] The query was not completed under the time quota...' .format(dataset_name)) logger.debug( '[/sparql/{}] Saving the execution to plan to generate a "next" link' .format(dataset_name)) next_page = encode_saved_plan(saved_plan) logger.debug( '[/sparql/{}] "next" link successfully generated'.format( dataset_name)) exportTime = (time() - start) * 1000 stats = { "cardinalities": cardinalities, "import": loading_time, "export": exportTime } if mimetype == "application/sparql-results+json": return json.jsonify(responses.json(bindings, next_page, stats)) if mimetype == "application/xml" or mimetype == "application/sparql-results+xml": return Response(responses.xml(bindings, next_page, stats), content_type="application/xml") return json.jsonify(responses.raw_json(bindings, next_page, stats)) except Exception: abort(500)