def enter_grades_validation_data(): assignment_names = [assignment.name for assignment in config.assignments] min_scores = {assignment.name: assignment.min_score for assignment in config.assignments} max_scores = {assignment.name: assignment.max_score for assignment in config.assignments} with DbCursor() as c: valid_identifiers, ambiguous_identifiers = get_valid_ambiguous_identifiers(c) payload = { "assignment_names": assignment_names, "min_scores": min_scores, "max_scores": max_scores, "valid_identifiers": list(valid_identifiers), "ambiguous_identifiers": list(ambiguous_identifiers), } resp = Response("var enter_grades_validation_data = %s;" % json.dumps(payload)) resp.headers["Content-Type"] = "text/javascript" return resp
def enter_grades_validation_data(): assignment_names = [assignment.name for assignment in config.assignments] min_scores = { assignment.name: assignment.min_score for assignment in config.assignments } max_scores = { assignment.name: assignment.max_score for assignment in config.assignments } with DbCursor() as c: valid_identifiers, ambiguous_identifiers = get_valid_ambiguous_identifiers( c) payload = { "assignment_names": assignment_names, "min_scores": min_scores, "max_scores": max_scores, "valid_identifiers": list(valid_identifiers), "ambiguous_identifiers": list(ambiguous_identifiers), } resp = Response("var enter_grades_validation_data = %s;" % json.dumps(payload)) resp.headers["Content-Type"] = "text/javascript" return resp
def enter_grades_confirm(): try: f_step = request.form.get("f_step") if f_step not in ("1", "2"): fail_validation("Enum out of range (probably a programming error)") step = int(f_step) assignment_name = request.form.get("f_assignment") if not assignment_name: fail_validation("Assignment name is required") assignment = get_assignment_by_name(assignment_name) if assignment is None: fail_validation("Assignment not found: %s" % assignment_name) min_score, max_score = assignment.min_score, assignment.max_score description = request.form.get("f_description") if not description: fail_validation("Transaction description is required") transaction_source = github_username() entries = [] user_id_set = set() with DbCursor() as c: valid_identifiers, ambiguous_identifiers = get_valid_ambiguous_identifiers( c) def try_add(f_student, f_score, f_slipunits): if not any((f_student, f_score, f_slipunits)): return elif not f_student and (f_score or f_slipunits): fail_validation( "Expected student SID, login, or name, but none provided" ) elif f_student in ambiguous_identifiers: fail_validation( "The identifier '%s' is ambiguous. Please use another." % f_student) else: if step == 1: students = get_users_by_identifier(c, f_student) elif step == 2: student = get_user_by_id(c, f_student) # Let the usual error handling take care of this case students = [student] if student else [] if not students: fail_validation("Student or group not found: %s" % f_student) for student in students: user_id, student_name, _, _, _, _ = student if user_id in user_id_set: fail_validation( "Student was listed more than once: %s" % student_name) try: score = float_or_none(f_score) except ValueError: fail_validation("Not a valid score: %s" % f_score) try: slipunits = int_or_none(f_slipunits) except ValueError: fail_validation( "Slip %s amount not valid: %s" % (slip_unit_name_plural, f_slipunits)) if slipunits is not None and slipunits < 0: fail_validation("Slip %s cannot be negative" % slip_unit_name_plural) if score is not None and not min_score <= score <= max_score: fail_validation( "Score is out of allowed range: %s (Range: %s to %s)" % (f_score, str(min_score), str(max_score))) entries.append([user_id, score, slipunits]) user_id_set.add(user_id) if step == 1: f_students = request.form.getlist("f_student") f_scores = request.form.getlist("f_score") f_slipunitss = request.form.getlist("f_slipunits") if not same_length(f_students, f_scores, f_slipunitss): fail_validation( "Different numbers of students, scores, and slip %s " + "reported. Browser bug?" % slip_unit_name_plural) for f_student, f_score, f_slipunits in zip( f_students, f_scores, f_slipunitss): try_add(f_student, f_score, f_slipunits) f_csv = request.form.get("f_csv", "") for row in csv.reader(StringIO.StringIO(f_csv), delimiter=",", quotechar='"'): if len(row) != 3: fail_validation("CSV rows must contain 3 entries") try_add(*row) if not entries: fail_validation("No grade or slip %s changes entered" % slip_unit_name_plural) if step == 1: c.execute( '''SELECT id, name, sid, login, github FROM users WHERE id IN (%s)''' % (",".join(["?"] * len(entries))), [user_id for user_id, _, _ in entries]) students = c.fetchall() details_user = {} for user_id, name, sid, login, github in students: details_user[user_id] = [name, sid, login, github] c.execute( '''SELECT user, score, slipunits, updated FROM grades WHERE assignment = ? AND user IN (%s)''' % (",".join(["?"] * len(entries))), [assignment.name] + [user_id for user_id, _, _ in entries]) grades = c.fetchall() details_grade = {} for user_id, score, slipunits, updated in grades: details_grade[user_id] = [score, slipunits, updated] entries_details = [] for entry in entries: user_id = entry[0] entry_details = (entry + details_user.get(user_id, [None] * 4) + details_grade.get(user_id, [None] * 3)) entries_details.append(entry_details) elif step == 2: transaction_number = get_next_autoincrementing_value( c, "enter_grades_last_transaction_number") transaction_name = "enter-grades-%s" % transaction_number for user_id, score, slipunits in entries: assign_grade_batch(c, [user_id], assignment.name, score, slipunits, transaction_name, description, transaction_source, manual=True, dont_lower=False) if step == 1: entries_csv = StringIO.StringIO() entries_csv_writer = csv.writer(entries_csv, delimiter=",", quotechar='"') for entry in entries: entries_csv_writer.writerow(entry) return render_template("ta/enter_grades_confirm.html", entries_details=entries_details, entries_csv=entries_csv.getvalue(), assignment_name=assignment.name, description=description, full_score=assignment.full_score, **_template_common()) elif step == 2: if len(entries) == 1: flash("1 grade committed", "success") else: flash("%d grades committed" % len(entries), "success") return redirect(url_for("ta.enter_grades")) except ValidationError as e: return redirect_with_error(url_for("ta.enter_grades"), e)
def enter_grades_confirm(): try: f_step = request.form.get("f_step") if f_step not in ("1", "2"): fail_validation("Enum out of range (probably a programming error)") step = int(f_step) assignment_name = request.form.get("f_assignment") if not assignment_name: fail_validation("Assignment name is required") assignment = get_assignment_by_name(assignment_name) if assignment is None: fail_validation("Assignment not found: %s" % assignment_name) min_score, max_score = assignment.min_score, assignment.max_score description = request.form.get("f_description") if not description: fail_validation("Transaction description is required") transaction_source = github_username() entries = [] user_id_set = set() with DbCursor() as c: valid_identifiers, ambiguous_identifiers = get_valid_ambiguous_identifiers(c) def try_add(f_student, f_score, f_slipunits): if not any((f_student, f_score, f_slipunits)): return elif not f_student and (f_score or f_slipunits): fail_validation("Expected student SID, login, or name, but none provided") elif f_student in ambiguous_identifiers: fail_validation("The identifier '%s' is ambiguous. Please use another." % f_student) else: if step == 1: students = get_users_by_identifier(c, f_student) elif step == 2: student = get_user_by_id(c, f_student) # Let the usual error handling take care of this case students = [student] if student else [] if not students: fail_validation("Student or group not found: %s" % f_student) for student in students: user_id, student_name, _, _, _, _ = student if user_id in user_id_set: fail_validation("Student was listed more than once: %s" % student_name) try: score = float_or_none(f_score) except ValueError: fail_validation("Not a valid score: %s" % f_score) try: slipunits = int_or_none(f_slipunits) except ValueError: fail_validation("Slip %s amount not valid: %s" % (slip_unit_name_plural, f_slipunits)) if slipunits is not None and slipunits < 0: fail_validation("Slip %s cannot be negative" % slip_unit_name_plural) if score is not None and not min_score <= score <= max_score: fail_validation("Score is out of allowed range: %s (Range: %s to %s)" % (f_score, str(min_score), str(max_score))) entries.append([user_id, score, slipunits]) user_id_set.add(user_id) if step == 1: f_students = request.form.getlist("f_student") f_scores = request.form.getlist("f_score") f_slipunitss = request.form.getlist("f_slipunits") if not same_length(f_students, f_scores, f_slipunitss): fail_validation("Different numbers of students, scores, and slip %s " + "reported. Browser bug?" % slip_unit_name_plural) for f_student, f_score, f_slipunits in zip(f_students, f_scores, f_slipunitss): try_add(f_student, f_score, f_slipunits) f_csv = request.form.get("f_csv", "") for row in csv.reader(StringIO.StringIO(f_csv), delimiter=",", quotechar='"'): if len(row) != 3: fail_validation("CSV rows must contain 3 entries") try_add(*row) if not entries: fail_validation("No grade or slip %s changes entered" % slip_unit_name_plural) if step == 1: c.execute('''SELECT id, name, sid, login, github FROM users WHERE id IN (%s)''' % (",".join(["?"] * len(entries))), [user_id for user_id, _, _ in entries]) students = c.fetchall() details_user = {} for user_id, name, sid, login, github in students: details_user[user_id] = [name, sid, login, github] c.execute('''SELECT user, score, slipunits, updated FROM grades WHERE assignment = ? AND user IN (%s)''' % (",".join(["?"] * len(entries))), [assignment.name] + [user_id for user_id, _, _ in entries]) grades = c.fetchall() details_grade = {} for user_id, score, slipunits, updated in grades: details_grade[user_id] = [score, slipunits, updated] entries_details = [] for entry in entries: user_id = entry[0] entry_details = (entry + details_user.get(user_id, [None] * 4) + details_grade.get(user_id, [None] * 3)) entries_details.append(entry_details) elif step == 2: transaction_number = get_next_autoincrementing_value( c, "enter_grades_last_transaction_number") transaction_name = "enter-grades-%s" % transaction_number for user_id, score, slipunits in entries: assign_grade_batch(c, [user_id], assignment.name, score, slipunits, transaction_name, description, transaction_source, manual=True, dont_lower=False) if step == 1: entries_csv = StringIO.StringIO() entries_csv_writer = csv.writer(entries_csv, delimiter=",", quotechar='"') for entry in entries: entries_csv_writer.writerow(entry) return render_template("ta/enter_grades_confirm.html", entries_details=entries_details, entries_csv=entries_csv.getvalue(), assignment_name=assignment.name, description=description, full_score=assignment.full_score, **_template_common()) elif step == 2: if len(entries) == 1: flash("1 grade committed", "success") else: flash("%d grades committed" % len(entries), "success") return redirect(url_for("ta.enter_grades")) except ValidationError as e: return redirect_with_error(url_for("ta.enter_grades"), e)