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
6893bb35
Commit
6893bb35
authored
Dec 20, 2017
by
Jeremy Bowman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PLAT-1861 Upgrade to pyfilesystem2
parent
e063a8bd
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
121 additions
and
110 deletions
+121
-110
cms/djangoapps/contentstore/tests/test_contentstore.py
+44
-43
common/lib/capa/capa/tests/test_html_render.py
+1
-1
common/lib/xmodule/xmodule/assetstore/__init__.py
+2
-2
common/lib/xmodule/xmodule/course_module.py
+3
-3
common/lib/xmodule/xmodule/html_module.py
+7
-7
common/lib/xmodule/xmodule/modulestore/__init__.py
+2
-2
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+3
-3
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
+2
-2
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
+24
-21
common/lib/xmodule/xmodule/tests/test_export.py
+11
-11
common/lib/xmodule/xmodule/tests/test_import.py
+2
-2
common/lib/xmodule/xmodule/xml_module.py
+2
-2
lms/djangoapps/courseware/courses.py
+4
-4
requirements/edx/base.txt
+10
-1
requirements/edx/github.txt
+3
-5
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
6893bb35
...
@@ -23,6 +23,7 @@ from opaque_keys import InvalidKeyError
...
@@ -23,6 +23,7 @@ from opaque_keys import InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
opaque_keys.edx.locations
import
AssetLocation
,
CourseLocator
from
opaque_keys.edx.locations
import
AssetLocation
,
CourseLocator
from
path
import
Path
as
path
from
path
import
Path
as
path
from
six
import
text_type
from
waffle.testutils
import
override_switch
from
waffle.testutils
import
override_switch
from
contentstore.tests.utils
import
AjaxEnabledTestClient
,
CourseTestCase
,
get_url
,
parse_json
from
contentstore.tests.utils
import
AjaxEnabledTestClient
,
CourseTestCase
,
get_url
,
parse_json
...
@@ -117,7 +118,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -117,7 +118,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
Asset name in XML: "/invalid
\\
displayname/subs-esLhHcdKGWvKs.srt"
Asset name in XML: "/invalid
\\
displayname/subs-esLhHcdKGWvKs.srt"
"""
"""
content_store
=
contentstore
()
content_store
=
contentstore
()
expected_displayname
=
'_invalid_displayname_subs-esLhHcdKGWvKs.srt'
expected_displayname
=
u
'_invalid_displayname_subs-esLhHcdKGWvKs.srt'
import_course_from_xml
(
import_course_from_xml
(
self
.
store
,
self
.
store
,
...
@@ -156,10 +157,10 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -156,10 +157,10 @@ class ImportRequiredTestCases(ContentStoreTestCase):
# Test course export does not fail
# Test course export does not fail
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
export_course_to_xml
(
self
.
store
,
content_store
,
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course
.
id
,
root_dir
,
u
'test_export'
)
filesystem
=
OSFS
(
root_dir
/
'test_export/static'
)
filesystem
=
OSFS
(
text_type
(
root_dir
/
'test_export/static'
)
)
exported_static_files
=
filesystem
.
listdir
()
exported_static_files
=
filesystem
.
listdir
(
u'/'
)
# Verify that asset have been overwritten during export.
# Verify that asset have been overwritten during export.
self
.
assertEqual
(
len
(
exported_static_files
),
1
)
self
.
assertEqual
(
len
(
exported_static_files
),
1
)
...
@@ -236,18 +237,18 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -236,18 +237,18 @@ class ImportRequiredTestCases(ContentStoreTestCase):
self
.
assertIsNotNone
(
course_updates
)
self
.
assertIsNotNone
(
course_updates
)
# check that course which is imported has files 'updates.html' and 'updates.items.json'
# check that course which is imported has files 'updates.html' and 'updates.items.json'
filesystem
=
OSFS
(
data_dir
+
'/course_info_updates/info'
)
filesystem
=
OSFS
(
text_type
(
data_dir
+
'/course_info_updates/info'
)
)
self
.
assertTrue
(
filesystem
.
exists
(
'updates.html'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'updates.html'
))
self
.
assertTrue
(
filesystem
.
exists
(
'updates.items.json'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'updates.items.json'
))
# verify that course info update module has same data content as in data file from which it is imported
# verify that course info update module has same data content as in data file from which it is imported
# check 'data' field content
# check 'data' field content
with
filesystem
.
open
(
'updates.html'
,
'r'
)
as
course_policy
:
with
filesystem
.
open
(
u
'updates.html'
,
'r'
)
as
course_policy
:
on_disk
=
course_policy
.
read
()
on_disk
=
course_policy
.
read
()
self
.
assertEqual
(
course_updates
.
data
,
on_disk
)
self
.
assertEqual
(
course_updates
.
data
,
on_disk
)
# check 'items' field content
# check 'items' field content
with
filesystem
.
open
(
'updates.items.json'
,
'r'
)
as
course_policy
:
with
filesystem
.
open
(
u
'updates.items.json'
,
'r'
)
as
course_policy
:
on_disk
=
loads
(
course_policy
.
read
())
on_disk
=
loads
(
course_policy
.
read
())
self
.
assertEqual
(
course_updates
.
items
,
on_disk
)
self
.
assertEqual
(
course_updates
.
items
,
on_disk
)
...
@@ -255,19 +256,19 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -255,19 +256,19 @@ class ImportRequiredTestCases(ContentStoreTestCase):
# with same content as in course 'info' directory
# with same content as in course 'info' directory
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
export_course_to_xml
(
self
.
store
,
content_store
,
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course
.
id
,
root_dir
,
u
'test_export'
)
# check that exported course has files 'updates.html' and 'updates.items.json'
# check that exported course has files 'updates.html' and 'updates.items.json'
filesystem
=
OSFS
(
root_dir
/
'test_export/info'
)
filesystem
=
OSFS
(
text_type
(
root_dir
/
'test_export/info'
)
)
self
.
assertTrue
(
filesystem
.
exists
(
'updates.html'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'updates.html'
))
self
.
assertTrue
(
filesystem
.
exists
(
'updates.items.json'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'updates.items.json'
))
# verify that exported course has same data content as in course_info_update module
# verify that exported course has same data content as in course_info_update module
with
filesystem
.
open
(
'updates.html'
,
'r'
)
as
grading_policy
:
with
filesystem
.
open
(
u
'updates.html'
,
'r'
)
as
grading_policy
:
on_disk
=
grading_policy
.
read
()
on_disk
=
grading_policy
.
read
()
self
.
assertEqual
(
on_disk
,
course_updates
.
data
)
self
.
assertEqual
(
on_disk
,
course_updates
.
data
)
with
filesystem
.
open
(
'updates.items.json'
,
'r'
)
as
grading_policy
:
with
filesystem
.
open
(
u
'updates.items.json'
,
'r'
)
as
grading_policy
:
on_disk
=
loads
(
grading_policy
.
read
())
on_disk
=
loads
(
grading_policy
.
read
())
self
.
assertEqual
(
on_disk
,
course_updates
.
items
)
self
.
assertEqual
(
on_disk
,
course_updates
.
items
)
...
@@ -315,39 +316,39 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -315,39 +316,39 @@ class ImportRequiredTestCases(ContentStoreTestCase):
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
# export out to a tempdir
# export out to a tempdir
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
u
'test_export'
)
# check for static tabs
# check for static tabs
self
.
verify_content_existence
(
self
.
store
,
root_dir
,
course_id
,
'tabs'
,
'static_tab'
,
'.html'
)
self
.
verify_content_existence
(
self
.
store
,
root_dir
,
course_id
,
u
'tabs'
,
'static_tab'
,
'.html'
)
# check for about content
# check for about content
self
.
verify_content_existence
(
self
.
store
,
root_dir
,
course_id
,
'about'
,
'about'
,
'.html'
)
self
.
verify_content_existence
(
self
.
store
,
root_dir
,
course_id
,
u
'about'
,
'about'
,
'.html'
)
# assert that there is an html and video directory in drafts:
# assert that there is an html and video directory in drafts:
draft_dir
=
OSFS
(
root_dir
/
'test_export/drafts'
)
draft_dir
=
OSFS
(
root_dir
/
'test_export/drafts'
)
self
.
assertTrue
(
draft_dir
.
exists
(
'html'
))
self
.
assertTrue
(
draft_dir
.
exists
(
u
'html'
))
self
.
assertTrue
(
draft_dir
.
exists
(
'video'
))
self
.
assertTrue
(
draft_dir
.
exists
(
u
'video'
))
# and assert that they contain the created modules
# and assert that they contain the created modules
self
.
assertIn
(
self
.
DRAFT_HTML
+
".xml"
,
draft_dir
.
listdir
(
'html'
))
self
.
assertIn
(
self
.
DRAFT_HTML
+
".xml"
,
draft_dir
.
listdir
(
u
'html'
))
self
.
assertIn
(
self
.
DRAFT_VIDEO
+
".xml"
,
draft_dir
.
listdir
(
'video'
))
self
.
assertIn
(
self
.
DRAFT_VIDEO
+
".xml"
,
draft_dir
.
listdir
(
u
'video'
))
# and assert the child of the orphaned draft wasn't exported
# and assert the child of the orphaned draft wasn't exported
self
.
assertNotIn
(
self
.
ORPHAN_DRAFT_HTML
+
".xml"
,
draft_dir
.
listdir
(
'html'
))
self
.
assertNotIn
(
self
.
ORPHAN_DRAFT_HTML
+
".xml"
,
draft_dir
.
listdir
(
u
'html'
))
# check for grading_policy.json
# check for grading_policy.json
filesystem
=
OSFS
(
root_dir
/
'test_export/policies/2012_Fall'
)
filesystem
=
OSFS
(
root_dir
/
'test_export/policies/2012_Fall'
)
self
.
assertTrue
(
filesystem
.
exists
(
'grading_policy.json'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'grading_policy.json'
))
course
=
self
.
store
.
get_course
(
course_id
)
course
=
self
.
store
.
get_course
(
course_id
)
# compare what's on disk compared to what we have in our course
# compare what's on disk compared to what we have in our course
with
filesystem
.
open
(
'grading_policy.json'
,
'r'
)
as
grading_policy
:
with
filesystem
.
open
(
u
'grading_policy.json'
,
'r'
)
as
grading_policy
:
on_disk
=
loads
(
grading_policy
.
read
())
on_disk
=
loads
(
grading_policy
.
read
())
self
.
assertEqual
(
on_disk
,
course
.
grading_policy
)
self
.
assertEqual
(
on_disk
,
course
.
grading_policy
)
# check for policy.json
# check for policy.json
self
.
assertTrue
(
filesystem
.
exists
(
'policy.json'
))
self
.
assertTrue
(
filesystem
.
exists
(
u
'policy.json'
))
# compare what's on disk to what we have in the course module
# compare what's on disk to what we have in the course module
with
filesystem
.
open
(
'policy.json'
,
'r'
)
as
course_policy
:
with
filesystem
.
open
(
u
'policy.json'
,
'r'
)
as
course_policy
:
on_disk
=
loads
(
course_policy
.
read
())
on_disk
=
loads
(
course_policy
.
read
())
self
.
assertIn
(
'course/2012_Fall'
,
on_disk
)
self
.
assertIn
(
'course/2012_Fall'
,
on_disk
)
self
.
assertEqual
(
on_disk
[
'course/2012_Fall'
],
own_metadata
(
course
))
self
.
assertEqual
(
on_disk
[
'course/2012_Fall'
],
own_metadata
(
course
))
...
@@ -417,7 +418,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -417,7 +418,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
# export out to a tempdir
# export out to a tempdir
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
u
'test_export'
)
shutil
.
rmtree
(
root_dir
)
shutil
.
rmtree
(
root_dir
)
...
@@ -443,7 +444,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -443,7 +444,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
# export out to a tempdir
# export out to a tempdir
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
u
'test_export'
)
shutil
.
rmtree
(
root_dir
)
shutil
.
rmtree
(
root_dir
)
...
@@ -496,7 +497,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -496,7 +497,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
# Export the course
# Export the course
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
'test_roundtrip'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
u
'test_roundtrip'
)
# Reimport and get the video back
# Reimport and get the video back
import_course_from_xml
(
self
.
store
,
self
.
user
.
id
,
root_dir
)
import_course_from_xml
(
self
.
store
,
self
.
user
.
id
,
root_dir
)
...
@@ -517,7 +518,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -517,7 +518,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
# Export the course
# Export the course
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
'test_roundtrip'
)
export_course_to_xml
(
self
.
store
,
content_store
,
course_id
,
root_dir
,
u
'test_roundtrip'
)
# Reimport and get the video back
# Reimport and get the video back
import_course_from_xml
(
self
.
store
,
self
.
user
.
id
,
root_dir
,
create_if_not_present
=
True
)
import_course_from_xml
(
self
.
store
,
self
.
user
.
id
,
root_dir
,
create_if_not_present
=
True
)
...
@@ -541,7 +542,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -541,7 +542,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
export_course_to_xml
(
self
.
store
,
None
,
course_id
,
root_dir
,
'test_export_no_content_store'
)
export_course_to_xml
(
self
.
store
,
None
,
course_id
,
root_dir
,
u
'test_export_no_content_store'
)
# Delete the course from module store and reimport it
# Delete the course from module store and reimport it
...
@@ -596,7 +597,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
...
@@ -596,7 +597,7 @@ class ImportRequiredTestCases(ContentStoreTestCase):
content_store
,
content_store
,
course_id
,
course_id
,
root_dir
,
root_dir
,
'test_no_xml_attributes'
u
'test_no_xml_attributes'
)
)
...
@@ -695,7 +696,7 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -695,7 +696,7 @@ class MiscCourseTests(ContentStoreTestCase):
def
test_export_on_invalid_displayname
(
self
,
invalid_displayname
):
def
test_export_on_invalid_displayname
(
self
,
invalid_displayname
):
""" Tests that assets with invalid 'displayname' does not cause export to fail """
""" Tests that assets with invalid 'displayname' does not cause export to fail """
content_store
=
contentstore
()
content_store
=
contentstore
()
exported_asset_name
=
'_Fake_asset_displayname'
exported_asset_name
=
u
'_Fake_asset_displayname'
# Create an asset with slash `invalid_displayname` '
# Create an asset with slash `invalid_displayname` '
asset_key
=
self
.
course
.
id
.
make_asset_key
(
'asset'
,
"fake_asset.txt"
)
asset_key
=
self
.
course
.
id
.
make_asset_key
(
'asset'
,
"fake_asset.txt"
)
...
@@ -713,10 +714,10 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -713,10 +714,10 @@ class MiscCourseTests(ContentStoreTestCase):
# Now export the course to a tempdir and test that it contains assets. The export should pass
# Now export the course to a tempdir and test that it contains assets. The export should pass
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
u
'test_export'
)
filesystem
=
OSFS
(
root_dir
/
'test_export/static'
)
filesystem
=
OSFS
(
root_dir
/
'test_export/static'
)
exported_static_files
=
filesystem
.
listdir
()
exported_static_files
=
filesystem
.
listdir
(
u'/'
)
# Verify that only single asset has been exported with the expected asset name.
# Verify that only single asset has been exported with the expected asset name.
self
.
assertTrue
(
filesystem
.
exists
(
exported_asset_name
))
self
.
assertTrue
(
filesystem
.
exists
(
exported_asset_name
))
...
@@ -737,13 +738,13 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -737,13 +738,13 @@ class MiscCourseTests(ContentStoreTestCase):
# Make an existing unit a draft
# Make an existing unit a draft
self
.
store
.
convert_to_draft
(
self
.
problem
.
location
,
self
.
user
.
id
)
self
.
store
.
convert_to_draft
(
self
.
problem
.
location
,
self
.
user
.
id
)
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
export_course_to_xml
(
self
.
store
,
None
,
self
.
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
None
,
self
.
course
.
id
,
root_dir
,
u
'test_export'
)
# Verify that problem is exported in the drafts. This is expected because we are
# Verify that problem is exported in the drafts. This is expected because we are
# mocking get_item to for drafts. Expect no draft is exported.
# mocking get_item to for drafts. Expect no draft is exported.
# Specifically get_item is used in `xmodule.modulestore.xml_exporter._export_drafts`
# Specifically get_item is used in `xmodule.modulestore.xml_exporter._export_drafts`
export_draft_dir
=
OSFS
(
root_dir
/
'test_export/drafts'
)
export_draft_dir
=
OSFS
(
root_dir
/
'test_export/drafts'
)
self
.
assertEqual
(
len
(
export_draft_dir
.
listdir
()),
0
)
self
.
assertEqual
(
len
(
export_draft_dir
.
listdir
(
u'/'
)),
0
)
# Remove tempdir
# Remove tempdir
shutil
.
rmtree
(
root_dir
)
shutil
.
rmtree
(
root_dir
)
...
@@ -751,7 +752,7 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -751,7 +752,7 @@ class MiscCourseTests(ContentStoreTestCase):
def
test_assets_overwrite
(
self
):
def
test_assets_overwrite
(
self
):
""" Tests that assets will similar 'displayname' will be overwritten during export """
""" Tests that assets will similar 'displayname' will be overwritten during export """
content_store
=
contentstore
()
content_store
=
contentstore
()
asset_displayname
=
'Fake_asset.txt'
asset_displayname
=
u
'Fake_asset.txt'
# Create two assets with similar 'displayname'
# Create two assets with similar 'displayname'
for
i
in
range
(
2
):
for
i
in
range
(
2
):
...
@@ -773,11 +774,11 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -773,11 +774,11 @@ class MiscCourseTests(ContentStoreTestCase):
# Now export the course to a tempdir and test that it contains assets.
# Now export the course to a tempdir and test that it contains assets.
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
print
'Exporting to tempdir = {0}'
.
format
(
root_dir
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
u
'test_export'
)
# Verify that asset have been overwritten during export.
# Verify that asset have been overwritten during export.
filesystem
=
OSFS
(
root_dir
/
'test_export/static'
)
filesystem
=
OSFS
(
root_dir
/
'test_export/static'
)
exported_static_files
=
filesystem
.
listdir
()
exported_static_files
=
filesystem
.
listdir
(
u'/'
)
self
.
assertTrue
(
filesystem
.
exists
(
asset_displayname
))
self
.
assertTrue
(
filesystem
.
exists
(
asset_displayname
))
self
.
assertEqual
(
len
(
exported_static_files
),
1
)
self
.
assertEqual
(
len
(
exported_static_files
),
1
)
...
@@ -2109,7 +2110,7 @@ class ContentLicenseTest(ContentStoreTestCase):
...
@@ -2109,7 +2110,7 @@ class ContentLicenseTest(ContentStoreTestCase):
root_dir
=
path
(
mkdtemp_clean
())
root_dir
=
path
(
mkdtemp_clean
())
self
.
course
.
license
=
"creative-commons: BY SA"
self
.
course
.
license
=
"creative-commons: BY SA"
self
.
store
.
update_item
(
self
.
course
,
None
)
self
.
store
.
update_item
(
self
.
course
,
None
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
'test_license'
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
u
'test_license'
)
fname
=
"{block}.xml"
.
format
(
block
=
self
.
course
.
scope_ids
.
usage_id
.
block_id
)
fname
=
"{block}.xml"
.
format
(
block
=
self
.
course
.
scope_ids
.
usage_id
.
block_id
)
run_file_path
=
root_dir
/
"test_license"
/
"course"
/
fname
run_file_path
=
root_dir
/
"test_license"
/
"course"
/
fname
run_xml
=
etree
.
parse
(
run_file_path
.
open
())
run_xml
=
etree
.
parse
(
run_file_path
.
open
())
...
@@ -2122,7 +2123,7 @@ class ContentLicenseTest(ContentStoreTestCase):
...
@@ -2122,7 +2123,7 @@ class ContentLicenseTest(ContentStoreTestCase):
parent_location
=
self
.
course
.
location
,
category
=
'video'
,
parent_location
=
self
.
course
.
location
,
category
=
'video'
,
license
=
"all-rights-reserved"
license
=
"all-rights-reserved"
)
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
'test_license'
)
export_course_to_xml
(
self
.
store
,
content_store
,
self
.
course
.
id
,
root_dir
,
u
'test_license'
)
fname
=
"{block}.xml"
.
format
(
block
=
video_descriptor
.
scope_ids
.
usage_id
.
block_id
)
fname
=
"{block}.xml"
.
format
(
block
=
video_descriptor
.
scope_ids
.
usage_id
.
block_id
)
video_file_path
=
root_dir
/
"test_license"
/
"video"
/
fname
video_file_path
=
root_dir
/
"test_license"
/
"video"
/
fname
video_xml
=
etree
.
parse
(
video_file_path
.
open
())
video_xml
=
etree
.
parse
(
video_file_path
.
open
())
...
...
common/lib/capa/capa/tests/test_html_render.py
View file @
6893bb35
...
@@ -43,7 +43,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
...
@@ -43,7 +43,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
def
test_include_html
(
self
):
def
test_include_html
(
self
):
# Create a test file to include
# Create a test file to include
self
.
_create_test_file
(
self
.
_create_test_file
(
'test_include.xml'
,
u
'test_include.xml'
,
'<test>Test include</test>'
'<test>Test include</test>'
)
)
...
...
common/lib/xmodule/xmodule/assetstore/__init__.py
View file @
6893bb35
...
@@ -45,10 +45,10 @@ class AssetMetadata(object):
...
@@ -45,10 +45,10 @@ class AssetMetadata(object):
ASSET_XML_TAG
=
'asset'
ASSET_XML_TAG
=
'asset'
# Top-level directory name in exported course XML which holds asset metadata.
# Top-level directory name in exported course XML which holds asset metadata.
EXPORTED_ASSET_DIR
=
'assets'
EXPORTED_ASSET_DIR
=
u
'assets'
# Filename of all asset metadata exported as XML.
# Filename of all asset metadata exported as XML.
EXPORTED_ASSET_FILENAME
=
'assets.xml'
EXPORTED_ASSET_FILENAME
=
u
'assets.xml'
@contract
(
asset_id
=
'AssetKey'
,
@contract
(
asset_id
=
'AssetKey'
,
pathname
=
'basestring|None'
,
internal_name
=
'basestring|None'
,
pathname
=
'basestring|None'
,
internal_name
=
'basestring|None'
,
...
...
common/lib/xmodule/xmodule/course_module.py
View file @
6893bb35
...
@@ -1002,12 +1002,12 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
...
@@ -1002,12 +1002,12 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
policy_dir
=
None
policy_dir
=
None
url_name
=
xml_obj
.
get
(
'url_name'
,
xml_obj
.
get
(
'slug'
))
url_name
=
xml_obj
.
get
(
'url_name'
,
xml_obj
.
get
(
'slug'
))
if
url_name
:
if
url_name
:
policy_dir
=
'policies/'
+
url_name
policy_dir
=
u
'policies/'
+
url_name
# Try to load grading policy
# Try to load grading policy
paths
=
[
'grading_policy.json'
]
paths
=
[
u
'grading_policy.json'
]
if
policy_dir
:
if
policy_dir
:
paths
=
[
policy_dir
+
'/grading_policy.json'
]
+
paths
paths
=
[
policy_dir
+
u
'/grading_policy.json'
]
+
paths
try
:
try
:
policy
=
json
.
loads
(
cls
.
read_grading_policy
(
paths
,
system
))
policy
=
json
.
loads
(
cls
.
read_grading_policy
(
paths
,
system
))
...
...
common/lib/xmodule/xmodule/html_module.py
View file @
6893bb35
...
@@ -7,7 +7,7 @@ import textwrap
...
@@ -7,7 +7,7 @@ import textwrap
from
datetime
import
datetime
from
datetime
import
datetime
from
django.conf
import
settings
from
django.conf
import
settings
from
fs.errors
import
ResourceNotFound
Error
from
fs.errors
import
ResourceNotFound
from
lxml
import
etree
from
lxml
import
etree
from
path
import
Path
as
path
from
path
import
Path
as
path
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
...
@@ -236,7 +236,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
...
@@ -236,7 +236,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
)
)
base
=
path
(
pointer_path
)
.
dirname
()
base
=
path
(
pointer_path
)
.
dirname
()
# log.debug("base = {0}, base.dirname={1}, filename={2}".format(base, base.dirname(), filename))
# log.debug("base = {0}, base.dirname={1}, filename={2}".format(base, base.dirname(), filename))
filepath
=
"{base}/{name}.html"
.
format
(
base
=
base
,
name
=
filename
)
filepath
=
u
"{base}/{name}.html"
.
format
(
base
=
base
,
name
=
filename
)
# log.debug("looking for html file for {0} at {1}".format(location, filepath))
# log.debug("looking for html file for {0} at {1}".format(location, filepath))
# VS[compat]
# VS[compat]
...
@@ -259,8 +259,8 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
...
@@ -259,8 +259,8 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
break
break
try
:
try
:
with
system
.
resources_fs
.
open
(
filepath
)
as
infile
:
with
system
.
resources_fs
.
open
(
filepath
,
encoding
=
'utf-8'
)
as
infile
:
html
=
infile
.
read
()
.
decode
(
'utf-8'
)
html
=
infile
.
read
()
# Log a warning if we can't parse the file, but don't error
# Log a warning if we can't parse the file, but don't error
if
not
check_html
(
html
)
and
len
(
html
)
>
0
:
if
not
check_html
(
html
)
and
len
(
html
)
>
0
:
msg
=
"Couldn't parse html in {0}, content = {1}"
.
format
(
filepath
,
html
)
msg
=
"Couldn't parse html in {0}, content = {1}"
.
format
(
filepath
,
html
)
...
@@ -275,7 +275,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
...
@@ -275,7 +275,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
return
definition
,
[]
return
definition
,
[]
except
(
ResourceNotFoundError
)
as
err
:
except
ResourceNotFound
as
err
:
msg
=
'Unable to load file contents at path {0}: {1} '
.
format
(
msg
=
'Unable to load file contents at path {0}: {1} '
.
format
(
filepath
,
err
)
filepath
,
err
)
# add more info and re-raise
# add more info and re-raise
...
@@ -295,8 +295,8 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
...
@@ -295,8 +295,8 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
pathname
=
pathname
pathname
=
pathname
)
)
resource_fs
.
makedir
(
os
.
path
.
dirname
(
filepath
),
recursive
=
True
,
allow_
recreate
=
True
)
resource_fs
.
makedir
s
(
os
.
path
.
dirname
(
filepath
),
recreate
=
True
)
with
resource_fs
.
open
(
filepath
,
'w'
)
as
filestream
:
with
resource_fs
.
open
(
filepath
,
'w
b
'
)
as
filestream
:
html_data
=
self
.
data
.
encode
(
'utf-8'
)
html_data
=
self
.
data
.
encode
(
'utf-8'
)
filestream
.
write
(
html_data
)
filestream
.
write
(
html_data
)
...
...
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
6893bb35
...
@@ -34,8 +34,8 @@ new_contract('AssetKey', AssetKey)
...
@@ -34,8 +34,8 @@ new_contract('AssetKey', AssetKey)
new_contract
(
'AssetMetadata'
,
AssetMetadata
)
new_contract
(
'AssetMetadata'
,
AssetMetadata
)
new_contract
(
'XBlock'
,
XBlock
)
new_contract
(
'XBlock'
,
XBlock
)
LIBRARY_ROOT
=
'library.xml'
LIBRARY_ROOT
=
u
'library.xml'
COURSE_ROOT
=
'course.xml'
COURSE_ROOT
=
u
'course.xml'
# List of names of computed fields on xmodules that are of type usage keys.
# List of names of computed fields on xmodules that are of type usage keys.
# This list can be used to determine which fields need to be stripped of
# This list can be used to determine which fields need to be stripped of
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
View file @
6893bb35
...
@@ -39,7 +39,7 @@ COURSE_DATA_NAMES = (
...
@@ -39,7 +39,7 @@ COURSE_DATA_NAMES = (
'split_test_module_draft'
,
'split_test_module_draft'
,
)
)
EXPORTED_COURSE_DIR_NAME
=
'exported_source_course'
EXPORTED_COURSE_DIR_NAME
=
u
'exported_source_course'
@ddt.ddt
@ddt.ddt
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
View file @
6893bb35
...
@@ -572,7 +572,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
...
@@ -572,7 +572,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
root_dir
=
path
(
mkdtemp
())
root_dir
=
path
(
mkdtemp
())
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course_key
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course_key
,
root_dir
,
u
'test_export'
)
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/images_course_image.jpg'
)
.
isfile
())
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/images_course_image.jpg'
)
.
isfile
())
...
@@ -588,7 +588,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
...
@@ -588,7 +588,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
root_dir
=
path
(
mkdtemp
())
root_dir
=
path
(
mkdtemp
())
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course
.
id
,
root_dir
,
u
'test_export'
)
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/just_a_test.jpg'
)
.
isfile
())
self
.
assertTrue
(
path
(
root_dir
/
'test_export/static/just_a_test.jpg'
)
.
isfile
())
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
...
@@ -601,7 +601,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
...
@@ -601,7 +601,7 @@ class TestMongoModuleStore(TestMongoModuleStoreBase):
course
=
self
.
draft_store
.
get_course
(
CourseKey
.
from_string
(
'edX/simple_with_draft/2012_Fall'
))
course
=
self
.
draft_store
.
get_course
(
CourseKey
.
from_string
(
'edX/simple_with_draft/2012_Fall'
))
root_dir
=
path
(
mkdtemp
())
root_dir
=
path
(
mkdtemp
())
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
self
.
addCleanup
(
shutil
.
rmtree
,
root_dir
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course
.
id
,
root_dir
,
'test_export'
)
export_course_to_xml
(
self
.
draft_store
,
self
.
content_store
,
course
.
id
,
root_dir
,
u
'test_export'
)
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images/course_image.jpg'
)
.
isfile
())
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images_course_image.jpg'
)
.
isfile
())
self
.
assertFalse
(
path
(
root_dir
/
'test_export/static/images_course_image.jpg'
)
.
isfile
())
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
View file @
6893bb35
...
@@ -497,8 +497,8 @@ class DraftPublishedOpBaseTestSetup(OLXFormatChecker, DraftPublishedOpTestCourse
...
@@ -497,8 +497,8 @@ class DraftPublishedOpBaseTestSetup(OLXFormatChecker, DraftPublishedOpTestCourse
Setup base class for draft/published/OLX tests.
Setup base class for draft/published/OLX tests.
"""
"""
EXPORTED_COURSE_BEFORE_DIR_NAME
=
'exported_course_before'
EXPORTED_COURSE_BEFORE_DIR_NAME
=
u
'exported_course_before'
EXPORTED_COURSE_AFTER_DIR_NAME
=
'exported_course_after_{}'
EXPORTED_COURSE_AFTER_DIR_NAME
=
u
'exported_course_after_{}'
def
setUp
(
self
):
def
setUp
(
self
):
super
(
DraftPublishedOpBaseTestSetup
,
self
)
.
setUp
()
super
(
DraftPublishedOpBaseTestSetup
,
self
)
.
setUp
()
...
...
common/lib/xmodule/xmodule/modulestore/xml_exporter.py
View file @
6893bb35
...
@@ -4,6 +4,7 @@ Methods for exporting course data to XML
...
@@ -4,6 +4,7 @@ Methods for exporting course data to XML
import
logging
import
logging
from
abc
import
abstractmethod
from
abc
import
abstractmethod
from
six
import
text_type
import
lxml.etree
import
lxml.etree
from
xblock.fields
import
Scope
,
Reference
,
ReferenceList
,
ReferenceValueDict
from
xblock.fields
import
Scope
,
Reference
,
ReferenceList
,
ReferenceValueDict
from
xmodule.contentstore.content
import
StaticContent
from
xmodule.contentstore.content
import
StaticContent
...
@@ -42,7 +43,7 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key):
...
@@ -42,7 +43,7 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key):
# Only modules with changes will be exported into the /drafts directory.
# Only modules with changes will be exported into the /drafts directory.
draft_modules
=
[
module
for
module
in
draft_modules
if
modulestore
.
has_changes
(
module
)]
draft_modules
=
[
module
for
module
in
draft_modules
if
modulestore
.
has_changes
(
module
)]
if
draft_modules
:
if
draft_modules
:
draft_course_dir
=
export_fs
.
make
opendir
(
DRAFT_DIR
)
draft_course_dir
=
export_fs
.
make
dir
(
DRAFT_DIR
,
recreate
=
True
)
# accumulate tuples of draft_modules and their parents in
# accumulate tuples of draft_modules and their parents in
# this list:
# this list:
...
@@ -118,7 +119,7 @@ class ExportManager(object):
...
@@ -118,7 +119,7 @@ class ExportManager(object):
self
.
contentstore
=
contentstore
self
.
contentstore
=
contentstore
self
.
courselike_key
=
courselike_key
self
.
courselike_key
=
courselike_key
self
.
root_dir
=
root_dir
self
.
root_dir
=
root_dir
self
.
target_dir
=
t
arget_dir
self
.
target_dir
=
t
ext_type
(
target_dir
)
@abstractmethod
@abstractmethod
def
get_key
(
self
):
def
get_key
(
self
):
...
@@ -160,7 +161,7 @@ class ExportManager(object):
...
@@ -160,7 +161,7 @@ class ExportManager(object):
# export only the published content
# export only the published content
with
self
.
modulestore
.
branch_setting
(
ModuleStoreEnum
.
Branch
.
published_only
,
self
.
courselike_key
):
with
self
.
modulestore
.
branch_setting
(
ModuleStoreEnum
.
Branch
.
published_only
,
self
.
courselike_key
):
courselike
=
self
.
get_courselike
()
courselike
=
self
.
get_courselike
()
export_fs
=
courselike
.
runtime
.
export_fs
=
fsm
.
make
opendir
(
self
.
target_dir
)
export_fs
=
courselike
.
runtime
.
export_fs
=
fsm
.
make
dir
(
self
.
target_dir
,
recreate
=
True
)
# change all of the references inside the course to use the xml expected key type w/o version & branch
# change all of the references inside the course to use the xml expected key type w/o version & branch
xml_centric_courselike_key
=
self
.
get_key
()
xml_centric_courselike_key
=
self
.
get_key
()
...
@@ -196,8 +197,8 @@ class CourseExportManager(ExportManager):
...
@@ -196,8 +197,8 @@ class CourseExportManager(ExportManager):
return
self
.
modulestore
.
get_course
(
self
.
courselike_key
,
depth
=
None
,
lazy
=
False
)
return
self
.
modulestore
.
get_course
(
self
.
courselike_key
,
depth
=
None
,
lazy
=
False
)
def
process_root
(
self
,
root
,
export_fs
):
def
process_root
(
self
,
root
,
export_fs
):
with
export_fs
.
open
(
'course.xml'
,
'w
'
)
as
course_xml
:
with
export_fs
.
open
(
u'course.xml'
,
'wb
'
)
as
course_xml
:
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_xml
)
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_xml
,
encoding
=
'utf-8'
)
def
process_extra
(
self
,
root
,
courselike
,
root_courselike_dir
,
xml_centric_courselike_key
,
export_fs
):
def
process_extra
(
self
,
root
,
courselike
,
root_courselike_dir
,
xml_centric_courselike_key
,
export_fs
):
# Export the modulestore's asset metadata.
# Export the modulestore's asset metadata.
...
@@ -210,11 +211,11 @@ class CourseExportManager(ExportManager):
...
@@ -210,11 +211,11 @@ class CourseExportManager(ExportManager):
# All asset types are exported using the "asset" tag - but their asset type is specified in each asset key.
# All asset types are exported using the "asset" tag - but their asset type is specified in each asset key.
asset
=
lxml
.
etree
.
SubElement
(
asset_root
,
AssetMetadata
.
ASSET_XML_TAG
)
asset
=
lxml
.
etree
.
SubElement
(
asset_root
,
AssetMetadata
.
ASSET_XML_TAG
)
asset_md
.
to_xml
(
asset
)
asset_md
.
to_xml
(
asset
)
with
OSFS
(
asset_dir
)
.
open
(
AssetMetadata
.
EXPORTED_ASSET_FILENAME
,
'w'
)
as
asset_xml_file
:
with
OSFS
(
asset_dir
)
.
open
(
AssetMetadata
.
EXPORTED_ASSET_FILENAME
,
'w
b
'
)
as
asset_xml_file
:
lxml
.
etree
.
ElementTree
(
asset_root
)
.
write
(
asset_xml_file
)
lxml
.
etree
.
ElementTree
(
asset_root
)
.
write
(
asset_xml_file
,
encoding
=
'utf-8'
)
# export the static assets
# export the static assets
policies_dir
=
export_fs
.
make
opendir
(
'policies'
)
policies_dir
=
export_fs
.
make
dir
(
'policies'
,
recreate
=
True
)
if
self
.
contentstore
:
if
self
.
contentstore
:
self
.
contentstore
.
export_all_for_course
(
self
.
contentstore
.
export_all_for_course
(
self
.
courselike_key
,
self
.
courselike_key
,
...
@@ -238,7 +239,7 @@ class CourseExportManager(ExportManager):
...
@@ -238,7 +239,7 @@ class CourseExportManager(ExportManager):
output_dir
=
root_courselike_dir
+
'/static/images/'
output_dir
=
root_courselike_dir
+
'/static/images/'
if
not
os
.
path
.
isdir
(
output_dir
):
if
not
os
.
path
.
isdir
(
output_dir
):
os
.
makedirs
(
output_dir
)
os
.
makedirs
(
output_dir
)
with
OSFS
(
output_dir
)
.
open
(
'course_image.jpg'
,
'wb'
)
as
course_image_file
:
with
OSFS
(
output_dir
)
.
open
(
u
'course_image.jpg'
,
'wb'
)
as
course_image_file
:
course_image_file
.
write
(
course_image
.
data
)
course_image_file
.
write
(
course_image
.
data
)
# export the static tabs
# export the static tabs
...
@@ -270,16 +271,17 @@ class CourseExportManager(ExportManager):
...
@@ -270,16 +271,17 @@ class CourseExportManager(ExportManager):
# Use url_name for split mongo because course_run is not used when loading policies.
# Use url_name for split mongo because course_run is not used when loading policies.
course_policy_dir_name
=
courselike
.
url_name
course_policy_dir_name
=
courselike
.
url_name
course_run_policy_dir
=
policies_dir
.
make
opendir
(
course_policy_dir_nam
e
)
course_run_policy_dir
=
policies_dir
.
make
dir
(
course_policy_dir_name
,
recreate
=
Tru
e
)
# export the grading policy
# export the grading policy
with
course_run_policy_dir
.
open
(
'grading_policy.json'
,
'w'
)
as
grading_policy
:
with
course_run_policy_dir
.
open
(
u'grading_policy.json'
,
'wb'
)
as
grading_policy
:
grading_policy
.
write
(
dumps
(
courselike
.
grading_policy
,
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
))
grading_policy
.
write
(
dumps
(
courselike
.
grading_policy
,
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
)
.
encode
(
'utf-8'
))
# export all of the course metadata in policy.json
# export all of the course metadata in policy.json
with
course_run_policy_dir
.
open
(
'policy.json'
,
'w
'
)
as
course_policy
:
with
course_run_policy_dir
.
open
(
u'policy.json'
,
'wb
'
)
as
course_policy
:
policy
=
{
'course/'
+
courselike
.
location
.
name
:
own_metadata
(
courselike
)}
policy
=
{
'course/'
+
courselike
.
location
.
name
:
own_metadata
(
courselike
)}
course_policy
.
write
(
dumps
(
policy
,
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
))
course_policy
.
write
(
dumps
(
policy
,
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
)
.
encode
(
'utf-8'
)
)
_export_drafts
(
self
.
modulestore
,
self
.
courselike_key
,
export_fs
,
xml_centric_courselike_key
)
_export_drafts
(
self
.
modulestore
,
self
.
courselike_key
,
export_fs
,
xml_centric_courselike_key
)
...
@@ -315,7 +317,7 @@ class LibraryExportManager(ExportManager):
...
@@ -315,7 +317,7 @@ class LibraryExportManager(ExportManager):
to ease in duck typing during import. This may be expanded as a useful feature eventually.
to ease in duck typing during import. This may be expanded as a useful feature eventually.
"""
"""
# export the static assets
# export the static assets
export_fs
.
make
opendir
(
'policies'
)
export_fs
.
make
dir
(
'policies'
,
recreate
=
True
)
if
self
.
contentstore
:
if
self
.
contentstore
:
self
.
contentstore
.
export_all_for_course
(
self
.
contentstore
.
export_all_for_course
(
...
@@ -332,7 +334,7 @@ class LibraryExportManager(ExportManager):
...
@@ -332,7 +334,7 @@ class LibraryExportManager(ExportManager):
called library.xml.
called library.xml.
"""
"""
# Create the Library.xml file, which acts as the index of all library contents.
# Create the Library.xml file, which acts as the index of all library contents.
xml_file
=
export_fs
.
open
(
LIBRARY_ROOT
,
'w'
)
xml_file
=
export_fs
.
open
(
LIBRARY_ROOT
,
'w
b
'
)
xml_file
.
write
(
lxml
.
etree
.
tostring
(
root
,
pretty_print
=
True
,
encoding
=
'utf-8'
))
xml_file
.
write
(
lxml
.
etree
.
tostring
(
root
,
pretty_print
=
True
,
encoding
=
'utf-8'
))
xml_file
.
close
()
xml_file
.
close
()
...
@@ -387,19 +389,20 @@ def _export_field_content(xblock_item, item_dir):
...
@@ -387,19 +389,20 @@ def _export_field_content(xblock_item, item_dir):
for
field_name
in
module_data
:
for
field_name
in
module_data
:
if
field_name
not
in
DEFAULT_CONTENT_FIELDS
:
if
field_name
not
in
DEFAULT_CONTENT_FIELDS
:
# filename format: {dirname}.{field_name}.json
# filename format: {dirname}.{field_name}.json
with
item_dir
.
open
(
'{0}.{1}.{2}'
.
format
(
xblock_item
.
location
.
name
,
field_name
,
'json'
),
with
item_dir
.
open
(
u'{0}.{1}.{2}'
.
format
(
xblock_item
.
location
.
name
,
field_name
,
'json'
),
'w'
)
as
field_content_file
:
'wb'
)
as
field_content_file
:
field_content_file
.
write
(
dumps
(
module_data
.
get
(
field_name
,
{}),
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
))
field_content_file
.
write
(
dumps
(
module_data
.
get
(
field_name
,
{}),
cls
=
EdxJSONEncoder
,
sort_keys
=
True
,
indent
=
4
)
.
encode
(
'utf-8'
))
def
export_extra_content
(
export_fs
,
modulestore
,
source_course_key
,
dest_course_key
,
category_type
,
dirname
,
file_suffix
=
''
):
def
export_extra_content
(
export_fs
,
modulestore
,
source_course_key
,
dest_course_key
,
category_type
,
dirname
,
file_suffix
=
''
):
items
=
modulestore
.
get_items
(
source_course_key
,
qualifiers
=
{
'category'
:
category_type
})
items
=
modulestore
.
get_items
(
source_course_key
,
qualifiers
=
{
'category'
:
category_type
})
if
len
(
items
)
>
0
:
if
len
(
items
)
>
0
:
item_dir
=
export_fs
.
make
opendir
(
dirnam
e
)
item_dir
=
export_fs
.
make
dir
(
dirname
,
recreate
=
Tru
e
)
for
item
in
items
:
for
item
in
items
:
adapt_references
(
item
,
dest_course_key
,
export_fs
)
adapt_references
(
item
,
dest_course_key
,
export_fs
)
with
item_dir
.
open
(
item
.
location
.
name
+
file_suffix
,
'w'
)
as
item_file
:
with
item_dir
.
open
(
item
.
location
.
name
+
file_suffix
,
'w
b
'
)
as
item_file
:
item_file
.
write
(
item
.
data
.
encode
(
'utf8'
))
item_file
.
write
(
item
.
data
.
encode
(
'utf8'
))
# export content fields other then metadata and data in json format in current directory
# export content fields other then metadata and data in json format in current directory
...
...
common/lib/xmodule/xmodule/tests/test_export.py
View file @
6893bb35
...
@@ -71,14 +71,14 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -71,14 +71,14 @@ class RoundTripTestCase(unittest.TestCase):
@mock.patch
(
'xmodule.video_module.video_module.edxval_api'
,
None
)
@mock.patch
(
'xmodule.video_module.video_module.edxval_api'
,
None
)
@mock.patch
(
'xmodule.course_module.requests.get'
)
@mock.patch
(
'xmodule.course_module.requests.get'
)
@ddt.data
(
@ddt.data
(
"toy"
,
u
"toy"
,
"simple"
,
u
"simple"
,
"conditional_and_poll"
,
u
"conditional_and_poll"
,
"conditional"
,
u
"conditional"
,
"self_assessment"
,
u
"self_assessment"
,
"test_exam_registration"
,
u
"test_exam_registration"
,
"word_cloud"
,
u
"word_cloud"
,
"pure_xblock"
,
u
"pure_xblock"
,
)
)
@XBlock.register_temp_plugin
(
PureXBlock
,
'pure'
)
@XBlock.register_temp_plugin
(
PureXBlock
,
'pure'
)
def
test_export_roundtrip
(
self
,
course_dir
,
mock_get
):
def
test_export_roundtrip
(
self
,
course_dir
,
mock_get
):
...
@@ -107,12 +107,12 @@ class RoundTripTestCase(unittest.TestCase):
...
@@ -107,12 +107,12 @@ class RoundTripTestCase(unittest.TestCase):
# will still be there.
# will still be there.
print
"Starting export"
print
"Starting export"
file_system
=
OSFS
(
root_dir
)
file_system
=
OSFS
(
root_dir
)
initial_course
.
runtime
.
export_fs
=
file_system
.
make
opendir
(
course_dir
)
initial_course
.
runtime
.
export_fs
=
file_system
.
make
dir
(
course_dir
,
recreate
=
True
)
root
=
lxml
.
etree
.
Element
(
'root'
)
root
=
lxml
.
etree
.
Element
(
'root'
)
initial_course
.
add_xml_to_node
(
root
)
initial_course
.
add_xml_to_node
(
root
)
with
initial_course
.
runtime
.
export_fs
.
open
(
'course.xml'
,
'w'
)
as
course_xml
:
with
initial_course
.
runtime
.
export_fs
.
open
(
'course.xml'
,
'w
b
'
)
as
course_xml
:
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_xml
)
lxml
.
etree
.
ElementTree
(
root
)
.
write
(
course_xml
,
encoding
=
'utf-8'
)
print
"Starting second import"
print
"Starting second import"
second_import
=
XMLModuleStore
(
root_dir
,
source_dirs
=
[
course_dir
],
xblock_mixins
=
(
XModuleMixin
,))
second_import
=
XMLModuleStore
(
root_dir
,
source_dirs
=
[
course_dir
],
xblock_mixins
=
(
XModuleMixin
,))
...
...
common/lib/xmodule/xmodule/tests/test_import.py
View file @
6893bb35
...
@@ -219,7 +219,7 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -219,7 +219,7 @@ class ImportTestCase(BaseCourseTestCase):
self
.
assertEqual
(
node
.
attrib
[
'org'
],
ORG
)
self
.
assertEqual
(
node
.
attrib
[
'org'
],
ORG
)
# Does the course still have unicorns?
# Does the course still have unicorns?
with
descriptor
.
runtime
.
export_fs
.
open
(
'course/{url_name}.xml'
.
format
(
url_name
=
url_name
))
as
f
:
with
descriptor
.
runtime
.
export_fs
.
open
(
u
'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'
],
unicorn_color
)
self
.
assertEqual
(
course_xml
.
attrib
[
'unicorn'
],
unicorn_color
)
...
@@ -233,7 +233,7 @@ class ImportTestCase(BaseCourseTestCase):
...
@@ -233,7 +233,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
descriptor
.
runtime
.
export_fs
.
open
(
'chapter/ch.xml'
)
as
f
:
with
descriptor
.
runtime
.
export_fs
.
open
(
u
'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
.
assertNotIn
(
'due'
,
chapter_xml
.
attrib
)
self
.
assertNotIn
(
'due'
,
chapter_xml
.
attrib
)
...
...
common/lib/xmodule/xmodule/xml_module.py
View file @
6893bb35
...
@@ -475,8 +475,8 @@ class XmlParserMixin(object):
...
@@ -475,8 +475,8 @@ class XmlParserMixin(object):
# Write the definition to a file
# Write the definition to a file
url_path
=
name_to_pathname
(
self
.
url_name
)
url_path
=
name_to_pathname
(
self
.
url_name
)
filepath
=
self
.
_format_filepath
(
self
.
category
,
url_path
)
filepath
=
self
.
_format_filepath
(
self
.
category
,
url_path
)
self
.
runtime
.
export_fs
.
makedir
(
os
.
path
.
dirname
(
filepath
),
recursive
=
True
,
allow_
recreate
=
True
)
self
.
runtime
.
export_fs
.
makedir
s
(
os
.
path
.
dirname
(
filepath
),
recreate
=
True
)
with
self
.
runtime
.
export_fs
.
open
(
filepath
,
'w'
)
as
fileobj
:
with
self
.
runtime
.
export_fs
.
open
(
filepath
,
'w
b
'
)
as
fileobj
:
ElementTree
(
xml_object
)
.
write
(
fileobj
,
pretty_print
=
True
,
encoding
=
'utf-8'
)
ElementTree
(
xml_object
)
.
write
(
fileobj
,
pretty_print
=
True
,
encoding
=
'utf-8'
)
else
:
else
:
# Write all attributes from xml_object onto node
# Write all attributes from xml_object onto node
...
...
lms/djangoapps/courseware/courses.py
View file @
6893bb35
...
@@ -25,7 +25,7 @@ from django.core.urlresolvers import reverse
...
@@ -25,7 +25,7 @@ from django.core.urlresolvers import reverse
from
django.http
import
Http404
,
QueryDict
from
django.http
import
Http404
,
QueryDict
from
enrollment.api
import
get_course_enrollment_details
from
enrollment.api
import
get_course_enrollment_details
from
edxmako.shortcuts
import
render_to_string
from
edxmako.shortcuts
import
render_to_string
from
fs.errors
import
ResourceNotFound
Error
from
fs.errors
import
ResourceNotFound
from
lms.djangoapps.courseware.courseware_access_exception
import
CoursewareAccessException
from
lms.djangoapps.courseware.courseware_access_exception
import
CoursewareAccessException
from
lms.djangoapps.courseware.exceptions
import
CourseAccessRedirect
from
lms.djangoapps.courseware.exceptions
import
CourseAccessRedirect
from
opaque_keys.edx.keys
import
UsageKey
from
opaque_keys.edx.keys
import
UsageKey
...
@@ -207,13 +207,13 @@ def find_file(filesystem, dirs, filename):
...
@@ -207,13 +207,13 @@ def find_file(filesystem, dirs, filename):
dirs: a list of path objects
dirs: a list of path objects
filename: a string
filename: a string
Returns d / filename if found in dir d, else raises ResourceNotFound
Error
.
Returns d / filename if found in dir d, else raises ResourceNotFound.
"""
"""
for
directory
in
dirs
:
for
directory
in
dirs
:
filepath
=
path
(
directory
)
/
filename
filepath
=
path
(
directory
)
/
filename
if
filesystem
.
exists
(
filepath
):
if
filesystem
.
exists
(
filepath
):
return
filepath
return
filepath
raise
ResourceNotFound
Error
(
u"Could not find {0}"
.
format
(
filename
))
raise
ResourceNotFound
(
u"Could not find {0}"
.
format
(
filename
))
def
get_course_about_section
(
request
,
course
,
section_key
):
def
get_course_about_section
(
request
,
course
,
section_key
):
...
@@ -419,7 +419,7 @@ def get_course_syllabus_section(course, section_key):
...
@@ -419,7 +419,7 @@ def get_course_syllabus_section(course, section_key):
course_id
=
course
.
id
,
course_id
=
course
.
id
,
static_asset_path
=
course
.
static_asset_path
,
static_asset_path
=
course
.
static_asset_path
,
)
)
except
ResourceNotFound
Error
:
except
ResourceNotFound
:
log
.
exception
(
log
.
exception
(
u"Missing syllabus section
%
s in course
%
s"
,
u"Missing syllabus section
%
s in course
%
s"
,
section_key
,
course
.
location
.
to_deprecated_string
()
section_key
,
course
.
location
.
to_deprecated_string
()
...
...
requirements/edx/base.txt
View file @
6893bb35
...
@@ -4,12 +4,15 @@
...
@@ -4,12 +4,15 @@
# * @edx/ospr - to check licensing
# * @edx/ospr - to check licensing
# * @edx/devops - to check system requirements
# * @edx/devops - to check system requirements
appdirs==1.4.3
attrs==17.2.0
attrs==17.2.0
beautifulsoup4==4.1.3
beautifulsoup4==4.1.3
beautifulsoup==3.2.1
beautifulsoup==3.2.1
bleach==1.4
bleach==1.4
html5lib==0.999
html5lib==0.999
boto==2.39.0
boto==2.39.0
boto3==1.4.8
botocore==1.8.17
celery==3.1.18
celery==3.1.18
cryptography==1.9
cryptography==1.9
cssselect==0.9.1
cssselect==0.9.1
...
@@ -25,7 +28,7 @@ django-model-utils==3.0.0
...
@@ -25,7 +28,7 @@ django-model-utils==3.0.0
django-mptt>=0.8.6,<0.9
django-mptt>=0.8.6,<0.9
django-oauth-toolkit==0.12.0
django-oauth-toolkit==0.12.0
django-pipeline-forgiving==1.0.0
django-pipeline-forgiving==1.0.0
django-pyfs==1.0.7
#
django-pyfs==1.0.7
django-sekizai>=0.10
django-sekizai>=0.10
django-ses==0.8.4
django-ses==0.8.4
django-simple-history==1.9.0
django-simple-history==1.9.0
...
@@ -35,6 +38,7 @@ django-method-override==0.1.0
...
@@ -35,6 +38,7 @@ django-method-override==0.1.0
django-user-tasks==0.1.5
django-user-tasks==0.1.5
django-waffle==0.12.0
django-waffle==0.12.0
djangorestframework-jwt==1.11.0
djangorestframework-jwt==1.11.0
docutils==0.14
enum34==1.1.6
enum34==1.1.6
edx-ace==0.1.6
edx-ace==0.1.6
edx-ccx-keys==0.2.1
edx-ccx-keys==0.2.1
...
@@ -59,11 +63,15 @@ edxval==0.1.6
...
@@ -59,11 +63,15 @@ edxval==0.1.6
event-tracking==0.2.4
event-tracking==0.2.4
feedparser==5.1.3
feedparser==5.1.3
firebase-token-generator==1.3.2
firebase-token-generator==1.3.2
fs==2.0.17
fs-s3fs==0.1.5
futures==3.2.0 ; python_version == "2.7"
GitPython==0.3.2.RC1
GitPython==0.3.2.RC1
glob2==0.3
glob2==0.3
gunicorn==0.17.4
gunicorn==0.17.4
help-tokens==1.0.3
help-tokens==1.0.3
httpretty==0.8.3
httpretty==0.8.3
jmespath==0.9.3
lazy==1.1
lazy==1.1
mako==1.0.2
mako==1.0.2
Markdown>=2.6,<2.7
Markdown>=2.6,<2.7
...
@@ -95,6 +103,7 @@ pysrt==0.4.7
...
@@ -95,6 +103,7 @@ pysrt==0.4.7
PyYAML==3.12
PyYAML==3.12
requests-oauthlib==0.4.1
requests-oauthlib==0.4.1
rules==1.1.1
rules==1.1.1
s3transfer==0.1.12
scipy==0.14.0
scipy==0.14.0
Shapely==1.2.16
Shapely==1.2.16
singledispatch==3.4.0.2
singledispatch==3.4.0.2
...
...
requirements/edx/github.txt
View file @
6893bb35
...
@@ -57,10 +57,8 @@ git+https://github.com/edx/nltk.git@2.0.6#egg=nltk==2.0.6
...
@@ -57,10 +57,8 @@ git+https://github.com/edx/nltk.git@2.0.6#egg=nltk==2.0.6
-e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme
-e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme
git+https://github.com/mitodl/django-cas.git@afac57bc523f145ae826f4ed3d4fa8b2c86c5364#egg=django-cas==2.1.1
git+https://github.com/mitodl/django-cas.git@afac57bc523f145ae826f4ed3d4fa8b2c86c5364#egg=django-cas==2.1.1
-e git+https://github.com/dgrtwo/ParsePy.git@7949b9f754d1445eff8e8f20d0e967b9a6420639#egg=parse_rest
-e git+https://github.com/dgrtwo/ParsePy.git@7949b9f754d1445eff8e8f20d0e967b9a6420639#egg=parse_rest
# Master pyfs has a bug working with VPC auth. This is a fix. We should switch
# This will be replaced with an actual release requirement before this PR is merged
# back to master when and if this fix is merged back.
git+https://github.com/edx/django-pyfs.git@5296382609a8233272d13f94813cb436f35d1408#egg=django-pyfs==2.0
# fs==0.4.0
git+https://github.com/edx/pyfs.git@96e1922348bfe6d99201b9512a9ed946c87b7e0b#egg=fs==0.4.0
# The officially released version of django-debug-toolbar-mongo doesn't support DJDT 1.x. This commit does.
# The officially released version of django-debug-toolbar-mongo doesn't support DJDT 1.x. This commit does.
git+https://github.com/hmarr/django-debug-toolbar-mongo.git@b0686a76f1ce3532088c4aee6e76b9abe61cc808#egg=django-debug-toolbar-mongo==0.1.10
git+https://github.com/hmarr/django-debug-toolbar-mongo.git@b0686a76f1ce3532088c4aee6e76b9abe61cc808#egg=django-debug-toolbar-mongo==0.1.10
...
@@ -91,7 +89,7 @@ git+https://github.com/edx/django-celery.git@756cb57aad765cb2b0d37372c1855b8f5f3
...
@@ -91,7 +89,7 @@ git+https://github.com/edx/django-celery.git@756cb57aad765cb2b0d37372c1855b8f5f3
-e git+https://github.com/edx/django-splash.git@v0.2#egg=django-splash==0.2
-e git+https://github.com/edx/django-splash.git@v0.2#egg=django-splash==0.2
-e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock
-e git+https://github.com/edx/acid-block.git@e46f9cda8a03e121a00c7e347084d142d22ebfb7#egg=acid-xblock
git+https://github.com/edx/edx-ora2.git@2.1.8#egg=ora2==2.1.8
git+https://github.com/edx/edx-ora2.git@2.1.8#egg=ora2==2.1.8
git+https://github.com/edx/RecommenderXBlock.git@
0e744b393cf1f8b886fe77bc697e7d9d78d65cd6#egg=recommender-xblock==1.2
git+https://github.com/edx/RecommenderXBlock.git@
e0f777c3d2295c28a6f21652b9f1773a1910a8f3#egg=recommender-xblock==1.3
git+https://github.com/solashirai/crowdsourcehinter.git@518605f0a95190949fe77bd39158450639e2e1dc#egg=crowdsourcehinter-xblock==0.1
git+https://github.com/solashirai/crowdsourcehinter.git@518605f0a95190949fe77bd39158450639e2e1dc#egg=crowdsourcehinter-xblock==0.1
-e git+https://github.com/edx/RateXBlock.git@367e19c0f6eac8a5f002fd0f1559555f8e74bfff#egg=rate-xblock
-e git+https://github.com/edx/RateXBlock.git@367e19c0f6eac8a5f002fd0f1559555f8e74bfff#egg=rate-xblock
-e git+https://github.com/edx/DoneXBlock.git@01a14f3bd80ae47dd08cdbbe2f88f3eb88d00fba#egg=done-xblock
-e git+https://github.com/edx/DoneXBlock.git@01a14f3bd80ae47dd08cdbbe2f88f3eb88d00fba#egg=done-xblock
...
...
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