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
adb7fbcb
Commit
adb7fbcb
authored
Mar 11, 2014
by
Don Mitchell
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2849 from edx/dhm/split_course_id
Make course_id a required arg to split.create_course
parents
50b82a0b
d7547912
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
87 additions
and
70 deletions
+87
-70
cms/djangoapps/contentstore/management/commands/tests/test_migrate_to_split.py
+3
-1
cms/djangoapps/contentstore/tests/test_crud.py
+22
-9
common/lib/xmodule/xmodule/modulestore/django.py
+1
-1
common/lib/xmodule/xmodule/modulestore/exceptions.py
+13
-0
common/lib/xmodule/xmodule/modulestore/mixed.py
+4
-8
common/lib/xmodule/xmodule/modulestore/split_migrator.py
+2
-2
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+11
-31
common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
+6
-2
common/lib/xmodule/xmodule/modulestore/tests/persistent_factories.py
+5
-4
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
+1
-1
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+19
-11
No files found.
cms/djangoapps/contentstore/management/commands/tests/test_migrate_to_split.py
View file @
adb7fbcb
...
@@ -10,7 +10,7 @@ from contentstore.management.commands.migrate_to_split import Command
...
@@ -10,7 +10,7 @@ from contentstore.management.commands.migrate_to_split import Command
from
contentstore.tests.modulestore_config
import
TEST_MODULESTORE
from
contentstore.tests.modulestore_config
import
TEST_MODULESTORE
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.django
import
modulestore
,
loc_mapper
from
xmodule.modulestore.django
import
modulestore
,
loc_mapper
,
clear_existing_modulestores
from
xmodule.modulestore.locator
import
CourseLocator
from
xmodule.modulestore.locator
import
CourseLocator
# pylint: disable=E1101
# pylint: disable=E1101
...
@@ -56,6 +56,8 @@ class TestMigrateToSplit(ModuleStoreTestCase):
...
@@ -56,6 +56,8 @@ class TestMigrateToSplit(ModuleStoreTestCase):
password
=
'foo'
password
=
'foo'
self
.
user
=
User
.
objects
.
create_user
(
uname
,
email
,
password
)
self
.
user
=
User
.
objects
.
create_user
(
uname
,
email
,
password
)
self
.
course
=
CourseFactory
()
self
.
course
=
CourseFactory
()
self
.
addCleanup
(
ModuleStoreTestCase
.
drop_mongo_collections
,
'split'
)
self
.
addCleanup
(
clear_existing_modulestores
)
def
test_user_email
(
self
):
def
test_user_email
(
self
):
call_command
(
call_command
(
...
...
cms/djangoapps/contentstore/tests/test_crud.py
View file @
adb7fbcb
...
@@ -8,10 +8,11 @@ from xmodule.modulestore.django import modulestore, loc_mapper, clear_existing_m
...
@@ -8,10 +8,11 @@ from xmodule.modulestore.django import modulestore, loc_mapper, clear_existing_m
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.modulestore.locator
import
CourseLocator
,
BlockUsageLocator
,
LocalId
from
xmodule.modulestore.locator
import
CourseLocator
,
BlockUsageLocator
,
LocalId
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
DuplicateCourseError
from
xmodule.html_module
import
HtmlDescriptor
from
xmodule.html_module
import
HtmlDescriptor
from
xmodule.modulestore
import
inheritance
from
xmodule.modulestore
import
inheritance
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
class
TemplateTests
(
unittest
.
TestCase
):
class
TemplateTests
(
unittest
.
TestCase
):
...
@@ -20,7 +21,9 @@ class TemplateTests(unittest.TestCase):
...
@@ -20,7 +21,9 @@ class TemplateTests(unittest.TestCase):
"""
"""
def
setUp
(
self
):
def
setUp
(
self
):
clear_existing_modulestores
()
clear_existing_modulestores
()
# redundant w/ cleanup but someone was getting errors
self
.
addCleanup
(
ModuleStoreTestCase
.
drop_mongo_collections
,
'split'
)
self
.
addCleanup
(
clear_existing_modulestores
)
def
test_get_templates
(
self
):
def
test_get_templates
(
self
):
found
=
templates
.
all_templates
()
found
=
templates
.
all_templates
()
...
@@ -53,8 +56,10 @@ class TemplateTests(unittest.TestCase):
...
@@ -53,8 +56,10 @@ class TemplateTests(unittest.TestCase):
self
.
assertIsNotNone
(
HtmlDescriptor
.
get_template
(
'announcement.yaml'
))
self
.
assertIsNotNone
(
HtmlDescriptor
.
get_template
(
'announcement.yaml'
))
def
test_factories
(
self
):
def
test_factories
(
self
):
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
prettyid
=
'tempcourse'
,
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
course_id
=
'testx.tempcourse'
,
org
=
'testx'
,
prettyid
=
'tempcourse'
,
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
self
.
assertIsInstance
(
test_course
,
CourseDescriptor
)
self
.
assertIsInstance
(
test_course
,
CourseDescriptor
)
self
.
assertEqual
(
test_course
.
display_name
,
'fun test course'
)
self
.
assertEqual
(
test_course
.
display_name
,
'fun test course'
)
index_info
=
modulestore
(
'split'
)
.
get_course_index_info
(
test_course
.
location
)
index_info
=
modulestore
(
'split'
)
.
get_course_index_info
(
test_course
.
location
)
...
@@ -68,12 +73,20 @@ class TemplateTests(unittest.TestCase):
...
@@ -68,12 +73,20 @@ class TemplateTests(unittest.TestCase):
test_course
=
modulestore
(
'split'
)
.
get_course
(
test_chapter
.
location
)
test_course
=
modulestore
(
'split'
)
.
get_course
(
test_chapter
.
location
)
self
.
assertIn
(
test_chapter
.
location
.
block_id
,
test_course
.
children
)
self
.
assertIn
(
test_chapter
.
location
.
block_id
,
test_course
.
children
)
with
self
.
assertRaises
(
DuplicateCourseError
):
persistent_factories
.
PersistentCourseFactory
.
create
(
course_id
=
'testx.tempcourse'
,
org
=
'testx'
,
prettyid
=
'tempcourse'
,
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
def
test_temporary_xblocks
(
self
):
def
test_temporary_xblocks
(
self
):
"""
"""
Test using load_from_json to create non persisted xblocks
Test using load_from_json to create non persisted xblocks
"""
"""
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
prettyid
=
'tempcourse'
,
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
course_id
=
'testx.tempcourse'
,
org
=
'testx'
,
prettyid
=
'tempcourse'
,
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
test_chapter
=
self
.
load_from_json
({
'category'
:
'chapter'
,
test_chapter
=
self
.
load_from_json
({
'category'
:
'chapter'
,
'fields'
:
{
'display_name'
:
'chapter n'
}},
'fields'
:
{
'display_name'
:
'chapter n'
}},
...
@@ -98,7 +111,7 @@ class TemplateTests(unittest.TestCase):
...
@@ -98,7 +111,7 @@ class TemplateTests(unittest.TestCase):
try saving temporary xblocks
try saving temporary xblocks
"""
"""
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
prettyid
=
'tempcourse'
,
course_id
=
'testx.tempcourse'
,
org
=
'testx'
,
prettyid
=
'tempcourse'
,
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
display_name
=
'fun test course'
,
user_id
=
'testbot'
)
test_chapter
=
self
.
load_from_json
({
'category'
:
'chapter'
,
test_chapter
=
self
.
load_from_json
({
'category'
:
'chapter'
,
'fields'
:
{
'display_name'
:
'chapter n'
}},
'fields'
:
{
'display_name'
:
'chapter n'
}},
...
@@ -135,7 +148,7 @@ class TemplateTests(unittest.TestCase):
...
@@ -135,7 +148,7 @@ class TemplateTests(unittest.TestCase):
def
test_delete_course
(
self
):
def
test_delete_course
(
self
):
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
course_id
=
'edu.harvard.history.doomed'
,
org
=
'testx'
,
prettyid
=
'edu.harvard.history.doomed'
,
prettyid
=
'edu.harvard.history.doomed'
,
display_name
=
'doomed test course'
,
display_name
=
'doomed test course'
,
user_id
=
'testbot'
)
user_id
=
'testbot'
)
...
@@ -159,7 +172,7 @@ class TemplateTests(unittest.TestCase):
...
@@ -159,7 +172,7 @@ class TemplateTests(unittest.TestCase):
Test get_block_generations
Test get_block_generations
"""
"""
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
course_id
=
'edu.harvard.history.hist101'
,
org
=
'testx'
,
prettyid
=
'edu.harvard.history.hist101'
,
prettyid
=
'edu.harvard.history.hist101'
,
display_name
=
'history test course'
,
display_name
=
'history test course'
,
user_id
=
'testbot'
)
user_id
=
'testbot'
)
...
...
common/lib/xmodule/xmodule/modulestore/django.py
View file @
adb7fbcb
...
@@ -184,7 +184,7 @@ def editable_modulestore(name='default'):
...
@@ -184,7 +184,7 @@ def editable_modulestore(name='default'):
# At this point, we either have the ability to create
# At this point, we either have the ability to create
# items in the store, or we do not.
# items in the store, or we do not.
if
hasattr
(
store
,
'create_
xmodul
e'
):
if
hasattr
(
store
,
'create_
cours
e'
):
return
store
return
store
else
:
else
:
...
...
common/lib/xmodule/xmodule/modulestore/exceptions.py
View file @
adb7fbcb
...
@@ -46,3 +46,16 @@ class VersionConflictError(Exception):
...
@@ -46,3 +46,16 @@ class VersionConflictError(Exception):
super
(
VersionConflictError
,
self
)
.
__init__
()
super
(
VersionConflictError
,
self
)
.
__init__
()
self
.
requestedLocation
=
requestedLocation
self
.
requestedLocation
=
requestedLocation
self
.
currentHeadVersionGuid
=
currentHeadVersionGuid
self
.
currentHeadVersionGuid
=
currentHeadVersionGuid
class
DuplicateCourseError
(
Exception
):
"""
An attempt to create a course whose id duplicates an existing course's
"""
def
__init__
(
self
,
course_id
,
existing_entry
):
"""
existing_entry will have the who, when, and other properties of the existing entry
"""
super
(
DuplicateCourseError
,
self
)
.
__init__
()
self
.
course_id
=
course_id
self
.
existing_entry
=
existing_entry
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
adb7fbcb
...
@@ -282,7 +282,6 @@ class MixedModuleStore(ModuleStoreWriteBase):
...
@@ -282,7 +282,6 @@ class MixedModuleStore(ModuleStoreWriteBase):
:param fields: a dict of xblock field name - value pairs for the course module.
:param fields: a dict of xblock field name - value pairs for the course module.
:param metadata: the old way of setting fields by knowing which ones are scope.settings v scope.content
:param metadata: the old way of setting fields by knowing which ones are scope.settings v scope.content
:param definition_data: the complement to metadata which is also a subset of fields
:param definition_data: the complement to metadata which is also a subset of fields
:param id_root: the split-mongo course_id starting value (see split.create_course)
:param pretty_id: a field split.create_course uses and may quit using
:param pretty_id: a field split.create_course uses and may quit using
:returns: course xblock
:returns: course xblock
"""
"""
...
@@ -290,22 +289,19 @@ class MixedModuleStore(ModuleStoreWriteBase):
...
@@ -290,22 +289,19 @@ class MixedModuleStore(ModuleStoreWriteBase):
if
not
hasattr
(
store
,
'create_course'
):
if
not
hasattr
(
store
,
'create_course'
):
raise
NotImplementedError
(
u"Cannot create a course on store
%
s"
%
store_name
)
raise
NotImplementedError
(
u"Cannot create a course on store
%
s"
%
store_name
)
if
store
.
get_modulestore_type
(
course_id
)
==
SPLIT_MONGO_MODULESTORE_TYPE
:
if
store
.
get_modulestore_type
(
course_id
)
==
SPLIT_MONGO_MODULESTORE_TYPE
:
id_root
=
kwargs
.
get
(
'id_root'
)
try
:
try
:
course_dict
=
Location
.
parse_course_id
(
course_id
)
course_dict
=
Location
.
parse_course_id
(
course_id
)
org
=
course_dict
[
'org'
]
org
=
course_dict
[
'org'
]
if
id_root
is
None
:
course_id
=
"{org}.{course}.{name}"
.
format
(
**
course_dict
)
id_root
=
"{org}.{course}.{name}"
.
format
(
**
course_dict
)
except
ValueError
:
except
ValueError
:
org
=
None
org
=
None
if
id_root
is
None
:
id_root
=
course_id
org
=
kwargs
.
pop
(
'org'
,
org
)
org
=
kwargs
.
pop
(
'org'
,
org
)
pretty_id
=
kwargs
.
pop
(
'pretty_id'
,
id_root
)
pretty_id
=
kwargs
.
pop
(
'pretty_id'
,
course_id
)
fields
=
kwargs
.
pop
(
'fields'
,
{})
fields
=
kwargs
.
pop
(
'fields'
,
{})
fields
.
update
(
kwargs
.
pop
(
'metadata'
,
{}))
fields
.
update
(
kwargs
.
pop
(
'metadata'
,
{}))
fields
.
update
(
kwargs
.
pop
(
'definition_data'
,
{}))
fields
.
update
(
kwargs
.
pop
(
'definition_data'
,
{}))
course
=
store
.
create_course
(
org
,
pretty_id
,
user_id
,
id_root
=
id_root
,
fields
=
fields
,
**
kwargs
)
course
=
store
.
create_course
(
course_id
,
org
,
pretty_id
,
user_id
,
fields
=
fields
,
**
kwargs
)
else
:
# assume mongo
else
:
# assume mongo
course
=
store
.
create_course
(
course_id
,
**
kwargs
)
course
=
store
.
create_course
(
course_id
,
**
kwargs
)
...
...
common/lib/xmodule/xmodule/modulestore/split_migrator.py
View file @
adb7fbcb
...
@@ -47,8 +47,8 @@ class SplitMigrator(object):
...
@@ -47,8 +47,8 @@ class SplitMigrator(object):
original_course
=
self
.
direct_modulestore
.
get_item
(
course_location
)
original_course
=
self
.
direct_modulestore
.
get_item
(
course_location
)
new_course_root_locator
=
self
.
loc_mapper
.
translate_location
(
old_course_id
,
course_location
)
new_course_root_locator
=
self
.
loc_mapper
.
translate_location
(
old_course_id
,
course_location
)
new_course
=
self
.
split_modulestore
.
create_course
(
new_course
=
self
.
split_modulestore
.
create_course
(
course_location
.
org
,
original_course
.
display_name
,
new_package_id
,
course_location
.
org
,
original_course
.
display_name
,
user
.
id
,
id_root
=
new_package_id
,
user
.
id
,
fields
=
self
.
_get_json_fields_translate_children
(
original_course
,
old_course_id
,
True
),
fields
=
self
.
_get_json_fields_translate_children
(
original_course
,
old_course_id
,
True
),
root_block_id
=
new_course_root_locator
.
block_id
,
root_block_id
=
new_course_root_locator
.
block_id
,
master_branch
=
new_course_root_locator
.
branch
master_branch
=
new_course_root_locator
.
branch
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
adb7fbcb
...
@@ -59,7 +59,8 @@ from xmodule.modulestore.locator import (
...
@@ -59,7 +59,8 @@ from xmodule.modulestore.locator import (
BlockUsageLocator
,
DefinitionLocator
,
CourseLocator
,
VersionTree
,
BlockUsageLocator
,
DefinitionLocator
,
CourseLocator
,
VersionTree
,
LocalId
,
Locator
LocalId
,
Locator
)
)
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
,
VersionConflictError
,
DuplicateItemError
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
,
VersionConflictError
,
DuplicateItemError
,
\
DuplicateCourseError
from
xmodule.modulestore
import
inheritance
,
ModuleStoreWriteBase
,
Location
,
SPLIT_MONGO_MODULESTORE_TYPE
from
xmodule.modulestore
import
inheritance
,
ModuleStoreWriteBase
,
Location
,
SPLIT_MONGO_MODULESTORE_TYPE
from
..exceptions
import
ItemNotFoundError
from
..exceptions
import
ItemNotFoundError
...
@@ -675,26 +676,6 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -675,26 +676,6 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
serial
+=
1
serial
+=
1
return
category
+
str
(
serial
)
return
category
+
str
(
serial
)
def
_generate_package_id
(
self
,
id_root
):
"""
Generate a somewhat readable course id unique w/in this db using the id_root
:param course_blocks: the current list of blocks.
:param category:
"""
existing_uses
=
self
.
db_connection
.
find_matching_course_indexes
({
"_id"
:
{
"$regex"
:
id_root
}})
if
existing_uses
.
count
()
>
0
:
max_found
=
0
matcher
=
re
.
compile
(
id_root
+
r'(\d+)'
)
for
entry
in
existing_uses
:
serial
=
re
.
search
(
matcher
,
entry
[
'_id'
])
if
serial
is
not
None
and
serial
.
groups
>
0
:
value
=
int
(
serial
.
group
(
1
))
if
value
>
max_found
:
max_found
=
value
return
id_root
+
str
(
max_found
+
1
)
else
:
return
id_root
# DHM: Should I rewrite this to take a new xblock instance rather than to construct it? That is, require the
# DHM: Should I rewrite this to take a new xblock instance rather than to construct it? That is, require the
# caller to use XModuleDescriptor.load_from_json thus reducing similar code and making the object creation and
# caller to use XModuleDescriptor.load_from_json thus reducing similar code and making the object creation and
# validation behavior a responsibility of the model layer rather than the persistence layer.
# validation behavior a responsibility of the model layer rather than the persistence layer.
...
@@ -830,7 +811,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -830,7 +811,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
return
self
.
get_item
(
item_loc
)
return
self
.
get_item
(
item_loc
)
def
create_course
(
def
create_course
(
self
,
org
,
prettyid
,
user_id
,
id_root
=
None
,
fields
=
None
,
self
,
course_id
,
org
,
prettyid
,
user_id
,
fields
=
None
,
master_branch
=
'draft'
,
versions_dict
=
None
,
root_category
=
'course'
,
master_branch
=
'draft'
,
versions_dict
=
None
,
root_category
=
'course'
,
root_block_id
=
'course'
root_block_id
=
'course'
):
):
...
@@ -838,8 +819,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -838,8 +819,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
Create a new entry in the active courses index which points to an existing or new structure. Returns
Create a new entry in the active courses index which points to an existing or new structure. Returns
the course root of the resulting entry (the location has the course id)
the course root of the resulting entry (the location has the course id)
id_root: allows the caller to specify the package_id. It's a root in that, if it's already taken,
course_id: If it's already taken, this method will raise DuplicateCourseError
this method will append things to the root to make it unique. (defaults to org)
fields: if scope.settings fields provided, will set the fields of the root course object in the
fields: if scope.settings fields provided, will set the fields of the root course object in the
new course. If both
new course. If both
...
@@ -865,6 +845,11 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -865,6 +845,11 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
provide any fields overrides, see above). if not provided, will create a mostly empty course
provide any fields overrides, see above). if not provided, will create a mostly empty course
structure with just a category course root xblock.
structure with just a category course root xblock.
"""
"""
# check course_id's uniqueness
index
=
self
.
db_connection
.
get_course_index
(
course_id
)
if
index
is
not
None
:
raise
DuplicateCourseError
(
course_id
,
index
)
partitioned_fields
=
self
.
partition_fields_by_scope
(
root_category
,
fields
)
partitioned_fields
=
self
.
partition_fields_by_scope
(
root_category
,
fields
)
block_fields
=
partitioned_fields
.
setdefault
(
Scope
.
settings
,
{})
block_fields
=
partitioned_fields
.
setdefault
(
Scope
.
settings
,
{})
if
Scope
.
children
in
partitioned_fields
:
if
Scope
.
children
in
partitioned_fields
:
...
@@ -929,20 +914,15 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -929,20 +914,15 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
self
.
db_connection
.
insert_structure
(
draft_structure
)
self
.
db_connection
.
insert_structure
(
draft_structure
)
versions_dict
[
master_branch
]
=
new_id
versions_dict
[
master_branch
]
=
new_id
# create the index entry
if
id_root
is
None
:
id_root
=
org
new_id
=
self
.
_generate_package_id
(
id_root
)
index_entry
=
{
index_entry
=
{
'_id'
:
new
_id
,
'_id'
:
course
_id
,
'org'
:
org
,
'org'
:
org
,
'prettyid'
:
prettyid
,
'prettyid'
:
prettyid
,
'edited_by'
:
user_id
,
'edited_by'
:
user_id
,
'edited_on'
:
datetime
.
datetime
.
now
(
UTC
),
'edited_on'
:
datetime
.
datetime
.
now
(
UTC
),
'versions'
:
versions_dict
}
'versions'
:
versions_dict
}
self
.
db_connection
.
insert_course_index
(
index_entry
)
self
.
db_connection
.
insert_course_index
(
index_entry
)
return
self
.
get_course
(
CourseLocator
(
package_id
=
new
_id
,
branch
=
master_branch
))
return
self
.
get_course
(
CourseLocator
(
package_id
=
course
_id
,
branch
=
master_branch
))
def
update_item
(
self
,
descriptor
,
user_id
,
allow_not_found
=
False
,
force
=
False
):
def
update_item
(
self
,
descriptor
,
user_id
,
allow_not_found
=
False
,
force
=
False
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/tests/django_utils.py
View file @
adb7fbcb
...
@@ -209,20 +209,24 @@ class ModuleStoreTestCase(TestCase):
...
@@ -209,20 +209,24 @@ class ModuleStoreTestCase(TestCase):
return
updated_course
return
updated_course
@staticmethod
@staticmethod
def
drop_mongo_collections
():
def
drop_mongo_collections
(
store_name
=
'default'
):
"""
"""
If using a Mongo-backed modulestore & contentstore, drop the collections.
If using a Mongo-backed modulestore & contentstore, drop the collections.
"""
"""
# This will return the mongo-backed modulestore
# This will return the mongo-backed modulestore
# even if we're using a mixed modulestore
# even if we're using a mixed modulestore
store
=
editable_modulestore
()
store
=
editable_modulestore
(
store_name
)
if
hasattr
(
store
,
'collection'
):
if
hasattr
(
store
,
'collection'
):
connection
=
store
.
collection
.
database
.
connection
connection
=
store
.
collection
.
database
.
connection
store
.
collection
.
drop
()
store
.
collection
.
drop
()
connection
.
close
()
connection
.
close
()
elif
hasattr
(
store
,
'close_all_connections'
):
elif
hasattr
(
store
,
'close_all_connections'
):
store
.
close_all_connections
()
store
.
close_all_connections
()
elif
hasattr
(
store
,
'db'
):
connection
=
store
.
db
.
connection
connection
.
drop_database
(
store
.
db
.
name
)
connection
.
close
()
if
contentstore
()
.
fs_files
:
if
contentstore
()
.
fs_files
:
db
=
contentstore
()
.
fs_files
.
database
db
=
contentstore
()
.
fs_files
.
database
...
...
common/lib/xmodule/xmodule/modulestore/tests/persistent_factories.py
View file @
adb7fbcb
...
@@ -33,15 +33,16 @@ class PersistentCourseFactory(SplitFactory):
...
@@ -33,15 +33,16 @@ class PersistentCourseFactory(SplitFactory):
# pylint: disable=W0613
# pylint: disable=W0613
@classmethod
@classmethod
def
_create
(
cls
,
target_class
,
org
=
'testX'
,
prettyid
=
'999'
,
user_id
=
'test_user'
,
def
_create
(
cls
,
target_class
,
course_id
=
'testX.999'
,
org
=
'testX'
,
prettyid
=
'999'
,
user_id
=
'test_user'
,
master_branch
=
'draft'
,
id_root
=
None
,
**
kwargs
):
master_branch
=
'draft'
,
**
kwargs
):
modulestore
=
kwargs
.
pop
(
'modulestore'
)
modulestore
=
kwargs
.
pop
(
'modulestore'
)
root_block_id
=
kwargs
.
pop
(
'root_block_id'
,
'course'
)
root_block_id
=
kwargs
.
pop
(
'root_block_id'
,
'course'
)
# Write the data to the mongo datastore
# Write the data to the mongo datastore
new_course
=
modulestore
.
create_course
(
new_course
=
modulestore
.
create_course
(
org
,
prettyid
,
user_id
,
fields
=
kwargs
,
id_root
=
id_root
or
prettyid
,
course_id
,
org
,
prettyid
,
user_id
,
fields
=
kwargs
,
master_branch
=
master_branch
,
root_block_id
=
root_block_id
)
master_branch
=
master_branch
,
root_block_id
=
root_block_id
)
return
new_course
return
new_course
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
View file @
adb7fbcb
...
@@ -114,7 +114,7 @@ class TestOrphan(unittest.TestCase):
...
@@ -114,7 +114,7 @@ class TestOrphan(unittest.TestCase):
fields
.
update
(
data
)
fields
.
update
(
data
)
# split requires the course to be created separately from creating items
# split requires the course to be created separately from creating items
self
.
split_mongo
.
create_course
(
self
.
split_mongo
.
create_course
(
'test_org'
,
'my course'
,
self
.
userid
,
self
.
split_package_
id
,
fields
=
fields
,
root_block_id
=
'runid'
self
.
split_package_id
,
'test_org'
,
'my course'
,
self
.
user
id
,
fields
=
fields
,
root_block_id
=
'runid'
)
)
self
.
course_location
=
Location
(
'i4x'
,
'test_org'
,
'test_course'
,
'course'
,
'runid'
)
self
.
course_location
=
Location
(
'i4x'
,
'test_org'
,
'test_course'
,
'course'
,
'runid'
)
self
.
old_mongo
.
create_and_save_xmodule
(
self
.
course_location
,
data
,
metadata
)
self
.
old_mongo
.
create_and_save_xmodule
(
self
.
course_location
,
data
,
metadata
)
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
View file @
adb7fbcb
...
@@ -12,7 +12,7 @@ from importlib import import_module
...
@@ -12,7 +12,7 @@ from importlib import import_module
from
xblock.fields
import
Scope
from
xblock.fields
import
Scope
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
,
ItemNotFoundError
,
VersionConflictError
,
\
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
,
ItemNotFoundError
,
VersionConflictError
,
\
DuplicateItemError
DuplicateItemError
,
DuplicateCourseError
from
xmodule.modulestore.locator
import
CourseLocator
,
BlockUsageLocator
,
VersionTree
,
DefinitionLocator
from
xmodule.modulestore.locator
import
CourseLocator
,
BlockUsageLocator
,
VersionTree
,
DefinitionLocator
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.modulestore.inheritance
import
InheritanceMixin
from
xmodule.x_module
import
XModuleMixin
from
xmodule.x_module
import
XModuleMixin
...
@@ -652,7 +652,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -652,7 +652,7 @@ class TestItemCrud(SplitModuleTest):
"""
"""
# start transaction w/ simple creation
# start transaction w/ simple creation
user
=
random
.
getrandbits
(
32
)
user
=
random
.
getrandbits
(
32
)
new_course
=
modulestore
()
.
create_course
(
'test_org'
,
'test_transaction'
,
user
)
new_course
=
modulestore
()
.
create_course
(
'test_org
.test_transaction'
,
'test_org
'
,
'test_transaction'
,
user
)
new_course_locator
=
new_course
.
location
.
as_course_locator
()
new_course_locator
=
new_course
.
location
.
as_course_locator
()
index_history_info
=
modulestore
()
.
get_course_history_info
(
new_course
.
location
)
index_history_info
=
modulestore
()
.
get_course_history_info
(
new_course
.
location
)
course_block_prev_version
=
new_course
.
previous_version
course_block_prev_version
=
new_course
.
previous_version
...
@@ -901,7 +901,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -901,7 +901,7 @@ class TestItemCrud(SplitModuleTest):
check_subtree
(
nodes
[
0
])
check_subtree
(
nodes
[
0
])
def
create_course_for_deletion
(
self
):
def
create_course_for_deletion
(
self
):
course
=
modulestore
()
.
create_course
(
'nihilx'
,
'deletion'
,
'deleting_user'
)
course
=
modulestore
()
.
create_course
(
'nihilx
.deletion'
,
'nihilx
'
,
'deletion'
,
'deleting_user'
)
root
=
BlockUsageLocator
(
root
=
BlockUsageLocator
(
package_id
=
course
.
location
.
package_id
,
package_id
=
course
.
location
.
package_id
,
block_id
=
course
.
location
.
block_id
,
block_id
=
course
.
location
.
block_id
,
...
@@ -929,7 +929,7 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -929,7 +929,7 @@ class TestCourseCreation(SplitModuleTest):
"""
"""
# Oddly getting differences of 200nsec
# Oddly getting differences of 200nsec
pre_time
=
datetime
.
datetime
.
now
(
UTC
)
-
datetime
.
timedelta
(
milliseconds
=
1
)
pre_time
=
datetime
.
datetime
.
now
(
UTC
)
-
datetime
.
timedelta
(
milliseconds
=
1
)
new_course
=
modulestore
()
.
create_course
(
'test_org'
,
'test_course'
,
'create_user'
)
new_course
=
modulestore
()
.
create_course
(
'test_org
.test_course'
,
'test_org
'
,
'test_course'
,
'create_user'
)
new_locator
=
new_course
.
location
new_locator
=
new_course
.
location
# check index entry
# check index entry
index_info
=
modulestore
()
.
get_course_index_info
(
new_locator
)
index_info
=
modulestore
()
.
get_course_index_info
(
new_locator
)
...
@@ -963,14 +963,14 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -963,14 +963,14 @@ class TestCourseCreation(SplitModuleTest):
original_locator
=
CourseLocator
(
package_id
=
"wonderful"
,
branch
=
'draft'
)
original_locator
=
CourseLocator
(
package_id
=
"wonderful"
,
branch
=
'draft'
)
original_index
=
modulestore
()
.
get_course_index_info
(
original_locator
)
original_index
=
modulestore
()
.
get_course_index_info
(
original_locator
)
new_draft
=
modulestore
()
.
create_course
(
new_draft
=
modulestore
()
.
create_course
(
'
leech'
,
'best_course'
,
'leech_master'
,
id_root
=
'best
'
,
'
best'
,
'leech'
,
'best_course'
,
'leech_master
'
,
versions_dict
=
original_index
[
'versions'
])
versions_dict
=
original_index
[
'versions'
])
new_draft_locator
=
new_draft
.
location
new_draft_locator
=
new_draft
.
location
self
.
assertRegexpMatches
(
new_draft_locator
.
package_id
,
r'best.*
'
)
self
.
assertRegexpMatches
(
new_draft_locator
.
package_id
,
'best
'
)
# the edited_by and other meta fields on the new course will be the original author not this one
# the edited_by and other meta fields on the new course will be the original author not this one
self
.
assertEqual
(
new_draft
.
edited_by
,
'test@edx.org'
)
self
.
assertEqual
(
new_draft
.
edited_by
,
'test@edx.org'
)
self
.
assertLess
(
new_draft
.
edited_on
,
pre_time
)
self
.
assertLess
(
new_draft
.
edited_on
,
pre_time
)
self
.
assertEqual
(
new_draft
.
location
.
version_guid
,
original_index
[
'versions'
][
'draft'
])
self
.
assertEqual
(
new_draft
_locator
.
version_guid
,
original_index
[
'versions'
][
'draft'
])
# however the edited_by and other meta fields on course_index will be this one
# however the edited_by and other meta fields on course_index will be this one
new_index
=
modulestore
()
.
get_course_index_info
(
new_draft_locator
)
new_index
=
modulestore
()
.
get_course_index_info
(
new_draft_locator
)
self
.
assertGreaterEqual
(
new_index
[
"edited_on"
],
pre_time
)
self
.
assertGreaterEqual
(
new_index
[
"edited_on"
],
pre_time
)
...
@@ -1028,16 +1028,16 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -1028,16 +1028,16 @@ class TestCourseCreation(SplitModuleTest):
fields
[
'grading_policy'
][
'GRADE_CUTOFFS'
]
=
{
'A'
:
.
9
,
'B'
:
.
8
,
'C'
:
.
65
}
fields
[
'grading_policy'
][
'GRADE_CUTOFFS'
]
=
{
'A'
:
.
9
,
'B'
:
.
8
,
'C'
:
.
65
}
fields
[
'display_name'
]
=
'Derivative'
fields
[
'display_name'
]
=
'Derivative'
new_draft
=
modulestore
()
.
create_course
(
new_draft
=
modulestore
()
.
create_course
(
'
leech'
,
'derivative'
,
'leech_master'
,
id_root
=
'coun
ter'
,
'
counter'
,
'leech'
,
'derivative'
,
'leech_mas
ter'
,
versions_dict
=
{
'draft'
:
original_index
[
'versions'
][
'draft'
]},
versions_dict
=
{
'draft'
:
original_index
[
'versions'
][
'draft'
]},
fields
=
fields
fields
=
fields
)
)
new_draft_locator
=
new_draft
.
location
new_draft_locator
=
new_draft
.
location
self
.
assertRegexpMatches
(
new_draft_locator
.
package_id
,
r'counter.*
'
)
self
.
assertRegexpMatches
(
new_draft_locator
.
package_id
,
'counter
'
)
# the edited_by and other meta fields on the new course will be the original author not this one
# the edited_by and other meta fields on the new course will be the original author not this one
self
.
assertEqual
(
new_draft
.
edited_by
,
'leech_master'
)
self
.
assertEqual
(
new_draft
.
edited_by
,
'leech_master'
)
self
.
assertGreaterEqual
(
new_draft
.
edited_on
,
pre_time
)
self
.
assertGreaterEqual
(
new_draft
.
edited_on
,
pre_time
)
self
.
assertNotEqual
(
new_draft
.
location
.
version_guid
,
original_index
[
'versions'
][
'draft'
])
self
.
assertNotEqual
(
new_draft
_locator
.
version_guid
,
original_index
[
'versions'
][
'draft'
])
# however the edited_by and other meta fields on course_index will be this one
# however the edited_by and other meta fields on course_index will be this one
new_index
=
modulestore
()
.
get_course_index_info
(
new_draft_locator
)
new_index
=
modulestore
()
.
get_course_index_info
(
new_draft_locator
)
self
.
assertGreaterEqual
(
new_index
[
"edited_on"
],
pre_time
)
self
.
assertGreaterEqual
(
new_index
[
"edited_on"
],
pre_time
)
...
@@ -1086,7 +1086,7 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -1086,7 +1086,7 @@ class TestCourseCreation(SplitModuleTest):
"""
"""
user
=
random
.
getrandbits
(
32
)
user
=
random
.
getrandbits
(
32
)
new_course
=
modulestore
()
.
create_course
(
new_course
=
modulestore
()
.
create_course
(
'test_org'
,
'test_transaction'
,
user
,
'test_org
.test_transaction'
,
'test_org
'
,
'test_transaction'
,
user
,
root_block_id
=
'top'
,
root_category
=
'chapter'
root_block_id
=
'top'
,
root_category
=
'chapter'
)
)
self
.
assertEqual
(
new_course
.
location
.
block_id
,
'top'
)
self
.
assertEqual
(
new_course
.
location
.
block_id
,
'top'
)
...
@@ -1100,6 +1100,14 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -1100,6 +1100,14 @@ class TestCourseCreation(SplitModuleTest):
self
.
assertIn
(
'top'
,
db_structure
[
'blocks'
])
self
.
assertIn
(
'top'
,
db_structure
[
'blocks'
])
self
.
assertEqual
(
db_structure
[
'blocks'
][
'top'
][
'category'
],
'chapter'
)
self
.
assertEqual
(
db_structure
[
'blocks'
][
'top'
][
'category'
],
'chapter'
)
def
test_create_id_dupe
(
self
):
"""
Test create_course rejects duplicate id
"""
user
=
random
.
getrandbits
(
32
)
courses
=
modulestore
()
.
get_courses
()
with
self
.
assertRaises
(
DuplicateCourseError
):
modulestore
()
.
create_course
(
courses
[
0
]
.
location
.
package_id
,
'org'
,
'pretty'
,
user
)
class
TestInheritance
(
SplitModuleTest
):
class
TestInheritance
(
SplitModuleTest
):
...
...
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