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
f8668544
Commit
f8668544
authored
12 years ago
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Load grading policy from policy/{url_name}/grading_policy.json
* with backcompat location /grading_policy.json
parent
eeadf0ba
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
98 additions
and
30 deletions
+98
-30
common/lib/xmodule/xmodule/course_module.py
+14
-19
common/lib/xmodule/xmodule/graders.py
+9
-7
common/lib/xmodule/xmodule/modulestore/xml.py
+37
-4
common/lib/xmodule/xmodule/tests/test_import.py
+3
-0
common/test/data/two_toys/policies/TT_2012_Fall/grading_policy.json
+35
-0
No files found.
common/lib/xmodule/xmodule/course_module.py
View file @
f8668544
...
...
@@ -18,7 +18,7 @@ class CourseDescriptor(SequenceDescriptor):
class
Textbook
:
def
__init__
(
self
,
title
,
book_url
):
self
.
title
=
title
self
.
book_url
=
book_url
self
.
book_url
=
book_url
self
.
table_of_contents
=
self
.
_get_toc_from_s3
()
@classmethod
...
...
@@ -30,11 +30,11 @@ class CourseDescriptor(SequenceDescriptor):
return
self
.
table_of_contents
def
_get_toc_from_s3
(
self
):
'''
"""
Accesses the textbook's table of contents (default name "toc.xml") at the URL self.book_url
Returns XML tree representation of the table of contents
'''
"""
toc_url
=
self
.
book_url
+
'toc.xml'
# Get the table of contents from S3
...
...
@@ -72,6 +72,15 @@ class CourseDescriptor(SequenceDescriptor):
self
.
enrollment_start
=
self
.
_try_parse_time
(
"enrollment_start"
)
self
.
enrollment_end
=
self
.
_try_parse_time
(
"enrollment_end"
)
# NOTE: relies on the modulestore to call set_grading_policy() right after
# init. (Modulestore is in charge of figuring out where to load the policy from)
def
set_grading_policy
(
self
,
policy_str
):
"""Parse the policy specified in policy_str, and save it"""
self
.
_grading_policy
=
load_grading_policy
(
policy_str
)
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
textbooks
=
[]
...
...
@@ -87,25 +96,11 @@ class CourseDescriptor(SequenceDescriptor):
@property
def
grader
(
self
):
return
self
.
_
_
grading_policy
[
'GRADER'
]
return
self
.
_grading_policy
[
'GRADER'
]
@property
def
grade_cutoffs
(
self
):
return
self
.
__grading_policy
[
'GRADE_CUTOFFS'
]
@lazyproperty
def
__grading_policy
(
self
):
policy_string
=
""
try
:
with
self
.
system
.
resources_fs
.
open
(
"grading_policy.json"
)
as
grading_policy_file
:
policy_string
=
grading_policy_file
.
read
()
except
(
IOError
,
ResourceNotFoundError
):
log
.
warning
(
"Unable to load course settings file from grading_policy.json in course "
+
self
.
id
)
grading_policy
=
load_grading_policy
(
policy_string
)
return
grading_policy
return
self
.
_grading_policy
[
'GRADE_CUTOFFS'
]
@lazyproperty
def
grading_context
(
self
):
...
...
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/graders.py
View file @
f8668544
...
...
@@ -14,11 +14,11 @@ def load_grading_policy(course_policy_string):
"""
This loads a grading policy from a string (usually read from a file),
which can be a JSON object or an empty string.
The JSON object can have the keys GRADER and GRADE_CUTOFFS. If either is
missing, it reverts to the default.
"""
default_policy_string
=
"""
{
"GRADER" : [
...
...
@@ -56,7 +56,7 @@ def load_grading_policy(course_policy_string):
}
}
"""
# Load the global settings as a dictionary
grading_policy
=
json
.
loads
(
default_policy_string
)
...
...
@@ -64,15 +64,15 @@ def load_grading_policy(course_policy_string):
course_policy
=
{}
if
course_policy_string
:
course_policy
=
json
.
loads
(
course_policy_string
)
# Override any global settings with the course settings
grading_policy
.
update
(
course_policy
)
# Here is where we should parse any configurations, so that we can fail early
grading_policy
[
'GRADER'
]
=
grader_from_conf
(
grading_policy
[
'GRADER'
])
return
grading_policy
def
aggregate_scores
(
scores
,
section_name
=
"summary"
):
"""
...
...
@@ -130,7 +130,9 @@ def grader_from_conf(conf):
raise
ValueError
(
"Configuration has no appropriate grader class."
)
except
(
TypeError
,
ValueError
)
as
error
:
errorString
=
"Unable to parse grader configuration:
\n
"
+
str
(
subgraderconf
)
+
"
\n
Error was:
\n
"
+
str
(
error
)
errorString
=
(
"Unable to parse grader configuration:
\n
"
+
str
(
subgraderconf
)
+
"
\n
Error was:
\n
"
+
str
(
error
))
log
.
critical
(
errorString
)
raise
ValueError
(
errorString
)
...
...
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
f8668544
...
...
@@ -4,16 +4,17 @@ import os
import
re
from
collections
import
defaultdict
from
cStringIO
import
StringIO
from
fs.osfs
import
OSFS
from
importlib
import
import_module
from
lxml
import
etree
from
lxml.html
import
HtmlComment
from
path
import
path
from
xmodule.errortracker
import
ErrorLog
,
make_error_tracker
from
xmodule.x_module
import
XModuleDescriptor
,
XMLParsingSystem
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.mako_module
import
MakoDescriptorSystem
from
cStringIO
import
StringIO
from
xmodule.x_module
import
XModuleDescriptor
,
XMLParsingSystem
from
.
import
ModuleStoreBase
,
Location
from
.exceptions
import
ItemNotFoundError
...
...
@@ -202,6 +203,27 @@ class XMLModuleStore(ModuleStoreBase):
return
{}
def
read_grading_policy
(
self
,
paths
,
tracker
):
"""Load a grading policy from the specified paths, in order, if it exists."""
# Default to a blank policy
policy_str
=
""
for
policy_path
in
paths
:
if
not
os
.
path
.
exists
(
policy_path
):
continue
try
:
with
open
(
policy_path
)
as
grading_policy_file
:
policy_str
=
grading_policy_file
.
read
()
# if we successfully read the file, stop looking at backups
break
except
(
IOError
):
msg
=
"Unable to load course settings file from '{0}'"
.
format
(
policy_path
)
tracker
(
msg
)
log
.
warning
(
msg
)
return
policy_str
def
load_course
(
self
,
course_dir
,
tracker
):
"""
Load a course into this module store
...
...
@@ -242,9 +264,11 @@ class XMLModuleStore(ModuleStoreBase):
course
=
course_dir
url_name
=
course_data
.
get
(
'url_name'
,
course_data
.
get
(
'slug'
))
policy_dir
=
None
if
url_name
:
old_policy_path
=
self
.
data_dir
/
course_dir
/
'policies'
/
url_name
/
'policy.json'
policy
=
self
.
load_policy
(
old_policy_path
,
tracker
)
policy_dir
=
self
.
data_dir
/
course_dir
/
'policies'
/
url_name
policy_path
=
policy_dir
/
'policy.json'
policy
=
self
.
load_policy
(
policy_path
,
tracker
)
# VS[compat]: remove once courses use the policy dirs.
if
policy
==
{}:
...
...
@@ -273,6 +297,15 @@ class XMLModuleStore(ModuleStoreBase):
# after we have the course descriptor.
XModuleDescriptor
.
compute_inherited_metadata
(
course_descriptor
)
# Try to load grading policy
paths
=
[
self
.
data_dir
/
'grading_policy.json'
]
if
policy_dir
:
paths
=
[
policy_dir
/
'grading_policy.json'
]
+
paths
policy_str
=
self
.
read_grading_policy
(
paths
,
tracker
)
course_descriptor
.
set_grading_policy
(
policy_str
)
log
.
debug
(
'========> Done with course import from {0}'
.
format
(
course_dir
))
return
course_descriptor
...
...
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/tests/test_import.py
View file @
f8668544
...
...
@@ -233,6 +233,9 @@ class ImportTestCase(unittest.TestCase):
self
.
assertEqual
(
toy_ch
.
display_name
,
"Overview"
)
self
.
assertEqual
(
two_toys_ch
.
display_name
,
"Two Toy Overview"
)
# Also check that the grading policy loaded
self
.
assertEqual
(
two_toys
.
grade_cutoffs
[
'C'
],
0.5999
)
def
test_definition_loading
(
self
):
"""When two courses share the same org and course name and
...
...
This diff is collapsed.
Click to expand it.
common/test/data/two_toys/policies/TT_2012_Fall/grading_policy.json
0 → 100644
View file @
f8668544
{
"GRADER"
:
[
{
"type"
:
"Homework"
,
"min_count"
:
12
,
"drop_count"
:
2
,
"short_label"
:
"HW"
,
"weight"
:
0.15
},
{
"type"
:
"Lab"
,
"min_count"
:
12
,
"drop_count"
:
2
,
"category"
:
"Labs"
,
"weight"
:
0.15
},
{
"type"
:
"Midterm"
,
"name"
:
"Midterm Exam"
,
"short_label"
:
"Midterm"
,
"weight"
:
0.3
},
{
"type"
:
"Final"
,
"name"
:
"Final Exam"
,
"short_label"
:
"Final"
,
"weight"
:
0.4
}
],
"GRADE_CUTOFFS"
:
{
"A"
:
0.87
,
"B"
:
0.7
,
"C"
:
0.5999
}
}
This diff is collapsed.
Click to expand it.
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