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
a2cc8d99
Commit
a2cc8d99
authored
Nov 12, 2014
by
John Eskew
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Enable cross-modulestore copying of course asset metadata.
https://openedx.atlassian.net/browse/PLAT-38
parent
51927808
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
67 additions
and
22 deletions
+67
-22
common/lib/xmodule/xmodule/assetstore/__init__.py
+2
-2
common/lib/xmodule/xmodule/modulestore/__init__.py
+2
-2
common/lib/xmodule/xmodule/modulestore/mixed.py
+15
-5
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+3
-3
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+3
-3
common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
+31
-3
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
+11
-4
No files found.
common/lib/xmodule/xmodule/assetstore/__init__.py
View file @
a2cc8d99
...
...
@@ -87,7 +87,7 @@ class AssetMetadata(object):
else
:
self
.
fields
[
attr
]
=
val
def
to_
mongo
(
self
):
def
to_
storable
(
self
):
"""
Converts metadata properties into a MongoDB-storable dict.
"""
...
...
@@ -106,7 +106,7 @@ class AssetMetadata(object):
}
@contract
(
asset_doc
=
'dict|None'
)
def
from_
mongo
(
self
,
asset_doc
):
def
from_
storable
(
self
,
asset_doc
):
"""
Fill in all metadata fields from a MongoDB document.
...
...
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
a2cc8d99
...
...
@@ -336,7 +336,7 @@ class ModuleStoreAssetInterface(object):
info
=
asset_key
.
block_type
mdata
=
AssetMetadata
(
asset_key
,
asset_key
.
path
,
**
kwargs
)
all_assets
=
course_assets
[
info
]
mdata
.
from_
mongo
(
all_assets
[
asset_idx
])
mdata
.
from_
storable
(
all_assets
[
asset_idx
])
return
mdata
@contract
(
course_key
=
'CourseKey'
,
start
=
'int | None'
,
maxresults
=
'int | None'
,
sort
=
'tuple(str,(int,>=1,<=2))|None'
,)
...
...
@@ -392,7 +392,7 @@ class ModuleStoreAssetInterface(object):
for
idx
in
xrange
(
start_idx
,
end_idx
,
step_incr
):
raw_asset
=
all_assets
[
idx
]
new_asset
=
AssetMetadata
(
course_key
.
make_asset_key
(
asset_type
,
raw_asset
[
'filename'
]))
new_asset
.
from_
mongo
(
raw_asset
)
new_asset
.
from_
storable
(
raw_asset
)
ret_assets
.
append
(
new_asset
)
return
ret_assets
...
...
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
a2cc8d99
...
...
@@ -391,11 +391,21 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
source_course_key (CourseKey): identifier of course to copy from
dest_course_key (CourseKey): identifier of course to copy to
"""
# When implementing this in https://openedx.atlassian.net/browse/PLAT-78 , consider this:
# Check the modulestores of both the source and dest course_keys. If in different modulestores,
# export all asset data from one modulestore and import it into the dest one.
store
=
self
.
_get_modulestore_for_courseid
(
source_course_key
)
return
store
.
copy_all_asset_metadata
(
source_course_key
,
dest_course_key
,
user_id
)
source_store
=
self
.
_get_modulestore_for_courseid
(
source_course_key
)
dest_store
=
self
.
_get_modulestore_for_courseid
(
dest_course_key
)
if
source_store
!=
dest_store
:
with
self
.
bulk_operations
(
dest_course_key
):
# Get all the asset metadata in the source course.
all_assets
=
source_store
.
get_all_asset_metadata
(
source_course_key
,
'asset'
)
# Store it all in the dest course.
for
asset
in
all_assets
:
new_asset_key
=
dest_course_key
.
make_asset_key
(
'asset'
,
asset
.
asset_id
.
path
)
copied_asset
=
AssetMetadata
(
new_asset_key
)
copied_asset
.
from_storable
(
asset
.
to_storable
())
dest_store
.
save_asset_metadata
(
copied_asset
,
user_id
)
else
:
# Courses in the same modulestore can be handled by the modulestore itself.
source_store
.
copy_all_asset_metadata
(
source_course_key
,
dest_course_key
,
user_id
)
@contract
(
asset_key
=
'AssetKey'
,
attr
=
str
)
def
set_asset_metadata_attr
(
self
,
asset_key
,
attr
,
value
,
user_id
):
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
a2cc8d99
...
...
@@ -1504,7 +1504,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
asset_metadata
.
update
({
'edited_by'
:
user_id
,
'edited_on'
:
datetime
.
now
(
UTC
)})
# Translate metadata to Mongo format.
metadata_to_insert
=
asset_metadata
.
to_
mongo
()
metadata_to_insert
=
asset_metadata
.
to_
storable
()
if
asset_idx
is
None
:
# Add new metadata sorted into the list.
all_assets
.
add
(
metadata_to_insert
)
...
...
@@ -1562,11 +1562,11 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
# Form an AssetMetadata.
all_assets
=
course_assets
[
asset_key
.
block_type
]
md
=
AssetMetadata
(
asset_key
,
asset_key
.
path
)
md
.
from_
mongo
(
all_assets
[
asset_idx
])
md
.
from_
storable
(
all_assets
[
asset_idx
])
md
.
update
(
attr_dict
)
# Generate a Mongo doc from the metadata and update the course asset info.
all_assets
[
asset_idx
]
=
md
.
to_
mongo
()
all_assets
[
asset_idx
]
=
md
.
to_
storable
()
self
.
asset_collection
.
update
({
'_id'
:
course_assets
[
'_id'
]},
{
"$set"
:
{
asset_key
.
block_type
:
all_assets
}})
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
a2cc8d99
...
...
@@ -2182,7 +2182,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
"""
The guts of saving a new or updated asset
"""
metadata_to_insert
=
asset_metadata
.
to_
mongo
()
metadata_to_insert
=
asset_metadata
.
to_
storable
()
def
_internal_method
(
all_assets
,
asset_idx
):
"""
...
...
@@ -2218,11 +2218,11 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
# Form an AssetMetadata.
mdata
=
AssetMetadata
(
asset_key
,
asset_key
.
path
)
mdata
.
from_
mongo
(
all_assets
[
asset_idx
])
mdata
.
from_
storable
(
all_assets
[
asset_idx
])
mdata
.
update
(
attr_dict
)
# Generate a Mongo doc from the metadata and update the course asset info.
all_assets
[
asset_idx
]
=
mdata
.
to_
mongo
()
all_assets
[
asset_idx
]
=
mdata
.
to_
storable
()
return
all_assets
self
.
_update_course_assets
(
user_id
,
asset_key
,
_internal_method
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
View file @
a2cc8d99
...
...
@@ -12,7 +12,8 @@ from xmodule.modulestore import ModuleStoreEnum
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.test_cross_modulestore_import_export
import
(
MODULESTORE_SETUPS
,
MongoContentstoreBuilder
,
XmlModulestoreBuilder
,
MixedModulestoreBuilder
,
MongoModulestoreBuilder
MIXED_MODULESTORE_BOTH_SETUP
,
MODULESTORE_SETUPS
,
MongoContentstoreBuilder
,
XmlModulestoreBuilder
,
MixedModulestoreBuilder
,
MongoModulestoreBuilder
)
...
...
@@ -414,9 +415,9 @@ class TestMongoAssetMetadataStorage(unittest.TestCase):
store
.
get_all_asset_metadata
(
course_key
,
'asset'
)
@ddt.data
(
*
MODULESTORE_SETUPS
)
def
test_copy_all_assets
(
self
,
storebuilder
):
def
test_copy_all_assets
_same_modulestore
(
self
,
storebuilder
):
"""
Create a course with assets
and such, copy it all to another cours
e, and check on it.
Create a course with assets
, copy them all to another course in the same modulestor
e, and check on it.
"""
with
MongoContentstoreBuilder
()
.
build
()
as
contentstore
:
with
storebuilder
.
build
(
contentstore
)
as
store
:
...
...
@@ -433,3 +434,30 @@ class TestMongoAssetMetadataStorage(unittest.TestCase):
self
.
assertEquals
(
len
(
all_assets
),
2
)
self
.
assertEquals
(
all_assets
[
0
]
.
asset_id
.
path
,
'pic1.jpg'
)
self
.
assertEquals
(
all_assets
[
1
]
.
asset_id
.
path
,
'shout.ogg'
)
@ddt.data
(
(
'mongo'
,
'split'
),
(
'split'
,
'mongo'
),
)
@ddt.unpack
def
test_copy_all_assets_cross_modulestore
(
self
,
from_store
,
to_store
):
"""
Create a course with assets, copy them all to another course in a different modulestore, and check on it.
"""
mixed_builder
=
MIXED_MODULESTORE_BOTH_SETUP
with
MongoContentstoreBuilder
()
.
build
()
as
contentstore
:
with
mixed_builder
.
build
(
contentstore
)
as
mixed_store
:
with
mixed_store
.
default_store
(
from_store
):
course1
=
CourseFactory
.
create
(
modulestore
=
mixed_store
)
with
mixed_store
.
default_store
(
to_store
):
course2
=
CourseFactory
.
create
(
modulestore
=
mixed_store
)
self
.
setup_assets
(
course1
.
id
,
None
,
mixed_store
)
self
.
assertEquals
(
len
(
mixed_store
.
get_all_asset_metadata
(
course1
.
id
,
'asset'
)),
2
)
self
.
assertEquals
(
len
(
mixed_store
.
get_all_asset_metadata
(
course2
.
id
,
'asset'
)),
0
)
mixed_store
.
copy_all_asset_metadata
(
course1
.
id
,
course2
.
id
,
ModuleStoreEnum
.
UserID
.
test
*
102
)
all_assets
=
mixed_store
.
get_all_asset_metadata
(
course2
.
id
,
'asset'
,
sort
=
(
'displayname'
,
ModuleStoreEnum
.
SortOrder
.
ascending
)
)
self
.
assertEquals
(
len
(
all_assets
),
2
)
self
.
assertEquals
(
all_assets
[
0
]
.
asset_id
.
path
,
'pic1.jpg'
)
self
.
assertEquals
(
all_assets
[
1
]
.
asset_id
.
path
,
'shout.ogg'
)
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
View file @
a2cc8d99
...
...
@@ -265,13 +265,20 @@ class MongoContentstoreBuilder(object):
def
__repr__
(
self
):
return
'MongoContentstoreBuilder()'
MODULESTORE_SETUPS
=
(
MongoModulestoreBuilder
(),
# VersioningModulestoreBuilder(), # FIXME LMS-11227
MIXED_MODULESTORE_BOTH_SETUP
=
MixedModulestoreBuilder
([
(
'draft'
,
MongoModulestoreBuilder
()),
(
'split'
,
VersioningModulestoreBuilder
())
])
MIXED_MODULESTORE_SETUPS
=
(
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())]),
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())]),
)
DIRECT_MODULESTORE_SETUPS
=
(
MongoModulestoreBuilder
(),
# VersioningModulestoreBuilder(), # FUTUREDO: LMS-11227
)
MODULESTORE_SETUPS
=
DIRECT_MODULESTORE_SETUPS
+
MIXED_MODULESTORE_SETUPS
CONTENTSTORE_SETUPS
=
(
MongoContentstoreBuilder
(),)
COURSE_DATA_NAMES
=
(
'toy'
,
...
...
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