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
27229a1f
Commit
27229a1f
authored
Oct 03, 2017
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Optimize grade reports for ZeroCourseGrades.
EDUCATOR-558
parent
0b1d22f0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
59 additions
and
8 deletions
+59
-8
lms/djangoapps/grades/course_grade.py
+20
-0
lms/djangoapps/grades/subsection_grade.py
+15
-0
lms/djangoapps/grades/tests/test_course_grade_factory.py
+1
-1
lms/djangoapps/instructor_task/tasks_helper/grades.py
+3
-5
lms/djangoapps/instructor_task/tests/test_integration.py
+1
-1
lms/djangoapps/instructor_task/tests/test_tasks_helper.py
+19
-1
No files found.
lms/djangoapps/grades/course_grade.py
View file @
27229a1f
...
@@ -44,6 +44,20 @@ class CourseGradeBase(object):
...
@@ -44,6 +44,20 @@ class CourseGradeBase(object):
"""
"""
return
False
return
False
def
subsection_grade
(
self
,
subsection_key
):
"""
Returns the subsection grade for given subsection usage key.
Raises KeyError if the user doesn't have access to that subsection.
"""
return
self
.
_get_subsection_grade
(
self
.
course_data
.
structure
[
subsection_key
])
@abstractmethod
def
assignment_average
(
self
,
assignment_type
):
"""
Returns the average of all assignments of the given assignment type.
"""
raise
NotImplementedError
@lazy
@lazy
def
graded_subsections_by_format
(
self
):
def
graded_subsections_by_format
(
self
):
"""
"""
...
@@ -207,6 +221,9 @@ class ZeroCourseGrade(CourseGradeBase):
...
@@ -207,6 +221,9 @@ class ZeroCourseGrade(CourseGradeBase):
Course Grade class for Zero-value grades when no problems were
Course Grade class for Zero-value grades when no problems were
attempted in the course.
attempted in the course.
"""
"""
def
assignment_average
(
self
,
assignment_type
):
return
0.0
def
_get_subsection_grade
(
self
,
subsection
):
def
_get_subsection_grade
(
self
,
subsection
):
return
ZeroSubsectionGrade
(
subsection
,
self
.
course_data
)
return
ZeroSubsectionGrade
(
subsection
,
self
.
course_data
)
...
@@ -248,6 +265,9 @@ class CourseGrade(CourseGradeBase):
...
@@ -248,6 +265,9 @@ class CourseGrade(CourseGradeBase):
return
True
return
True
return
False
return
False
def
assignment_average
(
self
,
assignment_type
):
return
self
.
grader_result
[
'grade_breakdown'
]
.
get
(
assignment_type
,
{})
.
get
(
'percent'
)
def
_get_subsection_grade
(
self
,
subsection
):
def
_get_subsection_grade
(
self
,
subsection
):
if
self
.
force_update_subsections
:
if
self
.
force_update_subsections
:
return
self
.
_subsection_grade_factory
.
update
(
subsection
)
return
self
.
_subsection_grade_factory
.
update
(
subsection
)
...
...
lms/djangoapps/grades/subsection_grade.py
View file @
27229a1f
...
@@ -53,6 +53,13 @@ class SubsectionGradeBase(object):
...
@@ -53,6 +53,13 @@ class SubsectionGradeBase(object):
"""
"""
return
ShowCorrectness
.
correctness_available
(
self
.
show_correctness
,
self
.
due
,
has_staff_access
)
return
ShowCorrectness
.
correctness_available
(
self
.
show_correctness
,
self
.
due
,
has_staff_access
)
@property
def
attempted_graded
(
self
):
"""
Returns whether the user had attempted a graded problem in this subsection.
"""
raise
NotImplementedError
class
ZeroSubsectionGrade
(
SubsectionGradeBase
):
class
ZeroSubsectionGrade
(
SubsectionGradeBase
):
"""
"""
...
@@ -64,6 +71,10 @@ class ZeroSubsectionGrade(SubsectionGradeBase):
...
@@ -64,6 +71,10 @@ class ZeroSubsectionGrade(SubsectionGradeBase):
self
.
course_data
=
course_data
self
.
course_data
=
course_data
@property
@property
def
attempted_graded
(
self
):
return
False
@property
def
all_total
(
self
):
def
all_total
(
self
):
return
self
.
_aggregate_scores
[
0
]
return
self
.
_aggregate_scores
[
0
]
...
@@ -174,6 +185,10 @@ class SubsectionGrade(SubsectionGradeBase):
...
@@ -174,6 +185,10 @@ class SubsectionGrade(SubsectionGradeBase):
self
.
_log_event
(
log
.
debug
,
u"update_or_create_model"
,
student
)
self
.
_log_event
(
log
.
debug
,
u"update_or_create_model"
,
student
)
return
PersistentSubsectionGrade
.
update_or_create_grade
(
**
self
.
_persisted_model_params
(
student
))
return
PersistentSubsectionGrade
.
update_or_create_grade
(
**
self
.
_persisted_model_params
(
student
))
@property
def
attempted_graded
(
self
):
return
self
.
graded_total
.
first_attempted
is
not
None
def
_should_persist_per_attempted
(
self
,
score_deleted
=
False
):
def
_should_persist_per_attempted
(
self
,
score_deleted
=
False
):
"""
"""
Returns whether the SubsectionGrade's model should be
Returns whether the SubsectionGrade's model should be
...
...
lms/djangoapps/grades/tests/test_course_grade_factory.py
View file @
27229a1f
...
@@ -36,7 +36,7 @@ class TestCourseGradeFactory(GradeTestBase):
...
@@ -36,7 +36,7 @@ class TestCourseGradeFactory(GradeTestBase):
def
test_course_grade_no_access
(
self
):
def
test_course_grade_no_access
(
self
):
"""
"""
Test to ensure a grade can b
a
calculated for a student in a course, even if they themselves do not have access.
Test to ensure a grade can b
e
calculated for a student in a course, even if they themselves do not have access.
"""
"""
invisible_course
=
CourseFactory
.
create
(
visible_to_staff_only
=
True
)
invisible_course
=
CourseFactory
.
create
(
visible_to_staff_only
=
True
)
access
=
has_access
(
self
.
request
.
user
,
'load'
,
invisible_course
)
access
=
has_access
(
self
.
request
.
user
,
'load'
,
invisible_course
)
...
...
lms/djangoapps/instructor_task/tasks_helper/grades.py
View file @
27229a1f
...
@@ -306,19 +306,17 @@ class CourseGradeReport(object):
...
@@ -306,19 +306,17 @@ class CourseGradeReport(object):
for
assignment_type
,
assignment_info
in
context
.
graded_assignments
.
iteritems
():
for
assignment_type
,
assignment_info
in
context
.
graded_assignments
.
iteritems
():
for
subsection_location
in
assignment_info
[
'subsection_headers'
]:
for
subsection_location
in
assignment_info
[
'subsection_headers'
]:
try
:
try
:
subsection_grade
=
course_grade
.
graded_subsections_by_format
[
assignment_type
][
subsection_location
]
subsection_grade
=
course_grade
.
subsection_grade
(
subsection_location
)
except
KeyError
:
except
KeyError
:
grade_result
=
u'Not Available'
grade_result
=
u'Not Available'
else
:
else
:
if
subsection_grade
.
graded_total
.
first_attempted
is
not
None
:
if
subsection_grade
.
attempted_graded
:
grade_result
=
subsection_grade
.
graded_total
.
earned
/
subsection_grade
.
graded_total
.
possible
grade_result
=
subsection_grade
.
graded_total
.
earned
/
subsection_grade
.
graded_total
.
possible
else
:
else
:
grade_result
=
u'Not Attempted'
grade_result
=
u'Not Attempted'
grade_results
.
append
([
grade_result
])
grade_results
.
append
([
grade_result
])
if
assignment_info
[
'separate_subsection_avg_headers'
]:
if
assignment_info
[
'separate_subsection_avg_headers'
]:
assignment_average
=
course_grade
.
grader_result
[
'grade_breakdown'
]
.
get
(
assignment_type
,
{})
.
get
(
assignment_average
=
course_grade
.
assignment_average
(
assignment_type
)
'percent'
)
grade_results
.
append
([
assignment_average
])
grade_results
.
append
([
assignment_average
])
return
[
course_grade
.
percent
]
+
_flatten
(
grade_results
)
return
[
course_grade
.
percent
]
+
_flatten
(
grade_results
)
...
...
lms/djangoapps/instructor_task/tests/test_integration.py
View file @
27229a1f
...
@@ -679,7 +679,7 @@ class TestGradeReportConditionalContent(TestReportMixin, TestConditionalContent,
...
@@ -679,7 +679,7 @@ class TestGradeReportConditionalContent(TestReportMixin, TestConditionalContent,
{
{
self
.
student_b
:
{
self
.
student_b
:
{
u'Grade'
:
'0.0'
,
u'Grade'
:
'0.0'
,
u'Homework'
:
u'Not A
vailable
'
,
u'Homework'
:
u'Not A
ttempted
'
,
}
}
},
},
],
],
...
...
lms/djangoapps/instructor_task/tests/test_tasks_helper.py
View file @
27229a1f
...
@@ -1769,6 +1769,7 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
...
@@ -1769,6 +1769,7 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
with
patch
(
'lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'
):
with
patch
(
'lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'
):
result
=
CourseGradeReport
.
generate
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
result
=
CourseGradeReport
.
generate
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
self
.
assertDictContainsSubset
(
self
.
assertDictContainsSubset
(
{
'action_name'
:
'graded'
,
'attempted'
:
1
,
'succeeded'
:
1
,
'failed'
:
0
},
{
'action_name'
:
'graded'
,
'attempted'
:
1
,
'succeeded'
:
1
,
'failed'
:
0
},
result
,
result
,
...
@@ -1783,13 +1784,30 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
...
@@ -1783,13 +1784,30 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
u'Homework 1: Subsection'
:
'0.5'
,
u'Homework 1: Subsection'
:
'0.5'
,
u'Homework 2: Hidden'
:
u'Not Available'
,
u'Homework 2: Hidden'
:
u'Not Available'
,
u'Homework 3: Unattempted'
:
u'Not Attempted'
,
u'Homework 3: Unattempted'
:
u'Not Attempted'
,
u'Homework 4: Empty'
:
u'Not A
vailable
'
,
u'Homework 4: Empty'
:
u'Not A
ttempted
'
,
u'Homework (Avg)'
:
'0.125'
,
u'Homework (Avg)'
:
'0.125'
,
},
},
],
],
ignore_other_columns
=
True
,
ignore_other_columns
=
True
,
)
)
def
test_fast_generation_zero_grade
(
self
):
with
patch
(
'lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'
):
with
patch
(
'lms.djangoapps.grades.course_grade.CourseGradeBase._prep_course_for_grading'
)
as
mock_grader
:
with
patch
(
'lms.djangoapps.grades.subsection_grade.get_score'
)
as
mock_get_score
:
CourseGradeReport
.
generate
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
self
.
assertFalse
(
mock_grader
.
called
)
self
.
assertFalse
(
mock_get_score
.
called
)
def
test_slow_generation_nonzero_grade
(
self
):
self
.
submit_student_answer
(
self
.
student
.
username
,
u'Problem1'
,
[
'Option 1'
])
with
patch
(
'lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'
):
with
patch
(
'lms.djangoapps.grades.course_grade.CourseGradeBase._prep_course_for_grading'
)
as
mock_grader
:
with
patch
(
'lms.djangoapps.grades.subsection_grade.get_score'
)
as
mock_get_score
:
CourseGradeReport
.
generate
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
self
.
assertTrue
(
mock_grader
.
called
)
self
.
assertTrue
(
mock_get_score
.
called
)
@ddt.ddt
@ddt.ddt
@patch
(
'lms.djangoapps.instructor_task.tasks_helper.misc.DefaultStorage'
,
new
=
MockDefaultStorage
)
@patch
(
'lms.djangoapps.instructor_task.tasks_helper.misc.DefaultStorage'
,
new
=
MockDefaultStorage
)
...
...
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