Пример #1
0
        def checkout_to_tag_then_test(hw_instance):
            nonlocal tag_name
            current_tag = hw_instance.repo.git.describe("--always")
            if tag_name != current_tag:
                # Clean first
                hw_instance.repo.git.checkout("--", "*")
                try:
                    if tag_name == "master":
                        tag_name = f"{hw_instance.submitter}"
                        hw_instance.repo.git.checkout(tag_name)
                        printing.print_green(
                                f"[ Checked out to {tag_name}/master ]\n")
                    else:
                        hw_instance.repo.git.checkout(tag_name)
                        printing.print_green(f"[ Checked out to {tag_name} ]\n")
                except git.GitError:
                    printing.print_red(f"[ Couldn't checkout to {tag_name} ]")
                    printing.print_cyan(
                            "[ Opening shell -- ^D/exit when resolved ]")
                    os.system("bash")
            else:
                # No cleaning in case the TA made necessary changes to the
                # submission that we don't want to throw away
                printing.print_green(f"[ Checked out to {tag_name} ]\n")

            hw_instance.repo.git.clean("-f", "-d")
            return test_func(hw_instance)
Пример #2
0
def check_late(deadline_path, iso_timestamp):
    """Checks if iso_timestamp is past the deadline

    Arguments:
        deadline_path: Location of the recorded assignment deadline
            (e.g. ~/.grade/hw1/deadline.txt)
        iso_timestamp: The ISO timestamp to compare against deadline
            (e.g. git log -n 1 --format='%aI')
    """
    submission = datetime.fromisoformat(iso_timestamp)

    with open(deadline_path, "r") as d:
        deadline_string = d.readline()

    if not deadline_string:
        return False

    raw_deadline = datetime.strptime(deadline_string, "%m/%d/%y %I:%M %p")

    nyc_tz = timezone("America/New_York")
    deadline = nyc_tz.localize(raw_deadline.replace(second=59, tzinfo=None))

    if submission <= deadline:
        printing.print_green("[ SUBMISSION ON TIME ]")
        return False

    diff = relativedelta(submission, deadline)
    printing.print_red(f"[SUBMISSION LATE]: Submitted {diff.days} days, "
                       f"{diff.hours} hrs, {diff.minutes} mins, "
                       f"and {diff.seconds} secs late")

    return True
Пример #3
0
 def cd_then_test(hw_instance):
     try:
         hw_instance.do_cd('' if start_dir == "root" else start_dir)
     except ValueError:
         printing.print_red("[ Couldn't cd into tester's @directory, "
                            "opening shell.. ]")
         os.system("bash")
     return test_func(hw_instance)
Пример #4
0
    def grade_C2(self):
        """C2: dynamic analysis"""
        if u.compile_code():  # Non-zero exit code (e.g. compilation failed)
            return

        swap = u.cmd_popen(f"{os.path.join(os.getcwd(), 'swap')} 1 2")
        out, code = swap.communicate()

        if code:
            pr.print_red("[ Non-zero exit code ]")

        print(out)
        if out.splitlines()[1] == "After: 2 1":
            pr.print_green("[ PASS ]")
        else:
            pr.print_red("[ FAIL ] Didn't match 'After: 2 1'")
Пример #5
0
    def grade_item(self, rubric_item: RubricItem):
        if (not self.env["test_only"] and not self.env["regrade"] and all(
                self.grades.is_graded(f"{rubric_item.code}.{si}")
                for si, _ in enumerate(rubric_item.subitems, 1))):
            p.print_yellow(
                f"[ {rubric_item.code} has been graded, skipping... ]")
            return

        # if --grade-only/-g is not provided, run tests else skip tests
        autogrades = None
        if not self.env["grade_only"]:

            def test_wrapper():
                nonlocal autogrades
                self.print_header(rubric_item)
                autogrades = rubric_item.tester()

            try:
                utils.run_and_prompt(test_wrapper)
            except Exception as e:  # pylint: disable=W0703
                p.print_red(f"\n\n[ Exception: {e} ]")
        else:
            self.print_headerline(rubric_item)

        # if -t is not provided, ask for grade. If -t is provided skip
        if not self.env["test_only"]:
            p.print_line()
            is_late = self.hw_class.check_late_submission()
            if is_late:
                # Once we find one part of the submission that is late, the
                # whole thing is considered late.

                # Since this happens after run_and_prompt, the submission_dir
                # will still be checked out to the specified tag.

                # TODO: I actually think we shouldn't do this here, since
                # we don't want to mark submissions that are late on master
                # late if none of the tags are late...
                self.grades.set_late(True)
            self.prompt_grade(rubric_item, autogrades)
        else:
            # Let the grader know if the subitems have been graded yet
            for i in range(1, len(rubric_item.subitems) + 1):
                code = f"{rubric_item.code}.{i}"
                self.print_subitem_grade(code, warn=True)
Пример #6
0
def to_branch(hw_instance, branch_name: str):
    current_branch = hw_instance.repo.git.rev_parse("--abbrev-ref", "HEAD")
    target_branch = f"{hw_instance.submitter}-{branch_name}"
    if current_branch != target_branch:
        # Clean first
        hw_instance.repo.git.checkout("--", "*")
        try:
            hw_instance.repo.git.checkout(target_branch)
            printing.print_green(f"[ Checked out to {branch_name} ]\n")
        except git.GitError:
            printing.print_red(f"[ Couldn't checkout to {branch_name} ]")
            printing.print_cyan(
                    "[ Opening shell -- ^D/exit when resolved ]")
            os.system("bash")
    else:
        # No cleaning in case the TA made necessary changes to the
        # submission that we don't want to throw away
        printing.print_green(f"[ Checked out to {branch_name} ]\n")

    hw_instance.repo.git.clean("-f", "-d")
Пример #7
0
def main():
    """Entry-point into the grader"""
    parser = argparse.ArgumentParser(
        description="pygrader: Python Grading Framework")

    parser.add_argument("hw", type=str, help="homework to grade")
    parser.add_argument("submitter",
                        type=str,
                        nargs="?",
                        default=None,
                        help="the name of student/group to grade")
    parser.add_argument("-c",
                        "--code",
                        type=str,
                        nargs="?",
                        default="all",
                        help=("rubric item (e.g. A, B4) to grade; "
                              "defaults to all"))

    grading_mode = parser.add_mutually_exclusive_group()
    grading_mode.add_argument("-g",
                              "--grade-only",
                              action="store_true",
                              help="grade without running any tests",
                              dest="grade_only")
    grading_mode.add_argument("-t",
                              "--test-only",
                              action="store_true",
                              help=("run tests without grading"),
                              dest="test_only")
    script_mode = parser.add_mutually_exclusive_group()
    script_mode.add_argument("-r",
                             "--regrade",
                             action="store_true",
                             help="do not skip previously graded items",
                             dest="regrade")
    script_mode.add_argument("-d",
                             "--dump-grades",
                             action="store_true",
                             help=("dump grades for this homework -- "
                                   "all if no submitter specified"),
                             dest="dump_grades")
    script_mode.add_argument(
        "-s",
        "--status",
        action="store_true",
        help=("return grading status for this homework -- "
              "all if no submitter specified"),
        dest="status")
    script_mode.add_argument("-i",
                             "--inspect",
                             action="store_true",
                             help=("drop into shell to inspect submission"),
                             dest="inspect")

    args = parser.parse_args()
    env = {
        "regrade": args.regrade,
        "grade_only": args.grade_only,
        "test_only": args.test_only,
        "dump_grades": args.dump_grades,
        "status": args.status,
        "inspect": args.inspect
    }

    rubric_code = args.code if args.code else "all"

    tester = Grader(args.hw, args.submitter, rubric_code, env)

    if args.dump_grades:
        tester.grades.dump_grades(args.submitter, rubric_code.upper())
        sys.exit()

    if args.status:
        all_graded = tester.grades.status(args.submitter, rubric_code.upper())
        sys.exit(not all_graded)  # If all graded, exit with 0 (success)

    if args.inspect:
        # (pygrader)user@host:pwd $
        prompt = (f"{p.CGREEN}({p.CYELLOW}pygrader{p.CGREEN}){p.CEND}"
                  f":{p.CBLUE}\\w{p.CCYAN} \${p.CEND} ")
        p.print_red("[ ^D/exit when done ]")
        os.system(f"PROMPT_COMMAND='PS1=\"{prompt}\"; unset PROMPT_COMMAND' "
                  f"bash")
        sys.exit()

    if not args.submitter:
        sys.exit("unspecified student/team")
    tester.grade()

    # TODO: add progress/percentage complete?
    p.print_magenta(
        f"\n[ Pretty-printing pts/comments for {args.submitter}... ]")
    _, _, s = tester.grades.get_submission_grades(args.submitter,
                                                  rubric_code.upper())
    print(s)
    # clean up
    tester.hw_class.cleanup()
Пример #8
0
 def default_grader(self):
     """Generic grade function."""
     printing.print_red("[ Opening shell, ^D/exit when done. ]")
     os.system("bash")