Example #1
0
 def test_languages(self):
     # All languages are described.
     for lang in LANGUAGES:
         assert lang in LANGUAGE_NAMES
         assert lang in LANGUAGE_TO_SOURCE_EXT_MAP
         # This isn't true, as not all languages need headers.
         # assert lang in LANGUAGE_TO_HEADER_EXT_MAP
     # All default languages are languages.
     for lang in DEFAULT_LANGUAGES:
         assert lang in LANGUAGES
     # All keys are languages.
     for lang in LANGUAGE_TO_SOURCE_EXT_MAP.iterkeys():
         assert lang in LANGUAGES
     for lang in LANGUAGE_TO_HEADER_EXT_MAP.iterkeys():
         assert lang in LANGUAGES
     # All values are languages.
     for lang in SOURCE_EXT_TO_LANGUAGE_MAP.itervalues():
         assert lang in LANGUAGES
     # Extensions are sane.
     for lang in LANGUAGES:
         assert LANGUAGE_TO_SOURCE_EXT_MAP[lang][0] == "."
         assert lang == \
             SOURCE_EXT_TO_LANGUAGE_MAP[LANGUAGE_TO_SOURCE_EXT_MAP[lang]]
     for ext in SOURCE_EXT_TO_LANGUAGE_MAP:
         assert ext[0] == "."
Example #2
0
    def submission_handler(self):
        if local.data['action'] == 'list':
            task = local.session.query(Task)\
                .filter(Task.name == local.data['task_name']).first()
            if task is None:
                return 'Not found'
            if local.user is None:
                return 'Unauthorized'
            subs = local.session.query(Submission)\
                .filter(Submission.user_id == local.user.id)\
                .filter(Submission.task_id == task.id)\
                .order_by(desc(Submission.timestamp)).all()
            submissions = []
            for s in subs:
                submission = dict()
                submission['id'] = s.id
                submission['task_id'] = s.task_id
                submission['timestamp'] = make_timestamp(s.timestamp)
                submission['files'] = []
                for name, f in s.files.iteritems():
                    fi = dict()
                    if s.language is None:
                        fi['name'] = name
                    else:
                        fi['name'] = name.replace('%l', s.language)
                    fi['digest'] = f.digest
                    submission['files'].append(fi)
                result = s.get_result()
                for i in ['compilation_outcome', 'evaluation_outcome']:
                    submission[i] = getattr(result, i, None)
                if result is not None and result.score is not None:
                    submission['score'] = round(result.score, 2)
                submissions.append(submission)
            local.resp['submissions'] = submissions
        elif local.data['action'] == 'details':
            s = local.session.query(Submission)\
                .filter(Submission.id == local.data['id']).first()
            if s is None:
                return 'Not found'
            if local.user is None or s.user_id != local.user.id:
                return 'Unauthorized'
            submission = dict()
            submission['id'] = s.id
            submission['task_id'] = s.task_id
            submission['timestamp'] = make_timestamp(s.timestamp)
            submission['language'] = s.language
            submission['files'] = []
            for name, f in s.files.iteritems():
                fi = dict()
                if s.language is None:
                    fi['name'] = name
                else:
                    fi['name'] = name.replace('%l', s.language)
                fi['digest'] = f.digest
                submission['files'].append(fi)
            result = s.get_result()
            for i in ['compilation_outcome', 'evaluation_outcome',
                      'compilation_stdout', 'compilation_stderr',
                      'compilation_time', 'compilation_memory']:
                submission[i] = getattr(result, i, None)
            if result is not None and result.score is not None:
                submission['score'] = round(result.score, 2)
            if result is not None and result.score_details is not None:
                tmp = json.loads(result.score_details)
                if len(tmp) > 0 and 'text' in tmp[0]:
                    subt = dict()
                    subt['testcases'] = tmp
                    subt['score'] = submission['score']
                    subt['max_score'] = 100
                    submission['score_details'] = [subt]
                else:
                    submission['score_details'] = tmp
                for subtask in submission['score_details']:
                    for testcase in subtask['testcases']:
                        data = json.loads(testcase['text'])
                        testcase['text'] = data[0] % tuple(data[1:])
            else:
                submission['score_details'] = None
            local.resp = submission
        elif local.data['action'] == 'new':
            if local.user is None:
                return 'Unauthorized'
            lastsub = local.session.query(Submission)\
                .filter(Submission.user_id == local.user.id)\
                .order_by(desc(Submission.timestamp)).first()
            if lastsub is not None and \
               make_datetime() - lastsub.timestamp < timedelta(seconds=20):
                return 'submission.short_interval'

            try:
                task = local.session.query(Task)\
                    .filter(Task.name == local.data['task_name'])\
                    .filter(Task.access_level >= local.access_level).first()
            except KeyError:
                return 'Not found'

            def decode_file(f):
                f['data'] = f['data'].split(',')[-1]
                f['body'] = b64decode(f['data'])
                del f['data']
                return f

            if len(local.data['files']) == 1 and \
               'submission' in local.data['files']:
                archive_data = decode_file(local.data['files']['submission'])
                del local.data['files']['submission']
                temp_archive_file, temp_archive_filename = \
                    tempfile.mkstemp(dir=config.temp_dir)
                with os.fdopen(temp_archive_file, "w") as temp_archive_file:
                    temp_archive_file.write(archive_data['body'])
                archive_contents = extract_archive(temp_archive_filename,
                                                   archive_data['filename'])
                if archive_contents is None:
                    return 'Invalid archive!'
                files_sent = dict([(i['filename'], i)
                                   for i in archive_contents])
            else:
                files_sent = \
                    dict([(k, decode_file(v))
                          for k, v in local.data['files'].iteritems()])

            # TODO: implement partial submissions (?)

            # Detect language
            files = []
            sub_lang = None
            for sfe in task.submission_format:
                f = files_sent.get(sfe.filename)
                if f is None:
                    return 'Some files are missing!'
                if len(f['body']) > config.max_submission_length:
                    return 'The files you sent are too big!'
                f['name'] = sfe.filename
                files.append(f)
                if sfe.filename.endswith('.%l'):
                    language = None
                    for ext, l in SOURCE_EXT_TO_LANGUAGE_MAP.iteritems():
                        if f['filename'].endswith(ext):
                            language = l
                    if language is None:
                        return 'The language of the files you sent is not ' + \
                               'recognized!'
                    elif sub_lang is not None and sub_lang != language:
                        return 'The files you sent are in different languages!'
                    else:
                        sub_lang = language

            # Add the submission
            timestamp = make_datetime()
            submission = Submission(timestamp,
                                    sub_lang,
                                    user=local.user,
                                    task=task)
            for f in files:
                digest = self.file_cacher.put_file_content(
                    f['body'],
                    'Submission file %s sent by %s at %d.' % (
                        f['name'], local.user.username,
                        make_timestamp(timestamp)))
                local.session.add(File(f['name'],
                                       digest,
                                       submission=submission))
            local.session.add(submission)
            local.session.commit()

            # Notify ES
            self.evaluation_service.new_submission(
                submission_id=submission.id
            )

            # Answer with submission data
            local.resp['id'] = submission.id
            local.resp['task_id'] = submission.task_id
            local.resp['timestamp'] = make_timestamp(submission.timestamp)
            local.resp['compilation_outcome'] = None
            local.resp['evaluation_outcome'] = None
            local.resp['score'] = None
            local.resp['files'] = []
            for name, f in submission.files.iteritems():
                fi = dict()
                if submission.language is None:
                    fi['name'] = name
                else:
                    fi['name'] = name.replace('%l', submission.language)
                fi['digest'] = f.digest
                local.resp['files'].append(fi)
        else:
            return 'Bad request'
Example #3
0
    def submission_handler(self):
        if local.data['action'] == 'list':
            task = local.session.query(Task)\
                .filter(Task.name == local.data['task_name']).first()
            if task is None:
                return 'Not found'
            if local.user is None:
                return 'Unauthorized'
            subs = local.session.query(Submission)\
                .filter(Submission.participation_id == local.participation.id)\
                .filter(Submission.task_id == task.id)\
                .order_by(desc(Submission.timestamp)).all()
            submissions = []
            for s in subs:
                submission = dict()
                submission['id'] = s.id
                submission['task_id'] = s.task_id
                submission['timestamp'] = make_timestamp(s.timestamp)
                submission['files'] = []
                for name, f in s.files.iteritems():
                    fi = dict()
                    if s.language is None:
                        fi['name'] = name
                    else:
                        fi['name'] = name.replace('%l', s.language)
                    fi['digest'] = f.digest
                    submission['files'].append(fi)
                result = s.get_result()
                for i in ['compilation_outcome', 'evaluation_outcome']:
                    submission[i] = getattr(result, i, None)
                if result is not None and result.score is not None:
                    submission['score'] = round(result.score, 2)
                submissions.append(submission)
            local.resp['submissions'] = submissions
        elif local.data['action'] == 'details':
            s = local.session.query(Submission)\
                .filter(Submission.id == local.data['id']).first()
            if s is None:
                return 'Not found'
            if local.user is None or s.participation_id != local.participation.id:
                return 'Unauthorized'
            submission = dict()
            submission['id'] = s.id
            submission['task_id'] = s.task_id
            submission['timestamp'] = make_timestamp(s.timestamp)
            submission['language'] = s.language
            submission['files'] = []
            for name, f in s.files.iteritems():
                fi = dict()
                if s.language is None:
                    fi['name'] = name
                else:
                    fi['name'] = name.replace('%l', s.language)
                fi['digest'] = f.digest
                submission['files'].append(fi)
            result = s.get_result()
            for i in ['compilation_outcome', 'evaluation_outcome',
                      'compilation_stdout', 'compilation_stderr',
                      'compilation_time', 'compilation_memory']:
                submission[i] = getattr(result, i, None)
            if result is not None and result.score is not None:
                submission['score'] = round(result.score, 2)
            if result is not None and result.score_details is not None:
                tmp = json.loads(result.score_details)
                if len(tmp) > 0 and 'text' in tmp[0]:
                    subt = dict()
                    subt['testcases'] = tmp
                    subt['score'] = submission['score']
                    subt['max_score'] = 100
                    submission['score_details'] = [subt]
                else:
                    submission['score_details'] = tmp
                for subtask in submission['score_details']:
                    for testcase in subtask['testcases']:
                        data = json.loads(testcase['text'])
                        testcase['text'] = data[0] % tuple(data[1:])
            else:
                submission['score_details'] = None
            local.resp = submission
        elif local.data['action'] == 'new':
            if local.user is None:
                return 'Unauthorized'
            lastsub = local.session.query(Submission)\
                .filter(Submission.participation_id == local.participation.id)\
                .order_by(desc(Submission.timestamp)).first()
            if lastsub is not None and \
               make_datetime() - lastsub.timestamp < timedelta(seconds=20):
                return 'Too frequent submissions!'

            try:
                task = local.session.query(Task)\
                    .join(SocialTask)\
                    .filter(Task.name == local.data['task_name'])\
                    .filter(SocialTask.access_level >= local.access_level).first()
            except KeyError:
                return 'Not found'

            def decode_file(f):
                f['data'] = f['data'].split(',')[-1]
                f['body'] = b64decode(f['data'])
                del f['data']
                return f

            if len(local.data['files']) == 1 and \
               'submission' in local.data['files']:
                archive_data = decode_file(local.data['files']['submission'])
                del local.data['files']['submission']

                # Create the archive.
                archive = Archive.from_raw_data(archive_data["body"])

                if archive is None:
                    return 'Invalid archive!'

                # Extract the archive.
                unpacked_dir = archive.unpack()
                for name in archive.namelist():
                    filename = os.path.basename(name)
                    body = open(os.path.join(unpacked_dir, filename), "r").read()
                    local.data['files'][filename] = {
                        'filename': filename,
                        'body': body
                    }

                files_sent = local.data['files']

                archive.cleanup()
            else:
                files_sent = \
                    dict([(k, decode_file(v))
                          for k, v in local.data['files'].iteritems()])

            # TODO: implement partial submissions (?)

            # Detect language
            files = []
            sub_lang = None
            for sfe in task.submission_format:
                f = files_sent.get(sfe.filename)
                if f is None:
                    return 'Some files are missing!'
                if len(f['body']) > config.get("core", "max_submission_length"):
                    return 'The files you sent are too big!'
                f['name'] = sfe.filename
                files.append(f)
                if sfe.filename.endswith('.%l'):
                    language = None
                    for ext, l in SOURCE_EXT_TO_LANGUAGE_MAP.iteritems():
                        if f['filename'].endswith(ext):
                            language = l
                    if language is None:
                        return 'The language of the files you sent is not ' + \
                               'recognized!'
                    elif sub_lang is not None and sub_lang != language:
                        return 'The files you sent are in different languages!'
                    else:
                        sub_lang = language

            # Add the submission
            timestamp = make_datetime()
            submission = Submission(timestamp,
                                    sub_lang,
                                    participation=local.participation,
                                    task=task)
            for f in files:
                digest = self.file_cacher.put_file_content(
                    f['body'],
                    'Submission file %s sent by %s at %d.' % (
                        f['name'], local.user.username,
                        make_timestamp(timestamp)))
                local.session.add(File(f['name'],
                                       digest,
                                       submission=submission))
            local.session.add(submission)
            local.session.commit()

            # Notify ES
            self.evaluation_service.new_submission(
                submission_id=submission.id
            )

            # Answer with submission data
            local.resp['id'] = submission.id
            local.resp['task_id'] = submission.task_id
            local.resp['timestamp'] = make_timestamp(submission.timestamp)
            local.resp['compilation_outcome'] = None
            local.resp['evaluation_outcome'] = None
            local.resp['score'] = None
            local.resp['files'] = []
            for name, f in submission.files.iteritems():
                fi = dict()
                if submission.language is None:
                    fi['name'] = name
                else:
                    fi['name'] = name.replace('%l', submission.language)
                fi['digest'] = f.digest
                local.resp['files'].append(fi)
        else:
            return 'Bad request'
Example #4
0
import functools
import shutil
import tempfile
import yaml
import logging

from cms import utf8_decoder, SOURCE_EXT_TO_LANGUAGE_MAP, \
    LANGUAGE_TO_SOURCE_EXT_MAP, LANGUAGE_TO_HEADER_EXT_MAP, LANG_PASCAL
from cms.grading import get_compilation_commands
from cmstaskenv.Test import test_testcases, clean_test_env
from cmscommon.terminal import move_cursor, add_color_to_string, \
    colors, directions

SOL_DIRNAME = 'sol'
SOL_FILENAME = 'soluzione'
SOL_EXTS = SOURCE_EXT_TO_LANGUAGE_MAP.keys()
CHECK_DIRNAME = 'cor'
CHECK_EXTS = SOL_EXTS
TEXT_DIRNAME = 'testo'
TEXT_TEX = 'testo.tex'
TEXT_PDF = 'testo.pdf'
TEXT_AUX = 'testo.aux'
TEXT_LOG = 'testo.log'
INPUT0_TXT = 'input0.txt'
OUTPUT0_TXT = 'output0.txt'
GEN_DIRNAME = 'gen'
GEN_GEN = 'GEN'
GEN_BASENAME = 'generatore'
GEN_EXTS = ['.py', '.sh', '.cpp', '.c', '.pas']
VALIDATOR_BASENAME = 'valida'
GRAD_BASENAME = 'grader'
Example #5
0
    def submission_handler(self):
        if local.data["action"] == "list":
            task = local.session.query(Task).filter(Task.name == local.data["task_name"]).first()
            if task is None:
                return "Not found"
            if local.user is None:
                return "Unauthorized"
            subs = (
                local.session.query(Submission)
                .filter(Submission.user_id == local.user.id)
                .filter(Submission.task_id == task.id)
                .order_by(desc(Submission.timestamp))
                .all()
            )
            submissions = []
            for s in subs:
                submission = dict()
                submission["id"] = s.id
                submission["task_id"] = s.task_id
                submission["timestamp"] = make_timestamp(s.timestamp)
                submission["files"] = []
                for name, f in s.files.iteritems():
                    fi = dict()
                    if s.language is None:
                        fi["name"] = name
                    else:
                        fi["name"] = name.replace("%l", s.language)
                    fi["digest"] = f.digest
                    submission["files"].append(fi)
                result = s.get_result()
                for i in ["compilation_outcome", "evaluation_outcome"]:
                    submission[i] = getattr(result, i, None)
                if result is not None and result.score is not None:
                    submission["score"] = round(result.score, 2)
                submissions.append(submission)
            local.resp["submissions"] = submissions
        elif local.data["action"] == "details":
            s = local.session.query(Submission).filter(Submission.id == local.data["id"]).first()
            if s is None:
                return "Not found"
            if local.user is None or s.user_id != local.user.id:
                return "Unauthorized"
            submission = dict()
            submission["id"] = s.id
            submission["task_id"] = s.task_id
            submission["timestamp"] = make_timestamp(s.timestamp)
            submission["language"] = s.language
            submission["files"] = []
            for name, f in s.files.iteritems():
                fi = dict()
                if s.language is None:
                    fi["name"] = name
                else:
                    fi["name"] = name.replace("%l", s.language)
                fi["digest"] = f.digest
                submission["files"].append(fi)
            result = s.get_result()
            for i in [
                "compilation_outcome",
                "evaluation_outcome",
                "compilation_stdout",
                "compilation_stderr",
                "compilation_time",
                "compilation_memory",
            ]:
                submission[i] = getattr(result, i, None)
            if result is not None and result.score is not None:
                submission["score"] = round(result.score, 2)
            if result is not None and result.score_details is not None:
                tmp = json.loads(result.score_details)
                if len(tmp) > 0 and "text" in tmp[0]:
                    subt = dict()
                    subt["testcases"] = tmp
                    subt["score"] = submission["score"]
                    subt["max_score"] = 100
                    submission["score_details"] = [subt]
                else:
                    submission["score_details"] = tmp
                for subtask in submission["score_details"]:
                    for testcase in subtask["testcases"]:
                        data = json.loads(testcase["text"])
                        testcase["text"] = data[0] % tuple(data[1:])
            else:
                submission["score_details"] = None
            local.resp = submission
        elif local.data["action"] == "new":
            if local.user is None:
                return "Unauthorized"
            lastsub = (
                local.session.query(Submission)
                .filter(Submission.user_id == local.user.id)
                .order_by(desc(Submission.timestamp))
                .first()
            )
            if lastsub is not None and make_datetime() - lastsub.timestamp < timedelta(seconds=20):
                return "Too frequent submissions!"

            try:
                task = (
                    local.session.query(Task)
                    .filter(Task.name == local.data["task_name"])
                    .filter(Task.access_level >= local.access_level)
                    .first()
                )
            except KeyError:
                return "Not found"

            def decode_file(f):
                f["data"] = f["data"].split(",")[-1]
                f["body"] = b64decode(f["data"])
                del f["data"]
                return f

            if len(local.data["files"]) == 1 and "submission" in local.data["files"]:
                archive_data = decode_file(local.data["files"]["submission"])
                del local.data["files"]["submission"]

                # Create the archive.
                archive = Archive.from_raw_data(archive_data["body"])

                if archive is None:
                    return "Invalid archive!"

                # Extract the archive.
                unpacked_dir = archive.unpack()
                for name in archive.namelist():
                    filename = os.path.basename(name)
                    body = open(os.path.join(unpacked_dir, filename), "r").read()
                    self.request.files[filename] = [{"filename": filename, "body": body}]

                files_sent = dict([(i["filename"], i) for i in archive_contents])

                archive.cleanup()
            else:
                files_sent = dict([(k, decode_file(v)) for k, v in local.data["files"].iteritems()])

            # TODO: implement partial submissions (?)

            # Detect language
            files = []
            sub_lang = None
            for sfe in task.submission_format:
                f = files_sent.get(sfe.filename)
                if f is None:
                    return "Some files are missing!"
                if len(f["body"]) > config.max_submission_length:
                    return "The files you sent are too big!"
                f["name"] = sfe.filename
                files.append(f)
                if sfe.filename.endswith(".%l"):
                    language = None
                    for ext, l in SOURCE_EXT_TO_LANGUAGE_MAP.iteritems():
                        if f["filename"].endswith(ext):
                            language = l
                    if language is None:
                        return "The language of the files you sent is not " + "recognized!"
                    elif sub_lang is not None and sub_lang != language:
                        return "The files you sent are in different languages!"
                    else:
                        sub_lang = language

            # Add the submission
            timestamp = make_datetime()
            submission = Submission(timestamp, sub_lang, user=local.user, task=task)
            for f in files:
                digest = self.file_cacher.put_file_content(
                    f["body"],
                    "Submission file %s sent by %s at %d."
                    % (f["name"], local.user.username, make_timestamp(timestamp)),
                )
                local.session.add(File(f["name"], digest, submission=submission))
            local.session.add(submission)
            local.session.commit()

            # Notify ES
            self.evaluation_service.new_submission(submission_id=submission.id)

            # Answer with submission data
            local.resp["id"] = submission.id
            local.resp["task_id"] = submission.task_id
            local.resp["timestamp"] = make_timestamp(submission.timestamp)
            local.resp["compilation_outcome"] = None
            local.resp["evaluation_outcome"] = None
            local.resp["score"] = None
            local.resp["files"] = []
            for name, f in submission.files.iteritems():
                fi = dict()
                if submission.language is None:
                    fi["name"] = name
                else:
                    fi["name"] = name.replace("%l", submission.language)
                fi["digest"] = f.digest
                local.resp["files"].append(fi)
        else:
            return "Bad request"
Example #6
0
import subprocess
import copy
import functools
import shutil
import tempfile
import yaml
import logging

from cms import utf8_decoder, SOURCE_EXT_TO_LANGUAGE_MAP, LANGUAGE_TO_SOURCE_EXT_MAP, LANGUAGE_TO_HEADER_EXT_MAP
from cms.grading import get_compilation_commands
from cmstaskenv.Test import test_testcases, clean_test_env
from cmscommon.terminal import move_cursor, add_color_to_string, colors, directions

SOL_DIRNAME = "sol"
SOL_FILENAME = "soluzione"
SOL_EXTS = SOURCE_EXT_TO_LANGUAGE_MAP.keys()
CHECK_DIRNAME = "cor"
CHECK_EXTS = SOL_EXTS
TEXT_DIRNAME = "testo"
TEXT_TEX = "testo.tex"
TEXT_PDF = "testo.pdf"
TEXT_AUX = "testo.aux"
TEXT_LOG = "testo.log"
INPUT0_TXT = "input0.txt"
OUTPUT0_TXT = "output0.txt"
GEN_DIRNAME = "gen"
GEN_GEN = "GEN"
GEN_BASENAME = "generatore"
GEN_EXTS = [".py", ".sh", ".cpp", ".c", ".pas"]
VALIDATOR_BASENAME = "valida"
GRAD_BASENAME = "grader"