Skip to content

Commit 071da2d

Browse files
authored
Merge pull request #29834 from mitodl/arslan/286-catch-courseoverview-ex
fix: catch and log the CourseOverview.DoesNotExist instead of raising
2 parents 43cf7e6 + 43d215f commit 071da2d

File tree

2 files changed

+48
-5
lines changed

2 files changed

+48
-5
lines changed

openedx/core/djangoapps/credit/services.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Implementation of "credit" XBlock service
33
"""
4+
from datetime import datetime, timedelta
45
import logging
56

67
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
@@ -100,11 +101,30 @@ def get_credit_state(self, user_id, course_key_or_id, return_course_info=False):
100101
}
101102

102103
if return_course_info:
103-
course_overview = CourseOverview.get_from_id(course_key)
104-
result.update({
105-
'course_name': course_overview.display_name,
106-
'course_end_date': course_overview.end,
107-
})
104+
try:
105+
course_overview = CourseOverview.get_from_id(course_key)
106+
result.update({
107+
'course_name': course_overview.display_name,
108+
'course_end_date': course_overview.end,
109+
})
110+
except CourseOverview.DoesNotExist:
111+
# NOTE: Since the caller requested "return_course_info=True" and we don't have course to get that info.
112+
# Also, The "get_credit_state" is called from several places directly or indirectly (Mostly from
113+
# exams/grades services) which relatively depend upon course end date.
114+
# As per the current structure of edX the exam attempts can exist without a course and they can request
115+
# credit state so, the safest options would be to send some date/time in the past (One hour in past to
116+
# be safe) so that those attempts can be marked or treated as expired/completed instead of any other
117+
# status that could be error prone.
118+
119+
one_hour_past = datetime.now() - timedelta(hours=1)
120+
result.update({
121+
'course_end_date': one_hour_past,
122+
})
123+
log.exception(
124+
"Could not get name and end_date for course %s, This happened because we were unable to "
125+
"get/create CourseOverview object for the course. It's possible that the Course has been deleted.",
126+
str(course_key),
127+
)
108128
return result
109129

110130
def set_credit_requirement_status(self, user_id, course_key_or_id, req_namespace,

openedx/core/djangoapps/credit/tests/test_services.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
"""
44

55

6+
from unittest.mock import patch
7+
from datetime import datetime
68
import ddt
79

810
from common.djangoapps.course_modes.models import CourseMode
11+
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
912
from openedx.core.djangoapps.credit.api.eligibility import set_credit_requirements
1013
from openedx.core.djangoapps.credit.models import CreditCourse
1114
from openedx.core.djangoapps.credit.services import CreditService
@@ -261,6 +264,26 @@ def test_course_name(self):
261264
assert 'course_name' in credit_state
262265
assert credit_state['course_name'] == self.course.display_name
263266

267+
@patch("openedx.core.djangoapps.credit.services.log")
268+
def test_get_info_from_non_existent_course(self, exception_log):
269+
"""
270+
Make sure we catch the CourseOverview.DoesNotExist exception and log it instead of raising
271+
"""
272+
with patch("openedx.core.djangoapps.content.course_overviews.models.CourseOverview.get_from_id",
273+
side_effect=CourseOverview.DoesNotExist):
274+
275+
self.enroll()
276+
credit_state = self.service.get_credit_state(self.user.id, self.course.id, return_course_info=True)
277+
278+
assert credit_state is not None
279+
# When exception is caught, the course_end_date should always be in past
280+
assert credit_state["course_end_date"] < datetime.now()
281+
282+
exception_log.exception.assert_called_once_with(
283+
"Could not get name and end_date for course %s, This happened because we were unable to "
284+
"get/create CourseOverview object for the course. It's possible that the Course has been deleted.",
285+
str(self.course.id))
286+
264287
def test_set_status_non_credit(self):
265288
"""
266289
assert that we can still try to update a credit status but return quickly if

0 commit comments

Comments
 (0)