Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
66fdd2fb
Commit
66fdd2fb
authored
Jul 20, 2017
by
Sanford Student
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EDUCATOR-915: force subsection grades to update when course grade updates
parent
42fffdfa
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
46 additions
and
11 deletions
+46
-11
lms/djangoapps/grades/new/course_grade.py
+9
-3
lms/djangoapps/grades/new/course_grade_factory.py
+22
-7
lms/djangoapps/grades/tasks.py
+1
-1
lms/djangoapps/grades/tests/test_new.py
+14
-0
No files found.
lms/djangoapps/grades/new/course_grade.py
View file @
66fdd2fb
...
@@ -21,7 +21,7 @@ class CourseGradeBase(object):
...
@@ -21,7 +21,7 @@ class CourseGradeBase(object):
"""
"""
Base class for Course Grades.
Base class for Course Grades.
"""
"""
def
__init__
(
self
,
user
,
course_data
,
percent
=
0
,
letter_grade
=
None
,
passed
=
False
):
def
__init__
(
self
,
user
,
course_data
,
percent
=
0
,
letter_grade
=
None
,
passed
=
False
,
force_update_subsections
=
False
):
self
.
user
=
user
self
.
user
=
user
self
.
course_data
=
course_data
self
.
course_data
=
course_data
...
@@ -30,6 +30,7 @@ class CourseGradeBase(object):
...
@@ -30,6 +30,7 @@ class CourseGradeBase(object):
# Convert empty strings to None when reading from the table
# Convert empty strings to None when reading from the table
self
.
letter_grade
=
letter_grade
or
None
self
.
letter_grade
=
letter_grade
or
None
self
.
force_update_subsections
=
force_update_subsections
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
u'Course Grade: percent: {}, letter_grade: {}, passed: {}'
.
format
(
return
u'Course Grade: percent: {}, letter_grade: {}, passed: {}'
.
format
(
...
@@ -203,7 +204,9 @@ class CourseGrade(CourseGradeBase):
...
@@ -203,7 +204,9 @@ class CourseGrade(CourseGradeBase):
def
update
(
self
):
def
update
(
self
):
"""
"""
Updates the grade for the course.
Updates the grade for the course. Also updates subsection grades
if self.force_update_subsections is true, via the lazy call
to self.grader_result.
"""
"""
grade_cutoffs
=
self
.
course_data
.
course
.
grade_cutoffs
grade_cutoffs
=
self
.
course_data
.
course
.
grade_cutoffs
self
.
percent
=
self
.
_compute_percent
(
self
.
grader_result
)
self
.
percent
=
self
.
_compute_percent
(
self
.
grader_result
)
...
@@ -224,7 +227,10 @@ class CourseGrade(CourseGradeBase):
...
@@ -224,7 +227,10 @@ class CourseGrade(CourseGradeBase):
def
_get_subsection_grade
(
self
,
subsection
):
def
_get_subsection_grade
(
self
,
subsection
):
# Pass read_only here so the subsection grades can be persisted in bulk at the end.
# Pass read_only here so the subsection grades can be persisted in bulk at the end.
return
self
.
_subsection_grade_factory
.
create
(
subsection
,
read_only
=
True
)
if
self
.
force_update_subsections
:
return
self
.
_subsection_grade_factory
.
update
(
subsection
)
else
:
return
self
.
_subsection_grade_factory
.
create
(
subsection
,
read_only
=
True
)
@staticmethod
@staticmethod
def
_compute_percent
(
grader_result
):
def
_compute_percent
(
grader_result
):
...
...
lms/djangoapps/grades/new/course_grade_factory.py
View file @
66fdd2fb
...
@@ -66,7 +66,15 @@ class CourseGradeFactory(object):
...
@@ -66,7 +66,15 @@ class CourseGradeFactory(object):
else
:
else
:
return
None
return
None
def
update
(
self
,
user
,
course
=
None
,
collected_block_structure
=
None
,
course_structure
=
None
,
course_key
=
None
):
def
update
(
self
,
user
,
course
=
None
,
collected_block_structure
=
None
,
course_structure
=
None
,
course_key
=
None
,
force_update_subsections
=
False
,
):
"""
"""
Computes, updates, and returns the CourseGrade for the given
Computes, updates, and returns the CourseGrade for the given
user in the course.
user in the course.
...
@@ -75,7 +83,7 @@ class CourseGradeFactory(object):
...
@@ -75,7 +83,7 @@ class CourseGradeFactory(object):
or course_key should be provided.
or course_key should be provided.
"""
"""
course_data
=
CourseData
(
user
,
course
,
collected_block_structure
,
course_structure
,
course_key
)
course_data
=
CourseData
(
user
,
course
,
collected_block_structure
,
course_structure
,
course_key
)
return
self
.
_update
(
user
,
course_data
,
read_only
=
False
)
return
self
.
_update
(
user
,
course_data
,
read_only
=
False
,
force_update_subsections
=
force_update_subsections
)
@contextmanager
@contextmanager
def
_course_transaction
(
self
,
course_key
):
def
_course_transaction
(
self
,
course_key
):
...
@@ -118,10 +126,17 @@ class CourseGradeFactory(object):
...
@@ -118,10 +126,17 @@ class CourseGradeFactory(object):
def
_iter_grade_result
(
self
,
user
,
course_data
,
force_update
):
def
_iter_grade_result
(
self
,
user
,
course_data
,
force_update
):
try
:
try
:
kwargs
=
{
'user'
:
user
,
'course'
:
course_data
.
course
,
'collected_block_structure'
:
course_data
.
collected_structure
,
'course_key'
:
course_data
.
course_key
}
if
force_update
:
kwargs
[
'force_update_subsections'
]
=
True
method
=
CourseGradeFactory
()
.
update
if
force_update
else
CourseGradeFactory
()
.
create
method
=
CourseGradeFactory
()
.
update
if
force_update
else
CourseGradeFactory
()
.
create
course_grade
=
method
(
course_grade
=
method
(
**
kwargs
)
user
,
course_data
.
course
,
course_data
.
collected_structure
,
course_key
=
course_data
.
course_key
,
)
return
self
.
GradeResult
(
user
,
course_grade
,
None
)
return
self
.
GradeResult
(
user
,
course_grade
,
None
)
except
Exception
as
exc
:
# pylint: disable=broad-except
except
Exception
as
exc
:
# pylint: disable=broad-except
# Keep marching on even if this student couldn't be graded for
# Keep marching on even if this student couldn't be graded for
...
@@ -165,14 +180,14 @@ class CourseGradeFactory(object):
...
@@ -165,14 +180,14 @@ class CourseGradeFactory(object):
return
course_grade
,
persistent_grade
.
grading_policy_hash
return
course_grade
,
persistent_grade
.
grading_policy_hash
@staticmethod
@staticmethod
def
_update
(
user
,
course_data
,
read_only
):
def
_update
(
user
,
course_data
,
read_only
,
force_update_subsections
=
False
):
"""
"""
Computes, saves, and returns a CourseGrade object for the
Computes, saves, and returns a CourseGrade object for the
given user and course.
given user and course.
Sends a COURSE_GRADE_CHANGED signal to listeners and a
Sends a COURSE_GRADE_CHANGED signal to listeners and a
COURSE_GRADE_NOW_PASSED if learner has passed course.
COURSE_GRADE_NOW_PASSED if learner has passed course.
"""
"""
course_grade
=
CourseGrade
(
user
,
course_data
)
course_grade
=
CourseGrade
(
user
,
course_data
,
force_update_subsections
=
force_update_subsections
)
course_grade
.
update
()
course_grade
.
update
()
should_persist
=
(
should_persist
=
(
...
...
lms/djangoapps/grades/tasks.py
View file @
66fdd2fb
...
@@ -106,7 +106,7 @@ def compute_grades_for_course_v2(self, **kwargs):
...
@@ -106,7 +106,7 @@ def compute_grades_for_course_v2(self, **kwargs):
@task
(
base
=
_BaseTask
)
@task
(
base
=
_BaseTask
)
def
compute_grades_for_course
(
course_key
,
offset
,
batch_size
,
**
kwargs
):
# pylint: disable=unused-argument
def
compute_grades_for_course
(
course_key
,
offset
,
batch_size
,
**
kwargs
):
# pylint: disable=unused-argument
"""
"""
Compute grades for a set of students in the specified course.
Compute
and save
grades for a set of students in the specified course.
The set of students will be determined by the order of enrollment date, and
The set of students will be determined by the order of enrollment date, and
limited to at most <batch_size> students, starting from the specified
limited to at most <batch_size> students, starting from the specified
...
...
lms/djangoapps/grades/tests/test_new.py
View file @
66fdd2fb
...
@@ -246,6 +246,20 @@ class TestCourseGradeFactory(GradeTestBase):
...
@@ -246,6 +246,20 @@ class TestCourseGradeFactory(GradeTestBase):
else
:
else
:
self
.
assertIsNone
(
course_grade
)
self
.
assertIsNone
(
course_grade
)
@ddt.data
(
True
,
False
)
def
test_iter_force_update
(
self
,
force_update
):
base_string
=
'lms.djangoapps.grades.new.subsection_grade_factory.SubsectionGradeFactory.{}'
desired_method_name
=
base_string
.
format
(
'update'
if
force_update
else
'create'
)
undesired_method_name
=
base_string
.
format
(
'create'
if
force_update
else
'update'
)
with
patch
(
desired_method_name
)
as
desired_call
:
with
patch
(
undesired_method_name
)
as
undesired_call
:
set
(
CourseGradeFactory
()
.
iter
(
users
=
[
self
.
request
.
user
],
course
=
self
.
course
,
force_update
=
force_update
))
self
.
assertTrue
(
desired_call
.
called
)
self
.
assertFalse
(
undesired_call
.
called
)
@ddt.ddt
@ddt.ddt
class
TestSubsectionGradeFactory
(
ProblemSubmissionTestMixin
,
GradeTestBase
):
class
TestSubsectionGradeFactory
(
ProblemSubmissionTestMixin
,
GradeTestBase
):
...
...
XuYS
@xys
mentioned in commit
c93df9b0
Dec 21, 2017
mentioned in commit
c93df9b0
mentioned in commit c93df9b04bcd75db3fbcd6fdcccdebf3b3bf1d98
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment