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}
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}