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
2ddf631e
Commit
2ddf631e
authored
Nov 12, 2014
by
John Eskew
Committed by
Zia Fazal
Apr 07, 2015
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
c33d3d22
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 @
2ddf631e
...
@@ -87,7 +87,7 @@ class AssetMetadata(object):
...
@@ -87,7 +87,7 @@ class AssetMetadata(object):
else
:
else
:
self
.
fields
[
attr
]
=
val
self
.
fields
[
attr
]
=
val
def
to_
mongo
(
self
):
def
to_
storable
(
self
):
"""
"""
Converts metadata properties into a MongoDB-storable dict.
Converts metadata properties into a MongoDB-storable dict.
"""
"""
...
@@ -106,7 +106,7 @@ class AssetMetadata(object):
...
@@ -106,7 +106,7 @@ class AssetMetadata(object):
}
}
@contract
(
asset_doc
=
'dict|None'
)
@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.
Fill in all metadata fields from a MongoDB document.
...
...
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
2ddf631e
...
@@ -336,7 +336,7 @@ class ModuleStoreAssetInterface(object):
...
@@ -336,7 +336,7 @@ class ModuleStoreAssetInterface(object):
info
=
asset_key
.
block_type
info
=
asset_key
.
block_type
mdata
=
AssetMetadata
(
asset_key
,
asset_key
.
path
,
**
kwargs
)
mdata
=
AssetMetadata
(
asset_key
,
asset_key
.
path
,
**
kwargs
)
all_assets
=
course_assets
[
info
]
all_assets
=
course_assets
[
info
]
mdata
.
from_
mongo
(
all_assets
[
asset_idx
])
mdata
.
from_
storable
(
all_assets
[
asset_idx
])
return
mdata
return
mdata
@contract
(
course_key
=
'CourseKey'
,
start
=
'int | None'
,
maxresults
=
'int | None'
,
sort
=
'tuple(str,(int,>=1,<=2))|None'
,)
@contract
(
course_key
=
'CourseKey'
,
start
=
'int | None'
,
maxresults
=
'int | None'
,
sort
=
'tuple(str,(int,>=1,<=2))|None'
,)
...
@@ -392,7 +392,7 @@ class ModuleStoreAssetInterface(object):
...
@@ -392,7 +392,7 @@ class ModuleStoreAssetInterface(object):
for
idx
in
xrange
(
start_idx
,
end_idx
,
step_incr
):
for
idx
in
xrange
(
start_idx
,
end_idx
,
step_incr
):
raw_asset
=
all_assets
[
idx
]
raw_asset
=
all_assets
[
idx
]
new_asset
=
AssetMetadata
(
course_key
.
make_asset_key
(
asset_type
,
raw_asset
[
'filename'
]))
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
)
ret_assets
.
append
(
new_asset
)
return
ret_assets
return
ret_assets
...
...
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
2ddf631e
...
@@ -391,11 +391,21 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
...
@@ -391,11 +391,21 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
source_course_key (CourseKey): identifier of course to copy from
source_course_key (CourseKey): identifier of course to copy from
dest_course_key (CourseKey): identifier of course to copy to
dest_course_key (CourseKey): identifier of course to copy to
"""
"""
# When implementing this in https://openedx.atlassian.net/browse/PLAT-78 , consider this:
source_store
=
self
.
_get_modulestore_for_courseid
(
source_course_key
)
# Check the modulestores of both the source and dest course_keys. If in different modulestores,
dest_store
=
self
.
_get_modulestore_for_courseid
(
dest_course_key
)
# export all asset data from one modulestore and import it into the dest one.
if
source_store
!=
dest_store
:
store
=
self
.
_get_modulestore_for_courseid
(
source_course_key
)
with
self
.
bulk_operations
(
dest_course_key
):
return
store
.
copy_all_asset_metadata
(
source_course_key
,
dest_course_key
,
user_id
)
# 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
)
@contract
(
asset_key
=
'AssetKey'
,
attr
=
str
)
def
set_asset_metadata_attr
(
self
,
asset_key
,
attr
,
value
,
user_id
):
def
set_asset_metadata_attr
(
self
,
asset_key
,
attr
,
value
,
user_id
):
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
2ddf631e
...
@@ -1513,7 +1513,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -1513,7 +1513,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
asset_metadata
.
update
({
'edited_by'
:
user_id
,
'edited_on'
:
datetime
.
now
(
UTC
)})
asset_metadata
.
update
({
'edited_by'
:
user_id
,
'edited_on'
:
datetime
.
now
(
UTC
)})
# Translate metadata to Mongo format.
# Translate metadata to Mongo format.
metadata_to_insert
=
asset_metadata
.
to_
mongo
()
metadata_to_insert
=
asset_metadata
.
to_
storable
()
if
asset_idx
is
None
:
if
asset_idx
is
None
:
# Add new metadata sorted into the list.
# Add new metadata sorted into the list.
all_assets
.
add
(
metadata_to_insert
)
all_assets
.
add
(
metadata_to_insert
)
...
@@ -1571,11 +1571,11 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -1571,11 +1571,11 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
# Form an AssetMetadata.
# Form an AssetMetadata.
all_assets
=
course_assets
[
asset_key
.
block_type
]
all_assets
=
course_assets
[
asset_key
.
block_type
]
md
=
AssetMetadata
(
asset_key
,
asset_key
.
path
)
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
)
md
.
update
(
attr_dict
)
# Generate a Mongo doc from the metadata and update the course asset info.
# 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
}})
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 @
2ddf631e
...
@@ -2182,7 +2182,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -2182,7 +2182,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
"""
"""
The guts of saving a new or updated asset
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
):
def
_internal_method
(
all_assets
,
asset_idx
):
"""
"""
...
@@ -2218,11 +2218,11 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -2218,11 +2218,11 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
# Form an AssetMetadata.
# Form an AssetMetadata.
mdata
=
AssetMetadata
(
asset_key
,
asset_key
.
path
)
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
)
mdata
.
update
(
attr_dict
)
# Generate a Mongo doc from the metadata and update the course asset info.
# 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
return
all_assets
self
.
_update_course_assets
(
user_id
,
asset_key
,
_internal_method
)
self
.
_update_course_assets
(
user_id
,
asset_key
,
_internal_method
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
View file @
2ddf631e
...
@@ -12,7 +12,8 @@ from xmodule.modulestore import ModuleStoreEnum
...
@@ -12,7 +12,8 @@ from xmodule.modulestore import ModuleStoreEnum
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.test_cross_modulestore_import_export
import
(
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):
...
@@ -414,9 +415,9 @@ class TestMongoAssetMetadataStorage(unittest.TestCase):
store
.
get_all_asset_metadata
(
course_key
,
'asset'
)
store
.
get_all_asset_metadata
(
course_key
,
'asset'
)
@ddt.data
(
*
MODULESTORE_SETUPS
)
@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
MongoContentstoreBuilder
()
.
build
()
as
contentstore
:
with
storebuilder
.
build
(
contentstore
)
as
store
:
with
storebuilder
.
build
(
contentstore
)
as
store
:
...
@@ -433,3 +434,30 @@ class TestMongoAssetMetadataStorage(unittest.TestCase):
...
@@ -433,3 +434,30 @@ class TestMongoAssetMetadataStorage(unittest.TestCase):
self
.
assertEquals
(
len
(
all_assets
),
2
)
self
.
assertEquals
(
len
(
all_assets
),
2
)
self
.
assertEquals
(
all_assets
[
0
]
.
asset_id
.
path
,
'pic1.jpg'
)
self
.
assertEquals
(
all_assets
[
0
]
.
asset_id
.
path
,
'pic1.jpg'
)
self
.
assertEquals
(
all_assets
[
1
]
.
asset_id
.
path
,
'shout.ogg'
)
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 @
2ddf631e
...
@@ -265,13 +265,20 @@ class MongoContentstoreBuilder(object):
...
@@ -265,13 +265,20 @@ class MongoContentstoreBuilder(object):
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'MongoContentstoreBuilder()'
return
'MongoContentstoreBuilder()'
MIXED_MODULESTORE_BOTH_SETUP
=
MixedModulestoreBuilder
([
MODULESTORE_SETUPS
=
(
(
'draft'
,
MongoModulestoreBuilder
()),
MongoModulestoreBuilder
(),
(
'split'
,
VersioningModulestoreBuilder
())
# VersioningModulestoreBuilder(), # FIXME LMS-11227
])
MIXED_MODULESTORE_SETUPS
=
(
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())]),
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())]),
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())]),
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())]),
)
)
DIRECT_MODULESTORE_SETUPS
=
(
MongoModulestoreBuilder
(),
# VersioningModulestoreBuilder(), # FUTUREDO: LMS-11227
)
MODULESTORE_SETUPS
=
DIRECT_MODULESTORE_SETUPS
+
MIXED_MODULESTORE_SETUPS
CONTENTSTORE_SETUPS
=
(
MongoContentstoreBuilder
(),)
CONTENTSTORE_SETUPS
=
(
MongoContentstoreBuilder
(),)
COURSE_DATA_NAMES
=
(
COURSE_DATA_NAMES
=
(
'toy'
,
'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