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
e3cef4e2
Commit
e3cef4e2
authored
Oct 31, 2013
by
Slater-Victoroff
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1545 from edx/slater/mixed_mongo_abstract
Proper abstraction of Module store base class implemented
parents
d41a9745
e2ba1122
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
139 additions
and
67 deletions
+139
-67
common/lib/xmodule/xmodule/modulestore/__init__.py
+84
-48
common/lib/xmodule/xmodule/modulestore/mixed.py
+7
-4
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+7
-4
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+12
-2
common/lib/xmodule/xmodule/modulestore/tests/test_abstraction.py
+16
-0
common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py
+4
-3
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
+2
-2
common/lib/xmodule/xmodule/modulestore/xml.py
+7
-4
No files found.
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
e3cef4e2
...
...
@@ -8,11 +8,14 @@ import re
from
collections
import
namedtuple
from
abc
import
ABCMeta
,
abstractmethod
from
.exceptions
import
InvalidLocationError
,
InsufficientSpecificationError
from
xmodule.errortracker
import
make_error_tracker
log
=
logging
.
getLogger
(
'mitx.'
+
'modulestore'
)
SPLIT_MONGO_MODULESTORE_TYPE
=
'split'
MONGO_MODULESTORE_TYPE
=
'mongo'
XML_MODULESTORE_TYPE
=
'xml'
...
...
@@ -254,17 +257,22 @@ class Location(_LocationBase):
return
self
.
_replace
(
**
kwargs
)
class
ModuleStore
(
object
):
class
ModuleStore
Read
(
object
):
"""
An abstract interface for a database backend that stores XModuleDescriptor
instances
instances
and extends read-only functionality
"""
__metaclass__
=
ABCMeta
@abstractmethod
def
has_item
(
self
,
course_id
,
location
):
"""
Returns True if location exists in this ModuleStore.
"""
raise
NotImplementedError
pass
@abstractmethod
def
get_item
(
self
,
location
,
depth
=
0
):
"""
Returns an XModuleDescriptor instance for the item at location.
...
...
@@ -282,15 +290,17 @@ class ModuleStore(object):
in the request. The depth is counted in the number of calls to
get_children() to cache. None indicates to cache all descendents
"""
raise
NotImplementedError
pass
@abstractmethod
def
get_instance
(
self
,
course_id
,
location
,
depth
=
0
):
"""
Get an instance of this location, with policy for course_id applied.
TODO (vshnayder): this may want to live outside the modulestore eventually
"""
raise
NotImplementedError
pass
@abstractmethod
def
get_item_errors
(
self
,
location
):
"""
Return a list of (msg, exception-or-None) errors that the modulestore
...
...
@@ -301,8 +311,9 @@ class ModuleStore(object):
Raises the same exceptions as get_item if the location isn't found or
isn't fully specified.
"""
raise
NotImplementedError
pass
@abstractmethod
def
get_items
(
self
,
location
,
course_id
=
None
,
depth
=
0
):
"""
Returns a list of XModuleDescriptor instances for the items
...
...
@@ -316,8 +327,58 @@ class ModuleStore(object):
in the request. The depth is counted in the number of calls to
get_children() to cache. None indicates to cache all descendents
"""
raise
NotImplementedError
pass
@abstractmethod
def
get_courses
(
self
):
'''
Returns a list containing the top level XModuleDescriptors of the courses
in this modulestore.
'''
pass
@abstractmethod
def
get_course
(
self
,
course_id
):
'''
Look for a specific course id. Returns the course descriptor, or None if not found.
'''
pass
@abstractmethod
def
get_parent_locations
(
self
,
location
,
course_id
):
'''Find all locations that are the parents of this location in this
course. Needed for path_to_location().
returns an iterable of things that can be passed to Location.
'''
pass
@abstractmethod
def
get_errored_courses
(
self
):
"""
Return a dictionary of course_dir -> [(msg, exception_str)], for each
course_dir where course loading failed.
"""
pass
@abstractmethod
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
pass
class
ModuleStoreWrite
(
ModuleStoreRead
):
"""
An abstract interface for a database backend that stores XModuleDescriptor
instances and extends both read and write functionality
"""
__metaclass__
=
ABCMeta
@abstractmethod
def
update_item
(
self
,
location
,
data
,
allow_not_found
=
False
):
"""
Set the data in the item specified by the location to
...
...
@@ -326,8 +387,9 @@ class ModuleStore(object):
location: Something that can be passed to Location
data: A nested dictionary of problem data
"""
raise
NotImplementedError
pass
@abstractmethod
def
update_children
(
self
,
location
,
children
):
"""
Set the children for the item specified by the location to
...
...
@@ -336,8 +398,9 @@ class ModuleStore(object):
location: Something that can be passed to Location
children: A list of child item identifiers
"""
raise
NotImplementedError
pass
@abstractmethod
def
update_metadata
(
self
,
location
,
metadata
):
"""
Set the metadata for the item specified by the location to
...
...
@@ -346,58 +409,24 @@ class ModuleStore(object):
location: Something that can be passed to Location
metadata: A nested dictionary of module metadata
"""
raise
NotImplementedError
pass
@abstractmethod
def
delete_item
(
self
,
location
):
"""
Delete an item from this modulestore
location: Something that can be passed to Location
"""
raise
NotImplementedError
pass
def
get_courses
(
self
):
'''
Returns a list containing the top level XModuleDescriptors of the courses
in this modulestore.
'''
course_filter
=
Location
(
"i4x"
,
category
=
"course"
)
return
self
.
get_items
(
course_filter
)
def
get_course
(
self
,
course_id
):
'''
Look for a specific course id. Returns the course descriptor, or None if not found.
'''
raise
NotImplementedError
def
get_parent_locations
(
self
,
location
,
course_id
):
'''Find all locations that are the parents of this location in this
course. Needed for path_to_location().
returns an iterable of things that can be passed to Location.
'''
raise
NotImplementedError
def
get_errored_courses
(
self
):
"""
Return a dictionary of course_dir -> [(msg, exception_str)], for each
course_dir where course loading failed.
"""
raise
NotImplementedError
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
"""
raise
NotImplementedError
class
ModuleStoreBase
(
ModuleStore
):
class
ModuleStoreReadBase
(
ModuleStoreRead
):
'''
Implement interface functionality that can be shared.
'''
# pylint: disable=W0613
def
__init__
(
self
,
doc_store_config
=
None
,
# ignore if passed up
...
...
@@ -456,3 +485,10 @@ class ModuleStoreBase(ModuleStore):
if
c
.
id
==
course_id
:
return
c
return
None
class
ModuleStoreWriteBase
(
ModuleStoreReadBase
,
ModuleStoreWrite
):
'''
Implement interface functionality that can be shared.
'''
pass
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
e3cef4e2
...
...
@@ -6,14 +6,14 @@ In this way, courses can be served up both - say - XMLModuleStore or MongoModule
IMPORTANT: This modulestore only supports READONLY applications, e.g. LMS
"""
from
.
import
ModuleStoreBase
from
.
import
ModuleStore
Write
Base
from
xmodule.modulestore.django
import
create_modulestore_instance
import
logging
log
=
logging
.
getLogger
(
__name__
)
class
MixedModuleStore
(
ModuleStoreBase
):
class
MixedModuleStore
(
ModuleStore
Write
Base
):
"""
ModuleStore that can be backed by either XML or Mongo
"""
...
...
@@ -138,8 +138,11 @@ class MixedModuleStore(ModuleStoreBase):
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
Returns a type which identifies which modulestore is servicing the given course_id.
The return can be one of:
"xml" (for XML based courses),
"mongo" for old-style MongoDB backed courses,
"split" for new-style split MongoDB backed courses.
"""
return
self
.
_get_modulestore_for_courseid
(
course_id
)
.
get_modulestore_type
(
course_id
)
...
...
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
e3cef4e2
...
...
@@ -31,7 +31,7 @@ from xblock.runtime import DbModel
from
xblock.exceptions
import
InvalidScopeError
from
xblock.fields
import
Scope
,
ScopeIds
from
xmodule.modulestore
import
ModuleStoreBase
,
Location
,
MONGO_MODULESTORE_TYPE
from
xmodule.modulestore
import
ModuleStore
Write
Base
,
Location
,
MONGO_MODULESTORE_TYPE
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.inheritance
import
own_metadata
,
InheritanceMixin
,
inherit_metadata
,
InheritanceKeyValueStore
import
re
...
...
@@ -251,7 +251,7 @@ def metadata_cache_key(location):
return
u"{0.org}/{0.course}"
.
format
(
location
)
class
MongoModuleStore
(
ModuleStoreBase
):
class
MongoModuleStore
(
ModuleStore
Write
Base
):
"""
A Mongodb backed ModuleStore
"""
...
...
@@ -850,8 +850,11 @@ class MongoModuleStore(ModuleStoreBase):
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
Returns an enumeration-like type reflecting the type of this modulestore
The return can be one of:
"xml" (for XML based courses),
"mongo" for old-style MongoDB backed courses,
"split" for new-style split MongoDB backed courses.
"""
return
MONGO_MODULESTORE_TYPE
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
e3cef4e2
...
...
@@ -13,7 +13,7 @@ from xmodule.errortracker import null_error_tracker
from
xmodule.x_module
import
XModuleDescriptor
from
xmodule.modulestore.locator
import
BlockUsageLocator
,
DefinitionLocator
,
CourseLocator
,
VersionTree
,
LocalId
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
,
VersionConflictError
,
DuplicateItemError
from
xmodule.modulestore
import
inheritance
,
ModuleStore
Base
,
Location
from
xmodule.modulestore
import
inheritance
,
ModuleStore
WriteBase
,
Location
,
SPLIT_MONGO_MODULESTORE_TYPE
from
..exceptions
import
ItemNotFoundError
from
.definition_lazy_loader
import
DefinitionLazyLoader
...
...
@@ -44,7 +44,7 @@ log = logging.getLogger(__name__)
#==============================================================================
class
SplitMongoModuleStore
(
ModuleStoreBase
):
class
SplitMongoModuleStore
(
ModuleStore
Write
Base
):
"""
A Mongodb backed ModuleStore supporting versions, inheritance,
and sharing.
...
...
@@ -1455,3 +1455,13 @@ class SplitMongoModuleStore(ModuleStoreBase):
if
'category'
in
fields
:
del
fields
[
'category'
]
return
fields
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns an enumeration-like type reflecting the type of this modulestore
The return can be one of:
"xml" (for XML based courses),
"mongo" for old-style MongoDB backed courses,
"split" for new-style split MongoDB backed courses.
"""
return
SPLIT_MONGO_MODULESTORE_TYPE
common/lib/xmodule/xmodule/modulestore/tests/test_abstraction.py
0 → 100644
View file @
e3cef4e2
"""
Simple test to ensure that modulestore base classes remain abstract
"""
from
unittest
import
TestCase
from
xmodule.modulestore
import
ModuleStoreRead
,
ModuleStoreWrite
class
AbstractionTest
(
TestCase
):
"""
Tests that the ModuleStore objects are properly abstracted
"""
def
test_cant_instantiate_abstract_class
(
self
):
self
.
assertRaises
(
TypeError
,
ModuleStoreRead
)
# Cannot be instantiated due to explicit abstraction
self
.
assertRaises
(
TypeError
,
ModuleStoreWrite
)
common/lib/xmodule/xmodule/modulestore/tests/test_modulestore.py
View file @
e3cef4e2
...
...
@@ -3,10 +3,11 @@ from nose.tools import assert_equals, assert_raises # pylint: disable=E0611
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.search
import
path_to_location
def
check_path_to_location
(
modulestore
):
'''Make sure that path_to_location works: should be passed a modulestore
with the toy and simple courses loaded.'''
"""
Make sure that path_to_location works: should be passed a modulestore
with the toy and simple courses loaded.
"""
should_work
=
(
(
"i4x://edX/toy/video/Welcome"
,
(
"edX/toy/2012_Fall"
,
"Overview"
,
"Welcome"
,
None
)),
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py
View file @
e3cef4e2
...
...
@@ -13,7 +13,7 @@ from xblock.runtime import KeyValueStore
from
xblock.exceptions
import
InvalidScopeError
from
xmodule.tests
import
DATA_DIR
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
,
MONGO_MODULESTORE_TYPE
from
xmodule.modulestore.mongo
import
MongoModuleStore
,
MongoKeyValueStore
from
xmodule.modulestore.draft
import
DraftModuleStore
from
xmodule.modulestore.xml_importer
import
import_from_xml
,
perform_xlint
...
...
@@ -122,7 +122,7 @@ class TestMongoModuleStore(object):
{
'host'
:
HOST
,
'db'
:
DB
,
'collection'
:
COLLECTION
},
FS_ROOT
,
RENDER_TEMPLATE
,
default_class
=
DEFAULT_CLASS
)
assert_equals
(
store
.
get_modulestore_type
(
'foo/bar/baz'
),
'mongo'
)
assert_equals
(
store
.
get_modulestore_type
(
'foo/bar/baz'
),
MONGO_MODULESTORE_TYPE
)
def
test_get_courses
(
self
):
'''Make sure the course objects loaded properly'''
...
...
common/lib/xmodule/xmodule/modulestore/xml.py
View file @
e3cef4e2
...
...
@@ -24,7 +24,7 @@ from xblock.core import XBlock
from
xblock.fields
import
ScopeIds
from
xblock.field_data
import
DictFieldData
from
.
import
ModuleStoreBase
,
Location
,
XML_MODULESTORE_TYPE
from
.
import
ModuleStore
Read
Base
,
Location
,
XML_MODULESTORE_TYPE
from
.exceptions
import
ItemNotFoundError
from
.inheritance
import
compute_inherited_metadata
...
...
@@ -292,7 +292,7 @@ class ParentTracker(object):
return
list
(
self
.
_parents
[
child
])
class
XMLModuleStore
(
ModuleStoreBase
):
class
XMLModuleStore
(
ModuleStore
Read
Base
):
"""
An XML backed ModuleStore
"""
...
...
@@ -651,7 +651,10 @@ class XMLModuleStore(ModuleStoreBase):
def
get_modulestore_type
(
self
,
course_id
):
"""
Returns a type which identifies which modulestore is servicing the given
course_id. The return can be either "xml" (for XML based courses) or "mongo" for MongoDB backed courses
Returns an enumeration-like type reflecting the type of this modulestore
The return can be one of:
"xml" (for XML based courses),
"mongo" for old-style MongoDB backed courses,
"split" for new-style split MongoDB backed courses.
"""
return
XML_MODULESTORE_TYPE
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