Skip to content
Snippets Groups Projects
Commit 746572b0 authored by Dominik Seeger's avatar Dominik Seeger Committed by robinwilliam.hundt
Browse files

added import endpoint

parent 19fb9bcc
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !192. Comments created here will be created in the context of that merge request.
from rest_framework import status
from rest_framework.test import APIClient, APITestCase
from core.models import UserAccount, SubmissionType
from util.factories import GradyUserFactory
test_data = {
"meta": {
"version": "3.0.0"
},
"module": {
"module_reference": "test",
"pass_only": True,
"pass_score": 1,
"total_score": 99
},
"students": [
{
"fullname": "test",
"identifier": "test-test",
"submissions": [
{
"code": "some messy, perhaps incorrect stuff",
"tests": {},
"type": "[a0] coding stuff"
},
{
"code": "i don't know man",
"tests": {},
"type": "[a1] improvise"
}
],
}
],
"submission_types": [
{
"description": "code some 1337 stuff",
"full_score": 99,
"name": "[a0] coding stuff",
"programming_language": "c",
"solution": "how dare u"
},
{
"description": "now this one's hard",
"full_score": 1,
"name": "[a1] improvise",
"programming_language": "haskell",
"solution": "nope"
},
]
}
class ImportViewTest(APITestCase):
factory = GradyUserFactory()
def setUp(self):
self.url = '/api/import/'
self.client = APIClient()
self.client.force_login(user=self.factory.make_reviewer())
def test_can_not_submit_nothing(self):
res = self.client.post(self.url)
self.assertEqual(status.HTTP_400_BAD_REQUEST, res.status_code)
def test_will_fail_on_wrong_importer_version(self):
data = {"meta": {"version": "0.0.0"}}
res = self.client.post(self.url, data)
self.assertEqual(status.HTTP_409_CONFLICT, res.status_code)
def test_data_is_imported_correctly(self):
res = self.client.post(self.url, test_data)
sub_types = SubmissionType.objects.all()
students = UserAccount.objects.all().filter(role='Student')
self.assertEqual(2, len(sub_types))
self.assertEqual(1, len(students))
self.assertEqual(status.HTTP_201_CREATED, res.status_code)
...@@ -52,6 +52,7 @@ regular_views_urlpatterns = [ ...@@ -52,6 +52,7 @@ regular_views_urlpatterns = [
name='jwt-time-delta'), name='jwt-time-delta'),
path('instance/export/', views.InstanceExport.as_view(), name="instance-export"), path('instance/export/', views.InstanceExport.as_view(), name="instance-export"),
path('export/json/', views.StudentJSONExport.as_view(), name='export-json'), path('export/json/', views.StudentJSONExport.as_view(), name='export-json'),
path('import/', views.ImportApiViewSet.as_view(), name='import-json'),
re_path(r'swagger(?P<format>\.json|\.yaml)$', re_path(r'swagger(?P<format>\.json|\.yaml)$',
schema_view.without_ui(cache_timeout=0), name='schema-json'), schema_view.without_ui(cache_timeout=0), name='schema-json'),
re_path(r'swagger/$', schema_view.with_ui('swagger', cache_timeout=0), re_path(r'swagger/$', schema_view.with_ui('swagger', cache_timeout=0),
......
...@@ -3,3 +3,4 @@ from .subscription import SubscriptionApiViewSet, AssignmentApiViewSet # noqa ...@@ -3,3 +3,4 @@ from .subscription import SubscriptionApiViewSet, AssignmentApiViewSet # noqa
from .common_views import * # noqa from .common_views import * # noqa
from .export import StudentJSONExport, InstanceExport # noqa from .export import StudentJSONExport, InstanceExport # noqa
from .label import LabelApiViewSet, LabelStatistics # noqa from .label import LabelApiViewSet, LabelStatistics # noqa
from .importer import ImportApiViewSet # noqa
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.exceptions import ValidationError
from core.permissions import IsReviewer
from util.importer import parse_and_import_hektor_json
class ImportApiViewSet(APIView):
permission_classes = (IsReviewer, )
def post(self, request):
exam_data = request.data
if not exam_data:
return Response({"Error": "You need to submit the exam data to be imported"},
status.HTTP_400_BAD_REQUEST)
try:
parse_and_import_hektor_json(exam_data)
except ValidationError as err:
return Response({"ValidationError": err.detail},
status.HTTP_409_CONFLICT)
return Response({}, status.HTTP_201_CREATED)
...@@ -3,6 +3,7 @@ import os ...@@ -3,6 +3,7 @@ import os
import readline import readline
import logging import logging
from rest_framework.exceptions import ValidationError
from util.messages import warn from util.messages import warn
from core.models import ExamType, Feedback, Submission, SubmissionType, Test, FeedbackLabel from core.models import ExamType, Feedback, Submission, SubmissionType, Test, FeedbackLabel
from core.models import UserAccount as User from core.models import UserAccount as User
...@@ -119,11 +120,17 @@ def load_hektor_json(): ...@@ -119,11 +120,17 @@ def load_hektor_json():
with open(file, 'r') as f: with open(file, 'r') as f:
exam_data = json.JSONDecoder().decode(f.read()) exam_data = json.JSONDecoder().decode(f.read())
parse_and_import_hektor_json(exam_data)
def parse_and_import_hektor_json(exam_data):
hektor_version = exam_data['meta']['version'] hektor_version = exam_data['meta']['version']
if not (semver.match(hektor_version, RUSTY_HEKTOR_MIN_VER) and if not (semver.match(hektor_version, RUSTY_HEKTOR_MIN_VER) and
semver.match(hektor_version, RUSTY_HEKTOR_MAX_VER)): semver.match(hektor_version, RUSTY_HEKTOR_MAX_VER)):
warn(f'The data you\'re trying to import has the wrong version {hektor_version}\n' raise ValidationError(
f'Requirements: {RUSTY_HEKTOR_MIN_VER}, {RUSTY_HEKTOR_MAX_VER}') f'The data you\'re trying to import has the wrong version {hektor_version}\n'
f'Requirements: {RUSTY_HEKTOR_MIN_VER}, {RUSTY_HEKTOR_MAX_VER}'
)
exam, _ = ExamType.objects.get_or_create(**exam_data['module']) exam, _ = ExamType.objects.get_or_create(**exam_data['module'])
...@@ -131,7 +138,7 @@ def load_hektor_json(): ...@@ -131,7 +138,7 @@ def load_hektor_json():
_, created = SubmissionType.objects.update_or_create( _, created = SubmissionType.objects.update_or_create(
name=submission_type['name'], defaults=submission_type) name=submission_type['name'], defaults=submission_type)
if not created: if not created:
log.warning(f"Updated submission type {submission_type}") raise ValidationError(f"Updated submission type: {submission_type['name']}")
for student in exam_data['students']: for student in exam_data['students']:
student_obj = user_factory.make_student(exam=exam, is_active=False, student_obj = user_factory.make_student(exam=exam, is_active=False,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment