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
b0bed170
Commit
b0bed170
authored
Jan 17, 2014
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Enable (and test) xml export of pure XBlocks
[LMS-179] [LMS-209] [LMS-1345]
parent
69097e7b
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
132 additions
and
85 deletions
+132
-85
common/lib/xmodule/xmodule/abtest_module.py
+1
-1
common/lib/xmodule/xmodule/conditional_module.py
+4
-5
common/lib/xmodule/xmodule/crowdsource_hinter.py
+1
-2
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
+9
-4
common/lib/xmodule/xmodule/randomize_module.py
+1
-2
common/lib/xmodule/xmodule/seq_module.py
+1
-2
common/lib/xmodule/xmodule/tests/test_export.py
+61
-50
common/lib/xmodule/xmodule/tests/test_import.py
+15
-16
common/lib/xmodule/xmodule/x_module.py
+24
-0
common/test/data/pure_xblock/course.xml
+9
-0
lms/djangoapps/courseware/management/commands/clean_xml.py
+5
-2
requirements/edx/github.txt
+1
-1
No files found.
common/lib/xmodule/xmodule/abtest_module.py
View file @
b0bed170
...
@@ -149,7 +149,7 @@ class ABTestDescriptor(ABTestFields, RawDescriptor, XmlDescriptor):
...
@@ -149,7 +149,7 @@ class ABTestDescriptor(ABTestFields, RawDescriptor, XmlDescriptor):
for
child_loc
in
group
:
for
child_loc
in
group
:
child
=
self
.
system
.
load_item
(
child_loc
)
child
=
self
.
system
.
load_item
(
child_loc
)
group_elem
.
append
(
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
))
)
self
.
runtime
.
add_block_as_child_node
(
child
,
group_elem
)
return
xml_object
return
xml_object
...
...
common/lib/xmodule/xmodule/conditional_module.py
View file @
b0bed170
...
@@ -222,9 +222,9 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor):
...
@@ -222,9 +222,9 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor):
show_tag_list
=
[]
show_tag_list
=
[]
for
child
in
xml_object
:
for
child
in
xml_object
:
if
child
.
tag
==
'show'
:
if
child
.
tag
==
'show'
:
location
=
ConditionalDescriptor
.
parse_sources
(
child
,
system
)
location
s
=
ConditionalDescriptor
.
parse_sources
(
child
,
system
)
children
.
extend
(
location
)
children
.
extend
(
location
s
)
show_tag_list
.
extend
(
location
.
url
())
# pylint: disable=no-member
show_tag_list
.
extend
(
location
.
url
()
for
location
in
locations
)
# pylint: disable=no-member
else
:
else
:
try
:
try
:
descriptor
=
system
.
process_xml
(
etree
.
tostring
(
child
))
descriptor
=
system
.
process_xml
(
etree
.
tostring
(
child
))
...
@@ -244,6 +244,5 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor):
...
@@ -244,6 +244,5 @@ class ConditionalDescriptor(ConditionalFields, SequenceDescriptor):
tag_name
=
'show'
,
sources
=
location
)
tag_name
=
'show'
,
sources
=
location
)
xml_object
.
append
(
etree
.
fromstring
(
show_str
))
xml_object
.
append
(
etree
.
fromstring
(
show_str
))
else
:
else
:
xml_object
.
append
(
self
.
runtime
.
add_block_as_child_node
(
child
,
xml_object
)
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
return
xml_object
return
xml_object
common/lib/xmodule/xmodule/crowdsource_hinter.py
View file @
b0bed170
...
@@ -400,6 +400,5 @@ class CrowdsourceHinterDescriptor(CrowdsourceHinterFields, RawDescriptor):
...
@@ -400,6 +400,5 @@ class CrowdsourceHinterDescriptor(CrowdsourceHinterFields, RawDescriptor):
def
definition_to_xml
(
self
,
resource_fs
):
def
definition_to_xml
(
self
,
resource_fs
):
xml_object
=
etree
.
Element
(
'crowdsource_hinter'
)
xml_object
=
etree
.
Element
(
'crowdsource_hinter'
)
for
child
in
self
.
get_children
():
for
child
in
self
.
get_children
():
xml_object
.
append
(
self
.
runtime
.
add_block_as_child_node
(
child
,
xml_object
)
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
return
xml_object
return
xml_object
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
View file @
b0bed170
...
@@ -3,6 +3,7 @@ Methods for exporting course data to XML
...
@@ -3,6 +3,7 @@ Methods for exporting course data to XML
"""
"""
import
logging
import
logging
import
lxml.etree
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.inheritance
import
own_metadata
from
fs.osfs
import
OSFS
from
fs.osfs
import
OSFS
...
@@ -57,11 +58,13 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
...
@@ -57,11 +58,13 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
course
=
modulestore
.
get_course
(
course_id
)
course
=
modulestore
.
get_course
(
course_id
)
fs
=
OSFS
(
root_dir
)
fs
=
OSFS
(
root_dir
)
export_fs
=
fs
.
makeopendir
(
course_dir
)
export_fs
=
course
.
runtime
.
export_fs
=
fs
.
makeopendir
(
course_dir
)
root
=
lxml
.
etree
.
Element
(
'unknown'
)
course
.
add_xml_to_node
(
root
)
xml
=
course
.
export_to_xml
(
export_fs
)
with
export_fs
.
open
(
'course.xml'
,
'w'
)
as
course_xml
:
with
export_fs
.
open
(
'course.xml'
,
'w'
)
as
course_xml
:
course_xml
.
write
(
xml
)
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_
xml
)
# export the static assets
# export the static assets
policies_dir
=
export_fs
.
makeopendir
(
'policies'
)
policies_dir
=
export_fs
.
makeopendir
(
'policies'
)
...
@@ -112,7 +115,9 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
...
@@ -112,7 +115,9 @@ def export_to_xml(modulestore, contentstore, course_location, root_dir, course_d
sequential
=
modulestore
.
get_item
(
Location
(
parent_locs
[
0
]))
sequential
=
modulestore
.
get_item
(
Location
(
parent_locs
[
0
]))
index
=
sequential
.
children
.
index
(
draft_vertical
.
location
.
url
())
index
=
sequential
.
children
.
index
(
draft_vertical
.
location
.
url
())
draft_vertical
.
xml_attributes
[
'index_in_children_list'
]
=
str
(
index
)
draft_vertical
.
xml_attributes
[
'index_in_children_list'
]
=
str
(
index
)
draft_vertical
.
export_to_xml
(
draft_course_dir
)
draft_vertical
.
runtime
.
export_fs
=
draft_course_dir
node
=
lxml
.
etree
.
Element
(
'unknown'
)
draft_vertical
.
add_xml_to_node
(
node
)
def
export_extra_content
(
export_fs
,
modulestore
,
course_id
,
course_location
,
category_type
,
dirname
,
file_suffix
=
''
):
def
export_extra_content
(
export_fs
,
modulestore
,
course_id
,
course_location
,
category_type
,
dirname
,
file_suffix
=
''
):
...
...
common/lib/xmodule/xmodule/randomize_module.py
View file @
b0bed170
...
@@ -100,8 +100,7 @@ class RandomizeDescriptor(RandomizeFields, SequenceDescriptor):
...
@@ -100,8 +100,7 @@ class RandomizeDescriptor(RandomizeFields, SequenceDescriptor):
xml_object
=
etree
.
Element
(
'randomize'
)
xml_object
=
etree
.
Element
(
'randomize'
)
for
child
in
self
.
get_children
():
for
child
in
self
.
get_children
():
xml_object
.
append
(
self
.
runtime
.
add_block_as_child_node
(
child
,
xml_object
)
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
return
xml_object
return
xml_object
def
has_dynamic_children
(
self
):
def
has_dynamic_children
(
self
):
...
...
common/lib/xmodule/xmodule/seq_module.py
View file @
b0bed170
...
@@ -150,6 +150,5 @@ class SequenceDescriptor(SequenceFields, MakoModuleDescriptor, XmlDescriptor):
...
@@ -150,6 +150,5 @@ class SequenceDescriptor(SequenceFields, MakoModuleDescriptor, XmlDescriptor):
def
definition_to_xml
(
self
,
resource_fs
):
def
definition_to_xml
(
self
,
resource_fs
):
xml_object
=
etree
.
Element
(
'sequential'
)
xml_object
=
etree
.
Element
(
'sequential'
)
for
child
in
self
.
get_children
():
for
child
in
self
.
get_children
():
xml_object
.
append
(
self
.
runtime
.
add_block_as_child_node
(
child
,
xml_object
)
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
return
xml_object
return
xml_object
common/lib/xmodule/xmodule/tests/test_export.py
View file @
b0bed170
...
@@ -2,19 +2,25 @@
...
@@ -2,19 +2,25 @@
Tests of XML export
Tests of XML export
"""
"""
from
datetime
import
datetime
,
timedelta
,
tzinfo
import
ddt
from
tempfile
import
mkdtemp
import
lxml.etree
import
unittest
import
shutil
from
textwrap
import
dedent
import
mock
import
mock
import
os
import
pytz
import
pytz
import
shutil
import
tarfile
import
unittest
import
uuid
from
datetime
import
datetime
,
timedelta
,
tzinfo
from
fs.osfs
import
OSFS
from
fs.osfs
import
OSFS
from
path
import
path
from
path
import
path
import
uuid
from
tempfile
import
mkdtemp
import
tarfile
from
textwrap
import
dedent
import
os
from
xblock.core
import
XBlock
from
xblock.fields
import
String
,
Scope
,
Integer
from
xblock.test.tools
import
blocks_are_equivalent
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.modulestore.xml
import
XMLModuleStore
...
@@ -23,6 +29,7 @@ from xmodule.modulestore.xml_exporter import (
...
@@ -23,6 +29,7 @@ from xmodule.modulestore.xml_exporter import (
)
)
from
xmodule.tests
import
DATA_DIR
from
xmodule.tests
import
DATA_DIR
from
xmodule.tests.helpers
import
directories_equal
from
xmodule.tests.helpers
import
directories_equal
from
xmodule.x_module
import
XModuleMixin
def
strip_filenames
(
descriptor
):
def
strip_filenames
(
descriptor
):
...
@@ -43,6 +50,16 @@ def strip_filenames(descriptor):
...
@@ -43,6 +50,16 @@ def strip_filenames(descriptor):
descriptor
.
save
()
descriptor
.
save
()
class
PureXBlock
(
XBlock
):
"""Class for testing pure XBlocks."""
has_children
=
True
field1
=
String
(
default
=
"something"
,
scope
=
Scope
.
user_state
)
field2
=
Integer
(
scope
=
Scope
.
user_state
)
@ddt.ddt
class
RoundTripTestCase
(
unittest
.
TestCase
):
class
RoundTripTestCase
(
unittest
.
TestCase
):
"""
"""
Check that our test courses roundtrip properly.
Check that our test courses roundtrip properly.
...
@@ -51,8 +68,25 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -51,8 +68,25 @@ class RoundTripTestCase(unittest.TestCase):
Thus we make sure that export and import work properly.
Thus we make sure that export and import work properly.
"""
"""
def
setUp
(
self
):
self
.
maxDiff
=
None
self
.
temp_dir
=
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
self
.
temp_dir
)
@mock.patch
(
'xmodule.course_module.requests.get'
)
@mock.patch
(
'xmodule.course_module.requests.get'
)
def
check_export_roundtrip
(
self
,
data_dir
,
course_dir
,
mock_get
):
@ddt.data
(
"toy"
,
"simple"
,
"conditional_and_poll"
,
"self_assessment"
,
"graphic_slider_tool"
,
"test_exam_registration"
,
"word_cloud"
,
"pure_xblock"
,
)
@XBlock.register_temp_plugin
(
PureXBlock
,
'pure'
)
def
test_export_roundtrip
(
self
,
course_dir
,
mock_get
):
# Patch network calls to retrieve the textbook TOC
# Patch network calls to retrieve the textbook TOC
mock_get
.
return_value
.
text
=
dedent
(
"""
mock_get
.
return_value
.
text
=
dedent
(
"""
...
@@ -64,11 +98,11 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -64,11 +98,11 @@ class RoundTripTestCase(unittest.TestCase):
root_dir
=
path
(
self
.
temp_dir
)
root_dir
=
path
(
self
.
temp_dir
)
print
(
"Copying test course to temp dir {0}"
.
format
(
root_dir
))
print
(
"Copying test course to temp dir {0}"
.
format
(
root_dir
))
data_dir
=
path
(
data_dir
)
data_dir
=
path
(
DATA_DIR
)
shutil
.
copytree
(
data_dir
/
course_dir
,
root_dir
/
course_dir
)
shutil
.
copytree
(
data_dir
/
course_dir
,
root_dir
/
course_dir
)
print
(
"Starting import"
)
print
(
"Starting import"
)
initial_import
=
XMLModuleStore
(
root_dir
,
course_dirs
=
[
course_dir
])
initial_import
=
XMLModuleStore
(
root_dir
,
course_dirs
=
[
course_dir
]
,
xblock_mixins
=
(
XModuleMixin
,)
)
courses
=
initial_import
.
get_courses
()
courses
=
initial_import
.
get_courses
()
self
.
assertEquals
(
len
(
courses
),
1
)
self
.
assertEquals
(
len
(
courses
),
1
)
...
@@ -78,14 +112,15 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -78,14 +112,15 @@ class RoundTripTestCase(unittest.TestCase):
# will still be there.
# will still be there.
print
(
"Starting export"
)
print
(
"Starting export"
)
fs
=
OSFS
(
root_dir
)
fs
=
OSFS
(
root_dir
)
export_fs
=
fs
.
makeopendir
(
course_dir
)
initial_course
.
runtime
.
export_fs
=
fs
.
makeopendir
(
course_dir
)
root
=
lxml
.
etree
.
Element
(
'root'
)
xml
=
initial_course
.
export_to_xml
(
export_fs
)
initial_course
.
add_xml_to_node
(
root
)
with
export_fs
.
open
(
'course.xml'
,
'w'
)
as
course_xml
:
with
initial_course
.
runtime
.
export_fs
.
open
(
'course.xml'
,
'w'
)
as
course_xml
:
course_xml
.
write
(
xml
)
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_
xml
)
print
(
"Starting second import"
)
print
(
"Starting second import"
)
second_import
=
XMLModuleStore
(
root_dir
,
course_dirs
=
[
course_dir
])
second_import
=
XMLModuleStore
(
root_dir
,
course_dirs
=
[
course_dir
]
,
xblock_mixins
=
(
XModuleMixin
,)
)
courses2
=
second_import
.
get_courses
()
courses2
=
second_import
.
get_courses
()
self
.
assertEquals
(
len
(
courses2
),
1
)
self
.
assertEquals
(
len
(
courses2
),
1
)
...
@@ -98,48 +133,24 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -98,48 +133,24 @@ class RoundTripTestCase(unittest.TestCase):
strip_filenames
(
initial_course
)
strip_filenames
(
initial_course
)
strip_filenames
(
exported_course
)
strip_filenames
(
exported_course
)
self
.
assert
Equals
(
initial_course
,
exported_course
)
self
.
assert
True
(
blocks_are_equivalent
(
initial_course
,
exported_course
)
)
self
.
assertEquals
(
initial_course
.
id
,
exported_course
.
id
)
self
.
assertEquals
(
initial_course
.
id
,
exported_course
.
id
)
course_id
=
initial_course
.
id
course_id
=
initial_course
.
id
print
(
"Checking key equality"
)
print
(
"Checking key equality"
)
self
.
assertEquals
(
sorted
(
initial_import
.
modules
[
course_id
]
.
keys
()),
self
.
assertItemsEqual
(
sorted
(
second_import
.
modules
[
course_id
]
.
keys
()))
initial_import
.
modules
[
course_id
]
.
keys
(),
second_import
.
modules
[
course_id
]
.
keys
()
)
print
(
"Checking module equality"
)
print
(
"Checking module equality"
)
for
location
in
initial_import
.
modules
[
course_id
]
.
keys
():
for
location
in
initial_import
.
modules
[
course_id
]
.
keys
():
print
(
"Checking"
,
location
)
print
(
"Checking"
,
location
)
self
.
assertEquals
(
initial_import
.
modules
[
course_id
][
location
],
self
.
assertTrue
(
blocks_are_equivalent
(
second_import
.
modules
[
course_id
][
location
])
initial_import
.
modules
[
course_id
][
location
],
second_import
.
modules
[
course_id
][
location
]
def
setUp
(
self
):
))
self
.
maxDiff
=
None
self
.
temp_dir
=
mkdtemp
()
self
.
addCleanup
(
shutil
.
rmtree
,
self
.
temp_dir
)
def
test_toy_roundtrip
(
self
):
self
.
check_export_roundtrip
(
DATA_DIR
,
"toy"
)
def
test_simple_roundtrip
(
self
):
self
.
check_export_roundtrip
(
DATA_DIR
,
"simple"
)
def
test_conditional_and_poll_roundtrip
(
self
):
self
.
check_export_roundtrip
(
DATA_DIR
,
"conditional_and_poll"
)
def
test_selfassessment_roundtrip
(
self
):
#Test selfassessment xmodule to see if it exports correctly
self
.
check_export_roundtrip
(
DATA_DIR
,
"self_assessment"
)
def
test_graphicslidertool_roundtrip
(
self
):
#Test graphicslidertool xmodule to see if it exports correctly
self
.
check_export_roundtrip
(
DATA_DIR
,
"graphic_slider_tool"
)
def
test_exam_registration_roundtrip
(
self
):
# Test exam_registration xmodule to see if it exports correctly
self
.
check_export_roundtrip
(
DATA_DIR
,
"test_exam_registration"
)
def
test_word_cloud_roundtrip
(
self
):
self
.
check_export_roundtrip
(
DATA_DIR
,
"word_cloud"
)
class
TestEdxJsonEncoder
(
unittest
.
TestCase
):
class
TestEdxJsonEncoder
(
unittest
.
TestCase
):
...
...
common/lib/xmodule/xmodule/tests/test_import.py
View file @
b0bed170
...
@@ -158,9 +158,9 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -158,9 +158,9 @@ class ImportTestCase(BaseCourseTestCase):
system
=
self
.
get_system
()
system
=
self
.
get_system
()
descriptor
=
system
.
process_xml
(
bad_xml
)
descriptor
=
system
.
process_xml
(
bad_xml
)
resource_fs
=
None
node
=
etree
.
Element
(
'unknown'
)
tag_xml
=
descriptor
.
export_to_xml
(
resource_fs
)
descriptor
.
add_xml_to_node
(
node
)
re_import_descriptor
=
system
.
process_xml
(
tag_xml
)
re_import_descriptor
=
system
.
process_xml
(
etree
.
tostring
(
node
)
)
self
.
assertEqual
(
re_import_descriptor
.
__class__
.
__name__
,
'ErrorDescriptorWithMixins'
)
self
.
assertEqual
(
re_import_descriptor
.
__class__
.
__name__
,
'ErrorDescriptorWithMixins'
)
...
@@ -182,12 +182,11 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -182,12 +182,11 @@ class ImportTestCase(BaseCourseTestCase):
descriptor
=
system
.
process_xml
(
xml_str_in
)
descriptor
=
system
.
process_xml
(
xml_str_in
)
# export it
# export it
resource_fs
=
None
node
=
etree
.
Element
(
'unknown'
)
xml_str_out
=
descriptor
.
export_to_xml
(
resource_fs
)
descriptor
.
add_xml_to_node
(
node
)
# Now make sure the exported xml is a sequential
# Now make sure the exported xml is a sequential
xml_out
=
etree
.
fromstring
(
xml_str_out
)
self
.
assertEqual
(
node
.
tag
,
'sequential'
)
self
.
assertEqual
(
xml_out
.
tag
,
'sequential'
)
def
test_metadata_import_export
(
self
):
def
test_metadata_import_export
(
self
):
"""Two checks:
"""Two checks:
...
@@ -221,19 +220,19 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -221,19 +220,19 @@ class ImportTestCase(BaseCourseTestCase):
)
)
# Now export and check things
# Now export and check things
resource_fs
=
MemoryFS
()
descriptor
.
runtime
.
export_fs
=
MemoryFS
()
exported_xml
=
descriptor
.
export_to_xml
(
resource_fs
)
node
=
etree
.
Element
(
'unknown'
)
descriptor
.
add_xml_to_node
(
node
)
# Check that the exported xml is just a pointer
# Check that the exported xml is just a pointer
print
(
"Exported xml:"
,
exported_xml
)
print
(
"Exported xml:"
,
etree
.
tostring
(
node
))
pointer
=
etree
.
fromstring
(
exported_xml
)
self
.
assertTrue
(
is_pointer_tag
(
node
))
self
.
assertTrue
(
is_pointer_tag
(
pointer
))
# but it's a special case course pointer
# but it's a special case course pointer
self
.
assertEqual
(
pointer
.
attrib
[
'course'
],
COURSE
)
self
.
assertEqual
(
node
.
attrib
[
'course'
],
COURSE
)
self
.
assertEqual
(
pointer
.
attrib
[
'org'
],
ORG
)
self
.
assertEqual
(
node
.
attrib
[
'org'
],
ORG
)
# Does the course still have unicorns?
# Does the course still have unicorns?
with
resource
_fs
.
open
(
'course/{url_name}.xml'
.
format
(
url_name
=
url_name
))
as
f
:
with
descriptor
.
runtime
.
export
_fs
.
open
(
'course/{url_name}.xml'
.
format
(
url_name
=
url_name
))
as
f
:
course_xml
=
etree
.
fromstring
(
f
.
read
())
course_xml
=
etree
.
fromstring
(
f
.
read
())
self
.
assertEqual
(
course_xml
.
attrib
[
'unicorn'
],
'purple'
)
self
.
assertEqual
(
course_xml
.
attrib
[
'unicorn'
],
'purple'
)
...
@@ -247,7 +246,7 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -247,7 +246,7 @@ class ImportTestCase(BaseCourseTestCase):
# Does the chapter tag now have a due attribute?
# Does the chapter tag now have a due attribute?
# hardcoded path to child
# hardcoded path to child
with
resource
_fs
.
open
(
'chapter/ch.xml'
)
as
f
:
with
descriptor
.
runtime
.
export
_fs
.
open
(
'chapter/ch.xml'
)
as
f
:
chapter_xml
=
etree
.
fromstring
(
f
.
read
())
chapter_xml
=
etree
.
fromstring
(
f
.
read
())
self
.
assertEqual
(
chapter_xml
.
tag
,
'chapter'
)
self
.
assertEqual
(
chapter_xml
.
tag
,
'chapter'
)
self
.
assertFalse
(
'due'
in
chapter_xml
.
attrib
)
self
.
assertFalse
(
'due'
in
chapter_xml
.
attrib
)
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
b0bed170
...
@@ -222,6 +222,7 @@ class XModuleMixin(XBlockMixin):
...
@@ -222,6 +222,7 @@ class XModuleMixin(XBlockMixin):
for
child_loc
in
self
.
children
:
for
child_loc
in
self
.
children
:
try
:
try
:
child
=
self
.
runtime
.
get_block
(
child_loc
)
child
=
self
.
runtime
.
get_block
(
child_loc
)
child
.
runtime
.
export_fs
=
self
.
runtime
.
export_fs
except
ItemNotFoundError
:
except
ItemNotFoundError
:
log
.
exception
(
u'Unable to load item {loc}, skipping'
.
format
(
loc
=
child_loc
))
log
.
exception
(
u'Unable to load item {loc}, skipping'
.
format
(
loc
=
child_loc
))
continue
continue
...
@@ -685,6 +686,21 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
...
@@ -685,6 +686,21 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock):
"""
"""
raise
NotImplementedError
(
'Modules must implement from_xml to be parsable from xml'
)
raise
NotImplementedError
(
'Modules must implement from_xml to be parsable from xml'
)
def
add_xml_to_node
(
self
,
node
):
"""
Export this :class:`XModuleDescriptor` as XML, by setting attributes on the provided
`node`.
"""
xml_string
=
self
.
export_to_xml
(
self
.
runtime
.
export_fs
)
exported_node
=
etree
.
fromstring
(
xml_string
)
node
.
tag
=
exported_node
.
tag
node
.
text
=
exported_node
.
text
node
.
tail
=
exported_node
.
tail
for
key
,
value
in
exported_node
.
items
():
node
.
set
(
key
,
value
)
node
.
extend
(
list
(
exported_node
))
def
export_to_xml
(
self
,
resource_fs
):
def
export_to_xml
(
self
,
resource_fs
):
"""
"""
Returns an xml string representing this module, and all modules
Returns an xml string representing this module, and all modules
...
@@ -926,6 +942,9 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable
...
@@ -926,6 +942,9 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable
"""
"""
super
(
DescriptorSystem
,
self
)
.
__init__
(
**
kwargs
)
super
(
DescriptorSystem
,
self
)
.
__init__
(
**
kwargs
)
# This is used by XModules to write out separate files during xml export
self
.
export_fs
=
None
self
.
load_item
=
load_item
self
.
load_item
=
load_item
self
.
resources_fs
=
resources_fs
self
.
resources_fs
=
resources_fs
self
.
error_tracker
=
error_tracker
self
.
error_tracker
=
error_tracker
...
@@ -996,6 +1015,11 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable
...
@@ -996,6 +1015,11 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable
def
publish
(
self
,
block
,
event
):
def
publish
(
self
,
block
,
event
):
raise
NotImplementedError
(
"edX Platform doesn't currently implement XBlock publish"
)
raise
NotImplementedError
(
"edX Platform doesn't currently implement XBlock publish"
)
def
add_block_as_child_node
(
self
,
block
,
node
):
child
=
etree
.
SubElement
(
node
,
"unknown"
)
child
.
set
(
'url_name'
,
block
.
url_name
)
block
.
add_xml_to_node
(
child
)
class
XMLParsingSystem
(
DescriptorSystem
):
class
XMLParsingSystem
(
DescriptorSystem
):
def
__init__
(
self
,
process_xml
,
**
kwargs
):
def
__init__
(
self
,
process_xml
,
**
kwargs
):
...
...
common/test/data/pure_xblock/course.xml
0 → 100644
View file @
b0bed170
<course
org=
"edX"
course=
"pure_xblock"
url_name=
"2012_Fall"
>
<pure
field1=
"a.field1"
url_name=
"pure0"
>
<vertical
url_name=
"vert0"
>
<pure
field2=
"10"
url_name=
"pure1"
/>
<pure
field2=
"20"
url_name=
"pure2"
/>
</vertical>
</pure>
</course>
\ No newline at end of file
lms/djangoapps/courseware/management/commands/clean_xml.py
View file @
b0bed170
import
lxml.etree
import
os
import
os
import
sys
import
sys
import
traceback
import
traceback
...
@@ -30,9 +31,11 @@ def export(course, export_dir):
...
@@ -30,9 +31,11 @@ def export(course, export_dir):
' May clobber/confuse things'
.
format
(
dir
=
export_dir
))
' May clobber/confuse things'
.
format
(
dir
=
export_dir
))
try
:
try
:
xml
=
course
.
export_to_xml
(
fs
)
course
.
runtime
.
export_fs
=
fs
root
=
lxml
.
etree
.
Element
(
'root'
)
course
.
add_xml_to_node
(
root
)
with
fs
.
open
(
'course.xml'
,
mode
=
'w'
)
as
f
:
with
fs
.
open
(
'course.xml'
,
mode
=
'w'
)
as
f
:
f
.
write
(
xml
)
root
.
write
(
f
)
return
True
return
True
except
:
except
:
...
...
requirements/edx/github.txt
View file @
b0bed170
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
# Our libraries:
# Our libraries:
-e git+https://github.com/edx/XBlock.git@
de92d3bf798699a6bbd06b54012ef15934c41ac0
#egg=XBlock
-e git+https://github.com/edx/XBlock.git@
3830ee50015b460fad63ff3b71f77bf1a2684195
#egg=XBlock
-e git+https://github.com/edx/codejail.git@e3d98f9455#egg=codejail
-e git+https://github.com/edx/codejail.git@e3d98f9455#egg=codejail
-e git+https://github.com/edx/diff-cover.git@v0.2.9#egg=diff_cover
-e git+https://github.com/edx/diff-cover.git@v0.2.9#egg=diff_cover
-e git+https://github.com/edx/js-test-tool.git@v0.1.5#egg=js_test_tool
-e git+https://github.com/edx/js-test-tool.git@v0.1.5#egg=js_test_tool
...
...
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