def instructor_grading_create_grading_branches(ctx, course, assignment_id, all_teams, only): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams = get_teams(course, assignment, only = only, only_ready_for_grading=not all_teams) if teams is None: ctx.exit(CHISUBMIT_FAIL) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if repo is None: print "%s does not have a grading repository" % team.id continue ta = team.get_assignment(assignment.id) if ta.submitted_at is None: print "Skipping grading branch. %s has not submitted." % team.id elif repo.has_grading_branch(): print "Skipping grading branch. %s already has a grading branch." % team.id else: repo.create_grading_branch() print "Created grading branch for %s" % team.id return CHISUBMIT_SUCCESS
def grader_validate_rubrics(ctx, course, grader_id, assignment_id, only): grader = course.get_grader(grader_id) if not grader: print "Grader %s does not exist" % grader_id ctx.exit(CHISUBMIT_FAIL) assignment = course.get_assignment(assignment_id) if not assignment: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams = get_teams(course, assignment, grader=grader, only=only) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if not repo: print "Repository for %s does not exist" % (team.id) ctx.exit(CHISUBMIT_FAIL) rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.id if not os.path.exists(rubricfile): print "Repository for %s does not exist have a rubric for assignment %s" % ( team.id, assignment.id) ctx.exit(CHISUBMIT_FAIL) try: RubricFile.from_file(open(rubricfile), assignment) print "%s: Rubric OK." % team.id except ChisubmitRubricException, cre: print "%s: Rubric ERROR: %s" % (team.id, cre.message)
def instructor_grading_add_rubrics(ctx, course, assignment_id, commit, all_teams): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams_registrations = get_teams_registrations(course, assignment, only_ready_for_grading=not all_teams) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print "%s does not have a grading repository" % team.team_id continue rubric = RubricFile.from_assignment(assignment, registration.get_grades()) rubricfile = "%s.rubric.txt" % assignment.assignment_id rubricfilepath = "%s/%s" % (repo.repo_path, rubricfile) if commit: if not os.path.exists(rubricfilepath): rubric.save(rubricfilepath, include_blank_comments=True) rv = repo.commit([rubricfile], "Added grading rubric") if rv: print rubricfilepath, "(COMMITTED)" else: print rubricfilepath, "(NO CHANGES - Not committed)" else: print rubricfilepath, "(SKIPPED - already exists)" else: rubric.save(rubricfilepath, include_blank_comments=True) print rubricfilepath
def instructor_grading_add_rubrics(ctx, course, assignment_id, commit, all_teams): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams = get_teams(course, assignment, only_ready_for_grading=not all_teams) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) team_assignment = team.get_assignment(assignment_id) rubric = RubricFile.from_assignment(assignment, team_assignment) rubricfile = "%s.rubric.txt" % assignment.id rubricfilepath = "%s/%s" % (repo.repo_path, rubricfile) if commit: if not os.path.exists(rubricfilepath): rubric.save(rubricfilepath, include_blank_comments=True) rv = repo.commit([rubricfile], "Added grading rubric") if rv: print rubricfilepath, "(COMMITTED)" else: print rubricfilepath, "(NO CHANGES - Not committed)" else: print rubricfilepath, "(SKIPPED - already exists)" else: rubric.save(rubricfilepath, include_blank_comments=True) print rubricfilepath
def gradingrepo_push_grading_branch(config, course, team, assignment, to_students=False, to_staging=False): repo = GradingGitRepo.get_grading_repo(config, course, team, assignment) if repo is None: print "%s does not have a grading repository" % team.id return CHISUBMIT_FAIL if not repo.has_grading_branch(): print "%s does not have a grading branch" % team.id return CHISUBMIT_FAIL if repo.is_dirty(): print "Warning: %s grading repo has uncommitted changes." % team.id if to_students: repo.push_grading_branch_to_students() if to_staging: repo.push_grading_branch_to_staging() return CHISUBMIT_SUCCESS
def gradingrepo_pull_grading_branch(config, course, team, assignment, from_students=False, from_staging=False): assert(not (from_students and from_staging)) repo = GradingGitRepo.get_grading_repo(config, course, team, assignment) if repo is None: print "%s does not have a grading repository" % team.id return CHISUBMIT_FAIL if repo.is_dirty(): print "%s grading repo has uncommited changes. Cannot pull." % team.id return CHISUBMIT_FAIL if from_students: if not repo.has_grading_branch_staging(): print "%s does not have a grading branch on students' repository" % team.id else: repo.pull_grading_branch_from_students() if from_staging: if not repo.has_grading_branch_staging(): print "%s does not have a grading branch in staging" % team.id else: repo.pull_grading_branch_from_staging() return CHISUBMIT_SUCCESS
def gradingrepo_pull_grading_branch(config, course, team, assignment, from_students=False, from_staging=False): assert (not (from_students and from_staging)) repo = GradingGitRepo.get_grading_repo(config, course, team, assignment) if repo is None: print "%s does not have a grading repository" % team.id return CHISUBMIT_FAIL if repo.is_dirty(): print "%s grading repo has uncommited changes. Cannot pull." % team.id return CHISUBMIT_FAIL if from_students: if not repo.has_grading_branch_staging(): print "%s does not have a grading branch on students' repository" % team.id else: repo.pull_grading_branch_from_students() if from_staging: if not repo.has_grading_branch_staging(): print "%s does not have a grading branch in staging" % team.id else: repo.pull_grading_branch_from_staging() return CHISUBMIT_SUCCESS
def gradingrepo_pull_grading_branch(config, course, team, registration, from_students=False): repo = GradingGitRepo.get_grading_repo(config, course, team, registration) if repo is None: print("%s does not have a grading repository" % team.team_id) return CHISUBMIT_FAIL if repo.is_dirty(): print("%s grading repo has uncommited changes. Cannot pull." % team.team_id) return CHISUBMIT_FAIL if from_students: if not repo.has_grading_branch_staging(): print("%s does not have a grading branch on students' repository" % team.team_id) else: repo.pull_grading_branch_from_students() else: if not repo.has_grading_branch_staging(): print("%s does not have a grading branch in staging" % team.team_id) else: repo.pull_grading_branch_from_staging() return CHISUBMIT_SUCCESS
def grader_validate_rubrics(ctx, course, grader_id, assignment_id, only): grader = course.get_grader(grader_id) if not grader: print "Grader %s does not exist" % grader_id ctx.exit(CHISUBMIT_FAIL) assignment = course.get_assignment(assignment_id) if not assignment: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams = get_teams(course, assignment, grader = grader, only = only) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if not repo: print "Repository for %s does not exist" % (team.id) ctx.exit(CHISUBMIT_FAIL) rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.id if not os.path.exists(rubricfile): print "Repository for %s does not exist have a rubric for assignment %s" % (team.id, assignment.id) ctx.exit(CHISUBMIT_FAIL) try: RubricFile.from_file(open(rubricfile), assignment) print "%s: Rubric OK." % team.id except ChisubmitRubricException, cre: print "%s: Rubric ERROR: %s" % (team.id, cre.message)
def gradingrepo_push_grading_branch(config, course, team, registration, to_students=False): repo = GradingGitRepo.get_grading_repo(config, course, team, registration) if repo is None: print("%s does not have a grading repository" % team.team_id) return CHISUBMIT_FAIL if not repo.has_grading_branch(): print("%s does not have a grading branch" % team.team_id) return CHISUBMIT_FAIL if repo.is_dirty(): print("Warning: %s grading repo has uncommitted changes." % team.team_id) if to_students: repo.push_grading_branch_to_students() else: repo.push_grading_branch_to_staging() return CHISUBMIT_SUCCESS
def create_grading_repos(config, course, assignment, teams_registrations, staging_only): repos = [] teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(config, course, team, registration) if repo is None: print(("Creating grading repo for %s... " % team.team_id), end=' ') repo = GradingGitRepo.create_grading_repo(config, course, team, registration, staging_only) repo.sync() repos.append(repo) print("done") else: print("Grading repo for %s already exists" % team.team_id) return repos
def instructor_grading_create_grading_branches(ctx, course, assignment_id, all_teams, only): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) teams = get_teams(course, assignment, only=only, only_ready_for_grading=not all_teams) if teams is None: ctx.exit(CHISUBMIT_FAIL) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if repo is None: print "%s does not have a grading repository" % team.id continue ta = team.get_assignment(assignment.id) if ta.submitted_at is None: print "Skipping grading branch. %s has not submitted." % team.id elif repo.has_grading_branch(): print "Skipping grading branch. %s already has a grading branch." % team.id else: repo.create_grading_branch() print "Created grading branch for %s" % team.id return CHISUBMIT_SUCCESS
def instructor_grading_create_grading_repos(ctx, course, assignment_id, all_teams, only, master): assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations( course, assignment, only=only, only_ready_for_grading=not all_teams) if len(teams_registrations) == 0: ctx.exit(CHISUBMIT_FAIL) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print("%40s -- Creating grading repo... " % team.team_id), repo = GradingGitRepo.create_grading_repo(ctx.obj['config'], course, team, registration, staging_only=not master) repo.sync() if registration.final_submission is not None: if repo.has_grading_branch_staging(): gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print "done" else: if master: repo.create_grading_branch() print "done (and created grading branch)" else: print "done (warning: could not pull grading branch; it does not exist)" else: print "done (note: has not submitted yet)" else: print("%40s -- Updating grading repo... " % team.team_id), if repo.has_grading_branch_staging(): gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print "done (pulled latest grading branch)" elif repo.has_grading_branch(): print "nothing to update (grading branch is not in staging)" elif registration.final_submission is not None and master: repo.create_grading_branch() print "done (created missing grading branch)" else: print "nothing to update (there is no grading branch)" return CHISUBMIT_SUCCESS
def grader_pull_grading(ctx, course, grader, assignment_id): if grader is None: user = ctx.obj["client"].get_user() grader = get_grader_or_exit(ctx, course, user.username) else: grader = get_grader_or_exit(ctx, course, grader) assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations(course, assignment, grader=grader) if len(teams_registrations) == 0: print("No teams found") ctx.exit(CHISUBMIT_FAIL) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print(("%40s -- Creating grading repo... " % team.team_id), end=' ') repo = GradingGitRepo.create_grading_repo(ctx.obj['config'], course, team, registration, staging_only=True) repo.sync() gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) repo.set_grader_author() print("done") else: print(("%40s -- Pulling grading branch..." % team.team_id), end=' ') gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print("done") rubricfile = "%s.rubric.txt" % assignment.assignment_id rubricfilepath = "%s/%s" % (repo.repo_path, rubricfile) if not os.path.exists(rubricfilepath): rubric = RubricFile.from_assignment(assignment) rubric.save(rubricfilepath, include_blank_comments=True) return CHISUBMIT_SUCCESS
def validate_repo_rubric(ctx, course, assignment, team, registration): repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if not repo: print("Repository for %s does not exist" % (team.team_id)) ctx.exit(CHISUBMIT_FAIL) rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): print("Repository for %s does not exist have a rubric for assignment %s" % (team.team_id, assignment.assignment_id)) ctx.exit(CHISUBMIT_FAIL) try: RubricFile.from_file(open(rubricfile), assignment) return (True, None) except ChisubmitRubricException as cre: return (False, str(cre))
def validate_repo_rubric(ctx, course, assignment, team, registration): repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if not repo: print "Repository for %s does not exist" % (team.team_id) ctx.exit(CHISUBMIT_FAIL) rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): print "Repository for %s does not exist have a rubric for assignment %s" % (team.team_id, assignment.assignment_id) ctx.exit(CHISUBMIT_FAIL) try: RubricFile.from_file(open(rubricfile), assignment) return (True, None) except ChisubmitRubricException, cre: return (False, cre.message)
def create_grading_repos(config, course, assignment, teams): repos = [] for team in teams: repo = GradingGitRepo.get_grading_repo(config, course, team, assignment) if repo is None: print ("Creating grading repo for %s... " % team.id), repo = GradingGitRepo.create_grading_repo(config, course, team, assignment) repo.sync() repos.append(repo) print "done" else: print "Grading repo for %s already exists" % team.id return repos
def instructor_grading_create_grading_repos(ctx, course, assignment_id, all_teams, only, master): assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations(course, assignment, only = only, only_ready_for_grading=not all_teams) if len(teams_registrations) == 0: ctx.exit(CHISUBMIT_FAIL) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print ("%20s -- Creating grading repo... " % team.team_id), repo = GradingGitRepo.create_grading_repo(ctx.obj['config'], course, team, registration, staging_only = not master) repo.sync() if registration.final_submission is not None: if repo.has_grading_branch_staging(): gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print "done" else: if master: repo.create_grading_branch() print "done (and created grading branch)" else: print "done (warning: could not pull grading branch; it does not exist)" else: print "done (note: has not submitted yet)" else: print "%20s -- Updating grading repo... " % team.team_id if repo.has_grading_branch_staging(): gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print "done (pulled latest grading branch)" elif registration.final_submission is not None and master: repo.create_grading_branch() print "done (created missing grading branch)" else: print "nothing to update (there is no grading branch)" return CHISUBMIT_SUCCESS
def grader_pull_grading(ctx, course, grader, assignment_id): if grader is None: user = ctx.obj["client"].get_user() grader = get_grader_or_exit(ctx, course, user.username) else: grader = get_grader_or_exit(ctx, course, grader) assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations(course, assignment, grader = grader) if len(teams_registrations) == 0: print "No teams found" ctx.exit(CHISUBMIT_FAIL) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print ("%20s -- Creating grading repo... " % team.team_id), repo = GradingGitRepo.create_grading_repo(ctx.obj['config'], course, team, registration, staging_only = True) repo.sync() gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) repo.set_grader_author() print "done" else: print ("%20s -- Pulling grading branch..." % team.team_id), gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print "done" rubricfile = "%s.rubric.txt" % assignment.assignment_id rubricfilepath = "%s/%s" % (repo.repo_path, rubricfile) if not os.path.exists(rubricfilepath): rubric = RubricFile.from_assignment(assignment) rubric.save(rubricfilepath, include_blank_comments=True) return CHISUBMIT_SUCCESS
def create_grading_repos(config, course, assignment, teams): repos = [] for team in teams: repo = GradingGitRepo.get_grading_repo(config, course, team, assignment) if repo is None: print("Creating grading repo for %s... " % team.id), repo = GradingGitRepo.create_grading_repo(config, course, team, assignment) repo.sync() repos.append(repo) print "done" else: print "Grading repo for %s already exists" % team.id return repos
def instructor_grading_add_rubrics(ctx, course, assignment_id, commit, all_teams): assignment = course.get_assignment(assignment_id) if assignment is None: print("Assignment %s does not exist" % assignment_id) ctx.exit(CHISUBMIT_FAIL) teams_registrations = get_teams_registrations( course, assignment, only_ready_for_grading=not all_teams) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print("%s does not have a grading repository" % team.team_id) continue rubric = RubricFile.from_assignment(assignment, registration.get_grades()) rubricfile = "%s.rubric.txt" % assignment.assignment_id rubricfilepath = "%s/%s" % (repo.repo_path, rubricfile) if commit: if not os.path.exists(rubricfilepath): rubric.save(rubricfilepath, include_blank_comments=True) rv = repo.commit([rubricfile], "Added grading rubric") if rv: print(rubricfilepath, "(COMMITTED)") else: print(rubricfilepath, "(NO CHANGES - Not committed)") else: print(rubricfilepath, "(SKIPPED - already exists)") else: rubric.save(rubricfilepath, include_blank_comments=True) print(rubricfilepath)
def instructor_grading_show_grading_status(ctx, course, assignment_id, by_grader, include_diff_urls, use_stored_grades): assignment = get_assignment_or_exit(ctx, course, assignment_id, include_rubric=True) rubric_components = assignment.get_rubric_components() teams_registrations = get_teams_registrations( course, assignment, include_grades=use_stored_grades) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) team_status = [] graders = set() for team in teams: registration = teams_registrations[team] if registration.grader is None: grader_str = "<no grader assigned>" else: grader_str = registration.grader.user.username graders.add(grader_str) grading_status = None diff_url = "" if use_stored_grades: grades = registration.get_grades() total_grade = registration.get_total_grade() graded_rc_ids = [g.rubric_component_id for g in grades] else: total_grade = 0.0 repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: grading_status = "NO GRADING REPO" else: rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): grading_status = "NOT GRADED - No rubric" else: try: rubric = RubricFile.from_file(open(rubricfile), assignment) graded_rc_ids = [ rc.id for rc in rubric_components if rubric.points_obtained[rc.description] is not None ] total_grade = rubric.get_total_points_obtained() except ChisubmitRubricException as cre: grading_status = "ERROR: Rubric does not validate (%s)" % ( cre) if grading_status is None: has_some = False has_all = True for rc in rubric_components: if rc.id in graded_rc_ids: has_some = True else: has_all = False if not has_some: grading_status = "NOT GRADED" elif has_all: grading_status = "GRADED" else: grading_status = "PARTIALLY GRADED" if include_diff_urls and has_some: commit_sha = registration.final_submission.commit_sha[:8] diff_url = "https://mit.cs.uchicago.edu/%s-staging/%s/compare/%s...%s-grading" % ( course.course_id, team.team_id, commit_sha, assignment.assignment_id) team_status.append( (team.team_id, grader_str, total_grade, diff_url, grading_status)) if not by_grader: for team, grader, total_grade, diff_url, status in team_status: print("%-40s %-20s %-20.2f %10s %s" % (team, status, total_grade, grader, diff_url)) else: all_grades = [] for grader in sorted(list(graders)): print(grader) print("-" * len(grader)) grades = [] team_status_grader = [ts for ts in team_status if ts[1] == grader] for team, _, total_grade, diff_url, status in team_status_grader: if status == "NOT GRADED": print("%-40s %s %s" % (team, status, diff_url)) else: print("%-40s %s %8.2f %s" % (team, status, total_grade, diff_url)) if status == "GRADED": grades.append(total_grade) if len(grades) > 0: all_grades += grades print_grades_stats(grades) print() if len(all_grades) > 0: print("TOTAL") print("-----") print_grades_stats(all_grades) return CHISUBMIT_SUCCESS
def instructor_grading_show_grading_status(ctx, course, assignment_id, by_grader, include_diff_urls, use_stored_grades): assignment = get_assignment_or_exit(ctx, course, assignment_id, include_rubric=True) rubric_components = assignment.get_rubric_components() teams_registrations = get_teams_registrations(course, assignment, include_grades=True) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) team_status = [] graders = set() for team in teams: registration = teams_registrations[team] if registration.grader is None: grader_str = "<no grader assigned>" else: grader_str = registration.grader.user.username graders.add(grader_str) grading_status = None diff_url = "" if use_stored_grades: grades = registration.get_grades() total_grade = registration.get_total_grade() graded_rc_ids = [g.rubric_component_id for g in grades] else: total_grade = 0.0 repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: grading_status = "NO GRADING REPO" else: rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): grading_status = "NOT GRADED - No rubric" else: try: rubric = RubricFile.from_file(open(rubricfile), assignment) graded_rc_ids = [ rc.id for rc in rubric_components if rubric.points[rc.description] is not None ] for rc in rubric_components: grade = rubric.points[rc.description] if grade is not None: total_grade += grade if rubric.penalties is not None: for p in rubric.penalties.values(): total_grade += p if rubric.bonuses is not None: for p in rubric.bonuses.values(): total_grade += p except ChisubmitRubricException, cre: grading_status = "ERROR: Rubric does not validate (%s)" % ( cre.message) if grading_status is None: has_some = False has_all = True for rc in rubric_components: if rc.id in graded_rc_ids: has_some = True else: has_all = False if not has_some: grading_status = "NOT GRADED" elif has_all: grading_status = "GRADED" else: grading_status = "PARTIALLY GRADED" if include_diff_urls and has_some: commit_sha = registration.final_submission.commit_sha[:8] diff_url = "https://mit.cs.uchicago.edu/%s-staging/%s/compare/%s...%s-grading" % ( course.course_id, team.team_id, commit_sha, assignment.assignment_id) team_status.append( (team.team_id, grader_str, total_grade, diff_url, grading_status))
def instructor_grading_collect_rubrics(ctx, course, assignment_id, dry_run, only, grader_id): assignment = get_assignment_or_exit(ctx, course, assignment_id) if grader_id is not None: grader = get_grader_or_exit(ctx, course, grader_id) else: grader = None rcs = assignment.get_rubric_components() teams_registrations = get_teams_registrations(course, assignment, grader=grader, only=only) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print "Repository for %s does not exist" % (team.team_id) continue rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): print "Repository for %s does not have a rubric for assignment %s" % (team.team_id, assignment.assignment_id) continue try: rubric = RubricFile.from_file(open(rubricfile), assignment) except ChisubmitRubricException, cre: print "ERROR: Rubric for %s does not validate (%s)" % (team.team_id, cre.message) continue points = [] for rc in rcs: grade = rubric.points[rc.description] if grade is None: points.append(0.0) else: if not dry_run: registration.set_grade(rc, grade) points.append(grade) adjustments = {} total_penalties = 0.0 total_bonuses = 0.0 if rubric.penalties is not None: for desc, p in rubric.penalties.items(): adjustments[desc] = p total_penalties += p if rubric.bonuses is not None: for desc, p in rubric.bonuses.items(): adjustments[desc] = p total_bonuses += p if not dry_run: registration.grade_adjustments = adjustments if ctx.obj["verbose"]: print team.team_id print "Points Obtained: %s" % points print "Penalties: %.2f" % total_penalties print "Bonuses: %.2f" % total_bonuses if not dry_run: total_grade = registration.get_total_grade() else: total_grade = sum(points) + total_penalties + total_bonuses if ctx.obj["verbose"]: print "TOTAL: %.2f" % total_grade print else: print "%-40s %.2f" % (team.team_id, total_grade)
def instructor_grading_collect_rubrics(ctx, course, assignment_id, dry_run, only, grader_id): assignment = get_assignment_or_exit(ctx, course, assignment_id) if grader_id is not None: grader = get_grader_or_exit(ctx, course, grader_id) else: grader = None rcs = assignment.get_rubric_components() teams_registrations = get_teams_registrations(course, assignment, grader=grader, only=only) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print("Repository for %s does not exist" % (team.team_id)) continue rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): print( "Repository for %s does not have a rubric for assignment %s" % (team.team_id, assignment.assignment_id)) continue try: rubric = RubricFile.from_file(open(rubricfile), assignment) except ChisubmitRubricException as cre: print("ERROR: Rubric for %s does not validate (%s)" % (team.team_id, cre)) continue points = [] for rc in rcs: grade = rubric.points_obtained[rc.description] if grade is None: points.append(0.0) else: if not dry_run: registration.set_grade(rc, grade) points.append(grade) adjustments = {} total_penalties = 0.0 total_bonuses = 0.0 if rubric.penalties is not None: for desc, p in list(rubric.penalties.items()): adjustments[desc] = p total_penalties += p if rubric.bonuses is not None: for desc, p in list(rubric.bonuses.items()): adjustments[desc] = p total_bonuses += p if not dry_run: registration.grade_adjustments = adjustments if ctx.obj["verbose"]: print(team.team_id) print("Points Obtained: %s" % points) print("Penalties: %.2f" % total_penalties) print("Bonuses: %.2f" % total_bonuses) if not dry_run: total_grade = registration.get_total_grade() else: total_grade = sum(points) + total_penalties + total_bonuses if ctx.obj["verbose"]: print("TOTAL: %.2f" % total_grade) print() else: print("%-40s %.2f" % (team.team_id, total_grade))
def instructor_grading_show_grading_status(ctx, course, assignment_id, by_grader, include_diff_urls, use_stored_grades): assignment = get_assignment_or_exit(ctx, course, assignment_id, include_rubric = True) rubric_components = assignment.get_rubric_components() teams_registrations = get_teams_registrations(course, assignment, include_grades = use_stored_grades) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) team_status = [] graders = set() for team in teams: registration = teams_registrations[team] if registration.grader is None: grader_str = "<no grader assigned>" else: grader_str = registration.grader.user.username graders.add(grader_str) grading_status = None diff_url = "" if use_stored_grades: grades = registration.get_grades() total_grade = registration.get_total_grade() graded_rc_ids = [g.rubric_component_id for g in grades] else: total_grade = 0.0 repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: grading_status = "NO GRADING REPO" else: rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): grading_status = "NOT GRADED - No rubric" else: try: rubric = RubricFile.from_file(open(rubricfile), assignment) graded_rc_ids = [rc.id for rc in rubric_components if rubric.points_obtained[rc.description] is not None] total_grade = rubric.get_total_points_obtained() except ChisubmitRubricException as cre: grading_status = "ERROR: Rubric does not validate (%s)" % (cre) if grading_status is None: has_some = False has_all = True for rc in rubric_components: if rc.id in graded_rc_ids: has_some = True else: has_all = False if not has_some: grading_status = "NOT GRADED" elif has_all: grading_status = "GRADED" else: grading_status = "PARTIALLY GRADED" if include_diff_urls and has_some: commit_sha = registration.final_submission.commit_sha[:8] diff_url = "https://mit.cs.uchicago.edu/%s-staging/%s/compare/%s...%s-grading" % (course.course_id, team.team_id, commit_sha, assignment.assignment_id) team_status.append((team.team_id, grader_str, total_grade, diff_url, grading_status)) if not by_grader: for team, grader, total_grade, diff_url, status in team_status: print("%-40s %-20s %-20.2f %10s %s" % (team, status, total_grade, grader, diff_url)) else: all_grades = [] for grader in sorted(list(graders)): print(grader) print("-" * len(grader)) grades = [] team_status_grader = [ts for ts in team_status if ts[1] == grader] for team, _, total_grade, diff_url, status in team_status_grader: if status == "NOT GRADED": print("%-40s %s %s" % (team, status, diff_url)) else: print("%-40s %s %8.2f %s" % (team, status, total_grade, diff_url)) if status == "GRADED": grades.append(total_grade) if len(grades) > 0: all_grades += grades print_grades_stats(grades) print() if len(all_grades) > 0: print("TOTAL") print("-----") print_grades_stats(all_grades) return CHISUBMIT_SUCCESS
def instructor_grading_collect_rubrics(ctx, course, assignment_id, dry_run, grader_id): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) if grader_id is not None: grader = course.get_grader(grader_id) if grader is None: print "Grader %s does not exist" % grader_id ctx.exit(CHISUBMIT_FAIL) else: grader = None gcs = assignment.grade_components teams = get_teams(course, assignment, grader=grader) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if repo is None: print "Repository for %s does not exist" % (team.id) continue rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.id if not os.path.exists(rubricfile): print "Repository for %s does not have a rubric for assignment %s" % ( team.id, assignment.id) continue try: rubric = RubricFile.from_file(open(rubricfile), assignment) except ChisubmitRubricException, cre: print "ERROR: Rubric for %s does not validate (%s)" % (team.id, cre.message) continue points = [] for gc in gcs: grade = rubric.points[gc.description] if grade is None: points.append(0.0) else: if not dry_run: team.set_assignment_grade(assignment.id, gc.id, grade) points.append(grade) penalties = {} total_penalties = 0.0 if rubric.penalties is not None: for desc, p in rubric.penalties.items(): penalties[desc] = p total_penalties += p if not dry_run: team.set_assignment_penalties(assignment.id, penalties) if ctx.obj["verbose"]: print team.id print "+ %s" % points print "- %.2f" % total_penalties if not dry_run: new_team = course.get_team(team.id) assignment_team = new_team.get_assignment(assignment.id) total_grade = assignment_team.get_total_grade() else: total_grade = sum(points) + total_penalties if ctx.obj["verbose"]: print "TOTAL: %.2f" % total_grade print else: print "%-40s %.2f" % (team.id, total_grade)
def instructor_grading_create_grading_repos(ctx, course, assignment_id, all_teams, only, master): assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations( course, assignment, only=only, only_ready_for_grading=not all_teams) if len(teams_registrations) == 0: print("There are no grading repos to create.") ctx.exit(CHISUBMIT_FAIL) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print(("%40s -- Creating grading repo... " % team.team_id), end=' ') try: repo = GradingGitRepo.create_grading_repo( ctx.obj['config'], course, team, registration, staging_only=not master) repo.sync() except GitCommandError as gce: print(gce) if registration.final_submission is not None: if repo.has_grading_branch_staging(): if not registration.grading_started: print( "ERROR: This repo has a grading branch, but is not marked as ready for grading." ) else: gradingrepo_pull_grading_branch( ctx.obj['config'], course, team, registration) print("done") else: if master: repo.create_grading_branch() registration.grading_started = True print("done (and created grading branch)") else: print( "done (warning: could not pull grading branch; it does not exist)" ) else: if registration.grading_started: print( "ERROR: This team has not submitted this assignment, but the repo is marked as ready for grading." ) else: print("done (note: has not submitted yet)") else: print(("%40s -- Updating grading repo... " % team.team_id), end=' ') if repo.has_grading_branch_staging(): if not registration.grading_started: print( "ERROR: This repo has a grading branch, but is not marked as ready for grading." ) else: try: gradingrepo_pull_grading_branch( ctx.obj['config'], course, team, registration) print("done (pulled latest grading branch)") except GitCommandError as gce: print(gce) elif repo.has_grading_branch(): print("nothing to update (grading branch is not in staging)") elif registration.final_submission is not None and master: try: repo.create_grading_branch() if not registration.grading_started: registration.grading_started = True print("done (created missing grading branch)") except GitCommandError as gce: print(gce) else: print("nothing to update (there is no grading branch)") return CHISUBMIT_SUCCESS
def instructor_grading_collect_rubrics(ctx, course, assignment_id, dry_run, grader_id): assignment = course.get_assignment(assignment_id) if assignment is None: print "Assignment %s does not exist" % assignment_id ctx.exit(CHISUBMIT_FAIL) if grader_id is not None: grader = course.get_grader(grader_id) if grader is None: print "Grader %s does not exist" % grader_id ctx.exit(CHISUBMIT_FAIL) else: grader = None gcs = assignment.grade_components teams = get_teams(course, assignment, grader=grader) for team in teams: repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, assignment) if repo is None: print "Repository for %s does not exist" % (team.id) continue rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.id if not os.path.exists(rubricfile): print "Repository for %s does not have a rubric for assignment %s" % (team.id, assignment.id) continue try: rubric = RubricFile.from_file(open(rubricfile), assignment) except ChisubmitRubricException, cre: print "ERROR: Rubric for %s does not validate (%s)" % (team.id, cre.message) continue points = [] for gc in gcs: grade = rubric.points[gc.description] if grade is None: points.append(0.0) else: if not dry_run: team.set_assignment_grade(assignment.id, gc.id, grade) points.append(grade) penalties = {} total_penalties = 0.0 if rubric.penalties is not None: for desc, p in rubric.penalties.items(): penalties[desc] = p total_penalties += p if not dry_run: team.set_assignment_penalties(assignment.id, penalties) if ctx.obj["verbose"]: print team.id print "+ %s" % points print "- %.2f" % total_penalties if not dry_run: new_team = course.get_team(team.id) assignment_team = new_team.get_assignment(assignment.id) total_grade = assignment_team.get_total_grade() else: total_grade = sum(points) + total_penalties if ctx.obj["verbose"]: print "TOTAL: %.2f" % total_grade print else: print "%-40s %.2f" % (team.id, total_grade)
def instructor_grading_show_grading_status(ctx, course, assignment_id, by_grader, include_diff_urls, use_stored_grades): assignment = get_assignment_or_exit(ctx, course, assignment_id, include_rubric = True) rubric_components = assignment.get_rubric_components() teams_registrations = get_teams_registrations(course, assignment, include_grades = True) teams = sorted(teams_registrations.keys(), key=operator.attrgetter("team_id")) team_status = [] graders = set() for team in teams: registration = teams_registrations[team] if registration.grader is None: grader_str = "<no grader assigned>" else: grader_str = registration.grader.user.username graders.add(grader_str) grading_status = None if use_stored_grades: grades = registration.get_grades() total_grade = registration.get_total_grade() graded_rc_ids = [g.rubric_component_id for g in grades] else: total_grade = 0.0 repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: grading_status = "NO GRADING REPO" else: rubricfile = repo.repo_path + "/%s.rubric.txt" % assignment.assignment_id if not os.path.exists(rubricfile): grading_status = "NOT GRADED - No rubric" else: try: rubric = RubricFile.from_file(open(rubricfile), assignment) graded_rc_ids = [rc.id for rc in rubric_components if rubric.points[rc.description] is not None] for rc in rubric_components: grade = rubric.points[rc.description] if grade is not None: total_grade += grade if rubric.penalties is not None: for p in rubric.penalties.values(): total_grade += p if rubric.bonuses is not None: for p in rubric.bonuses.values(): total_grade += p except ChisubmitRubricException, cre: grading_status = "ERROR: Rubric does not validate (%s)" % (cre.message) if grading_status is None: has_some = False has_all = True for rc in rubric_components: if rc.id in graded_rc_ids: has_some = True else: has_all = False if not has_some: grading_status = "NOT GRADED" elif has_all: grading_status = "GRADED" else: grading_status = "PARTIALLY GRADED" if include_diff_urls and has_some: commit_sha = registration.final_submission.commit_sha[:8] diff_url = "https://mit.cs.uchicago.edu/%s-staging/%s/compare/%s...%s-grading" % (course.course_id, team.team_id, commit_sha, assignment.assignment_id) else: diff_url = "" team_status.append((team.team_id, grader_str, total_grade, diff_url, grading_status))
def instructor_gradescope_upload(ctx, course, assignment_id, dry_run, only, limit): config = ctx.obj['config'] gradescope_api_key = config.get_gradescope_api_key() if gradescope_api_key is None: print("No API key found for Gradescope") ctx.exit(CHISUBMIT_FAIL) if course.gradescope_id is None: print("{} does not have its 'gradescope_id' attribute set".format( course.course_id)) ctx.exit(CHISUBMIT_FAIL) assignment = get_assignment_or_exit(ctx, course, assignment_id) if assignment.gradescope_id is None: print("Assignment {} does not have its 'gradescope_id' attribute set". format(assignment_id)) ctx.exit(CHISUBMIT_FAIL) if assignment.expected_files is None: print("Assignment {} does not have a list of expected files".format( assignment_id)) ctx.exit(CHISUBMIT_FAIL) teams_registrations = get_teams_registrations(course, assignment, only=only) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) n_submissions = 0 for team_obj in teams: registration_obj = teams_registrations[team_obj] if registration_obj.gradescope_uploaded: print("[SKIPPED] {} has already been uploaded".format( team_obj.team_id)) continue repo = GradingGitRepo.get_grading_repo(config, course, team_obj, registration_obj) if repo is None: print("[SKIPPED] {} does not have a grading repo".format( team_obj.team_id)) continue files = [] missing_files = [] for pattern in assignment.expected_files.split(","): abs_pattern = "{}/{}".format(repo.repo_path, pattern) matching_files = glob.glob(abs_pattern) if len(matching_files) == 0: missing_files.append(pattern) continue for f in matching_files: files.append((os.path.basename(f), f)) if len(missing_files) > 0: print("[WARNING] {} does not have required file(s): {}".format( team_obj.team_id, " ".join(missing_files))) continue team_members = team_obj.get_team_members() if all(tm.student.dropped for tm in team_members): print("[SKIPPED] All students in {} have dropped the class".format( team_obj.team_id)) continue emails = [ "{}@uchicago.edu".format(tm.student.username) for tm in team_members ] if dry_run: print("[DRY RUN] upload_submission(..., {}, {}, '{}', {}".format( course.gradescope_id, assignment.gradescope_id, emails, files)) n_submissions += 1 else: try: submission_id = gradescope_upload_submission( gradescope_api_key, course.gradescope_id, assignment.gradescope_id, emails, files) print("[DONE]: Upload for {} (submission id: {})".format( team_obj.team_id, submission_id)) registration_obj.gradescope_uploaded = True n_submissions += 1 except GradescopeException: print("[ERROR] Could not upload submission for {}".format( team_obj.team_id)) if limit is not None and n_submissions >= limit: print("Reached submission limit ({})".format(limit)) break
def instructor_grading_create_grading_repos(ctx, course, assignment_id, all_teams, only, master): assignment = get_assignment_or_exit(ctx, course, assignment_id) teams_registrations = get_teams_registrations(course, assignment, only = only, only_ready_for_grading=not all_teams) if len(teams_registrations) == 0: print("There are no grading repos to create.") ctx.exit(CHISUBMIT_FAIL) teams = sorted(list(teams_registrations.keys()), key=operator.attrgetter("team_id")) for team in teams: registration = teams_registrations[team] repo = GradingGitRepo.get_grading_repo(ctx.obj['config'], course, team, registration) if repo is None: print(("%40s -- Creating grading repo... " % team.team_id), end=' ') try: repo = GradingGitRepo.create_grading_repo(ctx.obj['config'], course, team, registration, staging_only = not master) repo.sync() except GitCommandError as gce: print(gce) if registration.final_submission is not None: if repo.has_grading_branch_staging(): if not registration.grading_started: print("ERROR: This repo has a grading branch, but is not marked as ready for grading.") else: gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print("done") else: if master: repo.create_grading_branch() registration.grading_started = True print("done (and created grading branch)") else: print("done (warning: could not pull grading branch; it does not exist)") else: if registration.grading_started: print("ERROR: This team has not submitted this assignment, but the repo is marked as ready for grading.") else: print("done (note: has not submitted yet)") else: print(("%40s -- Updating grading repo... " % team.team_id), end=' ') if repo.has_grading_branch_staging(): if not registration.grading_started: print("ERROR: This repo has a grading branch, but is not marked as ready for grading.") else: try: gradingrepo_pull_grading_branch(ctx.obj['config'], course, team, registration) print("done (pulled latest grading branch)") except GitCommandError as gce: print(gce) elif repo.has_grading_branch(): print("nothing to update (grading branch is not in staging)") elif registration.final_submission is not None and master: try: repo.create_grading_branch() if not registration.grading_started: registration.grading_started = True print("done (created missing grading branch)") except GitCommandError as gce: print(gce) else: print("nothing to update (there is no grading branch)") return CHISUBMIT_SUCCESS