70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
"""
|
|
Functionality for course-level grades.
|
|
"""
|
|
from collections import namedtuple
|
|
from logging import getLogger
|
|
|
|
import dogstats_wrapper as dog_stats_api
|
|
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from courseware.courses import get_course_by_id
|
|
from .new.course_grade import CourseGradeFactory
|
|
|
|
|
|
log = getLogger(__name__)
|
|
|
|
|
|
GradeResult = namedtuple('GradeResult', ['student', 'gradeset', 'err_msg'])
|
|
|
|
|
|
def iterate_grades_for(course_or_id, students):
|
|
"""
|
|
Given a course_id and an iterable of students (User), yield a GradeResult
|
|
for every student enrolled in the course. GradeResult is a named tuple of:
|
|
|
|
(student, gradeset, err_msg)
|
|
|
|
If an error occurred, gradeset will be an empty dict and err_msg will be an
|
|
exception message. If there was no error, err_msg is an empty string.
|
|
|
|
The gradeset is a dictionary with the following fields:
|
|
|
|
- grade : A final letter grade.
|
|
- percent : The final percent for the class (rounded up).
|
|
- section_breakdown : A breakdown of each section that makes
|
|
up the grade. (For display)
|
|
- grade_breakdown : A breakdown of the major components that
|
|
make up the final grade. (For display)
|
|
- raw_scores: contains scores for every graded module
|
|
"""
|
|
if isinstance(course_or_id, (basestring, CourseKey)):
|
|
course = get_course_by_id(course_or_id)
|
|
else:
|
|
course = course_or_id
|
|
|
|
for student in students:
|
|
with dog_stats_api.timer('lms.grades.iterate_grades_for', tags=[u'action:{}'.format(course.id)]):
|
|
try:
|
|
gradeset = summary(student, course)
|
|
yield GradeResult(student, gradeset, "")
|
|
except Exception as exc: # pylint: disable=broad-except
|
|
# Keep marching on even if this student couldn't be graded for
|
|
# some reason, but log it for future reference.
|
|
log.exception(
|
|
'Cannot grade student %s (%s) in course %s because of exception: %s',
|
|
student.username,
|
|
student.id,
|
|
course.id,
|
|
exc.message
|
|
)
|
|
yield GradeResult(student, {}, exc.message)
|
|
|
|
|
|
def summary(student, course):
|
|
"""
|
|
Returns the grade summary of the student for the given course.
|
|
|
|
Also sends a signal to update the minimum grade requirement status.
|
|
"""
|
|
return CourseGradeFactory(student).create(course).summary
|