def __init__(self, path, contest_id, force=False): self.path = path self.contest_id = contest_id self.force = force self.file_cacher = FileCacher() self.loader = YamlLoader(self.file_cacher, False, None, None)
def __init__(self, path, contest_id): self.path = path self.contest_id = contest_id self.file_cacher = FileCacher() self.loader = YamlLoader(self.file_cacher, False, None, None)
class YamlReimporter: """This service load a contest from a tree structure "similar" to the one used in Italian IOI repository ***over*** a contest already in CMS. """ def __init__(self, path, contest_id, force=False): self.path = path self.contest_id = contest_id self.force = force self.file_cacher = FileCacher() self.loader = YamlLoader(self.file_cacher, False, None, None) def run(self): """Interface to make the class do its job.""" self.do_reimport() def do_reimport(self): """Ask the loader to load the contest and actually merge the two. """ # Create the dict corresponding to the new contest. yaml_contest = self.loader.import_contest(self.path) yaml_users = dict(((x['username'], x) for x in yaml_contest['users'])) yaml_tasks = dict(((x['name'], x) for x in yaml_contest['tasks'])) with SessionGen(commit=False) as session: # Create the dict corresponding to the old contest, from # the database. contest = Contest.get_from_id(self.contest_id, session) cms_contest = contest.export_to_dict() cms_users = dict((x['username'], x) for x in cms_contest['users']) cms_tasks = dict((x['name'], x) for x in cms_contest['tasks']) # Delete the old contest from the database. session.delete(contest) session.flush() # Do the actual merge: first of all update all users of # the old contest with the corresponding ones from the new # contest; if some user is present in the old contest but # not in the new one we check if we have to fail or remove # it and, in the latter case, add it to a list users_to_remove = [] for user_num, user in enumerate(cms_contest['users']): try: user_submissions = \ cms_contest['users'][user_num]['submissions'] cms_contest['users'][user_num] = \ yaml_users[user['username']] cms_contest['users'][user_num]['submissions'] = \ user_submissions except KeyError: if self.force: logger.warning("User %s exists in old contest, but " "not in the new one" % user['username']) users_to_remove.append(user_num) session.delete(contest.users[user_num]) else: logger.error("User %s exists in old contest, but " "not in the new one" % user['username']) return False # Delete the users for user_num in users_to_remove: del cms_contest['users'][user_num] # The append the users in the new contest, not present in # the old one. for user in yaml_contest['users']: if user['username'] not in cms_users.keys(): cms_contest['users'].append(user) # The same for tasks: update old tasks. tasks_to_remove = [] for task_num, task in enumerate(cms_contest['tasks']): try: cms_contest['tasks'][task_num] = yaml_tasks[task['name']] except KeyError: if self.force: logger.warning("Task %s exists in old contest, but " "not in the new one" % task['name']) tasks_to_remove.append(task_num) session.delete(contest.tasks[task_num]) else: logger.error("Task %s exists in old contest, but " "not in the new one" % task['name']) return False # Delete the tasks for task_num in tasks_to_remove: del cms_contest['tasks'][task_num] # And add new tasks. for task in yaml_contest['tasks']: if task['name'] not in cms_tasks.keys(): cms_contest['tasks'].append(task) # Reimport the contest in the db, with the previous ID. contest = Contest.import_from_dict(cms_contest) contest.id = self.contest_id session.add(contest) session.flush() logger.info("Analyzing database.") analyze_all_tables(session) session.commit() logger.info("Reimport of contest %s finished." % self.contest_id) return True
class YamlReimporter: """This service load a contest from a tree structure "similar" to the one used in Italian IOI repository ***over*** a contest already in CMS. """ def __init__(self, path, contest_id, force=False): self.path = path self.contest_id = contest_id self.force = force self.file_cacher = FileCacher() self.loader = YamlLoader(self.file_cacher, False, None, None) def run(self): """Interface to make the class do its job.""" self.do_reimport() def do_reimport(self): """Ask the loader to load the contest and actually merge the two. """ # Create the dict corresponding to the new contest. yaml_contest = self.loader.import_contest(self.path) yaml_users = dict(((x['username'], x) for x in yaml_contest['users'])) yaml_tasks = dict(((x['name'], x) for x in yaml_contest['tasks'])) with SessionGen(commit=False) as session: # Create the dict corresponding to the old contest, from # the database. contest = Contest.get_from_id(self.contest_id, session) cms_contest = contest.export_to_dict() cms_users = dict((x['username'], x) for x in cms_contest['users']) cms_tasks = dict((x['name'], x) for x in cms_contest['tasks']) # Delete the old contest from the database. session.delete(contest) session.flush() # Do the actual merge: first of all update all users of # the old contest with the corresponding ones from the new # contest; if some user is present in the old contest but # not in the new one we check if we have to fail or remove # it and, in the latter case, add it to a list users_to_remove = [] for user_num, user in enumerate(cms_contest['users']): if user['username'] in yaml_users: yaml_user = yaml_users[user['username']] yaml_user['submissions'] = user['submissions'] yaml_user['user_tests'] = user['user_tests'] yaml_user['questions'] = user['questions'] yaml_user['messages'] = user['messages'] cms_contest['users'][user_num] = yaml_user else: if self.force: logger.warning("User %s exists in old contest, but " "not in the new one" % user['username']) users_to_remove.append(user_num) # FIXME Do we need really to do this, given that # we already deleted the whole contest? session.delete(contest.users[user_num]) else: logger.error("User %s exists in old contest, but " "not in the new one" % user['username']) return False # Delete the users for user_num in users_to_remove: del cms_contest['users'][user_num] # The append the users in the new contest, not present in # the old one. for user in yaml_contest['users']: if user['username'] not in cms_users.keys(): cms_contest['users'].append(user) # The same for tasks: update old tasks. tasks_to_remove = [] for task_num, task in enumerate(cms_contest['tasks']): if task['name'] in yaml_tasks: yaml_task = yaml_tasks[task['name']] cms_contest['tasks'][task_num] = yaml_task else: if self.force: logger.warning("Task %s exists in old contest, but " "not in the new one" % task['name']) tasks_to_remove.append(task_num) # FIXME Do we need really to do this, given that # we already deleted the whole contest? session.delete(contest.tasks[task_num]) else: logger.error("Task %s exists in old contest, but " "not in the new one" % task['name']) return False # Delete the tasks for task_num in tasks_to_remove: del cms_contest['tasks'][task_num] # And add new tasks. for task in yaml_contest['tasks']: if task['name'] not in cms_tasks.keys(): cms_contest['tasks'].append(task) # Reimport the contest in the db, with the previous ID. contest = Contest.import_from_dict(cms_contest) contest.id = self.contest_id session.add(contest) session.flush() logger.info("Analyzing database.") analyze_all_tables(session) session.commit() logger.info("Reimport of contest %s finished." % self.contest_id) return True