def patch_submission(submission): """ Given a submission from a SQL query with some JOIN create a dict by splitting the keys using _ :param submission: A dict with the submission :return: A dict with some properties nested """ result = {} for k, v in submission.items(): if "_" in k: a, b = k.split("_") if a not in result: result[a] = {} result[a][b] = v else: result[k] = v feedback = json.loads(result["output"]["result"].decode()) result["feedback"] = feedback["feedback"] temp = InfoHandler.patch_output(result["output"]) del result["output"] result = BaseHandler.format_dates(result) result["output"] = temp return result
def generate_input(self, task, user): """ POST /generate_input """ token = user["token"] if Database.get_user_task(token, task["name"])["current_attempt"]: self.raise_exc(Forbidden, "FORBIDDEN", "You already have a ready input!") attempt = Database.get_next_attempt(token, task["name"]) id, path = ContestManager.get_input(task["name"], attempt) size = StorageManager.get_file_size(path) Database.begin() try: Database.add_input(id, token, task["name"], attempt, path, size, autocommit=False) Database.set_user_attempt(token, task["name"], attempt, autocommit=False) Database.commit() except: Database.rollback() raise Logger.info( "CONTEST", "Generated input %s for user %s on task %s" % (id, token, task["name"])) return BaseHandler.format_dates(Database.get_input(id=id))
def upload_source(self, input, file): """ POST /upload_source """ alerts = [] if get_exeflags(file["content"]): alerts.append({ "severity": "warning", "message": "You have submitted an executable! Please send the " "source code." }) Logger.info("UPLOAD", "User %s has uploaded an executable" % input["token"]) if not alerts: alerts.append({ "severity": "success", "message": "Source file uploaded correctly." }) source_id = Database.gen_id() try: path = StorageManager.new_source_file(source_id, file["name"]) except ValueError: BaseHandler.raise_exc(BadRequest, "INVALID_FILENAME", "The provided file has an invalid name") StorageManager.save_file(path, file["content"]) file_size = StorageManager.get_file_size(path) Database.add_source(source_id, input["id"], path, file_size) Logger.info("UPLOAD", "User %s has uploaded the source %s" % ( input["token"], source_id)) output = BaseHandler.format_dates(Database.get_source(source_id)) output["validation"] = {"alerts": alerts} return output
def start(self): """ POST /admin/start """ if Database.get_meta("start_time", default=None, type=int) is not None: BaseHandler.raise_exc(Forbidden, "FORBIDDEN", "Contest has already been started!") start_time = int(time.time()) Database.set_meta("start_time", start_time) Logger.info("CONTEST", "Contest started") return BaseHandler.format_dates({"start_time": start_time}, fields=["start_time"])
def status(self): """ POST /admin/status """ start_time = Database.get_meta('start_time', type=int) extra_time = Database.get_meta('extra_time', type=int, default=0) end_time = BaseHandler.get_end_time(0) return BaseHandler.format_dates( { "start_time": start_time, "extra_time": extra_time, "end_time": end_time, "loaded": ContestManager.has_contest }, fields=["start_time", "end_time"])
def get_user(self, user): """ GET /user/<token> """ token = user["token"] user["contest"] = self.get_contest() if not user["contest"]["has_started"]: del user["extra_time"] return user end_time = InfoHandler.get_end_time(user["extra_time"]) if user["contest_start_delay"] is not None: end_time = min( end_time, InfoHandler.get_window_end_time(user["extra_time"], user["contest_start_delay"]), ) user["end_time"] = end_time del user["extra_time"] user["tasks"] = {} tasks = Database.get_user_task(token) for task in tasks: task_name = task["task"] if task["current_attempt"] is not None: current_input = Database.get_input( token=token, task=task_name, attempt=task["current_attempt"]) else: current_input = None user["tasks"][task_name] = { "name": task_name, "score": task["score"], "current_input": current_input, } user["total_score"] = sum(task["score"] for task in tasks) return BaseHandler.format_dates(user, fields=["end_time"])
def patch_output(output): """ Given an output remove the private fields :param output: A dict from the outputs database table :return: The formatted and sanitized dict """ result = { "id": output["id"], "date": output["date"], "path": output["path"], "size": output["size"], "validation": json.loads(output["result"].decode())["validation"], } if "input" in output: result["input"] = output["input"] return BaseHandler.format_dates(result)
def log(self, start_date: str, end_date: str, level: str, category: str = None): """ POST /admin/log """ if level not in Logger.HUMAN_MESSAGES: self.raise_exc(BadRequest, "INVALID_PARAMETER", "The level provided is invalid") level = Logger.HUMAN_MESSAGES.index(level) try: start_date = dateutil.parser.parse(start_date).timestamp() end_date = dateutil.parser.parse(end_date).timestamp() except ValueError as e: BaseHandler.raise_exc(BadRequest, "INVALID_PARAMETER", str(e)) return BaseHandler.format_dates( {"items": Logger.get_logs(level, category, start_date, end_date)})
def start(self, start_time: str): """ POST /admin/start """ previous_start = Database.get_meta("start_time", type=int) now = int(time.time()) if previous_start and now > previous_start: BaseHandler.raise_exc(Forbidden, "FORBIDDEN", "Contest has already been started!") actual_start = None if start_time == "reset": Database.del_meta("start_time") return {"start_time": None} elif start_time == "now": actual_start = now else: actual_start = dateutil.parser.parse(start_time).timestamp() Database.set_meta("start_time", int(actual_start)) Logger.info("CONTEST", "Contest starts at " + str(actual_start)) return BaseHandler.format_dates({"start_time": actual_start}, fields=["start_time"])
def test_format_dates(self): dct = { "date": 12345678, "nondate": 12345678, "we": { "need": { "to": { "go": { "deeper": 1010101010 } } } } } formatted = BaseHandler.format_dates(dct, fields=["date", "deeper"]) self.assertEqual( datetime.datetime.fromtimestamp(12345678).isoformat(), formatted["date"]) self.assertEqual(12345678, formatted["nondate"]) self.assertEqual( datetime.datetime.fromtimestamp(1010101010).isoformat(), formatted["we"]["need"]["to"]["go"]["deeper"])
def get_source(self, source): """ GET /source/<source_id> """ return BaseHandler.format_dates(source)
def get_input(self, input): """ GET /input/<input_id> """ return BaseHandler.format_dates(input)
def user_list(self): """ POST /admin/user_list """ return BaseHandler.format_dates({"items": Database.get_users()}, fields=["first_date"])