icp/src/rest/views.py

304 lines
9.1 KiB
Python

from __future__ import absolute_import
# django
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
# rest framework
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework import serializers
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
# mongo
#import pymongo
#from pymongo import MongoClient
import json
from bson import json_util
from bson.objectid import ObjectId
from bson.errors import InvalidId
import datetime
import sys
import os
import pprint
import re
import os.path
import shutil
from courses.models import Course
from courses.models import Section
from courses.models import Slide
from courses.models import UserCourse
from courses.models import UserSolution
from runner.tasks import compile_and_run
import json
import random
def local_execute(dic):
id = random.randint(1,10000000)
file = "/data/run/jobs/%s/job.json" % (id)
while os.path.isfile(file):
id = random.randint(1,10000000)
file = "/data/run/jobs/%s/job.json" % (id)
ret = compile_and_run(id, dic)
print(ret, file=sys.stderr)
return {"details": "OK", "id" : id, "data": ret}
def local_execute_result(id):
#return {"status" : 201, "result": {"output" : False, "grade" : "PASS"}}
if not id.isdigit():
return {"status" : 0, "result": {"output" : False}}
dir = "/data/run/jobs/%s/" % (id)
print("Retrieving: " + dir)
if os.path.isfile(dir + "job.json"):
with open(dir + "job.json") as json_data:
d = json.load(json_data)
# cleanup of outdated directories
shutil.rmtree(dir) # remove files directories
return {"status" : 'SUCCESS', "result": d["response"]}
else:
return {"status" : 0, "result": {"output" : False}}
# helpers
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
class Entry(object):
def __init__(self):
pass
class EntrySerializer(serializers.Serializer):
def restore_object(self, attrs, instance=None):
if instance:
return instance
return Entry()
# django views
###############################################################################
def course(request, cid):
#try:
# user_course = UserCourse.objects.get(course=course_id)
#except UserCourse.DoesNotExist:
# raise Http404("Question does not exist")
data = {}
course = get_object_or_404(Course, pk=cid)
return render(request, 'courses/course.html', {'course': course, 'data': data})
def section(request, cid, seid):
data = {}
course = get_object_or_404(Course, pk=cid)
return render(request, 'courses/course.html', {'course': course, 'data': data})
def slide(request, cid, seid, slid):
data = {}
course = get_object_or_404(Course, pk=cid)
return render(request, 'courses/course.html', {'course': course, 'data': data})
def slide_check(request, cid, seid, slid):
data = {}
course = get_object_or_404(Course, pk=cid)
return render(request, 'courses/course.html', {'course': course, 'data': data})
###
def index(request):
return HttpResponse("Usage: /api/rest/..")
#@api_view(['GET','POST'])
@csrf_exempt
def entry_list(request, database_id):
data = str({"field1": "value1"})
if request.method == 'GET':
json_docs = [json.dumps(doc, default=json_util.default) for doc in cursor]
return HttpResponse("[%s]" % (",".join(json_docs)))
elif request.method == 'POST':
data = JSONParser().parse(request)
try:
_id = collection.insert(data)
data["_id"] = _id
json_docs = json.dumps(data, default=json_util.default)
return HttpResponse("%s" % json_docs, status=201)
except:
return JSONResponse("""{"error": "insert failed."}""", status=400)
# Event Stream API
###############################################################################
@api_view(['POST'])
@csrf_exempt
def event(request):
#event_db = mongo["events"]
#event_col = event_db["events"]
return JSONResponse({"details": "OK"}, status=201)
#if request.method == 'POST':
# # populate additional fields
# request.data["timestamp"] = datetime.datetime.now()
# request.data["referrer"] = request.META.get('HTTP_REFERER') # sic
# request.data["user_id"] = request.user.id
# #print(request.data, file=sys.stderr)
# try:
# _id = event_col.insert(request.data)
# print(request.data['type'], _id, file=sys.stderr)
# #json_docs = json.dumps(data, default=json_util.default)
# return JSONResponse({"details": "OK", "id": str(_id)}, status=201)
# except:
# return JSONResponse({"details": "insert failed."}, status=400)
#else:
# return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)
# Job API
###############################################################################
#@api_view(['GET','POST'])
@csrf_exempt
def job_status(request, jid):
#print("Job-status " + jid)
data = str({"field1": "value1"})
#job_db = mongo["jobs"]
#job_col = job_db["jobs"]
#return HttpResponse(status=404)
if request.method == 'GET':
#task = celery_task_compile_and_run.AsyncResult(jid)
task = local_execute_result(jid)
#print("results")
data = {"status": task["status"], "data": task["result"]}
#print("DONE!")
#json_docs = json.dumps(data, default=json_util.default)
#data = JSONParser().parse(json_docs)
return JSONResponse(data)
return HttpResponse("huh", status=401)
@api_view(['POST'])
@csrf_exempt
def job_new(request):
#job_db = mongo["jobs"]
#job_col = job_db["jobs"]
# Snipped in-case we would like to force the referrer to match the slide.
#slid = None
#referrer = request.META.get('HTTP_REFERER')
#result = re.findall(r'/courses/(?P<cid>[0-9]+)/(?P<seid>[0-9]+)/(?P<slid>[0-9]+)/$', referrer)
#print(result, file=sys.stderr)
#try:
# slid = Slide.objects.get(pk=result[0][2])
#except Comment.DoesNotExist:
# slid = None
#
#print(slid, file=sys.stderr)
if request.method == 'POST':
#print(datetime.datetime.now(), file=sys.stderr)
#print(request.data, file=sys.stderr)
slide = get_object_or_404(Slide, pk=request.data['slide'])
#print("Solution from: ", slide.title, file=sys.stderr)
job_dic = {}
#job_dic['timestamp'] = datetime.datetime.now()
job_dic['solution'] = request.data['solution']
job_dic['action'] = request.data['action']
job_dic['source_path'] = slide.source_path
job_dic['type'] = slide.slide_type
job_dic['data'] = json.loads(slide.data)
job_dic['user_id'] = request.user.id
#print('job_dic:', file=sys.stderr)
# Also create/update the user solution.
user_solution = None
if request.user.is_authenticated:
try:
item, created = UserSolution.objects.get_or_create(slide=slide, user=request.user)
user_solution = item
except UserSolution.DoesNotExist:
pass
#print(user_solution, file=sys.stderr)
if user_solution != None:
user_solution.data = json.dumps(request.data)
user_solution.save()
#pprint.pprint(job_dic, sys.stderr)
try:
#task = celery_task_compile_and_run.delay(job_dic)
data = local_execute(job_dic)
#_id = job_col.insert(request.data)
#print(_id, file=sys.stderr)
#json_docs = json.dumps(data, default=json_util.default)
return JSONResponse(data, status=201)
except:
print(sys.exc_info()[0])
return JSONResponse({"details": "Job submission failed."}, status=400)
#else:
# return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)
#else:
# return JSONResponse("""{"error": "HTTP request type not allowed."}""", status=400)
# return HttpResponse("huh")
#
# if request.method == 'GET':
# data = collection.find_one({"_id": _id})
# json_docs = json.dumps(data, default=json_util.default)
# return HttpResponse("%s" % json_docs)
#
# elif request.method == 'PUT':
# data = JSONParser().parse(request)
# data.pop("_id", None) # remove _id key from data for pymongo
# print >>sys.stdout, data
# try:
# collection.update({"_id": _id}, data)
# data["_id"] = _id
# json_docs = json.dumps(data, default=json_util.default)
# return HttpResponse("%s" % json_docs)
# except:
# return JSONResponse("""{"error": "update failed."}""", status=400)
#
# elif request.method == 'DELETE':
# collection.remove({"_id": _id})
# return HttpResponse(status=204)
#