From d3620a1c9236aa749f0516d5673323cc904289fc Mon Sep 17 00:00:00 2001 From: Hannah Bast Date: Sun, 9 Jul 2023 19:49:32 +0200 Subject: [PATCH] New command and view `examples` for getting example queries There is now a new command and view that can be used to retrieve all example queries for a given backend as TSV. Here is an example call: `docker exec -it qlever-ui bash -c "python manage.py examples wikidata"` To obtain the same result via an API call (no special permissions required): `curl -s https://qlever.cs.uni-freiburg.de/api/examples/wikidata` --- backend/management/commands/examples.py | 77 +++++++++++++++++++++++++ backend/urls.py | 1 + backend/views.py | 18 +++++- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 backend/management/commands/examples.py diff --git a/backend/management/commands/examples.py b/backend/management/commands/examples.py new file mode 100644 index 00000000..d7539029 --- /dev/null +++ b/backend/management/commands/examples.py @@ -0,0 +1,77 @@ +from django.core.management.base import BaseCommand, CommandError +from django.db.models import TextChoices +from backend.models import Backend +from backend.models import Link +from backend.models import Example +from pprint import pprint +import requests +import sys +import re + +# Command to get the example queries from the particular backend, with one line +# per query, in the format: +# +# name of querySPARQL query in one line without newlines +# +# TODO: Provide option to return result as JSON. +class Command(BaseCommand): + help = "Usage: python manage.py examples " + + # Copied from warmup.py, is this really needed? + def __init__(self, *args, **kwargs): + super().__init__( *args, **kwargs) + + # Custom log function. + def log(self, msg=""): + print(msg) + + # Command line arguments. + def add_arguments(self, parser): + parser.add_argument("slug", nargs=1, help="Slug of the backend") + + # This defines the actual behavior. + def handle(self, *args, returnLog=False, **options): + try: + slug = options["slug"][0] + except Exception as e: + self.log(f"Error parsing command line arguments: {e}") + self.log() + self.print_help("manage.py", "examples") + return + try: + backend = Backend.objects.filter(slug=slug).get() + except Exception as e: + self.log(f"Error finding config with slug \"{slug}\": {e}") + return + # self.log() + # self.log(f"ID of backend \"{slug}\" is: {backend.pk}") + # self.log() + # self.log(f"Keys of Example table: {Example._meta.fields}") + result = [] + for example in Example.objects.all(): + if example.backend.pk == backend.pk: + query_name = example.name + query_string = self.normalize_query(example.query) + result.append(f"{query_name}\t{query_string}") + self.log(f"Returning {len(result)} example queries for backend \"{slug}\"") + return "\n".join(result) + "\n" + + # Helper function for normalizing a query (translated from + # static/js/helper.js). + def normalize_query(self, query): + # Replace # in IRIs by %23. + query = re.sub(r'(<[^>]+)#', r'\1%23', query) + # Remove comments. + query = re.sub(r'#.*\n', ' ', query, flags=re.MULTILINE) + # Re-replace %23 in IRIs by #. + query = re.sub(r'(<[^>]+)%23', r'\1#', query) + # Replace all sequences of whitespace by a single space. + query = re.sub(r'\s+', ' ', query) + # Remove . before }. + query = re.sub(r'\s*\.\s*}', ' }', query) + # Remove any trailing whitespace. + query = query.strip() + + return query + + diff --git a/backend/urls.py b/backend/urls.py index 8a9e599a..0301e577 100644 --- a/backend/urls.py +++ b/backend/urls.py @@ -9,4 +9,5 @@ name='index'), re_path(r'^api/share$', views.shareLink, name='shareLink'), re_path(r'^api/warmup/(?P[^/]+)/(?P[a-zA-Z0-9_-]+)$', views.warmup, name='warmup'), + re_path(r'^api/examples/(?P[^/]+)$', views.examples, name='examples'), ] diff --git a/backend/views.py b/backend/views.py index f241da62..52d6cdb6 100644 --- a/backend/views.py +++ b/backend/views.py @@ -8,6 +8,7 @@ from .models import * from backend.management.commands.warmup import Command as WarmupCommand +from backend.management.commands.examples import Command as ExamplesCommand import json import urllib @@ -122,6 +123,7 @@ def shareLink(request): return redirect('/') +# Handle "warmup" request. def warmup(request, backend, target): token = request.GET.get("token") backends = Backend.objects.filter(slug=backend) @@ -143,12 +145,24 @@ def warmup(request, backend, target): except Exception as e: return JsonResponse({"status":"error", "message": str(e)}) return JsonResponse({"status":"ok", "log": log}) + +# Handle "examples" request, for example: # -# Helpers +# With the URL https://qlever.cs.uni-freiburg.de/api/examples/wikidata # +# this function is called with backend = "wikidata". +def examples(request, backend): + print_to_log(f"Call of \"examples\" in views.py with backend = \"{backend}\"") + command = ExamplesCommand() + try: + tsv = command.handle(returnLog=True, slug=[backend]) + except Exception as e: + return HttpResponse("Error: " + str(e), status=500) + return HttpResponse(tsv, content_type="text/tab-separated-values") -def log(msg, output=print): +# Helpers +def print_to_log(msg, output=print): """ Helper to log things that happen during the process """