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
fa75245e
Commit
fa75245e
authored
Dec 21, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: Start cleaning up CMS to work with new field format
parent
16d5a769
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
76 additions
and
100 deletions
+76
-100
cms/djangoapps/contentstore/tests/factories.py
+4
-8
cms/djangoapps/contentstore/views.py
+4
-10
cms/djangoapps/models/settings/course_details.py
+4
-4
cms/djangoapps/models/settings/course_grading.py
+14
-4
common/lib/xmodule/xmodule/capa_module.py
+3
-53
common/lib/xmodule/xmodule/fields.py
+40
-0
common/lib/xmodule/xmodule/html_module.py
+2
-2
common/lib/xmodule/xmodule/self_assessment_module.py
+2
-4
common/lib/xmodule/xmodule/tests/test_export.py
+1
-14
lms/xmodule_namespace.py
+2
-1
No files found.
cms/djangoapps/contentstore/tests/factories.py
View file @
fa75245e
...
@@ -38,10 +38,9 @@ class XModuleCourseFactory(Factory):
...
@@ -38,10 +38,9 @@ class XModuleCourseFactory(Factory):
# This metadata code was copied from cms/djangoapps/contentstore/views.py
# This metadata code was copied from cms/djangoapps/contentstore/views.py
if
display_name
is
not
None
:
if
display_name
is
not
None
:
new_course
.
metadata
[
'display_name'
]
=
display_name
new_course
.
lms
.
display_name
=
display_name
new_course
.
metadata
[
'data_dir'
]
=
uuid4
()
.
hex
new_course
.
start
=
gmtime
()
new_course
.
metadata
[
'start'
]
=
stringify_time
(
gmtime
())
new_course
.
tabs
=
[{
"type"
:
"courseware"
},
new_course
.
tabs
=
[{
"type"
:
"courseware"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"course_info"
,
"name"
:
"Course Info"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
{
"type"
:
"discussion"
,
"name"
:
"Discussion"
},
...
@@ -89,17 +88,14 @@ class XModuleItemFactory(Factory):
...
@@ -89,17 +88,14 @@ class XModuleItemFactory(Factory):
new_item
=
store
.
clone_item
(
template
,
dest_location
)
new_item
=
store
.
clone_item
(
template
,
dest_location
)
# TODO: This needs to be deleted when we have proper storage for static content
new_item
.
metadata
[
'data_dir'
]
=
parent
.
metadata
[
'data_dir'
]
# replace the display name with an optional parameter passed in from the caller
# replace the display name with an optional parameter passed in from the caller
if
display_name
is
not
None
:
if
display_name
is
not
None
:
new_item
.
metadata
[
'display_name'
]
=
display_name
new_item
.
lms
.
display_name
=
display_name
store
.
update_metadata
(
new_item
.
location
.
url
(),
own_metadata
(
new_item
))
store
.
update_metadata
(
new_item
.
location
.
url
(),
own_metadata
(
new_item
))
if
new_item
.
location
.
category
not
in
DETACHED_CATEGORIES
:
if
new_item
.
location
.
category
not
in
DETACHED_CATEGORIES
:
store
.
update_children
(
parent_location
,
parent
.
definition
.
get
(
'children'
,
[])
+
[
new_item
.
location
.
url
()])
store
.
update_children
(
parent_location
,
parent
.
children
+
[
new_item
.
location
.
url
()])
return
new_item
return
new_item
...
...
cms/djangoapps/contentstore/views.py
View file @
fa75245e
...
@@ -706,17 +706,14 @@ def clone_item(request):
...
@@ -706,17 +706,14 @@ def clone_item(request):
new_item
=
get_modulestore
(
template
)
.
clone_item
(
template
,
dest_location
)
new_item
=
get_modulestore
(
template
)
.
clone_item
(
template
,
dest_location
)
# TODO: This needs to be deleted when we have proper storage for static content
new_item
.
metadata
[
'data_dir'
]
=
parent
.
metadata
[
'data_dir'
]
# replace the display name with an optional parameter passed in from the caller
# replace the display name with an optional parameter passed in from the caller
if
display_name
is
not
None
:
if
display_name
is
not
None
:
new_item
.
metadata
[
'display_name'
]
=
display_name
new_item
.
lms
.
display_name
=
display_name
get_modulestore
(
template
)
.
update_metadata
(
new_item
.
location
.
url
(),
own_metadata
(
new_item
))
get_modulestore
(
template
)
.
update_metadata
(
new_item
.
location
.
url
(),
own_metadata
(
new_item
))
if
new_item
.
location
.
category
not
in
DETACHED_CATEGORIES
:
if
new_item
.
location
.
category
not
in
DETACHED_CATEGORIES
:
get_modulestore
(
parent
.
location
)
.
update_children
(
parent_location
,
parent
.
definition
.
get
(
'children'
,
[])
+
[
new_item
.
location
.
url
()])
get_modulestore
(
parent
.
location
)
.
update_children
(
parent_location
,
parent
.
children
+
[
new_item
.
location
.
url
()])
return
HttpResponse
(
json
.
dumps
({
'id'
:
dest_location
.
url
()}))
return
HttpResponse
(
json
.
dumps
({
'id'
:
dest_location
.
url
()}))
...
@@ -1206,13 +1203,10 @@ def create_new_course(request):
...
@@ -1206,13 +1203,10 @@ def create_new_course(request):
new_course
=
modulestore
(
'direct'
)
.
clone_item
(
template
,
dest_location
)
new_course
=
modulestore
(
'direct'
)
.
clone_item
(
template
,
dest_location
)
if
display_name
is
not
None
:
if
display_name
is
not
None
:
new_course
.
metadata
[
'display_name'
]
=
display_name
new_course
.
display_name
=
display_name
# we need a 'data_dir' for legacy reasons
new_course
.
metadata
[
'data_dir'
]
=
uuid4
()
.
hex
# set a default start date to now
# set a default start date to now
new_course
.
metadata
[
'start'
]
=
stringify_time
(
time
.
gmtime
()
)
new_course
.
start
=
time
.
gmtime
(
)
initialize_course_tabs
(
new_course
)
initialize_course_tabs
(
new_course
)
...
...
cms/djangoapps/models/settings/course_details.py
View file @
fa75245e
...
@@ -44,25 +44,25 @@ class CourseDetails:
...
@@ -44,25 +44,25 @@ class CourseDetails:
temploc
=
course_location
.
_replace
(
category
=
'about'
,
name
=
'syllabus'
)
temploc
=
course_location
.
_replace
(
category
=
'about'
,
name
=
'syllabus'
)
try
:
try
:
course
.
syllabus
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
efinition
[
'data'
]
course
.
syllabus
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
ata
except
ItemNotFoundError
:
except
ItemNotFoundError
:
pass
pass
temploc
=
temploc
.
_replace
(
name
=
'overview'
)
temploc
=
temploc
.
_replace
(
name
=
'overview'
)
try
:
try
:
course
.
overview
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
efinition
[
'data'
]
course
.
overview
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
ata
except
ItemNotFoundError
:
except
ItemNotFoundError
:
pass
pass
temploc
=
temploc
.
_replace
(
name
=
'effort'
)
temploc
=
temploc
.
_replace
(
name
=
'effort'
)
try
:
try
:
course
.
effort
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
efinition
[
'data'
]
course
.
effort
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
ata
except
ItemNotFoundError
:
except
ItemNotFoundError
:
pass
pass
temploc
=
temploc
.
_replace
(
name
=
'video'
)
temploc
=
temploc
.
_replace
(
name
=
'video'
)
try
:
try
:
raw_video
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
efinition
[
'data'
]
raw_video
=
get_modulestore
(
temploc
)
.
get_item
(
temploc
)
.
d
ata
course
.
intro_video
=
CourseDetails
.
parse_video_tag
(
raw_video
)
course
.
intro_video
=
CourseDetails
.
parse_video_tag
(
raw_video
)
except
ItemNotFoundError
:
except
ItemNotFoundError
:
pass
pass
...
...
cms/djangoapps/models/settings/course_grading.py
View file @
fa75245e
...
@@ -235,11 +235,21 @@ class CourseGradingModel:
...
@@ -235,11 +235,21 @@ class CourseGradingModel:
@staticmethod
@staticmethod
def
convert_set_grace_period
(
descriptor
):
def
convert_set_grace_period
(
descriptor
):
# 5 hours 59 minutes 59 seconds => converted to iso format
# 5 hours 59 minutes 59 seconds => converted to iso format
rawgrace
=
descriptor
.
metadata
.
get
(
'graceperiod'
,
None
)
rawgrace
=
descriptor
.
lms
.
graceperiod
if
rawgrace
:
if
rawgrace
:
parsedgrace
=
{
str
(
key
):
val
for
(
val
,
key
)
in
re
.
findall
(
'
\
s*(
\
d+)
\
s*(
\
w+)'
,
rawgrace
)}
hours_from_day
=
rawgrace
.
days
*
24
return
parsedgrace
seconds
=
rawgrace
.
seconds
else
:
return
None
hours_from_seconds
=
int
(
seconds
/
3600
)
seconds
-=
hours_from_seconds
*
3600
minutes
=
int
(
seconds
/
60
)
seconds
-=
minutes
*
60
return
{
'hours'
:
hourse_from_days
+
hours_from_seconds
,
'minutes'
:
minutes_from_seconds
,
'seconds'
:
seconds
,
}
else
:
return
None
@staticmethod
@staticmethod
def
parse_grader
(
json_grader
):
def
parse_grader
(
json_grader
):
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
fa75245e
...
@@ -5,10 +5,8 @@ import dateutil.parser
...
@@ -5,10 +5,8 @@ import dateutil.parser
import
json
import
json
import
logging
import
logging
import
traceback
import
traceback
import
re
import
sys
import
sys
from
datetime
import
timedelta
from
lxml
import
etree
from
lxml
import
etree
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
...
@@ -20,6 +18,9 @@ from xmodule.x_module import XModule
...
@@ -20,6 +18,9 @@ from xmodule.x_module import XModule
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.raw_module
import
RawDescriptor
from
xmodule.exceptions
import
NotFoundError
from
xmodule.exceptions
import
NotFoundError
from
.model
import
Int
,
Scope
,
ModuleScope
,
ModelType
,
String
,
Boolean
,
Object
,
Float
from
.model
import
Int
,
Scope
,
ModuleScope
,
ModelType
,
String
,
Boolean
,
Object
,
Float
from
.fields
import
Timedelta
log
=
logging
.
getLogger
(
"mitx.courseware"
)
class
StringyInt
(
Int
):
class
StringyInt
(
Int
):
...
@@ -31,57 +32,6 @@ class StringyInt(Int):
...
@@ -31,57 +32,6 @@ class StringyInt(Int):
return
int
(
value
)
return
int
(
value
)
return
value
return
value
log
=
logging
.
getLogger
(
"mitx.courseware"
)
#-----------------------------------------------------------------------------
TIMEDELTA_REGEX
=
re
.
compile
(
r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$'
)
def
only_one
(
lst
,
default
=
""
,
process
=
lambda
x
:
x
):
"""
If lst is empty, returns default
If lst has a single element, applies process to that element and returns it.
Otherwise, raises an exception.
"""
if
len
(
lst
)
==
0
:
return
default
elif
len
(
lst
)
==
1
:
return
process
(
lst
[
0
])
else
:
raise
Exception
(
'Malformed XML: expected at most one element in list.'
)
class
Timedelta
(
ModelType
):
def
from_json
(
self
,
time_str
):
"""
time_str: A string with the following components:
<D> day[s] (optional)
<H> hour[s] (optional)
<M> minute[s] (optional)
<S> second[s] (optional)
Returns a datetime.timedelta parsed from the string
"""
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
if
not
parts
:
return
parts
=
parts
.
groupdict
()
time_params
=
{}
for
(
name
,
param
)
in
parts
.
iteritems
():
if
param
:
time_params
[
name
]
=
int
(
param
)
return
timedelta
(
**
time_params
)
def
to_json
(
self
,
value
):
values
=
[]
for
attr
in
(
'days'
,
'hours'
,
'minutes'
,
'seconds'
):
cur_value
=
getattr
(
value
,
attr
,
0
)
if
cur_value
>
0
:
values
.
append
(
"
%
d
%
s"
%
(
cur_value
,
attr
))
return
' '
.
join
(
values
)
class
Randomization
(
String
):
class
Randomization
(
String
):
def
from_json
(
self
,
value
):
def
from_json
(
self
,
value
):
...
...
common/lib/xmodule/xmodule/fields.py
View file @
fa75245e
import
time
import
time
import
logging
import
logging
import
re
from
datetime
import
timedelta
from
.model
import
ModelType
from
.model
import
ModelType
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -15,6 +17,9 @@ class Date(ModelType):
...
@@ -15,6 +17,9 @@ class Date(ModelType):
if it doesn't parse.
if it doesn't parse.
Return None if not present or invalid.
Return None if not present or invalid.
"""
"""
if
value
is
None
:
return
None
try
:
try
:
return
time
.
strptime
(
value
,
self
.
time_format
)
return
time
.
strptime
(
value
,
self
.
time_format
)
except
ValueError
as
e
:
except
ValueError
as
e
:
...
@@ -27,4 +32,38 @@ class Date(ModelType):
...
@@ -27,4 +32,38 @@ class Date(ModelType):
"""
"""
Convert a time struct to a string
Convert a time struct to a string
"""
"""
if
value
is
None
:
return
None
return
time
.
strftime
(
self
.
time_format
,
value
)
return
time
.
strftime
(
self
.
time_format
,
value
)
TIMEDELTA_REGEX
=
re
.
compile
(
r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$'
)
class
Timedelta
(
ModelType
):
def
from_json
(
self
,
time_str
):
"""
time_str: A string with the following components:
<D> day[s] (optional)
<H> hour[s] (optional)
<M> minute[s] (optional)
<S> second[s] (optional)
Returns a datetime.timedelta parsed from the string
"""
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
if
not
parts
:
return
parts
=
parts
.
groupdict
()
time_params
=
{}
for
(
name
,
param
)
in
parts
.
iteritems
():
if
param
:
time_params
[
name
]
=
int
(
param
)
return
timedelta
(
**
time_params
)
def
to_json
(
self
,
value
):
values
=
[]
for
attr
in
(
'days'
,
'hours'
,
'minutes'
,
'seconds'
):
cur_value
=
getattr
(
value
,
attr
,
0
)
if
cur_value
>
0
:
values
.
append
(
"
%
d
%
s"
%
(
cur_value
,
attr
))
return
' '
.
join
(
values
)
\ No newline at end of file
common/lib/xmodule/xmodule/html_module.py
View file @
fa75245e
...
@@ -149,7 +149,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
...
@@ -149,7 +149,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
string to filename.html.
string to filename.html.
'''
'''
try
:
try
:
return
etree
.
fromstring
(
self
.
d
efinition
[
'data'
]
)
return
etree
.
fromstring
(
self
.
d
ata
)
except
etree
.
XMLSyntaxError
:
except
etree
.
XMLSyntaxError
:
pass
pass
...
@@ -161,7 +161,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
...
@@ -161,7 +161,7 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
resource_fs
.
makedir
(
os
.
path
.
dirname
(
filepath
),
recursive
=
True
,
allow_recreate
=
True
)
resource_fs
.
makedir
(
os
.
path
.
dirname
(
filepath
),
recursive
=
True
,
allow_recreate
=
True
)
with
resource_fs
.
open
(
filepath
,
'w'
)
as
file
:
with
resource_fs
.
open
(
filepath
,
'w'
)
as
file
:
file
.
write
(
self
.
d
efinition
[
'data'
]
)
file
.
write
(
self
.
d
ata
)
# write out the relative name
# write out the relative name
relname
=
path
(
pathname
)
.
basename
()
relname
=
path
(
pathname
)
.
basename
()
...
...
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
fa75245e
...
@@ -18,13 +18,11 @@ from progress import Progress
...
@@ -18,13 +18,11 @@ from progress import Progress
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.capa_module
import
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
.stringify
import
stringify_children
from
.stringify
import
stringify_children
from
.x_module
import
XModule
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
.model
import
List
,
String
,
Scope
,
Int
from
.model
import
List
,
String
,
Scope
,
Int
log
=
logging
.
getLogger
(
"mitx.courseware"
)
log
=
logging
.
getLogger
(
"mitx.courseware"
)
...
@@ -436,7 +434,7 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
...
@@ -436,7 +434,7 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
elt
=
etree
.
Element
(
'selfassessment'
)
elt
=
etree
.
Element
(
'selfassessment'
)
def
add_child
(
k
):
def
add_child
(
k
):
child_str
=
'<{tag}>{body}</{tag}>'
.
format
(
tag
=
k
,
body
=
self
.
definition
[
k
]
)
child_str
=
'<{tag}>{body}</{tag}>'
.
format
(
tag
=
k
,
body
=
getattr
(
self
,
k
)
)
child_node
=
etree
.
fromstring
(
child_str
)
child_node
=
etree
.
fromstring
(
child_str
)
elt
.
append
(
child_node
)
elt
.
append
(
child_node
)
...
...
common/lib/xmodule/xmodule/tests/test_export.py
View file @
fa75245e
...
@@ -18,21 +18,12 @@ TEST_DIR = TEST_DIR / 'test'
...
@@ -18,21 +18,12 @@ TEST_DIR = TEST_DIR / 'test'
DATA_DIR
=
TEST_DIR
/
'data'
DATA_DIR
=
TEST_DIR
/
'data'
def
strip_metadata
(
descriptor
,
key
):
"""
Recursively strips tag from all children.
"""
print
"strip {key} from {desc}"
.
format
(
key
=
key
,
desc
=
descriptor
.
location
.
url
())
descriptor
.
metadata
.
pop
(
key
,
None
)
for
d
in
descriptor
.
get_children
():
strip_metadata
(
d
,
key
)
def
strip_filenames
(
descriptor
):
def
strip_filenames
(
descriptor
):
"""
"""
Recursively strips 'filename' from all children's definitions.
Recursively strips 'filename' from all children's definitions.
"""
"""
print
"strip filename from {desc}"
.
format
(
desc
=
descriptor
.
location
.
url
())
print
"strip filename from {desc}"
.
format
(
desc
=
descriptor
.
location
.
url
())
descriptor
.
definition
.
pop
(
'filename'
,
None
)
descriptor
.
_model_data
.
pop
(
'filename'
,
None
)
for
d
in
descriptor
.
get_children
():
for
d
in
descriptor
.
get_children
():
strip_filenames
(
d
)
strip_filenames
(
d
)
...
@@ -73,10 +64,6 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -73,10 +64,6 @@ class RoundTripTestCase(unittest.TestCase):
exported_course
=
courses2
[
0
]
exported_course
=
courses2
[
0
]
print
"Checking course equality"
print
"Checking course equality"
# HACK: data_dir metadata tags break equality because they
# aren't real metadata, and depend on paths. Remove them.
strip_metadata
(
initial_course
,
'data_dir'
)
strip_metadata
(
exported_course
,
'data_dir'
)
# HACK: filenames change when changing file formats
# HACK: filenames change when changing file formats
# during imports from old-style courses. Ignore them.
# during imports from old-style courses. Ignore them.
...
...
lms/xmodule_namespace.py
View file @
fa75245e
from
xmodule.model
import
Namespace
,
Boolean
,
Scope
,
String
,
List
from
xmodule.model
import
Namespace
,
Boolean
,
Scope
,
String
,
List
from
xmodule.fields
import
Date
from
xmodule.fields
import
Date
,
Timedelta
class
StringyBoolean
(
Boolean
):
class
StringyBoolean
(
Boolean
):
...
@@ -39,3 +39,4 @@ class LmsNamespace(Namespace):
...
@@ -39,3 +39,4 @@ class LmsNamespace(Namespace):
giturl
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
,
default
=
'https://github.com/MITx'
)
giturl
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
,
default
=
'https://github.com/MITx'
)
xqa_key
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
xqa_key
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
ispublic
=
Boolean
(
help
=
"Whether this course is open to the public, or only to admins"
,
scope
=
Scope
.
settings
)
ispublic
=
Boolean
(
help
=
"Whether this course is open to the public, or only to admins"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
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