def print_summary(self): print_info('{0} correcting session(s) opened for TP "{1}"'.format( len(self.__sessions), self.__moulinette.tp().slug())) for session in self.__sessions: print_info(session.submission().login(), end=': ') session.problems().print_one_liner()
def do_trish(self, args): """Usage: trish [LOGIN LOGIN...] Runs the Trish program and prints a ranking of the worst cheaters.""" if len(args) != 0 and len(args) < 2: raise _BadUsageException() logins = set(args) if len(args) != 0 else None scores = [] for i in range(len(self.__sessions.list())): sessionA = self.__sessions.list()[i] loginA = sessionA.submission().login() if logins is not None and loginA not in logins: continue for j in range(i + 1, len(self.__sessions.list())): sessionB = self.__sessions.list()[j] loginB = sessionB.submission().login() if logins is not None and loginB not in logins: continue try: score = CorrectingSession.run_trish(sessionA, sessionB) scores.append((score, sessionA, sessionB)) except Exception as e: loginA = sessionA.submission().login() loginB = sessionB.submission().login() print_error( f'Trish failed to compare {loginA} and {loginB}: {e}') scores.sort(key=lambda x: x[0]) for score, sessionA, sessionB in scores: loginA = sessionA.submission().login() loginB = sessionB.submission().login() print_info(f'{score}: {loginA} // {loginB}') return False
def run(self, login, login_path, project, project_path): print_info("Building project " + project) res = exec_in_folder( project_path, run_command, "msbuild " + os.path.join(os.path.basename(project) + ".csproj")) if res.returncode is not 0: print_error("Build failed:\n" + res.stdout + res.stderr) else: print_success("Build successful")
def cmd_list(tp_slug): """ List all the downloaded repos :param tp_slug: TP slug """ if tp_slug is None: for tp in Tp.get_local_tps(): print_info(tp.slug()) else: tp = Tp(tp_slug) for repo in tp.get_local_submissions(): print_info(repo.login()) return EXIT_SUCCESS
def run(self, login, login_path, project, project_path): print_info("Replacing all private/protected/... with public") replace_table = { "private": "public", "protected": "public", "internal": "public", "public set": "set", } for file in folder_find(project_path, includes=[".*\\.cs"], excludes=["AssemblyInfo.cs"]): for text_to_search, replacement_text in replace_table.items(): file_replace(file, text_to_search, replacement_text)
def archive_all(submissions, zip_file, verbose): files_to_zip = {} # Compute all files to archive for i, submission in enumerate(submissions): containing_dir = parent_dir(submission.local_dir()) if not verbose: print_info("Adding: " + submission.name(), percent_pos=i, percent_max=len(submissions)) for path in get_all_non_trash_files(submission.local_dir()): files_to_zip[os.path.relpath(path, containing_dir)] = path # Archive all files for i, arcname in enumerate(files_to_zip): if verbose: print_info("Adding: " + file_to_zip, percent_pos=i, percent_max=len(files_to_zip)) zip_file.write( files_to_zip[arcname], arcname=arcname, compress_type=zipfile.ZIP_DEFLATED)
def cmd_tag(tp_slug, tag_name, date, logins): """ Push a tag to the last commit of the students before 23h42 at the given date :param tp_slug: Slug of the TP :param tag_name: Tag name :param date: Date in yyyy-mm-dd format :param logins: List of student logins """ if tag_name is None: tag_name = SUBMISSION_TAG cmd_get(tp_slug, logins, False) for i, login in enumerate(logins): print_info(login + ":", percent_pos=i, percent_max=len(logins)) folder = Submission(tp_slug, login).local_dir() success = True try: exec_in_folder(folder, git_checkout_date, date, "23:42") print_success("Checkout last commit before " + date + " 23:42", 1) except GitException as e: print_error("Checkout: " + str(e), 1) success = False continue try: exec_in_folder(folder, git_tag, tag_name) print_success("Tagging commit", 1) except GitException as e: print_error("Tagging: " + str(e), 1) success = False continue try: exec_in_folder(folder, git_push_tags) print_success("Tagging commit", 1) except GitException as e: print_error("Tagging: " + str(e), 1) success = False continue return EXIT_SUCCESS if success else EXIT_FAILURE
def run(self, login, login_path, project, project_path): print_info("Copying files of " + login + " (" + project + ")") student_project_folder = os.path.join(login_path, project) files = folder_find(student_project_folder, includes=[".*\\.cs", ".*\\.csproj"], excludes=["AssemblyInfo.cs"]) if len(files) == 0: print_error("No files found") return for file in files: src = file dest = os.path.join(project_path, file[len(student_project_folder) + 1:]) folder_create(os.path.dirname(dest)) file_copy(src, dest) if file.endswith(".cs"): file_insert_text_every_n_lines(dest, "// " + login, 20)
def cmd_remove(tp_slug, logins, remove_all, remove_moulinette): """ Remove the students repo corresponding to the given TP slug :param tp_slug: Slug of the TP to remove :param logins: List of student logins :param remove_all: Should all the students files be removed :param remove_moulinette: Should the moulinette be removed """ success = True tp = Tp(tp_slug) if not tp.has_local_submissions(): print_error("TP " + tp_slug + " not found") else: if remove_all or len(logins) is 0: tp.remove_locally() print_success("Successfully removed " + tp_slug) else: for i, login in enumerate(logins): repo = Submission(tp, login) print_info("{tp_slug} ({login}) ".format( tp_slug=repo.tp().slug(), login=repo.login()), percent_pos=i, percent_max=len(logins), end='') if repo.exists_locally(): try: repo.remove_locally() print_success('') except IOError: print_error('') success = False continue else: print_error('') if remove_moulinette: tp.remove_moulinette_locally() return EXIT_SUCCESS if success else EXIT_FAILURE
def cmd_correct(tp_slug, logins, get_rendus): """ Start the correction tool :param tp_slug: Slug of the TP to correct :param logins: List of student logins :param get_rendus: Should we call get before correct? """ if get_rendus: cmd_get(tp_slug, logins, None) logins = list({login for login in logins}) tp = Tp(tp_slug) moulinette = tp.get_moulinette(DownloadPolicy.IF_REQUIRED) sessions = CorrectingSessionSet(moulinette) for i, login in enumerate(logins): try: print_info('Processing submission of {0}...'.format(login), percent_pos=i, percent_max=len(logins), end=' ') sessions.open(login) print_success('Done.') except Exception: print_current_exception() print_info('Done.') if sessions.current() is not None: dispatcher = CommandDispatcher(sessions) readline_history.push(CORRECTION_HISTORY_FILE, HISTORY_SIZE) try: dispatcher.cmdloop() finally: readline_history.pop() return EXIT_SUCCESS
def cmd_get(tp_slug, logins, overwrite_policy): """ Download the students repo corresponding to the given TP slug :param tp_slug: Slug of the TP to download :param logins: List of student logins """ tp = Tp(tp_slug) success = True # For each student for i, login in enumerate(logins): repo = Submission(tp_slug, login) dl_path = repo.local_dir() overwriting = False print_info(login + ":", percent_pos=i, percent_max=len(logins)) # If folder exists, delete it if repo.exists_locally(): overwriting = overwrite_policy if overwriting is None: print_error("Student project already downloaded", 1) ask = print_ask("Do you want to overwrite it?", ['y', 'n', 'ya', 'na'], 1) overwriting = ask in ['y', 'ya'] if ask == 'ya': overwrite_policy = True elif ask == 'na': overwrite_policy = False if not overwriting: print_info("Skipping student project", 1) continue print_info("Overwriting student project", 1) dl_path = to_tmp_path(repo.local_dir()) try: git_clone(repo.url(), dl_path) print_success("Download repository", 1) except GitException as e: if os.path.isdir(dl_path): shutil.rmtree(dl_path) print_error("Download: Repository not found", 1) success = False continue if overwriting: shutil.rmtree(repo.local_dir()) os.rename(dl_path, repo.local_dir()) try: # Checkout tag submission exec_in_folder(repo.local_dir(), git_checkout_tag, SUBMISSION_TAG) print_success("Checkout tag " + SUBMISSION_TAG, 1) except GitException as e: print_error("Checkout: Tag " + SUBMISSION_TAG + " not found", 1) success = False if len(folder_ls(repo.local_dir(), excludes=["\..*"])) == 0: print_warning("The repository is empty", 1) return EXIT_SUCCESS if success else EXIT_FAILURE
def run(self, login, login_path, project, project_path): print_info("Clearing files of project " + project) files = folder_find(project_path, includes=[".*\\.cs"], excludes=["AssemblyInfo.cs"]) files_remove(files)