diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 52f4d51c89..10acbf9447 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -56,6 +56,7 @@ from lms.djangoapps.grades.signals.signals import SCORE_PUBLISHED from lms.djangoapps.lms_xblock.field_data import LmsFieldData from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem +from lms.djangoapps.grades.util_services import GradesUtilService from lms.djangoapps.verify_student.services import XBlockVerificationService from openedx.core.djangoapps.bookmarks.services import BookmarksService from openedx.core.djangoapps.crawlers.models import CrawlersConfig @@ -821,6 +822,7 @@ def get_module_system_for_user( 'credit': CreditService(), 'bookmarks': BookmarksService(user=user), 'gating': GatingService(), + 'grade_utils': GradesUtilService(course_id=course_id), }, get_user_role=lambda: get_user_role(user, course_id), descriptor_runtime=descriptor._runtime, # pylint: disable=protected-access diff --git a/lms/djangoapps/grades/api/v1/gradebook_views.py b/lms/djangoapps/grades/api/v1/gradebook_views.py index 42508b1bf2..a0cbb0402b 100644 --- a/lms/djangoapps/grades/api/v1/gradebook_views.py +++ b/lms/djangoapps/grades/api/v1/gradebook_views.py @@ -36,7 +36,8 @@ from lms.djangoapps.grades.models import ( PersistentSubsectionGradeOverrideHistory, ) from lms.djangoapps.grades.subsection_grade import CreateSubsectionGrade -from lms.djangoapps.grades.tasks import are_grades_frozen, recalculate_subsection_grade_v3 +from lms.djangoapps.grades.tasks import recalculate_subsection_grade_v3 +from lms.djangoapps.grades.grade_utils import are_grades_frozen from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey from openedx.core.djangoapps.course_groups import cohorts diff --git a/lms/djangoapps/grades/grade_utils.py b/lms/djangoapps/grades/grade_utils.py new file mode 100644 index 0000000000..b3009d2bd4 --- /dev/null +++ b/lms/djangoapps/grades/grade_utils.py @@ -0,0 +1,18 @@ +""" +This module contains utility functions for grading. +""" +from datetime import timedelta +from django.utils import timezone +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from .config.waffle import ENFORCE_FREEZE_GRADE_AFTER_COURSE_END, waffle_flags + + +def are_grades_frozen(course_key): + """ Returns whether grades are frozen for the given course. """ + if waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END].is_enabled(course_key): + course = CourseOverview.get_from_id(course_key) + if course.end: + freeze_grade_date = course.end + timedelta(30) + now = timezone.now() + return now > freeze_grade_date + return False diff --git a/lms/djangoapps/grades/tasks.py b/lms/djangoapps/grades/tasks.py index b5b0d0129e..6c10b47d22 100644 --- a/lms/djangoapps/grades/tasks.py +++ b/lms/djangoapps/grades/tasks.py @@ -2,7 +2,6 @@ This module contains tasks for asynchronous execution of grade updates. """ -from datetime import timedelta from logging import getLogger import six @@ -12,7 +11,6 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.db.utils import DatabaseError -from django.utils import timezone from edx_django_utils.monitoring import set_custom_metric, set_custom_metrics_for_course_key from opaque_keys.edx.keys import CourseKey, UsageKey from opaque_keys.edx.locator import CourseLocator @@ -27,7 +25,7 @@ from track.event_transaction_utils import set_event_transaction_id, set_event_tr from util.date_utils import from_timestamp from xmodule.modulestore.django import modulestore -from .config.waffle import DISABLE_REGRADE_ON_POLICY_CHANGE, ENFORCE_FREEZE_GRADE_AFTER_COURSE_END, waffle, waffle_flags +from .config.waffle import DISABLE_REGRADE_ON_POLICY_CHANGE, waffle from .constants import ScoreDatabaseTableEnum from .course_grade_factory import CourseGradeFactory from .exceptions import DatabaseNotReadyError @@ -35,6 +33,7 @@ from .services import GradesService from .signals.signals import SUBSECTION_SCORE_CHANGED from .subsection_grade_factory import SubsectionGradeFactory from .transformer import GradesTransformer +from .grade_utils import are_grades_frozen log = getLogger(__name__) @@ -352,14 +351,3 @@ def _course_task_args(course_key, **kwargs): for offset in six.moves.range(0, enrollment_count, batch_size): yield (six.text_type(course_key), offset, batch_size) - - -def are_grades_frozen(course_key): - """ Returns whether grades are frozen for the given course. """ - if waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END].is_enabled(course_key): - course = CourseOverview.get_from_id(course_key) - if course.end: - freeze_grade_date = course.end + timedelta(30) - now = timezone.now() - return now > freeze_grade_date - return False diff --git a/lms/djangoapps/grades/util_services.py b/lms/djangoapps/grades/util_services.py new file mode 100644 index 0000000000..dff8f11b5c --- /dev/null +++ b/lms/djangoapps/grades/util_services.py @@ -0,0 +1,17 @@ +"A light weight interface to grading helper functions" + + +from .grade_utils import are_grades_frozen + + +class GradesUtilService(object): + """ + An interface to be used by xblocks. + """ + def __init__(self, **kwargs): + super(GradesUtilService, self).__init__() + self.course_id = kwargs.get('course_id', None) + + def are_grades_frozen(self): + "Check if grades are frozen for given course key" + return are_grades_frozen(self.course_id)