Skip to content

Commit

Permalink
new: proforma version 2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
KBorm committed May 28, 2020
1 parent 2c54ee4 commit eced0fe
Show file tree
Hide file tree
Showing 10 changed files with 1,103 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/VERSION.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-

version = "Version 4.3.3 | 20200514"
version = "Version 4.4.0 beta | 20200528"
3 changes: 0 additions & 3 deletions src/proforma/api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@

import os
import re
#import shutil
import logging
#import xmlschema
#from requests.exceptions import InvalidSchema
from . import task
from . import grade
import zipfile
Expand Down
2 changes: 0 additions & 2 deletions src/proforma/grade.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
from django.template.loader import render_to_string

import os
#import codecs
#import re
import logging


Expand Down
21 changes: 6 additions & 15 deletions src/proforma/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,13 @@


from os.path import dirname
from xml.dom import minidom
from xml.dom.minidom import Node

from django.core.exceptions import ObjectDoesNotExist
from django.core.files.uploadedfile import InMemoryUploadedFile

#from django.core.servers.basehttp import FileWrapper
from django.db import models

#from django.shortcuts import redirect
#from django.template import TemplateSyntaxError
#from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt
from django.core.files import File
from django.http import HttpResponse
from lxml import etree
from lxml import objectify
import logging
import zipfile
Expand All @@ -51,12 +42,7 @@
import hashlib
from tasks.models import Task

#from attestation.models import Rating
from checker.checker import CreateFileChecker
#from checker.models import Checker
#from solutions.models import Solution, SolutionFile
#from tasks.models import Task, MediaFile
#from . import task_v0_94
from . import task_v1_01
from . import task_v2_00

Expand Down Expand Up @@ -344,6 +330,7 @@ def import_task_internal(filename, task_file):
format_namespace_v0_9_4 = "urn:proforma:task:v0.9.4"
format_namespace_v1_0_1 = "urn:proforma:task:v1.0.1"
format_namespace_v2_0 = "urn:proforma:v2.0"
format_namespace_v2_0_1 = "urn:proforma:v2.0.1"

# rxcoding = re.compile(r"encoding=\"(?P<enc>[\w.-]+)")

Expand Down Expand Up @@ -386,7 +373,11 @@ def import_task_internal(filename, task_file):
response_data = task_v1_01.import_task(task_xml, xml_object, dict_zip_files)
elif format_namespace_v2_0 in list(xml_object.nsmap.values()):
logger.debug('handle 2.0 task')
task_2 = task_v2_00.Task_2_00(task_xml, xml_object, hash, dict_zip_files)
task_2 = task_v2_00.Task_2_00(task_xml, xml_object, hash, dict_zip_files, format_namespace_v2_0)
response_data = task_2.import_task()
elif format_namespace_v2_0_1 in list(xml_object.nsmap.values()):
logger.debug('handle 2.0.1 task')
task_2 = task_v2_00.Task_2_00(task_xml, xml_object, hash, dict_zip_files, format_namespace_v2_0_1)
response_data = task_2.import_task()
else:
raise Exception("The Exercise could not be imported!\r\nOnly support for the following namespaces: " +
Expand Down
4 changes: 1 addition & 3 deletions src/proforma/task_v0_94.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
# functions for importing ProFormA tasks version 0.9.4 into Praktomat database.
# Version 0.9.4 is depricated, do not use anymore!!

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.core.files import File
from django.views.decorators.csrf import csrf_exempt

from datetime import datetime
from lxml import objectify
Expand All @@ -38,7 +36,7 @@
from solutions.models import Solution, SolutionFile
from checker.checker import CreateFileChecker, CheckStyleChecker, JUnitChecker, AnonymityChecker, \
DejaGnu, TextNotChecker, PythonChecker, RemoteSQLChecker, TextChecker, SetlXChecker
from checker.builder import JavaBuilder
from checker.compiler import JavaBuilder

from . import task

Expand Down
3 changes: 0 additions & 3 deletions src/proforma/task_v1_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
# TASK VERSION 1.0.1 IS NO LONGER SUPPORTED


from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.core.files import File

Expand All @@ -33,14 +32,12 @@
import re
import tempfile
import logging
from os.path import dirname

from tasks.models import Task
from accounts.models import User
from solutions.models import Solution, SolutionFile
from checker.checker import CreateFileChecker, CheckStyleChecker, JUnitChecker, AnonymityChecker, \
PythonChecker, SetlXChecker
#from checker.checker import TextNotChecker, TextChecker, DejaGnu
from checker.compiler import JavaBuilder, CBuilder


Expand Down
65 changes: 33 additions & 32 deletions src/proforma/task_v2_00.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,11 @@
import os
import tempfile
from datetime import datetime
from operator import getitem

import xmlschema
#from django.views.decorators.csrf import csrf_exempt

from django.core.files import File
#from lxml import objectify


#from accounts.models import User
from checker.checker import PythonChecker, SetlXChecker
from checker.checker import CheckStyleChecker, JUnitChecker, \
CreateFileChecker
Expand All @@ -44,12 +39,13 @@
from django.conf import settings

import logging
from functools import reduce


logger = logging.getLogger(__name__)
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
PARENT_BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
XSD_V_2_PATH = "xsd/proforma_v2.0.xsd"
XSD_V_2_PATH = "proforma/xsd/proforma_v2.0.xsd"
XSD_V_2_01_PATH = "proforma/xsd/proforma_2.0.1_rc.xsd"
SYSUSER = "sys_prod"

CACHE_TASKS = True
Expand Down Expand Up @@ -103,10 +99,6 @@ def _getTask(self):
return self._task
object = property(_getTask)

def _getitem_from_dict(self, dataDict, mapList):
"""Iterate nested dictionary"""
return reduce(getitem, mapList, dataDict)

def delete(self):
self._task.delete()
self._task = None
Expand Down Expand Up @@ -140,13 +132,13 @@ def _read_basic_attributes(self, xml_dict):
def _read_submission_restriction(self, xml_dict):
# todo add file restrictions

path = ['submission-restrictions']
max_size = None
restriction = self._getitem_from_dict(xml_dict, path)
restriction = xml_dict.get('p:submission-restrictions')

try:
max_size = restriction.get("@max-size")
except AttributeError:
logger.error('could not find max-size, set to default')
# no max size given => use default (1MB)
max_size = 1000000

Expand Down Expand Up @@ -230,22 +222,21 @@ def save(self):


class Task_2_00:
_format_namespace = "urn:proforma:v2.0"
_ns = {"p": _format_namespace}

# constructor
def __init__(self, task_xml, xml_obj, hash, dict_zip_files=None):
def __init__(self, task_xml, xml_obj, hash, dict_zip_files, format_namespace):
self._task_xml = task_xml
self._xml_obj = xml_obj
self._hash = hash
self._dict_zip_files = dict_zip_files
self._praktomat_task = None
self._val_order = 1
self._praktomat_files = None
self._format_namespace = format_namespace
self._ns = {"p": self._format_namespace}

# read all files from task and put them into a dictionary
def _create_praktomat_files(self, xml_obj, external_file_dict=None, ):
namespace = Task_2_00._ns
namespace = self._ns

orphain_files = dict()

Expand All @@ -265,12 +256,14 @@ def _create_praktomat_files(self, xml_obj, external_file_dict=None, ):
orphain_files[k.attrib.get("id")] = my_temp
elif k.xpath("p:attached-bin-file", namespaces=namespace):
filename = k['attached-bin-file'].text
if external_file_dict is None:
raise Exception('no files in zip found')
logger.debug('attached task file: ' + k.attrib.get("id") + ' => ' + filename)
orphain_files[k.attrib.get("id")] = external_file_dict[filename]
elif k.xpath("p:attached-txt-file", namespaces=namespace):
filename = k['attached-txt-file'].text
logger.debug('attached task file: ' + k.attrib.get("id") + ' => ' + filename)
orphain_files[k.attrib.get("id")] = external_file_dict[filename]
else:
raise Exception('unsupported file type in task.xml (embedded-bin-file or attached-txt-file)')
raise task.TaskXmlException('embedded-bin-file is not supported')

# List with all files that are referenced by tests
list_of_test_files = xml_obj.xpath("/p:task/p:tests/p:test/p:test-configuration/"
Expand All @@ -297,13 +290,13 @@ def _create_java_compilertest(self, xmlTest):
_file_pattern=r"^.*\.[jJ][aA][vV][aA]$",
_main_required=False
)
x = Praktomat_Test_2_00(inst, Task_2_00._ns)
x = Praktomat_Test_2_00(inst, self._ns)
x.set_test_base_parameters(xmlTest)
x.save()


def _create_java_unit_test(self, xmlTest):
checker_ns = Task_2_00._ns.copy()
checker_ns = self._ns.copy()
checker_ns['unit_new'] = 'urn:proforma:tests:unittest:v1.1'
checker_ns['unit'] = 'urn:proforma:tests:unittest:v1'

Expand Down Expand Up @@ -339,13 +332,13 @@ def _create_java_unit_test(self, xmlTest):
# todo create: something like TaskException class
raise Exception("Junit-Version is not supported: " + str(junit_version))

x = Praktomat_Test_2_00(inst, Task_2_00._ns)
x = Praktomat_Test_2_00(inst, self._ns)
x.set_test_base_parameters(xmlTest)
self._val_order = x.add_files_to_test(xmlTest, self. _praktomat_files, self._val_order, None)
x.save()

def _create_java_checkstyle_test(self, xmlTest):
checker_ns = Task_2_00._ns.copy()
checker_ns = self._ns.copy()
checker_ns['check'] = 'urn:proforma:tests:java-checkstyle:v1.1'

inst = CheckStyleChecker.CheckStyleChecker.objects.create(task=self._praktomat_task.object, order=self._val_order)
Expand All @@ -372,7 +365,7 @@ def _create_java_checkstyle_test(self, xmlTest):
"check:java-checkstyle/"
"check:max-checkstyle-warnings", namespaces=checker_ns)[0]

x = Praktomat_Test_2_00(inst, Task_2_00._ns)
x = Praktomat_Test_2_00(inst, self._ns)
x.set_test_base_parameters(xmlTest)
def set_mainfile(inst, value):
inst.configuration = value
Expand All @@ -383,7 +376,7 @@ def set_mainfile(inst, value):

def _create_setlx_test(self, xmlTest):
inst = SetlXChecker.SetlXChecker.objects.create(task=self._praktomat_task.object, order=self._val_order)
x = Praktomat_Test_2_00(inst, Task_2_00._ns)
x = Praktomat_Test_2_00(inst, self._ns)
x.set_test_base_parameters(xmlTest)
def set_mainfile(inst, value):
inst.testFile = value
Expand All @@ -393,20 +386,26 @@ def set_mainfile(inst, value):

def _create_python_test(self, xmlTest):
inst = PythonChecker.PythonChecker.objects.create(task=self._praktomat_task.object, order=self._val_order)
x = Praktomat_Test_2_00(inst, Task_2_00._ns)
x = Praktomat_Test_2_00(inst, self._ns)
x.set_test_base_parameters(xmlTest)
def set_mainfile(inst, value):
inst.doctest = value
self._val_order = x.add_files_to_test(xmlTest, self. _praktomat_files, self._val_order, firstHandler=set_mainfile)
x.save()

def get_xsd_path(self):
if self._format_namespace == 'urn:proforma:v2.0':
return XSD_V_2_PATH
if self._format_namespace == 'urn:proforma:v2.0.1':
return XSD_V_2_01_PATH
raise Exception('ProForma XSD not found for namespace ' + self._format_namespace)

def import_task(self):

task_in_xml = self._xml_obj.xpath("/p:task", namespaces=Task_2_00._ns)
task_in_xml = self._xml_obj.xpath("/p:task", namespaces=self._ns)
task_uuid = task_in_xml[0].attrib.get("uuid")
logger.debug('uuid is ' + task_uuid)
task_title = self._xml_obj.xpath("/p:task/p:title", namespaces=Task_2_00._ns)[0]
task_title = self._xml_obj.xpath("/p:task/p:title", namespaces=self._ns)[0]
logger.debug('title is "' + task_title + '"')

# check if task is already in database
Expand All @@ -417,7 +416,7 @@ def import_task(self):

# no need to actually validate xml against xsd
# (it is only time consuming)
schema = xmlschema.XMLSchema(os.path.join(PARENT_BASE_DIR, XSD_V_2_PATH))
schema = xmlschema.XMLSchema(os.path.join(PARENT_BASE_DIR, self.get_xsd_path()))
# todo: remove because it is very expensive (bom, about 350ms)
# logger.debug('task_xml = ' + str(task_xml))
t = tempfile.NamedTemporaryFile(delete=True)
Expand All @@ -426,6 +425,8 @@ def import_task(self):
t.seek(0)

xml_dict = schema.to_dict(t)
if xml_dict == None:
raise Exception('cannot create dictionary from task')

# xml_dict = validate_xml(xml=task_xml)

Expand All @@ -440,7 +441,7 @@ def import_task(self):
self._create_praktomat_files(xml_obj=self._xml_obj, external_file_dict=self._dict_zip_files)
# create test objects
for xmlTest in self._xml_obj.tests.iterchildren():
testtype = xmlTest.xpath("p:test-type", namespaces=Task_2_00._ns)[0].text
testtype = xmlTest.xpath("p:test-type", namespaces=self._ns)[0].text
if testtype == "java-compilation": # todo check compilation_xsd
logger.debug('** create_java_compilertest')
self._create_java_compilertest(xmlTest)
Expand Down
File renamed without changes.
Loading

0 comments on commit eced0fe

Please sign in to comment.