Exemplo n.º 1
0
    def submit_output(self, to_group, output_file=None):
        user = request.identity['user']
        to_group = DBSession.query(Group).get(to_group)
        if not to_group:
            abort(404, "No such group")
        if to_group.competition_id != self.group.competition_id:
            abort(400, "Cannot submit to a group in another competition")
        if not hasattr(output_file, "file"):
            abort(400, "Must include file in submission")
        comp = self.group.competition
        existing = (DBSession.query(Output)
                             .filter(Output.group_id == self.group.id)
                             .filter(Output.input_id == to_group.input.id)
                             .filter(Output.active == True)
                             .one_or_none())
        if not (user.admin
                or comp.output_upload_open
                or (comp.resolution_open
                    and existing is not None
                    and not existing.use_ground_truth)):
            abort(403, "Forbidden to upload this output at this time")

        try:
            contents = output_file.file.read().decode("utf-8")
        except UnicodeDecodeError:
            return {'status': 'error',
                    'msg': 'Output contains invalid characters.'}

        problem = problemlib.load_problem(comp)

        try:
            output = problem.parse_output(to_group.input.data.file,
                                          StringIO(contents))
        except problemlib.FileFormatError as e:
            return {
                "status": "error",
                "msg": f"Output has formatting errors: {e}",
            }

        new_contents = StringIO()
        output.write(new_contents)

        f = FileIntent(
            BytesIO(new_contents.getvalue().encode("utf-8")),
            'output_from_{}_to_{}.txt'.format(self.group.id, to_group.id),
            'application/octet-stream')
        try:
            output.verify()
        except problemlib.VerificationError:
            ground_truth = VerificationStatus.rejected
        except Exception:
            ground_truth = VerificationStatus.waiting
        else:
            ground_truth = VerificationStatus.accepted

        use_ground_truth = (
            not comp.verification_begins
            or datetime.datetime.now() >= comp.verification_begins
        )

        if existing:
            if comp.resolution_open:
                existing.active = False
            else:
                DBSession.delete(existing)

        db_output = Output(
            data=f,
            group=self.group,
            input=to_group.input,
            score=output.score,
            original=comp.output_upload_open,
            ground_truth=ground_truth,
            use_ground_truth=use_ground_truth,
        )
        DBSession.add(db_output)
        DBSession.flush()

        return {'status': 'success', 'url': db_output.data.url}
Exemplo n.º 2
0
    def submit_output(self, to_group, output_file=None):
        user = request.identity['user']
        to_group = DBSession.query(Group).get(to_group)
        if not to_group:
            abort(404, "No such group")
        if to_group.competition_id != self.group.competition_id:
            abort(400, "Cannot submit to a group in another competition")
        if not hasattr(output_file, "file"):
            abort(400, "Must include file in submission")
        comp = self.group.competition
        existing = (DBSession.query(Output).filter(
            Output.group_id == self.group.id).filter(
                Output.input_id == to_group.input.id).filter(
                    Output.active == True).one_or_none())
        if not (user.admin or comp.output_upload_open or
                (comp.resolution_open and existing is not None
                 and not existing.use_ground_truth)):
            abort(403, "Forbidden to upload this output at this time")

        try:
            contents = file_normalize(output_file.file.read())
        except UnicodeDecodeError:
            return {
                'status': 'error',
                'msg': 'Output contains invalid characters.'
            }

        if len(contents) > 1E6:
            return {'status': 'error', 'msg': 'Output exceeds maximum size.'}

        try:
            score, _, _ = contents.partition('\n')
            score = int(score)
        except ValueError:
            return {
                'status': 'error',
                'msg': 'First line must only contain an integer.'
            }

        f = FileIntent(
            BytesIO(contents.encode('utf-8')),
            'output_from_{}_to_{}.txt'.format(self.group.id, to_group.id),
            'application/octet-stream')
        if existing:
            if comp.resolution_open:
                existing.active = False
            else:
                DBSession.delete(existing)
        output = Output(data=f,
                        group=self.group,
                        input=to_group.input,
                        score=score,
                        original=comp.output_upload_open)

        verif_mod = self.group.competition.output_verifier.module
        try:
            verif_mod.verify(to_group.input.data.file, StringIO(contents))
        except verif_mod.VerificationError:
            output.ground_truth = VerificationStatus.rejected
        except Exception:
            output.ground_truth = VerificationStatus.waiting
        else:
            output.ground_truth = VerificationStatus.accepted

        if comp.resolution_open or not comp.verification_begins:
            output.use_ground_truth = True

        DBSession.add(output)
        DBSession.flush()

        return {'status': 'success', 'url': output.data.url}