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
8267a762
Commit
8267a762
authored
Sep 24, 2015
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move *ModuleStoreBuilders into xmodule.modulestore.tests.utils
parent
972196fe
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
350 additions
and
322 deletions
+350
-322
cms/djangoapps/contentstore/tests/test_courseware_index.py
+4
-2
common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_asides.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
+3
-312
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/utils.py
+335
-0
common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py
+1
-1
No files found.
cms/djangoapps/contentstore/tests/test_courseware_index.py
View file @
8267a762
...
@@ -29,8 +29,10 @@ from xmodule.modulestore.tests.django_utils import (
...
@@ -29,8 +29,10 @@ from xmodule.modulestore.tests.django_utils import (
)
)
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
,
LibraryFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
,
LibraryFactory
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.test_cross_modulestore_import_export
import
MongoContentstoreBuilder
from
xmodule.modulestore.tests.utils
import
(
from
xmodule.modulestore.tests.utils
import
create_modulestore_instance
,
LocationMixin
,
MixedSplitTestCase
create_modulestore_instance
,
LocationMixin
,
MixedSplitTestCase
,
MongoContentstoreBuilder
)
from
xmodule.tests
import
DATA_DIR
from
xmodule.tests
import
DATA_DIR
from
xmodule.x_module
import
XModuleMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.partitions.partitions
import
UserPartition
from
xmodule.partitions.partitions
import
UserPartition
...
...
common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py
View file @
8267a762
...
@@ -16,7 +16,7 @@ from xmodule.assetstore import AssetMetadata
...
@@ -16,7 +16,7 @@ from xmodule.assetstore import AssetMetadata
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
(
from
xmodule.modulestore.tests.
utils
import
(
MODULESTORE_SETUPS
,
MODULESTORE_SETUPS
,
SHORT_NAME_MAP
,
SHORT_NAME_MAP
,
TEST_DATA_DIR
,
TEST_DATA_DIR
,
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_asides.py
View file @
8267a762
...
@@ -5,7 +5,7 @@ from xblock.core import XBlockAside
...
@@ -5,7 +5,7 @@ from xblock.core import XBlockAside
from
xblock.fields
import
Scope
,
String
from
xblock.fields
import
Scope
,
String
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
unittest
import
TestCase
from
unittest
import
TestCase
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
XmlModulestoreBuilder
from
xmodule.modulestore.tests.
utils
import
XmlModulestoreBuilder
from
mock
import
patch
from
mock
import
patch
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py
View file @
8267a762
...
@@ -14,7 +14,7 @@ from xmodule.assetstore import AssetMetadata
...
@@ -14,7 +14,7 @@ from xmodule.assetstore import AssetMetadata
from
xmodule.modulestore
import
ModuleStoreEnum
,
SortedAssetList
,
IncorrectlySortedList
from
xmodule.modulestore
import
ModuleStoreEnum
,
SortedAssetList
,
IncorrectlySortedList
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
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.
utils
import
(
MIXED_MODULESTORE_BOTH_SETUP
,
MODULESTORE_SETUPS
,
MIXED_MODULESTORE_BOTH_SETUP
,
MODULESTORE_SETUPS
,
XmlModulestoreBuilder
,
MixedModulestoreBuilder
XmlModulestoreBuilder
,
MixedModulestoreBuilder
)
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py
View file @
8267a762
...
@@ -15,7 +15,6 @@ from contextlib import contextmanager, nested
...
@@ -15,7 +15,6 @@ from contextlib import contextmanager, nested
import
itertools
import
itertools
import
os
import
os
from
path
import
Path
as
path
from
path
import
Path
as
path
import
random
from
shutil
import
rmtree
from
shutil
import
rmtree
from
tempfile
import
mkdtemp
from
tempfile
import
mkdtemp
...
@@ -24,326 +23,18 @@ from nose.plugins.attrib import attr
...
@@ -24,326 +23,18 @@ from nose.plugins.attrib import attr
from
mock
import
patch
from
mock
import
patch
from
xmodule.tests
import
CourseComparisonTest
from
xmodule.tests
import
CourseComparisonTest
from
xmodule.modulestore.mongo.base
import
ModuleStoreEnum
from
xmodule.modulestore.mongo.draft
import
DraftModuleStore
from
xmodule.modulestore.mixed
import
MixedModuleStore
from
xmodule.contentstore.mongo
import
MongoContentStore
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.split_mongo.split_draft
import
DraftVersioningModuleStore
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.utils
import
mock_tab_from_json
from
xmodule.modulestore.tests.utils
import
mock_tab_from_json
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.partitions.tests.test_partitions
import
PartitionTestCase
from
xmodule.partitions.tests.test_partitions
import
PartitionTestCase
from
xmodule.x_module
import
XModuleMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.modulestore.tests.utils
import
(
MongoContentstoreBuilder
,
MODULESTORE_SETUPS
,
SPLIT_MODULESTORE_SETUP
,
TEST_DATA_DIR
=
'common/test/data/'
CONTENTSTORE_SETUPS
,
TEST_DATA_DIR
COMMON_DOCSTORE_CONFIG
=
{
'host'
:
MONGO_HOST
,
'port'
:
MONGO_PORT_NUM
,
}
DATA_DIR
=
path
(
__file__
)
.
dirname
()
.
parent
.
parent
/
"tests"
/
"data"
/
"xml-course-root"
XBLOCK_MIXINS
=
(
InheritanceMixin
,
XModuleMixin
)
class
MemoryCache
(
object
):
"""
This fits the metadata_inheritance_cache_subsystem interface used by
the modulestore, and stores the data in a dictionary in memory.
"""
def
__init__
(
self
):
self
.
_data
=
{}
def
get
(
self
,
key
,
default
=
None
):
"""
Get a key from the cache.
Args:
key: The key to update.
default: The value to return if the key hasn't been set previously.
"""
return
self
.
_data
.
get
(
key
,
default
)
def
set
(
self
,
key
,
value
):
"""
Set a key in the cache.
Args:
key: The key to update.
value: The value change the key to.
"""
self
.
_data
[
key
]
=
value
class
MongoContentstoreBuilder
(
object
):
"""
A builder class for a MongoContentStore.
"""
@contextmanager
def
build
(
self
):
"""
A contextmanager that returns a MongoContentStore, and deletes its contents
when the context closes.
"""
contentstore
=
MongoContentStore
(
db
=
'contentstore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'content'
,
**
COMMON_DOCSTORE_CONFIG
)
contentstore
.
ensure_indexes
()
try
:
yield
contentstore
finally
:
# Delete the created database
contentstore
.
_drop_database
()
# pylint: disable=protected-access
def
__repr__
(
self
):
return
'MongoContentstoreBuilder()'
class
StoreBuilderBase
(
object
):
"""
Base class for all modulestore builders.
"""
@contextmanager
def
build
(
self
,
**
kwargs
):
"""
Build the modulstore, optionally building the contentstore as well.
"""
contentstore
=
kwargs
.
pop
(
'contentstore'
,
None
)
if
not
contentstore
:
with
self
.
build_without_contentstore
()
as
(
contentstore
,
modulestore
):
yield
contentstore
,
modulestore
else
:
with
self
.
build_with_contentstore
(
contentstore
)
as
modulestore
:
yield
modulestore
@contextmanager
def
build_without_contentstore
(
self
):
"""
Build both the contentstore and the modulestore.
"""
with
MongoContentstoreBuilder
()
.
build
()
as
contentstore
:
with
self
.
build_with_contentstore
(
contentstore
)
as
modulestore
:
yield
contentstore
,
modulestore
class
MongoModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a DraftModuleStore.
"""
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns an isolated mongo modulestore, and then deletes
all of its data at the end of the context.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
doc_store_config
=
dict
(
db
=
'modulestore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'xmodule'
,
asset_collection
=
'asset_metadata'
,
**
COMMON_DOCSTORE_CONFIG
)
# Set up a temp directory for storing filesystem content created during import
fs_root
=
mkdtemp
()
# pylint: disable=attribute-defined-outside-init
modulestore
=
DraftModuleStore
(
contentstore
,
doc_store_config
,
fs_root
,
render_template
=
repr
,
branch_setting_func
=
lambda
:
ModuleStoreEnum
.
Branch
.
draft_preferred
,
metadata_inheritance_cache_subsystem
=
MemoryCache
(),
xblock_mixins
=
XBLOCK_MIXINS
,
)
modulestore
.
ensure_indexes
()
try
:
yield
modulestore
finally
:
# Delete the created database
modulestore
.
_drop_database
()
# pylint: disable=protected-access
# Delete the created directory on the filesystem
rmtree
(
fs_root
,
ignore_errors
=
True
)
def
__repr__
(
self
):
return
'MongoModulestoreBuilder()'
class
VersioningModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a VersioningModuleStore.
"""
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns an isolated versioning modulestore, and then deletes
all of its data at the end of the context.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
# pylint: disable=unreachable
doc_store_config
=
dict
(
db
=
'modulestore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'split_module'
,
**
COMMON_DOCSTORE_CONFIG
)
# Set up a temp directory for storing filesystem content created during import
fs_root
=
mkdtemp
()
modulestore
=
DraftVersioningModuleStore
(
contentstore
,
doc_store_config
,
fs_root
,
render_template
=
repr
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
modulestore
.
ensure_indexes
()
try
:
yield
modulestore
finally
:
# Delete the created database
modulestore
.
_drop_database
()
# pylint: disable=protected-access
# Delete the created directory on the filesystem
rmtree
(
fs_root
,
ignore_errors
=
True
)
def
__repr__
(
self
):
return
'SplitModulestoreBuilder()'
class
XmlModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a XMLModuleStore.
"""
# pylint: disable=unused-argument
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
=
None
,
course_ids
=
None
):
"""
A contextmanager that returns an isolated xml modulestore
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
modulestore
=
XMLModuleStore
(
DATA_DIR
,
course_ids
=
course_ids
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
yield
modulestore
class
MixedModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a MixedModuleStore.
"""
def
__init__
(
self
,
store_builders
,
mappings
=
None
):
"""
Args:
store_builders: A list of modulestore builder objects. These will be instantiated, in order,
as the backing stores for the MixedModuleStore.
mappings: Any course mappings to pass to the MixedModuleStore on instantiation.
"""
self
.
store_builders
=
store_builders
self
.
mappings
=
mappings
or
{}
self
.
mixed_modulestore
=
None
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns a mixed modulestore built on top of modulestores
generated by other builder classes.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
names
,
generators
=
zip
(
*
self
.
store_builders
)
with
nested
(
*
(
gen
.
build_with_contentstore
(
contentstore
)
for
gen
in
generators
))
as
modulestores
:
# Make the modulestore creation function just return the already-created modulestores
store_iterator
=
iter
(
modulestores
)
create_modulestore_instance
=
lambda
*
args
,
**
kwargs
:
store_iterator
.
next
()
# Generate a fake list of stores to give the already generated stores appropriate names
stores
=
[{
'NAME'
:
name
,
'ENGINE'
:
'This space deliberately left blank'
}
for
name
in
names
]
self
.
mixed_modulestore
=
MixedModuleStore
(
contentstore
,
self
.
mappings
,
stores
,
create_modulestore_instance
=
create_modulestore_instance
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
yield
self
.
mixed_modulestore
def
__repr__
(
self
):
return
'MixedModulestoreBuilder({!r}, {!r})'
.
format
(
self
.
store_builders
,
self
.
mappings
)
def
asset_collection
(
self
):
"""
Returns the collection storing the asset metadata.
"""
all_stores
=
self
.
mixed_modulestore
.
modulestores
if
len
(
all_stores
)
>
1
:
return
None
store
=
all_stores
[
0
]
if
hasattr
(
store
,
'asset_collection'
):
# Mongo modulestore beneath mixed.
# Returns the entire collection with *all* courses' asset metadata.
return
store
.
asset_collection
else
:
# Split modulestore beneath mixed.
# Split stores all asset metadata in the structure collection.
return
store
.
db_connection
.
structures
MIXED_MODULESTORE_BOTH_SETUP
=
MixedModulestoreBuilder
([
(
'draft'
,
MongoModulestoreBuilder
()),
(
'split'
,
VersioningModulestoreBuilder
())
])
DRAFT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())])
SPLIT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())])
MIXED_MODULESTORE_SETUPS
=
(
DRAFT_MODULESTORE_SETUP
,
SPLIT_MODULESTORE_SETUP
,
)
MIXED_MS_SETUPS_SHORT
=
(
'mixed_mongo'
,
'mixed_split'
,
)
DIRECT_MODULESTORE_SETUPS
=
(
MongoModulestoreBuilder
(),
# VersioningModulestoreBuilder(), # FUTUREDO: LMS-11227
)
DIRECT_MS_SETUPS_SHORT
=
(
'mongo'
,
#'split',
)
)
MODULESTORE_SETUPS
=
DIRECT_MODULESTORE_SETUPS
+
MIXED_MODULESTORE_SETUPS
MODULESTORE_SHORTNAMES
=
DIRECT_MS_SETUPS_SHORT
+
MIXED_MS_SETUPS_SHORT
SHORT_NAME_MAP
=
dict
(
zip
(
MODULESTORE_SETUPS
,
MODULESTORE_SHORTNAMES
))
CONTENTSTORE_SETUPS
=
(
MongoContentstoreBuilder
(),)
COURSE_DATA_NAMES
=
(
COURSE_DATA_NAMES
=
(
'toy'
,
'toy'
,
'manual-testing-complete'
,
'manual-testing-complete'
,
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
View file @
8267a762
...
@@ -26,7 +26,7 @@ from tempfile import mkdtemp
...
@@ -26,7 +26,7 @@ from tempfile import mkdtemp
from
xmodule.x_module
import
XModuleMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.modulestore.edit_info
import
EditInfoMixin
from
xmodule.modulestore.edit_info
import
EditInfoMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
MongoContentstoreBuilder
from
xmodule.modulestore.tests.
utils
import
MongoContentstoreBuilder
from
xmodule.contentstore.content
import
StaticContent
from
xmodule.contentstore.content
import
StaticContent
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mongo_call_count.py
View file @
8267a762
...
@@ -11,7 +11,7 @@ import ddt
...
@@ -11,7 +11,7 @@ import ddt
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_importer
import
import_course_from_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.tests.factories
import
check_mongo_calls
from
xmodule.modulestore.tests.factories
import
check_mongo_calls
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
(
from
xmodule.modulestore.tests.
utils
import
(
MixedModulestoreBuilder
,
VersioningModulestoreBuilder
,
MixedModulestoreBuilder
,
VersioningModulestoreBuilder
,
MongoModulestoreBuilder
,
TEST_DATA_DIR
MongoModulestoreBuilder
,
TEST_DATA_DIR
)
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_publish.py
View file @
8267a762
...
@@ -19,7 +19,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
...
@@ -19,7 +19,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.xml_exporter
import
export_course_to_xml
from
xmodule.modulestore.tests.test_split_w_old_mongo
import
SplitWMongoCourseBootstrapper
from
xmodule.modulestore.tests.test_split_w_old_mongo
import
SplitWMongoCourseBootstrapper
from
xmodule.modulestore.tests.factories
import
check_mongo_calls
,
mongo_uses_error_check
,
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.factories
import
check_mongo_calls
,
mongo_uses_error_check
,
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
(
from
xmodule.modulestore.tests.
utils
import
(
MongoContentstoreBuilder
,
MODULESTORE_SETUPS
,
MongoContentstoreBuilder
,
MODULESTORE_SETUPS
,
DRAFT_MODULESTORE_SETUP
,
SPLIT_MODULESTORE_SETUP
,
MongoModulestoreBuilder
,
DRAFT_MODULESTORE_SETUP
,
SPLIT_MODULESTORE_SETUP
,
MongoModulestoreBuilder
,
)
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
View file @
8267a762
...
@@ -13,7 +13,7 @@ from xmodule.modulestore.inheritance import InheritanceMixin
...
@@ -13,7 +13,7 @@ from xmodule.modulestore.inheritance import InheritanceMixin
from
xmodule.modulestore.mongo
import
DraftMongoModuleStore
from
xmodule.modulestore.mongo
import
DraftMongoModuleStore
from
xmodule.modulestore.split_mongo.split
import
SplitMongoModuleStore
from
xmodule.modulestore.split_mongo.split
import
SplitMongoModuleStore
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
MemoryCache
from
xmodule.modulestore.tests.
utils
import
MemoryCache
@attr
(
'mongo'
)
@attr
(
'mongo'
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/utils.py
View file @
8267a762
"""
"""
Helper classes and methods for running modulestore tests without Django.
Helper classes and methods for running modulestore tests without Django.
"""
"""
import
random
from
contextlib
import
contextmanager
,
nested
from
importlib
import
import_module
from
importlib
import
import_module
from
opaque_keys.edx.keys
import
UsageKey
from
opaque_keys.edx.keys
import
UsageKey
from
path
import
Path
as
path
from
shutil
import
rmtree
from
tempfile
import
mkdtemp
from
unittest
import
TestCase
from
unittest
import
TestCase
from
xblock.fields
import
XBlockMixin
from
xblock.fields
import
XBlockMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.contentstore.mongo
import
MongoContentStore
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
from
xmodule.modulestore.edit_info
import
EditInfoMixin
from
xmodule.modulestore.edit_info
import
EditInfoMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.mixed
import
MixedModuleStore
from
xmodule.modulestore.mixed
import
MixedModuleStore
from
xmodule.modulestore.mongo.base
import
ModuleStoreEnum
from
xmodule.modulestore.mongo.draft
import
DraftModuleStore
from
xmodule.modulestore.split_mongo.split_draft
import
DraftVersioningModuleStore
from
xmodule.modulestore.tests.factories
import
ItemFactory
from
xmodule.modulestore.tests.factories
import
ItemFactory
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.tests.mongo_connection
import
MONGO_PORT_NUM
,
MONGO_HOST
from
xmodule.modulestore.xml
import
XMLModuleStore
from
xmodule.tests
import
DATA_DIR
from
xmodule.tests
import
DATA_DIR
...
@@ -174,3 +186,326 @@ class ProceduralCourseTestMixin(object):
...
@@ -174,3 +186,326 @@ class ProceduralCourseTestMixin(object):
with
self
.
store
.
bulk_operations
(
self
.
course
.
id
,
emit_signals
=
emit_signals
):
with
self
.
store
.
bulk_operations
(
self
.
course
.
id
,
emit_signals
=
emit_signals
):
descend
(
self
.
course
,
[
'chapter'
,
'sequential'
,
'vertical'
,
'problem'
])
descend
(
self
.
course
,
[
'chapter'
,
'sequential'
,
'vertical'
,
'problem'
])
class
MemoryCache
(
object
):
"""
This fits the metadata_inheritance_cache_subsystem interface used by
the modulestore, and stores the data in a dictionary in memory.
"""
def
__init__
(
self
):
self
.
_data
=
{}
def
get
(
self
,
key
,
default
=
None
):
"""
Get a key from the cache.
Args:
key: The key to update.
default: The value to return if the key hasn't been set previously.
"""
return
self
.
_data
.
get
(
key
,
default
)
def
set
(
self
,
key
,
value
):
"""
Set a key in the cache.
Args:
key: The key to update.
value: The value change the key to.
"""
self
.
_data
[
key
]
=
value
class
MongoContentstoreBuilder
(
object
):
"""
A builder class for a MongoContentStore.
"""
@contextmanager
def
build
(
self
):
"""
A contextmanager that returns a MongoContentStore, and deletes its contents
when the context closes.
"""
contentstore
=
MongoContentStore
(
db
=
'contentstore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'content'
,
**
COMMON_DOCSTORE_CONFIG
)
contentstore
.
ensure_indexes
()
try
:
yield
contentstore
finally
:
# Delete the created database
contentstore
.
_drop_database
()
# pylint: disable=protected-access
def
__repr__
(
self
):
return
'MongoContentstoreBuilder()'
class
StoreBuilderBase
(
object
):
"""
Base class for all modulestore builders.
"""
@contextmanager
def
build
(
self
,
**
kwargs
):
"""
Build the modulstore, optionally building the contentstore as well.
"""
contentstore
=
kwargs
.
pop
(
'contentstore'
,
None
)
if
not
contentstore
:
with
self
.
build_without_contentstore
()
as
(
contentstore
,
modulestore
):
yield
contentstore
,
modulestore
else
:
with
self
.
build_with_contentstore
(
contentstore
)
as
modulestore
:
yield
modulestore
@contextmanager
def
build_without_contentstore
(
self
):
"""
Build both the contentstore and the modulestore.
"""
with
MongoContentstoreBuilder
()
.
build
()
as
contentstore
:
with
self
.
build_with_contentstore
(
contentstore
)
as
modulestore
:
yield
contentstore
,
modulestore
class
MongoModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a DraftModuleStore.
"""
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns an isolated mongo modulestore, and then deletes
all of its data at the end of the context.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
doc_store_config
=
dict
(
db
=
'modulestore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'xmodule'
,
asset_collection
=
'asset_metadata'
,
**
COMMON_DOCSTORE_CONFIG
)
# Set up a temp directory for storing filesystem content created during import
fs_root
=
mkdtemp
()
# pylint: disable=attribute-defined-outside-init
modulestore
=
DraftModuleStore
(
contentstore
,
doc_store_config
,
fs_root
,
render_template
=
repr
,
branch_setting_func
=
lambda
:
ModuleStoreEnum
.
Branch
.
draft_preferred
,
metadata_inheritance_cache_subsystem
=
MemoryCache
(),
xblock_mixins
=
XBLOCK_MIXINS
,
)
modulestore
.
ensure_indexes
()
try
:
yield
modulestore
finally
:
# Delete the created database
modulestore
.
_drop_database
()
# pylint: disable=protected-access
# Delete the created directory on the filesystem
rmtree
(
fs_root
,
ignore_errors
=
True
)
def
__repr__
(
self
):
return
'MongoModulestoreBuilder()'
class
VersioningModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a VersioningModuleStore.
"""
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns an isolated versioning modulestore, and then deletes
all of its data at the end of the context.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
# pylint: disable=unreachable
doc_store_config
=
dict
(
db
=
'modulestore{}'
.
format
(
random
.
randint
(
0
,
10000
)),
collection
=
'split_module'
,
**
COMMON_DOCSTORE_CONFIG
)
# Set up a temp directory for storing filesystem content created during import
fs_root
=
mkdtemp
()
modulestore
=
DraftVersioningModuleStore
(
contentstore
,
doc_store_config
,
fs_root
,
render_template
=
repr
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
modulestore
.
ensure_indexes
()
try
:
yield
modulestore
finally
:
# Delete the created database
modulestore
.
_drop_database
()
# pylint: disable=protected-access
# Delete the created directory on the filesystem
rmtree
(
fs_root
,
ignore_errors
=
True
)
def
__repr__
(
self
):
return
'SplitModulestoreBuilder()'
class
XmlModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a XMLModuleStore.
"""
# pylint: disable=unused-argument
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
=
None
,
course_ids
=
None
):
"""
A contextmanager that returns an isolated xml modulestore
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
modulestore
=
XMLModuleStore
(
DATA_DIR
,
course_ids
=
course_ids
,
default_class
=
'xmodule.hidden_module.HiddenDescriptor'
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
yield
modulestore
class
MixedModulestoreBuilder
(
StoreBuilderBase
):
"""
A builder class for a MixedModuleStore.
"""
def
__init__
(
self
,
store_builders
,
mappings
=
None
):
"""
Args:
store_builders: A list of modulestore builder objects. These will be instantiated, in order,
as the backing stores for the MixedModuleStore.
mappings: Any course mappings to pass to the MixedModuleStore on instantiation.
"""
self
.
store_builders
=
store_builders
self
.
mappings
=
mappings
or
{}
self
.
mixed_modulestore
=
None
@contextmanager
def
build_with_contentstore
(
self
,
contentstore
):
"""
A contextmanager that returns a mixed modulestore built on top of modulestores
generated by other builder classes.
Args:
contentstore: The contentstore that this modulestore should use to store
all of its assets.
"""
names
,
generators
=
zip
(
*
self
.
store_builders
)
with
nested
(
*
(
gen
.
build_with_contentstore
(
contentstore
)
for
gen
in
generators
))
as
modulestores
:
# Make the modulestore creation function just return the already-created modulestores
store_iterator
=
iter
(
modulestores
)
next_modulestore
=
lambda
*
args
,
**
kwargs
:
store_iterator
.
next
()
# Generate a fake list of stores to give the already generated stores appropriate names
stores
=
[{
'NAME'
:
name
,
'ENGINE'
:
'This space deliberately left blank'
}
for
name
in
names
]
self
.
mixed_modulestore
=
MixedModuleStore
(
contentstore
,
self
.
mappings
,
stores
,
create_modulestore_instance
=
next_modulestore
,
xblock_mixins
=
XBLOCK_MIXINS
,
)
yield
self
.
mixed_modulestore
def
__repr__
(
self
):
return
'MixedModulestoreBuilder({!r}, {!r})'
.
format
(
self
.
store_builders
,
self
.
mappings
)
def
asset_collection
(
self
):
"""
Returns the collection storing the asset metadata.
"""
all_stores
=
self
.
mixed_modulestore
.
modulestores
if
len
(
all_stores
)
>
1
:
return
None
store
=
all_stores
[
0
]
if
hasattr
(
store
,
'asset_collection'
):
# Mongo modulestore beneath mixed.
# Returns the entire collection with *all* courses' asset metadata.
return
store
.
asset_collection
else
:
# Split modulestore beneath mixed.
# Split stores all asset metadata in the structure collection.
return
store
.
db_connection
.
structures
COMMON_DOCSTORE_CONFIG
=
{
'host'
:
MONGO_HOST
,
'port'
:
MONGO_PORT_NUM
,
}
DATA_DIR
=
path
(
__file__
)
.
dirname
()
.
parent
.
parent
/
"tests"
/
"data"
/
"xml-course-root"
TEST_DATA_DIR
=
'common/test/data/'
XBLOCK_MIXINS
=
(
InheritanceMixin
,
XModuleMixin
)
MIXED_MODULESTORE_BOTH_SETUP
=
MixedModulestoreBuilder
([
(
'draft'
,
MongoModulestoreBuilder
()),
(
'split'
,
VersioningModulestoreBuilder
())
])
DRAFT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'draft'
,
MongoModulestoreBuilder
())])
SPLIT_MODULESTORE_SETUP
=
MixedModulestoreBuilder
([(
'split'
,
VersioningModulestoreBuilder
())])
MIXED_MODULESTORE_SETUPS
=
(
DRAFT_MODULESTORE_SETUP
,
SPLIT_MODULESTORE_SETUP
,
)
MIXED_MS_SETUPS_SHORT
=
(
'mixed_mongo'
,
'mixed_split'
,
)
DIRECT_MODULESTORE_SETUPS
=
(
MongoModulestoreBuilder
(),
# VersioningModulestoreBuilder(), # FUTUREDO: LMS-11227
)
DIRECT_MS_SETUPS_SHORT
=
(
'mongo'
,
#'split',
)
MODULESTORE_SETUPS
=
DIRECT_MODULESTORE_SETUPS
+
MIXED_MODULESTORE_SETUPS
MODULESTORE_SHORTNAMES
=
DIRECT_MS_SETUPS_SHORT
+
MIXED_MS_SETUPS_SHORT
SHORT_NAME_MAP
=
dict
(
zip
(
MODULESTORE_SETUPS
,
MODULESTORE_SHORTNAMES
))
CONTENTSTORE_SETUPS
=
(
MongoContentstoreBuilder
(),)
class
PureModulestoreTestCase
(
TestCase
):
"""
A TestCase designed to make testing Modulestore implementations without using Django
easier.
"""
MODULESTORE
=
None
def
setUp
(
self
):
super
(
PureModulestoreTestCase
,
self
)
.
setUp
()
builder
=
self
.
MODULESTORE
.
build
()
self
.
assets
,
self
.
store
=
builder
.
__enter__
()
self
.
addCleanup
(
builder
.
__exit__
,
None
,
None
,
None
)
common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py
View file @
8267a762
...
@@ -22,7 +22,7 @@ from xmodule.course_metadata_utils import (
...
@@ -22,7 +22,7 @@ from xmodule.course_metadata_utils import (
may_certify_for_course
,
may_certify_for_course
,
)
)
from
xmodule.fields
import
Date
from
xmodule.fields
import
Date
from
xmodule.modulestore.tests.
test_cross_modulestore_import_export
import
(
from
xmodule.modulestore.tests.
utils
import
(
MongoModulestoreBuilder
,
MongoModulestoreBuilder
,
VersioningModulestoreBuilder
,
VersioningModulestoreBuilder
,
MixedModulestoreBuilder
MixedModulestoreBuilder
...
...
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