def _participation_to_db(session, contest, new_p): """Add the new participation to the DB and attach it to the contest session (Session): session to use. contest (Contest): the contest in the DB. new_p (dict): dictionary with the participation data, including at least "username"; may contain "team", "hidden", "ip", "password". return (Participation): the participation in the DB. raise (ImportDataError): in case of one of these errors: - the user for this participation does not already exist in the DB; - the team for this participation does not already exist in the DB. """ user = session.query(User)\ .filter(User.username == new_p["username"]).first() if user is None: # FIXME: it would be nice to automatically try to import. raise ImportDataError("User \"%s\" not found in database. " "Use cmsImportUser to import it." % new_p["username"]) team = session.query(Team)\ .filter(Team.code == new_p.get("team")).first() if team is None and new_p.get("team") is not None: # FIXME: it would be nice to automatically try to import. raise ImportDataError("Team \"%s\" not found in database. " "Use cmsImportTeam to import it." % new_p.get("team")) # Check that the participation is not already defined. p = session.query(Participation)\ .filter(Participation.user_id == user.id)\ .filter(Participation.contest_id == contest.id)\ .first() # FIXME: detect if some details of the participation have been updated # and thus the existing participation needs to be changed. if p is not None: logger.warning( "Participation of user %s in this contest already " "exists, not updating it.", new_p["username"]) return p # Prepare new participation args = { "user": user, "contest": contest, } if "team" in new_p: args["team"] = team if "hidden" in new_p: args["hidden"] = new_p["hidden"] if "ip" in new_p and new_p["ip"] is not None: args["ip"] = [ipaddress.ip_network(new_p["ip"])] if "password" in new_p: args["password"] = new_p["password"] new_p = Participation(**args) session.add(new_p) return new_p
def _task_to_db(self, session, contest, new_task, task_has_changed): """Add the task to the DB Return the task, or raise in case of one of these errors: - if the task is not in the DB and user did not ask to update it; - if the task is already in the DB and attached to another contest. """ task = session.query(Task).filter(Task.name == new_task.name).first() if task is None: if contest is not None: logger.info("Attaching task to contest (id %s.)", self.contest_id) new_task.num = len(contest.tasks) new_task.contest = contest session.add(new_task) return new_task if not self.update: raise ImportDataError("Task \"%s\" already exists in database. " "Use --update to update it." % new_task.name) if contest is not None and task.contest_id != contest.id: raise ImportDataError( "Task \"%s\" already tied to another contest." % task.name) if task_has_changed: logger.info("Task \"%s\" data has changed, updating it.", task.name) update_task(task, new_task, get_statements=not self.no_statement) else: logger.info("Task \"%s\" data has not changed.", task.name) return task
def _contest_to_db(self, session, new_contest, contest_has_changed): """Add the new contest to the DB session (Session): session to use. new_contest (Contest): contest that has to end up in the DB. contest_has_changed (bool): whether the loader thinks new_contest has changed since the last time it was imported. return (Contest): the contest in the DB. raise (ImportDataError): if the contest already exists on the DB and the user did not ask to update any data. """ contest = session.query(Contest)\ .filter(Contest.name == new_contest.name).first() if contest is None: # Contest not present, we import it. logger.info("Creating contest on the database.") contest = new_contest # Creating a new main group contest.main_group = Group("main") contest.groups = [contest.main_group] session.add(contest) else: if not (self.update_contest or self.update_tasks): # Contest already present, but user did not ask to update any # data. We cannot import anything and this is most probably # not what the user wanted, so we let them know. raise ImportDataError( "Contest \"%s\" already exists in database. " "Use --update-contest to update it." % contest.name) if self.update_contest: # Contest already present, user asked us to update it; we do so # if it has changed. if contest_has_changed: logger.info("Contest data has changed, updating it.") # Don't update the groups groups = [] for g_old in contest.groups: g = Group(name=g_old.name) update_group(g, g_old) groups.append(g) new_contest.groups = groups update_contest(contest, new_contest) contest.main_group = [ g for g in contest.groups if g.name == contest.main_group.name ][0] else: logger.info("Contest data has not changed.") return contest
def _dataset_to_db(session, dataset, task): old_dataset = session.query(Dataset)\ .filter(Dataset.task_id == task.id)\ .filter(Dataset.description == dataset.description).first() if old_dataset is not None: raise ImportDataError("Dataset \"%s\" already exists." % dataset.description) dataset.task = task session.add(dataset) return dataset
def _team_to_db(session, team, update=False): old_team = session.query(Team).filter(Team.code == team.code).first() if old_team is not None and update: old_team.name = team.name return old_team elif old_team is not None: raise ImportDataError("Team \"%s\" already exists." % team.code) else: session.add(team) return team
def _user_to_db(session, user): """Add the user to the DB Return the user again, or raise in case a user with the same username was already present in the DB. """ old_user = session.query(User)\ .filter(User.username == user.username).first() if old_user is not None: raise ImportDataError("User \"%s\" already exists." % user.username) session.add(user) return user
def _task_to_db(self, session, contest, tasknum, taskname): """Add the task to the DB and attach it to the contest session (Session): session to use. contest (Contest): the contest in the DB. tasknum (int): num the task should have in the contest. taskname (string): name of the task. return (Task): the task in the DB. raise (ImportDataError): in case of one of these errors: - if the task is not in the DB and user did not ask to import it; - if the loader cannot load the task; - if the task is already in the DB, attached to another contest. """ task_loader = self.loader.get_task_loader(taskname) task = session.query(Task).filter(Task.name == taskname).first() if task is None: # Task is not in the DB; if the user asked us to import it, we do # so, otherwise we return an error. if not self.import_tasks: raise ImportDataError("Task \"%s\" not found in database. " "Use --import-task to import it." % taskname) task = task_loader.get_task(get_statement=not self.no_statements) if task is None: raise ImportDataError("Could not import task \"%s\"." % taskname) session.add(task) elif not task_loader.task_has_changed(): # Task is in the DB and has not changed, nothing to do. logger.info("Task \"%s\" data has not changed.", taskname) elif self.update_tasks: # Task is in the DB, but has changed, and the user asked us to # update it. We do so. new_task = task_loader.get_task( get_statement=not self.no_statements) if new_task is None: raise ImportDataError("Could not reimport task \"%s\"." % taskname) logger.info("Task \"%s\" data has changed, updating it.", taskname) update_task(task, new_task, get_statements=not self.no_statements) else: # Task is in the DB, has changed, and the user didn't ask to update # it; we just show a warning. logger.warning( "Not updating task \"%s\", even if it has changed. " "Use --update-tasks to update it.", taskname) # Finally we tie the task to the contest, if it is not already used # elsewhere. if task.contest is not None and task.contest.name != contest.name: raise ImportDataError( "Task \"%s\" is already tied to contest \"%s\"." % (taskname, task.contest.name)) task.num = tasknum task.contest = contest return task
def _team_to_db(session, team): old_team = session.query(Team).filter(Team.code == team.code).first() if old_team is not None: raise ImportDataError("Team \"%s\" already exists." % team.code) session.add(team) return team