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
a6c8d90a
Commit
a6c8d90a
authored
Oct 24, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #958 from MITx/feature/cdodge/import-grading-policy
Feature/cdodge/import grading policy
parents
ef1ba6d9
ae4df32e
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
122 additions
and
104 deletions
+122
-104
common/lib/xmodule/xmodule/course_module.py
+120
-10
common/lib/xmodule/xmodule/graders.py
+0
-63
common/lib/xmodule/xmodule/modulestore/xml.py
+0
-29
common/lib/xmodule/xmodule/modulestore/xml_importer.py
+2
-2
No files found.
common/lib/xmodule/xmodule/course_module.py
View file @
a6c8d90a
from
fs.errors
import
ResourceNotFoundError
from
fs.errors
import
ResourceNotFoundError
import
logging
import
logging
import
json
from
lxml
import
etree
from
lxml
import
etree
from
path
import
path
# NOTE (THK): Only used for detecting presence of syllabus
from
path
import
path
# NOTE (THK): Only used for detecting presence of syllabus
import
requests
import
requests
import
time
import
time
from
cStringIO
import
StringIO
from
xmodule.util.decorators
import
lazyproperty
from
xmodule.util.decorators
import
lazyproperty
from
xmodule.graders
import
load_grading_policy
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.seq_module
import
SequenceDescriptor
,
SequenceModule
from
xmodule.seq_module
import
SequenceDescriptor
,
SequenceModule
from
xmodule.xml_module
import
XmlDescriptor
from
xmodule.timeparse
import
parse_time
,
stringify_time
from
xmodule.timeparse
import
parse_time
,
stringify_time
from
xmodule.graders
import
grader_from_conf
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
edx_xml_parser
=
etree
.
XMLParser
(
dtd_validation
=
False
,
load_dtd
=
False
,
remove_comments
=
True
,
remove_blank_text
=
True
)
class
CourseDescriptor
(
SequenceDescriptor
):
class
CourseDescriptor
(
SequenceDescriptor
):
module_class
=
SequenceModule
module_class
=
SequenceModule
...
@@ -96,16 +102,119 @@ class CourseDescriptor(SequenceDescriptor):
...
@@ -96,16 +102,119 @@ class CourseDescriptor(SequenceDescriptor):
# disable the syllabus content for courses that do not provide a syllabus
# disable the syllabus content for courses that do not provide a syllabus
self
.
syllabus_present
=
self
.
system
.
resources_fs
.
exists
(
path
(
'syllabus'
))
self
.
syllabus_present
=
self
.
system
.
resources_fs
.
exists
(
path
(
'syllabus'
))
def
set_grading_policy
(
self
,
policy_str
):
self
.
set_grading_policy
(
self
.
definition
[
'data'
]
.
get
(
'grading_policy'
,
None
))
"""Parse the policy specified in policy_str, and save it"""
def
set_grading_policy
(
self
,
course_policy
):
if
course_policy
is
None
:
course_policy
=
{}
"""
The JSON object can have the keys GRADER and GRADE_CUTOFFS. If either is
missing, it reverts to the default.
"""
default_policy_string
=
"""
{
"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.6
}
}
"""
# Load the global settings as a dictionary
grading_policy
=
json
.
loads
(
default_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'
])
self
.
_grading_policy
=
grading_policy
@classmethod
def
read_grading_policy
(
cls
,
paths
,
system
):
"""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
system
.
resources_fs
.
exists
(
policy_path
):
continue
log
.
debug
(
"Loading grading policy from {0}"
.
format
(
policy_path
))
try
:
try
:
self
.
_grading_policy
=
load_grading_policy
(
policy_str
)
with
system
.
resources_fs
.
open
(
policy_path
)
as
grading_policy_file
:
except
:
policy_str
=
grading_policy_file
.
read
()
self
.
system
.
error_tracker
(
"Failed to load grading policy"
)
# if we successfully read the file, stop looking at backups
# Setting this to an empty dictionary will lead to errors when
break
# grading needs to happen, but should allow course staff to see
except
(
IOError
):
# the error log.
msg
=
"Unable to load course settings file from '{0}'"
.
format
(
policy_path
)
self
.
_grading_policy
=
{}
log
.
warning
(
msg
)
return
policy_str
@classmethod
def
from_xml
(
cls
,
xml_data
,
system
,
org
=
None
,
course
=
None
):
instance
=
super
(
CourseDescriptor
,
cls
)
.
from_xml
(
xml_data
,
system
,
org
,
course
)
# bleh, have to parse the XML here to just pull out the url_name attribute
course_file
=
StringIO
(
xml_data
)
xml_obj
=
etree
.
parse
(
course_file
,
parser
=
edx_xml_parser
)
.
getroot
()
policy_dir
=
None
url_name
=
xml_obj
.
get
(
'url_name'
,
xml_obj
.
get
(
'slug'
))
if
url_name
:
policy_dir
=
'policies/'
+
url_name
# Try to load grading policy
paths
=
[
'grading_policy.json'
]
if
policy_dir
:
paths
=
[
policy_dir
+
'grading_policy.json'
]
+
paths
policy
=
json
.
loads
(
cls
.
read_grading_policy
(
paths
,
system
))
# cdodge: import the grading policy information that is on disk and put into the
# descriptor 'definition' bucket as a dictionary so that it is persisted in the DB
instance
.
definition
[
'data'
][
'grading_policy'
]
=
policy
# now set the current instance. set_grading_policy() will apply some inheritance rules
instance
.
set_grading_policy
(
policy
)
return
instance
@classmethod
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
def
definition_from_xml
(
cls
,
xml_object
,
system
):
...
@@ -284,3 +393,4 @@ class CourseDescriptor(SequenceDescriptor):
...
@@ -284,3 +393,4 @@ class CourseDescriptor(SequenceDescriptor):
def
org
(
self
):
def
org
(
self
):
return
self
.
location
.
org
return
self
.
location
.
org
common/lib/xmodule/xmodule/graders.py
View file @
a6c8d90a
...
@@ -13,69 +13,6 @@ log = logging.getLogger("mitx.courseware")
...
@@ -13,69 +13,6 @@ log = logging.getLogger("mitx.courseware")
# Section either indicates the name of the problem or the name of the section
# Section either indicates the name of the problem or the name of the section
Score
=
namedtuple
(
"Score"
,
"earned possible graded section"
)
Score
=
namedtuple
(
"Score"
,
"earned possible graded section"
)
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" : [
{
"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.6
}
}
"""
# Load the global settings as a dictionary
grading_policy
=
json
.
loads
(
default_policy_string
)
# Load the course policies as a dictionary
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"
):
def
aggregate_scores
(
scores
,
section_name
=
"summary"
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
a6c8d90a
...
@@ -341,27 +341,6 @@ class XMLModuleStore(ModuleStoreBase):
...
@@ -341,27 +341,6 @@ class XMLModuleStore(ModuleStoreBase):
return
{}
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
log
.
debug
(
"Loading grading policy from {0}"
.
format
(
policy_path
))
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
):
def
load_course
(
self
,
course_dir
,
tracker
):
"""
"""
...
@@ -444,14 +423,6 @@ class XMLModuleStore(ModuleStoreBase):
...
@@ -444,14 +423,6 @@ class XMLModuleStore(ModuleStoreBase):
# after we have the course descriptor.
# after we have the course descriptor.
XModuleDescriptor
.
compute_inherited_metadata
(
course_descriptor
)
XModuleDescriptor
.
compute_inherited_metadata
(
course_descriptor
)
# Try to load grading policy
paths
=
[
self
.
data_dir
/
course_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
))
log
.
debug
(
'========> Done with course import from {0}'
.
format
(
course_dir
))
return
course_descriptor
return
course_descriptor
...
...
common/lib/xmodule/xmodule/modulestore/xml_importer.py
View file @
a6c8d90a
...
@@ -76,11 +76,12 @@ def import_from_xml(store, data_dir, course_dirs=None,
...
@@ -76,11 +76,12 @@ def import_from_xml(store, data_dir, course_dirs=None,
all course dirs
all course dirs
"""
"""
module_store
=
XMLModuleStore
(
module_store
=
XMLModuleStore
(
data_dir
,
data_dir
,
default_class
=
default_class
,
default_class
=
default_class
,
course_dirs
=
course_dirs
,
course_dirs
=
course_dirs
,
load_error_modules
=
load_error_modules
,
load_error_modules
=
load_error_modules
)
)
# NOTE: the XmlModuleStore does not implement get_items() which would be a preferable means
# NOTE: the XmlModuleStore does not implement get_items() which would be a preferable means
...
@@ -124,5 +125,4 @@ def import_from_xml(store, data_dir, course_dirs=None,
...
@@ -124,5 +125,4 @@ def import_from_xml(store, data_dir, course_dirs=None,
# inherited metadata everywhere.
# inherited metadata everywhere.
store
.
update_metadata
(
module
.
location
,
dict
(
module
.
own_metadata
))
store
.
update_metadata
(
module
.
location
,
dict
(
module
.
own_metadata
))
return
module_store
,
course_items
return
module_store
,
course_items
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