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
47e3c6d4
Commit
47e3c6d4
authored
Sep 23, 2016
by
Nimisha Asthagiri
Committed by
GitHub
Sep 23, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13562 from edx/efischer/rm_dash_rf
Remove offline grade calc
parents
8930376b
8857b35b
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
2 additions
and
280 deletions
+2
-280
lms/djangoapps/instructor/management/__init__.py
+0
-0
lms/djangoapps/instructor/management/commands/__init__.py
+0
-0
lms/djangoapps/instructor/management/commands/compute_grades.py
+0
-50
lms/djangoapps/instructor/management/tests/__init__.py
+0
-3
lms/djangoapps/instructor/offline_gradecalc.py
+0
-117
lms/djangoapps/instructor/tests/test_offline_gradecalc.py
+0
-107
lms/djangoapps/instructor/views/gradebook_api.py
+2
-2
lms/djangoapps/instructor/views/instructor_dashboard.py
+0
-1
No files found.
lms/djangoapps/instructor/management/__init__.py
deleted
100644 → 0
View file @
8930376b
lms/djangoapps/instructor/management/commands/__init__.py
deleted
100644 → 0
View file @
8930376b
lms/djangoapps/instructor/management/commands/compute_grades.py
deleted
100644 → 0
View file @
8930376b
#!/usr/bin/python
"""
django management command: dump grades to csv files
for use by batch processes
"""
from
instructor.offline_gradecalc
import
offline_grade_calculation
from
courseware.courses
import
get_course_by_id
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
django.core.management.base
import
BaseCommand
class
Command
(
BaseCommand
):
help
=
"Compute grades for all students in a course, and store result in DB.
\n
"
help
+=
"Usage: compute_grades course_id_or_dir
\n
"
help
+=
" course_id_or_dir: either course_id or course_dir
\n
"
help
+=
'Example course_id: MITx/8.01rq_MW/Classical_Mechanics_Reading_Questions_Fall_2012_MW_Section'
def
handle
(
self
,
*
args
,
**
options
):
print
"args = "
,
args
if
len
(
args
)
>
0
:
course_id
=
args
[
0
]
else
:
print
self
.
help
return
course_key
=
None
# parse out the course id into a coursekey
try
:
course_key
=
CourseKey
.
from_string
(
course_id
)
# if it's not a new-style course key, parse it from an old-style
# course key
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
_course
=
get_course_by_id
(
course_key
)
except
Exception
as
err
:
print
"-----------------------------------------------------------------------------"
print
"Sorry, cannot find course with id {}"
.
format
(
course_id
)
print
"Got exception {}"
.
format
(
err
)
print
"Please provide a course ID or course data directory name, eg content-mit-801rq"
return
print
"-----------------------------------------------------------------------------"
print
"Computing grades for {}"
.
format
(
course_id
)
offline_grade_calculation
(
course_key
)
lms/djangoapps/instructor/management/tests/__init__.py
deleted
100644 → 0
View file @
8930376b
"""
Tests for the instructor app management commands.
"""
lms/djangoapps/instructor/offline_gradecalc.py
deleted
100644 → 0
View file @
8930376b
"""
======== Offline calculation of grades =============================================================
Computing grades of a large number of students can take a long time. These routines allow grades to
be computed offline, by a batch process (eg cronjob).
The grades are stored in the OfflineComputedGrade table of the courseware model.
"""
import
json
import
time
from
json
import
JSONEncoder
from
courseware
import
models
from
courseware.courses
import
get_course_by_id
from
django.contrib.auth.models
import
User
from
lms.djangoapps.grades
import
course_grades
from
opaque_keys
import
OpaqueKey
from
opaque_keys.edx.keys
import
UsageKey
from
xmodule.graders
import
Score
from
instructor.utils
import
DummyRequest
class
MyEncoder
(
JSONEncoder
):
""" JSON Encoder that can encode OpaqueKeys """
def
default
(
self
,
obj
):
# pylint: disable=method-hidden
""" Encode an object that the default encoder hasn't been able to. """
if
isinstance
(
obj
,
OpaqueKey
):
return
unicode
(
obj
)
return
JSONEncoder
.
default
(
self
,
obj
)
def
offline_grade_calculation
(
course_key
):
'''
Compute grades for all students for a specified course, and save results to the DB.
'''
tstart
=
time
.
time
()
enrolled_students
=
User
.
objects
.
filter
(
courseenrollment__course_id
=
course_key
,
courseenrollment__is_active
=
1
)
.
prefetch_related
(
"groups"
)
.
order_by
(
'username'
)
enc
=
MyEncoder
()
print
"{} enrolled students"
.
format
(
len
(
enrolled_students
))
course
=
get_course_by_id
(
course_key
)
for
student
in
enrolled_students
:
request
=
DummyRequest
()
request
.
user
=
student
request
.
session
=
{}
gradeset
=
course_grades
.
summary
(
student
,
course
)
# Convert Score namedtuples to dicts:
totaled_scores
=
gradeset
[
'totaled_scores'
]
for
section
in
totaled_scores
:
totaled_scores
[
section
]
=
[
score
.
_asdict
()
for
score
in
totaled_scores
[
section
]]
gradeset
[
'raw_scores'
]
=
[
score
.
_asdict
()
for
score
in
gradeset
[
'raw_scores'
]]
# Encode as JSON and save:
gradeset_str
=
enc
.
encode
(
gradeset
)
ocg
,
_created
=
models
.
OfflineComputedGrade
.
objects
.
get_or_create
(
user
=
student
,
course_id
=
course_key
)
ocg
.
gradeset
=
gradeset_str
ocg
.
save
()
print
"
%
s done"
%
student
# print statement used because this is run by a management command
tend
=
time
.
time
()
dt
=
tend
-
tstart
ocgl
=
models
.
OfflineComputedGradeLog
(
course_id
=
course_key
,
seconds
=
dt
,
nstudents
=
len
(
enrolled_students
))
ocgl
.
save
()
print
ocgl
print
"All Done!"
def
offline_grades_available
(
course_key
):
'''
Returns False if no offline grades available for specified course.
Otherwise returns latest log field entry about the available pre-computed grades.
'''
ocgl
=
models
.
OfflineComputedGradeLog
.
objects
.
filter
(
course_id
=
course_key
)
if
not
ocgl
:
return
False
return
ocgl
.
latest
(
'created'
)
def
student_grades
(
student
,
request
,
course
,
use_offline
=
False
):
# pylint: disable=unused-argument
'''
This is the main interface to get grades. It has the same parameters as grades.grade, as well
as use_offline. If use_offline is True then this will look for an offline computed gradeset in the DB.
'''
if
not
use_offline
:
return
course_grades
.
summary
(
student
,
course
)
try
:
ocg
=
models
.
OfflineComputedGrade
.
objects
.
get
(
user
=
student
,
course_id
=
course
.
id
)
except
models
.
OfflineComputedGrade
.
DoesNotExist
:
return
dict
(
raw_scores
=
[],
section_breakdown
=
[],
msg
=
'Error: no offline gradeset available for {}, {}'
.
format
(
student
,
course
.
id
)
)
gradeset
=
json
.
loads
(
ocg
.
gradeset
)
# Convert score dicts back to Score tuples:
def
score_from_dict
(
encoded
):
""" Given a formerly JSON-encoded Score tuple, return the Score tuple """
if
encoded
[
'module_id'
]:
encoded
[
'module_id'
]
=
UsageKey
.
from_string
(
encoded
[
'module_id'
])
return
Score
(
**
encoded
)
totaled_scores
=
gradeset
[
'totaled_scores'
]
for
section
in
totaled_scores
:
totaled_scores
[
section
]
=
[
score_from_dict
(
score
)
for
score
in
totaled_scores
[
section
]]
gradeset
[
'raw_scores'
]
=
[
score_from_dict
(
score
)
for
score
in
gradeset
[
'raw_scores'
]]
return
gradeset
lms/djangoapps/instructor/tests/test_offline_gradecalc.py
deleted
100644 → 0
View file @
8930376b
"""
Tests for offline_gradecalc.py
"""
import
json
from
mock
import
patch
from
courseware.models
import
OfflineComputedGrade
from
student.models
import
CourseEnrollment
from
student.tests.factories
import
UserFactory
from
xmodule.graders
import
Score
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
..offline_gradecalc
import
offline_grade_calculation
,
student_grades
def
mock_grade
(
_student
,
course
,
**
_kwargs
):
""" Return some fake grade data to mock grades.grade() """
return
{
'grade'
:
u'Pass'
,
'totaled_scores'
:
{
u'Homework'
:
[
Score
(
earned
=
10.0
,
possible
=
10.0
,
graded
=
True
,
section
=
u'Subsection 1'
,
module_id
=
None
),
]
},
'percent'
:
0.85
,
'raw_scores'
:
[
Score
(
earned
=
5.0
,
possible
=
5.0
,
graded
=
True
,
section
=
u'Numerical Input'
,
module_id
=
course
.
id
.
make_usage_key
(
'problem'
,
'problem1'
),
),
Score
(
earned
=
5.0
,
possible
=
5.0
,
graded
=
True
,
section
=
u'Multiple Choice'
,
module_id
=
course
.
id
.
make_usage_key
(
'problem'
,
'problem2'
),
),
],
'section_breakdown'
:
[
{
'category'
:
u'Homework'
,
'percent'
:
1.0
,
'detail'
:
u'Homework 1 - Test - 100
%
(10/10)'
,
'label'
:
u'HW 01'
},
{
'category'
:
u'Final Exam'
,
'prominent'
:
True
,
'percent'
:
0
,
'detail'
:
u'Final = 0
%
'
,
'label'
:
u'Final'
}
],
'grade_breakdown'
:
[
{
'category'
:
u'Homework'
,
'percent'
:
0.85
,
'detail'
:
u'Homework = 85.00
%
of a possible 85.00
%
'
},
{
'category'
:
u'Final Exam'
,
'percent'
:
0.0
,
'detail'
:
u'Final Exam = 0.00
%
of a possible 15.00
%
'
}
]
}
class
TestOfflineGradeCalc
(
ModuleStoreTestCase
):
""" Test Offline Grade Calculation with some mocked grades """
def
setUp
(
self
):
super
(
TestOfflineGradeCalc
,
self
)
.
setUp
()
with
modulestore
()
.
default_store
(
ModuleStoreEnum
.
Type
.
split
):
# Test with split b/c old mongo keys are messy
self
.
course
=
CourseFactory
.
create
()
self
.
user
=
UserFactory
.
create
()
CourseEnrollment
.
enroll
(
self
.
user
,
self
.
course
.
id
)
patcher
=
patch
(
'lms.djangoapps.grades.course_grades.summary'
,
new
=
mock_grade
)
patcher
.
start
()
self
.
addCleanup
(
patcher
.
stop
)
def
test_output
(
self
):
offline_grades
=
OfflineComputedGrade
.
objects
self
.
assertEqual
(
offline_grades
.
filter
(
user
=
self
.
user
,
course_id
=
self
.
course
.
id
)
.
count
(),
0
)
offline_grade_calculation
(
self
.
course
.
id
)
result
=
offline_grades
.
get
(
user
=
self
.
user
,
course_id
=
self
.
course
.
id
)
decoded
=
json
.
loads
(
result
.
gradeset
)
self
.
assertEqual
(
decoded
[
'grade'
],
"Pass"
)
self
.
assertEqual
(
decoded
[
'percent'
],
0.85
)
self
.
assertEqual
(
decoded
[
'totaled_scores'
],
{
"Homework"
:
[
{
"earned"
:
10.0
,
"possible"
:
10.0
,
"graded"
:
True
,
"section"
:
"Subsection 1"
,
"module_id"
:
None
}
]
})
self
.
assertEqual
(
decoded
[
'raw_scores'
],
[
{
"earned"
:
5.0
,
"possible"
:
5.0
,
"graded"
:
True
,
"section"
:
"Numerical Input"
,
"module_id"
:
unicode
(
self
.
course
.
id
.
make_usage_key
(
'problem'
,
'problem1'
)),
},
{
"earned"
:
5.0
,
"possible"
:
5.0
,
"graded"
:
True
,
"section"
:
"Multiple Choice"
,
"module_id"
:
unicode
(
self
.
course
.
id
.
make_usage_key
(
'problem'
,
'problem2'
)),
}
])
self
.
assertEqual
(
decoded
[
'section_breakdown'
],
[
{
"category"
:
"Homework"
,
"percent"
:
1.0
,
"detail"
:
"Homework 1 - Test - 100
%
(10/10)"
,
"label"
:
"HW 01"
},
{
"category"
:
"Final Exam"
,
"label"
:
"Final"
,
"percent"
:
0
,
"detail"
:
"Final = 0
%
"
,
"prominent"
:
True
}
])
self
.
assertEqual
(
decoded
[
'grade_breakdown'
],
[
{
"category"
:
"Homework"
,
"percent"
:
0.85
,
"detail"
:
"Homework = 85.00
%
of a possible 85.00
%
"
},
{
"category"
:
"Final Exam"
,
"percent"
:
0.0
,
"detail"
:
"Final Exam = 0.00
%
of a possible 15.00
%
"
}
])
def
test_student_grades
(
self
):
""" Test that the data returned by student_grades() and grades.grade() match """
offline_grade_calculation
(
self
.
course
.
id
)
with
patch
(
'lms.djangoapps.grades.course_grades.summary'
,
side_effect
=
AssertionError
(
'Should not re-grade'
)):
result
=
student_grades
(
self
.
user
,
None
,
self
.
course
,
use_offline
=
True
)
self
.
assertEqual
(
result
,
mock_grade
(
self
.
user
,
self
.
course
))
lms/djangoapps/instructor/views/gradebook_api.py
View file @
47e3c6d4
...
@@ -13,8 +13,8 @@ from opaque_keys.edx.keys import CourseKey
...
@@ -13,8 +13,8 @@ from opaque_keys.edx.keys import CourseKey
from
edxmako.shortcuts
import
render_to_response
from
edxmako.shortcuts
import
render_to_response
from
courseware.courses
import
get_course_with_access
from
courseware.courses
import
get_course_with_access
from
instructor.offline_gradecalc
import
student_grades
from
instructor.views.api
import
require_level
from
instructor.views.api
import
require_level
from
lms.djangoapps.grades
import
course_grades
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
@@ -91,7 +91,7 @@ def get_grade_book_page(request, course, course_key):
...
@@ -91,7 +91,7 @@ def get_grade_book_page(request, course, course_key):
'username'
:
student
.
username
,
'username'
:
student
.
username
,
'id'
:
student
.
id
,
'id'
:
student
.
id
,
'email'
:
student
.
email
,
'email'
:
student
.
email
,
'grade_summary'
:
student_grades
(
student
,
request
,
course
),
'grade_summary'
:
course_grades
.
summary
(
student
,
course
)
}
}
for
student
in
enrolled_students
for
student
in
enrolled_students
]
]
...
...
lms/djangoapps/instructor/views/instructor_dashboard.py
View file @
47e3c6d4
...
@@ -437,7 +437,6 @@ def _section_course_info(course, access):
...
@@ -437,7 +437,6 @@ def _section_course_info(course, access):
section_data
[
'grade_cutoffs'
]
=
reduce
(
advance
,
sorted_cutoffs
,
""
)[:
-
2
]
section_data
[
'grade_cutoffs'
]
=
reduce
(
advance
,
sorted_cutoffs
,
""
)[:
-
2
]
except
Exception
:
# pylint: disable=broad-except
except
Exception
:
# pylint: disable=broad-except
section_data
[
'grade_cutoffs'
]
=
"Not Available"
section_data
[
'grade_cutoffs'
]
=
"Not Available"
# section_data['offline_grades'] = offline_grades_available(course_key)
try
:
try
:
section_data
[
'course_errors'
]
=
[(
escape
(
a
),
''
)
for
(
a
,
_unused
)
in
modulestore
()
.
get_course_errors
(
course
.
id
)]
section_data
[
'course_errors'
]
=
[(
escape
(
a
),
''
)
for
(
a
,
_unused
)
in
modulestore
()
.
get_course_errors
(
course
.
id
)]
...
...
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