예제 #1
0
 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()
예제 #2
0
    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
예제 #3
0
    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")
예제 #4
0
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
예제 #5
0
    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)
예제 #6
0
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)
예제 #7
0
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
예제 #8
0
    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)
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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
예제 #12
0
 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)