MA-1036 Make CourseOverviews handle malformed grading policies
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Changing field 'CourseOverview.lowest_passing_grade'
|
||||
db.alter_column('course_overviews_courseoverview', 'lowest_passing_grade', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=5, decimal_places=2))
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Changing field 'CourseOverview.lowest_passing_grade'
|
||||
db.alter_column('course_overviews_courseoverview', 'lowest_passing_grade', self.gf('django.db.models.fields.DecimalField')(default=0.5, max_digits=5, decimal_places=2))
|
||||
|
||||
models = {
|
||||
'course_overviews.courseoverview': {
|
||||
'Meta': {'object_name': 'CourseOverview'},
|
||||
'_location': ('xmodule_django.models.UsageKeyField', [], {'max_length': '255'}),
|
||||
'_pre_requisite_courses_json': ('django.db.models.fields.TextField', [], {}),
|
||||
'advertised_start': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'cert_html_view_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'cert_name_long': ('django.db.models.fields.TextField', [], {}),
|
||||
'cert_name_short': ('django.db.models.fields.TextField', [], {}),
|
||||
'certificates_display_behavior': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'certificates_show_before_end': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'course_image_url': ('django.db.models.fields.TextField', [], {}),
|
||||
'days_early_for_beta': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
|
||||
'display_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'display_number_with_default': ('django.db.models.fields.TextField', [], {}),
|
||||
'display_org_with_default': ('django.db.models.fields.TextField', [], {}),
|
||||
'end': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'end_of_course_survey_url': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'facebook_url': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'has_any_active_web_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'primary_key': 'True', 'db_index': 'True'}),
|
||||
'lowest_passing_grade': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '5', 'decimal_places': '2'}),
|
||||
'mobile_available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'social_sharing_url': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'start': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'visible_to_staff_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['course_overviews']
|
||||
@@ -52,7 +52,7 @@ class CourseOverview(django.db.models.Model):
|
||||
cert_name_long = TextField()
|
||||
|
||||
# Grading
|
||||
lowest_passing_grade = DecimalField(max_digits=5, decimal_places=2)
|
||||
lowest_passing_grade = DecimalField(max_digits=5, decimal_places=2, null=True)
|
||||
|
||||
# Access parameters
|
||||
days_early_for_beta = FloatField(null=True)
|
||||
@@ -77,6 +77,16 @@ class CourseOverview(django.db.models.Model):
|
||||
from lms.djangoapps.certificates.api import get_active_web_certificate
|
||||
from lms.djangoapps.courseware.courses import course_image_url
|
||||
|
||||
# Workaround for a problem discovered in https://openedx.atlassian.net/browse/TNL-2806.
|
||||
# If the course has a malformed grading policy such that
|
||||
# course._grading_policy['GRADE_CUTOFFS'] = {}, then
|
||||
# course.lowest_passing_grade will raise a ValueError.
|
||||
# Work around this for now by defaulting to None.
|
||||
try:
|
||||
lowest_passing_grade = course.lowest_passing_grade
|
||||
except ValueError:
|
||||
lowest_passing_grade = None
|
||||
|
||||
return CourseOverview(
|
||||
id=course.id,
|
||||
_location=course.location,
|
||||
@@ -98,7 +108,7 @@ class CourseOverview(django.db.models.Model):
|
||||
has_any_active_web_certificate=(get_active_web_certificate(course) is not None),
|
||||
cert_name_short=course.cert_name_short,
|
||||
cert_name_long=course.cert_name_long,
|
||||
lowest_passing_grade=course.lowest_passing_grade,
|
||||
lowest_passing_grade=lowest_passing_grade,
|
||||
end_of_course_survey_url=course.end_of_course_survey_url,
|
||||
|
||||
days_early_for_beta=course.days_early_for_beta,
|
||||
|
||||
@@ -294,3 +294,18 @@ class CourseOverviewTestCase(ModuleStoreTestCase):
|
||||
# which causes get_from_id to raise an IOError.
|
||||
with self.assertRaises(IOError):
|
||||
CourseOverview.get_from_id(course.id)
|
||||
|
||||
def test_malformed_grading_policy(self):
|
||||
"""
|
||||
Test that CourseOverview handles courses with a malformed grading policy
|
||||
such that course._grading_policy['GRADE_CUTOFFS'] = {} by defaulting
|
||||
.lowest_passing_grade to None.
|
||||
|
||||
Created in response to https://openedx.atlassian.net/browse/TNL-2806.
|
||||
"""
|
||||
course = CourseFactory.create()
|
||||
course._grading_policy['GRADE_CUTOFFS'] = {} # pylint: disable=protected-access
|
||||
with self.assertRaises(ValueError):
|
||||
__ = course.lowest_passing_grade
|
||||
course_overview = CourseOverview._create_from_course(course) # pylint: disable=protected-access
|
||||
self.assertEqual(course_overview.lowest_passing_grade, None)
|
||||
|
||||
Reference in New Issue
Block a user