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
ba42c022
Commit
ba42c022
authored
Aug 06, 2012
by
Bridger Maxwell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved the generation of the 'grading context' to a lazy property in course descriptor.
parent
2348f71c
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
123 additions
and
63 deletions
+123
-63
common/djangoapps/util/decorators.py
+37
-0
common/lib/xmodule/xmodule/course_module.py
+63
-12
lms/djangoapps/courseware/grades.py
+20
-43
lms/djangoapps/courseware/views.py
+3
-8
No files found.
common/djangoapps/util/decorators.py
0 → 100644
View file @
ba42c022
def
lazyproperty
(
fn
):
"""
Use this decorator for lazy generation of properties that
are expensive to compute. From http://stackoverflow.com/a/3013910/86828
Example:
class Test(object):
@lazyproperty
def a(self):
print 'generating "a"'
return range(5)
Interactive Session:
>>> t = Test()
>>> t.__dict__
{}
>>> t.a
generating "a"
[0, 1, 2, 3, 4]
>>> t.__dict__
{'_lazy_a': [0, 1, 2, 3, 4]}
>>> t.a
[0, 1, 2, 3, 4]
"""
attr_name
=
'_lazy_'
+
fn
.
__name__
@property
def
_lazyprop
(
self
):
if
not
hasattr
(
self
,
attr_name
):
setattr
(
self
,
attr_name
,
fn
(
self
))
return
getattr
(
self
,
attr_name
)
return
_lazyprop
\ No newline at end of file
common/lib/xmodule/xmodule/course_module.py
View file @
ba42c022
...
...
@@ -3,6 +3,7 @@ import time
import
dateutil.parser
import
logging
from
util.decorators
import
lazyproperty
from
xmodule.graders
import
load_grading_policy
from
xmodule.modulestore
import
Location
from
xmodule.seq_module
import
SequenceDescriptor
,
SequenceModule
...
...
@@ -17,9 +18,6 @@ class CourseDescriptor(SequenceDescriptor):
def
__init__
(
self
,
system
,
definition
=
None
,
**
kwargs
):
super
(
CourseDescriptor
,
self
)
.
__init__
(
system
,
definition
,
**
kwargs
)
self
.
_grader
=
None
self
.
_grade_cutoffs
=
None
msg
=
None
try
:
self
.
start
=
time
.
strptime
(
self
.
metadata
[
"start"
],
"
%
Y-
%
m-
%
dT
%
H:
%
M"
)
...
...
@@ -42,17 +40,14 @@ class CourseDescriptor(SequenceDescriptor):
@property
def
grader
(
self
):
self
.
__load_grading_policy
()
return
self
.
_grader
return
self
.
__grading_policy
[
'GRADER'
]
@property
def
grade_cutoffs
(
self
):
self
.
__load_grading_policy
()
return
self
.
_grade_cutoffs
return
self
.
__grading_policy
[
'GRADE_CUTOFFS'
]
def
__load_grading_policy
(
self
):
if
not
self
.
_grader
or
not
self
.
_grade_cutoffs
:
@lazyproperty
def
__grading_policy
(
self
)
:
policy_string
=
""
try
:
...
...
@@ -63,8 +58,64 @@ class CourseDescriptor(SequenceDescriptor):
grading_policy
=
load_grading_policy
(
policy_string
)
self
.
_grader
=
grading_policy
[
'GRADER'
]
self
.
_grade_cutoffs
=
grading_policy
[
'GRADE_CUTOFFS'
]
return
grading_policy
@lazyproperty
def
grading_context
(
self
):
"""
This returns a dictionary with keys necessary for quickly grading
a student. They are used by grades.grade()
The grading context has two keys:
graded_sections - This contains the sections that are graded, as
well as all possible children modules that can effect the
grading. This allows some sections to be skipped if the student
hasn't seen any part of it.
The format is a dictionary keyed by section-type. The values are
arrays of dictionaries containing
"section_descriptor" : The section descriptor
"xmoduledescriptors" : An array of xmoduledescriptors that
could possibly be in the section, for any student
all_descriptors - This contains a list of all xmodules that can
effect grading a student. This is used to efficiently fetch
all the xmodule state for a StudentModuleCache without walking
the descriptor tree again.
"""
all_descriptors
=
[]
graded_sections
=
{}
def
yield_descriptor_descendents
(
module_descriptor
):
for
child
in
module_descriptor
.
get_children
():
yield
child
for
module_descriptor
in
yield_descriptor_descendents
(
child
):
yield
module_descriptor
for
c
in
self
.
get_children
():
sections
=
[]
for
s
in
c
.
get_children
():
if
s
.
metadata
.
get
(
'graded'
,
False
):
xmoduledescriptors
=
[]
for
module
in
yield_descriptor_descendents
(
s
):
# TODO: Only include modules that have a score here
xmoduledescriptors
.
append
(
module
)
section_description
=
{
'section_descriptor'
:
s
,
'xmoduledescriptors'
:
xmoduledescriptors
}
section_format
=
s
.
metadata
.
get
(
'format'
,
""
)
graded_sections
[
section_format
]
=
graded_sections
.
get
(
section_format
,
[]
)
+
[
section_description
]
all_descriptors
.
extend
(
xmoduledescriptors
)
all_descriptors
.
append
(
s
)
return
{
'graded_sections'
:
graded_sections
,
'all_descriptors'
:
all_descriptors
,}
@staticmethod
...
...
lms/djangoapps/courseware/grades.py
View file @
ba42c022
...
...
@@ -3,6 +3,7 @@ import logging
from
django.conf
import
settings
from
models
import
StudentModuleCache
from
module_render
import
get_module
,
get_instance_module
from
xmodule
import
graders
from
xmodule.graders
import
Score
...
...
@@ -10,54 +11,28 @@ from models import StudentModule
_log
=
logging
.
getLogger
(
"mitx.courseware"
)
def
get_graded_sections
(
course_descriptor
):
"""
Arguments:
course_descriptor: a CourseDescriptor object for the course to be graded
Returns:
A dictionary keyed by section-type. The values are arrays of dictionaries containing
"section_descriptor" : The section descriptor
"xmoduledescriptors" : An array of xmoduledescriptors that could possibly be in the section, for any student
"""
all_descriptors
=
[]
graded_sections
=
{}
for
c
in
course_descriptor
.
get_children
():
sections
=
[]
for
s
in
c
.
get_children
():
if
s
.
metadata
.
get
(
'graded'
,
False
):
xmoduledescriptors
=
[]
for
module
in
yield_descriptor_descendents
(
s
):
# TODO: Only include modules that have a score here
xmoduledescriptors
.
append
(
module
)
section_description
=
{
'section_descriptor'
:
s
,
'xmoduledescriptors'
:
xmoduledescriptors
}
section_format
=
s
.
metadata
.
get
(
'format'
,
""
)
graded_sections
[
section_format
]
=
graded_sections
.
get
(
section_format
,
[]
)
+
[
section_description
]
all_descriptors
.
extend
(
xmoduledescriptors
)
all_descriptors
.
append
(
s
)
return
graded_sections
,
all_descriptors
def
yield_descriptor_descendents
(
module_descriptor
):
for
child
in
module_descriptor
.
get_children
():
yield
child
for
module_descriptor
in
yield_descriptor_descendents
(
child
):
yield
module_descriptor
def
yield_module_descendents
(
module
):
for
child
in
module
.
get_display_items
():
yield
child
for
module
in
yield_module_descendents
(
child
):
yield
module
def
fast_grade
(
student
,
request
,
course_graded_sections
,
grader
,
student_module_cache
):
def
grade
(
student
,
request
,
course
,
student_module_cache
=
None
):
"""
This grades a student as quickly as possible. It reutns the
output from the course grader. More information on the format
is in the docstring for CourseGrader.
"""
grading_context
=
course
.
grading_context
if
student_module_cache
==
None
:
student_module_cache
=
StudentModuleCache
(
student
,
descriptors
=
grading_context
[
'all_descriptors'
])
totaled_scores
=
{}
for
section_format
,
sections
in
course_graded_sections
.
iteritems
():
# This next complicated loop is just to collect the totaled_scores, which is
# passed to the grader
for
section_format
,
sections
in
grading_context
[
'graded_sections'
]
.
iteritems
():
format_scores
=
[]
for
section
in
sections
:
section_descriptor
=
section
[
'section_descriptor'
]
...
...
@@ -72,6 +47,8 @@ def fast_grade(student, request, course_graded_sections, grader, student_module_
if
should_grade_section
:
scores
=
[]
# TODO: We need the request to pass into here. If we could forgo that, our arguments
# would be simpler
section_module
=
get_module
(
student
,
request
,
section_descriptor
.
location
,
student_module_cache
)
# TODO: We may be able to speed this up by only getting a list of children IDs from section_module
...
...
@@ -106,11 +83,11 @@ def fast_grade(student, request, course_graded_sections, grader, student_module_
totaled_scores
[
section_format
]
=
format_scores
grade_summary
=
grade_summary
=
grader
.
grade
(
totaled_scores
)
grade_summary
=
course
.
grader
.
grade
(
totaled_scores
)
return
grade_summary
def
grade_sheet
(
student
,
course
,
grader
,
student_module_cache
):
def
progress_summary
(
student
,
course
,
grader
,
student_module_cache
):
"""
This pulls a summary of all problems in the course.
...
...
lms/djangoapps/courseware/views.py
View file @
ba42c022
...
...
@@ -78,20 +78,16 @@ def gradebook(request, course_id):
raise
Http404
course
=
check_course
(
course_id
)
sections
,
all_descriptors
=
grades
.
get_graded_sections
(
course
)
student_objects
=
User
.
objects
.
all
()[:
100
]
student_info
=
[]
#TODO: Only select students who are in the course
for
student
in
student_objects
:
student_module_cache
=
StudentModuleCache
(
student
,
descriptors
=
all_descriptors
)
student_info
.
append
({
'username'
:
student
.
username
,
'id'
:
student
.
id
,
'email'
:
student
.
email
,
'grade_summary'
:
grades
.
fast_grade
(
student
,
request
,
sections
,
course
.
grader
,
student_module_cach
e
),
'grade_summary'
:
grades
.
grade
(
student
,
request
,
cours
e
),
'realname'
:
UserProfile
.
objects
.
get
(
user
=
student
)
.
name
})
...
...
@@ -117,9 +113,8 @@ def profile(request, course_id, student_id=None):
student_module_cache
=
StudentModuleCache
(
request
.
user
,
course
)
course_module
=
get_module
(
request
.
user
,
request
,
course
.
location
,
student_module_cache
)
courseware_summary
=
grades
.
grade_sheet
(
student
,
course_module
,
course
.
grader
,
student_module_cache
)
sections
,
_
=
grades
.
get_graded_sections
(
course
)
grade_summary
=
grades
.
fast_grade
(
request
.
user
,
request
,
sections
,
course
.
grader
,
student_module_cache
)
courseware_summary
=
grades
.
progress_summary
(
student
,
course_module
,
course
.
grader
,
student_module_cache
)
grade_summary
=
grades
.
grade
(
request
.
user
,
request
,
course
,
student_module_cache
)
context
=
{
'name'
:
user_info
.
name
,
'username'
:
student
.
username
,
...
...
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