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
213e3cdc
Commit
213e3cdc
authored
Aug 15, 2012
by
Calen Pennington
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #418 from MITx/feature/victor/strip-metadata
Feature/victor/strip metadata
parents
e524f3bf
a4d67bab
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
153 additions
and
3 deletions
+153
-3
common/lib/xmodule/xmodule/modulestore/xml.py
+28
-2
common/lib/xmodule/xmodule/x_module.py
+26
-0
common/lib/xmodule/xmodule/xml_module.py
+1
-1
lms/djangoapps/courseware/management/commands/metadata_to_json.py
+98
-0
No files found.
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
213e3cdc
import
json
import
logging
import
os
import
re
...
...
@@ -149,7 +150,7 @@ class XMLModuleStore(ModuleStoreBase):
for
course_dir
in
course_dirs
:
self
.
try_load_course
(
course_dir
)
def
try_load_course
(
self
,
course_dir
):
def
try_load_course
(
self
,
course_dir
):
'''
Load a course, keeping track of errors as we go along.
'''
...
...
@@ -170,7 +171,27 @@ class XMLModuleStore(ModuleStoreBase):
'''
String representation - for debugging
'''
return
'<XMLModuleStore>data_dir=
%
s,
%
d courses,
%
d modules'
%
(
self
.
data_dir
,
len
(
self
.
courses
),
len
(
self
.
modules
))
return
'<XMLModuleStore>data_dir=
%
s,
%
d courses,
%
d modules'
%
(
self
.
data_dir
,
len
(
self
.
courses
),
len
(
self
.
modules
))
def
load_policy
(
self
,
policy_path
,
tracker
):
"""
Attempt to read a course policy from policy_path. If the file
exists, but is invalid, log an error and return {}.
If the policy loads correctly, returns the deserialized version.
"""
if
not
os
.
path
.
exists
(
policy_path
):
return
{}
try
:
with
open
(
policy_path
)
as
f
:
return
json
.
load
(
f
)
except
(
IOError
,
ValueError
)
as
err
:
msg
=
"Error loading course policy from {}"
.
format
(
policy_path
)
tracker
(
msg
)
log
.
warning
(
msg
+
" "
+
str
(
err
))
return
{}
def
load_course
(
self
,
course_dir
,
tracker
):
"""
...
...
@@ -214,6 +235,11 @@ class XMLModuleStore(ModuleStoreBase):
system
=
ImportSystem
(
self
,
org
,
course
,
course_dir
,
tracker
)
course_descriptor
=
system
.
process_xml
(
etree
.
tostring
(
course_data
))
policy_path
=
self
.
data_dir
/
course_dir
/
'policy.json'
policy
=
self
.
load_policy
(
policy_path
,
tracker
)
XModuleDescriptor
.
apply_policy
(
course_descriptor
,
policy
)
# NOTE: The descriptors end up loading somewhat bottom up, which
# breaks metadata inheritance via get_children(). Instead
# (actually, in addition to, for now), we do a final inheritance pass
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
213e3cdc
...
...
@@ -298,6 +298,14 @@ class XModule(HTMLSnippet):
return
""
def
policy_key
(
location
):
"""
Get the key for a location in a policy file. (Since the policy file is
specific to a course, it doesn't need the full location url).
"""
return
'{cat}/{name}'
.
format
(
cat
=
location
.
category
,
name
=
location
.
name
)
class
XModuleDescriptor
(
Plugin
,
HTMLSnippet
):
"""
An XModuleDescriptor is a specification for an element of a course. This
...
...
@@ -416,6 +424,24 @@ class XModuleDescriptor(Plugin, HTMLSnippet):
return
dict
((
k
,
v
)
for
k
,
v
in
self
.
metadata
.
items
()
if
k
not
in
self
.
_inherited_metadata
)
@staticmethod
def
apply_policy
(
node
,
policy
):
"""
Given a descriptor, traverse all its descendants and update its metadata
with the policy.
Notes:
- this does not propagate inherited metadata. The caller should
call compute_inherited_metadata after applying the policy.
- metadata specified in the policy overrides metadata in the xml
"""
k
=
policy_key
(
node
.
location
)
if
k
in
policy
:
node
.
metadata
.
update
(
policy
[
k
])
for
c
in
node
.
get_children
():
XModuleDescriptor
.
apply_policy
(
c
,
policy
)
@staticmethod
def
compute_inherited_metadata
(
node
):
"""Given a descriptor, traverse all of its descendants and do metadata
...
...
common/lib/xmodule/xmodule/xml_module.py
View file @
213e3cdc
...
...
@@ -166,7 +166,7 @@ class XmlDescriptor(XModuleDescriptor):
Subclasses should not need to override this except in special
cases (e.g. html module)'''
# VS[compat] -- the filename
tag
should go away once everything is
# VS[compat] -- the filename
attr
should go away once everything is
# converted. (note: make sure html files still work once this goes away)
filename
=
xml_object
.
get
(
'filename'
)
if
filename
is
None
:
...
...
lms/djangoapps/courseware/management/commands/metadata_to_json.py
0 → 100644
View file @
213e3cdc
"""
A script to walk a course xml tree, generate a dictionary of all the metadata,
and print it out as a json dict.
"""
import
os
import
sys
import
json
from
collections
import
OrderedDict
from
path
import
path
from
django.core.management.base
import
BaseCommand
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.x_module
import
policy_key
def
import_course
(
course_dir
,
verbose
=
True
):
course_dir
=
path
(
course_dir
)
data_dir
=
course_dir
.
dirname
()
course_dirs
=
[
course_dir
.
basename
()]
# No default class--want to complain if it doesn't find plugins for any
# module.
modulestore
=
XMLModuleStore
(
data_dir
,
default_class
=
None
,
eager
=
True
,
course_dirs
=
course_dirs
)
def
str_of_err
(
tpl
):
(
msg
,
exc_str
)
=
tpl
return
'{msg}
\n
{exc}'
.
format
(
msg
=
msg
,
exc
=
exc_str
)
courses
=
modulestore
.
get_courses
()
n
=
len
(
courses
)
if
n
!=
1
:
sys
.
stderr
.
write
(
'ERROR: Expect exactly 1 course. Loaded {n}: {lst}
\n
'
.
format
(
n
=
n
,
lst
=
courses
))
return
None
course
=
courses
[
0
]
errors
=
modulestore
.
get_item_errors
(
course
.
location
)
if
len
(
errors
)
!=
0
:
sys
.
stderr
.
write
(
'ERRORs during import: {}
\n
'
.
format
(
'
\n
'
.
join
(
map
(
str_of_err
,
errors
))))
return
course
def
node_metadata
(
node
):
# make a copy
to_export
=
(
'format'
,
'display_name'
,
'graceperiod'
,
'showanswer'
,
'rerandomize'
,
'start'
,
'due'
,
'graded'
,
'hide_from_toc'
,
'ispublic'
,
'xqa_key'
)
orig
=
node
.
own_metadata
d
=
{
k
:
orig
[
k
]
for
k
in
to_export
if
k
in
orig
}
return
d
def
get_metadata
(
course
):
d
=
OrderedDict
({})
queue
=
[
course
]
while
len
(
queue
)
>
0
:
node
=
queue
.
pop
()
d
[
policy_key
(
node
.
location
)]
=
node_metadata
(
node
)
# want to print first children first, so put them at the end
# (we're popping from the end)
queue
.
extend
(
reversed
(
node
.
get_children
()))
return
d
def
print_metadata
(
course_dir
,
output
):
course
=
import_course
(
course_dir
)
if
course
:
meta
=
get_metadata
(
course
)
result
=
json
.
dumps
(
meta
,
indent
=
4
)
if
output
:
with
file
(
output
,
'w'
)
as
f
:
f
.
write
(
result
)
else
:
print
result
class
Command
(
BaseCommand
):
help
=
"""Imports specified course.xml and prints its
metadata as a json dict.
Usage: metadata_to_json PATH-TO-COURSE-DIR OUTPUT-PATH
if OUTPUT-PATH isn't given, print to stdout.
"""
def
handle
(
self
,
*
args
,
**
options
):
n
=
len
(
args
)
if
n
<
1
or
n
>
2
:
print
Command
.
help
return
output_path
=
args
[
1
]
if
n
>
1
else
None
print_metadata
(
args
[
0
],
output_path
)
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