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
6c4aae73
Commit
6c4aae73
authored
Dec 20, 2013
by
Don Mitchell
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1980 from edx/dhm/locator_block_id
Rename BlockUsageLocator's block_id field from usage_id
parents
1295e763
a46e112a
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
310 additions
and
296 deletions
+310
-296
cms/djangoapps/contentstore/tests/test_crud.py
+14
-5
cms/djangoapps/contentstore/views/assets.py
+1
-1
cms/djangoapps/contentstore/views/checklist.py
+1
-1
cms/djangoapps/contentstore/views/component.py
+2
-2
cms/djangoapps/contentstore/views/course.py
+5
-5
cms/djangoapps/contentstore/views/import_export.py
+3
-3
cms/djangoapps/contentstore/views/item.py
+2
-2
cms/djangoapps/contentstore/views/tabs.py
+1
-1
cms/djangoapps/contentstore/views/user.py
+1
-1
common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py
+23
-21
common/lib/xmodule/xmodule/modulestore/locator.py
+25
-26
common/lib/xmodule/xmodule/modulestore/split_migrator.py
+11
-11
common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py
+14
-14
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+89
-113
common/lib/xmodule/xmodule/modulestore/tests/test_location_mapper.py
+29
-11
common/lib/xmodule/xmodule/modulestore/tests/test_locators.py
+5
-5
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
+6
-6
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+77
-67
common/lib/xmodule/xmodule/x_module.py
+1
-1
No files found.
cms/djangoapps/contentstore/tests/test_crud.py
View file @
6c4aae73
...
@@ -64,7 +64,7 @@ class TemplateTests(unittest.TestCase):
...
@@ -64,7 +64,7 @@ class TemplateTests(unittest.TestCase):
self
.
assertIsInstance
(
test_chapter
,
SequenceDescriptor
)
self
.
assertIsInstance
(
test_chapter
,
SequenceDescriptor
)
# refetch parent which should now point to child
# refetch parent which should now point to child
test_course
=
modulestore
(
'split'
)
.
get_course
(
test_chapter
.
location
)
test_course
=
modulestore
(
'split'
)
.
get_course
(
test_chapter
.
location
)
self
.
assertIn
(
test_chapter
.
location
.
usage
_id
,
test_course
.
children
)
self
.
assertIn
(
test_chapter
.
location
.
block
_id
,
test_course
.
children
)
def
test_temporary_xblocks
(
self
):
def
test_temporary_xblocks
(
self
):
"""
"""
...
@@ -95,15 +95,20 @@ class TemplateTests(unittest.TestCase):
...
@@ -95,15 +95,20 @@ class TemplateTests(unittest.TestCase):
"""
"""
try saving temporary xblocks
try saving temporary xblocks
"""
"""
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
org
=
'testx'
,
prettyid
=
'tempcourse'
,
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
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'
}},
test_course
.
system
,
parent_xblock
=
test_course
)
test_course
.
system
,
parent_xblock
=
test_course
)
test_def_content
=
'<problem>boo</problem>'
test_def_content
=
'<problem>boo</problem>'
# create child
# create child
_
=
self
.
load_from_json
({
'category'
:
'problem'
,
self
.
load_from_json
({
'fields'
:
{
'data'
:
test_def_content
}},
'category'
:
'problem'
,
'fields'
:
{
'data'
:
test_def_content
,
'display_name'
:
'problem'
}},
test_course
.
system
,
parent_xblock
=
test_chapter
)
test_course
.
system
,
parent_xblock
=
test_chapter
)
# better to pass in persisted parent over the subdag so
# better to pass in persisted parent over the subdag so
# subdag gets the parent pointer (otherwise 2 ops, persist dag, update parent children,
# subdag gets the parent pointer (otherwise 2 ops, persist dag, update parent children,
...
@@ -117,6 +122,10 @@ class TemplateTests(unittest.TestCase):
...
@@ -117,6 +122,10 @@ class TemplateTests(unittest.TestCase):
persisted_problem
=
persisted_chapter
.
get_children
()[
0
]
persisted_problem
=
persisted_chapter
.
get_children
()[
0
]
self
.
assertEqual
(
persisted_problem
.
category
,
'problem'
)
self
.
assertEqual
(
persisted_problem
.
category
,
'problem'
)
self
.
assertEqual
(
persisted_problem
.
data
,
test_def_content
)
self
.
assertEqual
(
persisted_problem
.
data
,
test_def_content
)
# update it
persisted_problem
.
display_name
=
'altered problem'
persisted_problem
=
modulestore
(
'split'
)
.
persist_xblock_dag
(
persisted_problem
,
'testbot'
)
self
.
assertEqual
(
persisted_problem
.
display_name
,
'altered problem'
)
def
test_delete_course
(
self
):
def
test_delete_course
(
self
):
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
test_course
=
persistent_factories
.
PersistentCourseFactory
.
create
(
...
@@ -166,7 +175,7 @@ class TemplateTests(unittest.TestCase):
...
@@ -166,7 +175,7 @@ class TemplateTests(unittest.TestCase):
second_problem
=
persistent_factories
.
ItemFactory
.
create
(
second_problem
=
persistent_factories
.
ItemFactory
.
create
(
display_name
=
'problem 2'
,
display_name
=
'problem 2'
,
parent_location
=
BlockUsageLocator
(
updated_loc
,
usage_id
=
sub
.
location
.
usage
_id
),
parent_location
=
BlockUsageLocator
(
updated_loc
,
block_id
=
sub
.
location
.
block
_id
),
user_id
=
'testbot'
,
category
=
'problem'
,
user_id
=
'testbot'
,
category
=
'problem'
,
data
=
"<problem></problem>"
data
=
"<problem></problem>"
)
)
...
...
cms/djangoapps/contentstore/views/assets.py
View file @
6c4aae73
...
@@ -51,7 +51,7 @@ def assets_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -51,7 +51,7 @@ def assets_handler(request, tag=None, course_id=None, branch=None, version_guid=
DELETE
DELETE
json: delete an asset
json: delete an asset
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
...
cms/djangoapps/contentstore/views/checklist.py
View file @
6c4aae73
...
@@ -36,7 +36,7 @@ def checklists_handler(request, tag=None, course_id=None, branch=None, version_g
...
@@ -36,7 +36,7 @@ def checklists_handler(request, tag=None, course_id=None, branch=None, version_g
POST or PUT
POST or PUT
json: updates the checked state for items within a particular checklist. checklist_index is required.
json: updates the checked state for items within a particular checklist. checklist_index is required.
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
...
cms/djangoapps/contentstore/views/component.py
View file @
6c4aae73
...
@@ -62,7 +62,7 @@ def subsection_handler(request, tag=None, course_id=None, branch=None, version_g
...
@@ -62,7 +62,7 @@ def subsection_handler(request, tag=None, course_id=None, branch=None, version_g
json: not currently supported
json: not currently supported
"""
"""
if
'text/html'
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'text/html'
):
if
'text/html'
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'text/html'
):
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
try
:
try
:
old_location
,
course
,
item
,
lms_link
=
_get_item_in_course
(
request
,
locator
)
old_location
,
course
,
item
,
lms_link
=
_get_item_in_course
(
request
,
locator
)
except
ItemNotFoundError
:
except
ItemNotFoundError
:
...
@@ -151,7 +151,7 @@ def unit_handler(request, tag=None, course_id=None, branch=None, version_guid=No
...
@@ -151,7 +151,7 @@ def unit_handler(request, tag=None, course_id=None, branch=None, version_guid=No
json: not currently supported
json: not currently supported
"""
"""
if
'text/html'
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'text/html'
):
if
'text/html'
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'text/html'
):
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
try
:
try
:
old_location
,
course
,
item
,
lms_link
=
_get_item_in_course
(
request
,
locator
)
old_location
,
course
,
item
,
lms_link
=
_get_item_in_course
(
request
,
locator
)
except
ItemNotFoundError
:
except
ItemNotFoundError
:
...
...
cms/djangoapps/contentstore/views/course.py
View file @
6c4aae73
...
@@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _
...
@@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _
from
django.contrib.auth.decorators
import
login_required
from
django.contrib.auth.decorators
import
login_required
from
django_future.csrf
import
ensure_csrf_cookie
from
django_future.csrf
import
ensure_csrf_cookie
from
django.conf
import
settings
from
django.conf
import
settings
from
django.views.decorators.http
import
require_http_methods
,
require_POST
from
django.views.decorators.http
import
require_http_methods
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.http
import
HttpResponseBadRequest
,
HttpResponseNotFound
from
django.http
import
HttpResponseBadRequest
,
HttpResponseNotFound
...
@@ -60,12 +60,12 @@ __all__ = ['course_info_handler', 'course_handler', 'course_info_update_handler'
...
@@ -60,12 +60,12 @@ __all__ = ['course_info_handler', 'course_handler', 'course_info_update_handler'
'textbooks_list_handler'
,
'textbooks_detail_handler'
]
'textbooks_list_handler'
,
'textbooks_detail_handler'
]
def
_get_locator_and_course
(
course_id
,
branch
,
version_guid
,
usage
_id
,
user
,
depth
=
0
):
def
_get_locator_and_course
(
course_id
,
branch
,
version_guid
,
block
_id
,
user
,
depth
=
0
):
"""
"""
Internal method used to calculate and return the locator and course module
Internal method used to calculate and return the locator and course module
for the view functions in this file.
for the view functions in this file.
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage_id
=
usage
_id
)
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block_id
=
block
_id
)
if
not
has_access
(
user
,
locator
):
if
not
has_access
(
user
,
locator
):
raise
PermissionDenied
()
raise
PermissionDenied
()
course_location
=
loc_mapper
()
.
translate_locator_to_location
(
locator
)
course_location
=
loc_mapper
()
.
translate_locator_to_location
(
locator
)
...
@@ -104,7 +104,7 @@ def course_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -104,7 +104,7 @@ def course_handler(request, tag=None, course_id=None, branch=None, version_guid=
return
create_new_course
(
request
)
return
create_new_course
(
request
)
elif
not
has_access
(
elif
not
has_access
(
request
.
user
,
request
.
user
,
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
):
):
raise
PermissionDenied
()
raise
PermissionDenied
()
elif
request
.
method
==
'PUT'
:
elif
request
.
method
==
'PUT'
:
...
@@ -366,7 +366,7 @@ def course_info_update_handler(request, tag=None, course_id=None, branch=None, v
...
@@ -366,7 +366,7 @@ def course_info_update_handler(request, tag=None, course_id=None, branch=None, v
"""
"""
if
'application/json'
not
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'application/json'
):
if
'application/json'
not
in
request
.
META
.
get
(
'HTTP_ACCEPT'
,
'application/json'
):
return
HttpResponseBadRequest
(
"Only supports json requests"
)
return
HttpResponseBadRequest
(
"Only supports json requests"
)
updates_locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
updates_locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
updates_location
=
loc_mapper
()
.
translate_locator_to_location
(
updates_locator
)
updates_location
=
loc_mapper
()
.
translate_locator_to_location
(
updates_locator
)
if
provided_id
==
''
:
if
provided_id
==
''
:
provided_id
=
None
provided_id
=
None
...
...
cms/djangoapps/contentstore/views/import_export.py
View file @
6c4aae73
...
@@ -60,7 +60,7 @@ def import_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -60,7 +60,7 @@ def import_handler(request, tag=None, course_id=None, branch=None, version_guid=
POST or PUT
POST or PUT
json: import a course via the .tar.gz file specified in request.FILES
json: import a course via the .tar.gz file specified in request.FILES
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
@@ -271,7 +271,7 @@ def import_status_handler(request, tag=None, course_id=None, branch=None, versio
...
@@ -271,7 +271,7 @@ def import_status_handler(request, tag=None, course_id=None, branch=None, versio
3 : Importing to mongo
3 : Importing to mongo
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
@@ -302,7 +302,7 @@ def export_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -302,7 +302,7 @@ def export_handler(request, tag=None, course_id=None, branch=None, version_guid=
If the tar.gz file has been requested but the export operation fails, an HTML page will be returned
If the tar.gz file has been requested but the export operation fails, an HTML page will be returned
which describes the error.
which describes the error.
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
...
cms/djangoapps/contentstore/views/item.py
View file @
6c4aae73
...
@@ -79,7 +79,7 @@ def xblock_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -79,7 +79,7 @@ def xblock_handler(request, tag=None, course_id=None, branch=None, version_guid=
The locator (and old-style id) for the created xblock (minus children) is returned.
The locator (and old-style id) for the created xblock (minus children) is returned.
"""
"""
if
course_id
is
not
None
:
if
course_id
is
not
None
:
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
locator
):
if
not
has_access
(
request
.
user
,
locator
):
raise
PermissionDenied
()
raise
PermissionDenied
()
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
locator
)
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
locator
)
...
@@ -330,7 +330,7 @@ def orphan_handler(request, tag=None, course_id=None, branch=None, version_guid=
...
@@ -330,7 +330,7 @@ def orphan_handler(request, tag=None, course_id=None, branch=None, version_guid=
:param request:
:param request:
:param course_id: Locator syntax course_id
:param course_id: Locator syntax course_id
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
# DHM: when split becomes back-end, move or conditionalize this conversion
# DHM: when split becomes back-end, move or conditionalize this conversion
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
location
)
old_location
=
loc_mapper
()
.
translate_locator_to_location
(
location
)
if
request
.
method
==
'GET'
:
if
request
.
method
==
'GET'
:
...
...
cms/djangoapps/contentstore/views/tabs.py
View file @
6c4aae73
...
@@ -62,7 +62,7 @@ def tabs_handler(request, tag=None, course_id=None, branch=None, version_guid=No
...
@@ -62,7 +62,7 @@ def tabs_handler(request, tag=None, course_id=None, branch=None, version_guid=No
Creating a tab, deleting a tab, or changing its contents is not supported through this method.
Creating a tab, deleting a tab, or changing its contents is not supported through this method.
Instead use the general xblock URL (see item.xblock_handler).
Instead use the general xblock URL (see item.xblock_handler).
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
locator
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
locator
):
if
not
has_access
(
request
.
user
,
locator
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
...
cms/djangoapps/contentstore/views/user.py
View file @
6c4aae73
...
@@ -52,7 +52,7 @@ def course_team_handler(request, tag=None, course_id=None, branch=None, version_
...
@@ -52,7 +52,7 @@ def course_team_handler(request, tag=None, course_id=None, branch=None, version_
DELETE:
DELETE:
json: remove a particular course team member from the course team (email is required).
json: remove a particular course team member from the course team (email is required).
"""
"""
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
usage
_id
=
block
)
location
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
version_guid
=
version_guid
,
block
_id
=
block
)
if
not
has_access
(
request
.
user
,
location
):
if
not
has_access
(
request
.
user
,
location
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
...
common/lib/xmodule/xmodule/modulestore/loc_mapper_store.py
View file @
6c4aae73
...
@@ -6,7 +6,7 @@ import re
...
@@ -6,7 +6,7 @@ import re
import
pymongo
import
pymongo
import
bson.son
import
bson.son
from
xmodule.modulestore.exceptions
import
InvalidLocationError
,
ItemNotFoundError
,
DuplicateItemError
from
xmodule.modulestore.exceptions
import
InvalidLocationError
,
ItemNotFoundError
from
xmodule.modulestore.locator
import
BlockUsageLocator
from
xmodule.modulestore.locator
import
BlockUsageLocator
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
import
urllib
import
urllib
...
@@ -156,27 +156,27 @@ class LocMapperStore(object):
...
@@ -156,27 +156,27 @@ class LocMapperStore(object):
entry
=
item
entry
=
item
break
break
usage
_id
=
entry
[
'block_map'
]
.
get
(
self
.
_encode_for_mongo
(
location
.
name
))
block
_id
=
entry
[
'block_map'
]
.
get
(
self
.
_encode_for_mongo
(
location
.
name
))
if
usage
_id
is
None
:
if
block
_id
is
None
:
if
add_entry_if_missing
:
if
add_entry_if_missing
:
usage
_id
=
self
.
_add_to_block_map
(
location
,
location_id
,
entry
[
'block_map'
])
block
_id
=
self
.
_add_to_block_map
(
location
,
location_id
,
entry
[
'block_map'
])
else
:
else
:
raise
ItemNotFoundError
(
location
)
raise
ItemNotFoundError
(
location
)
elif
isinstance
(
usage
_id
,
dict
):
elif
isinstance
(
block
_id
,
dict
):
# name is not unique, look through for the right category
# name is not unique, look through for the right category
if
location
.
category
in
usage
_id
:
if
location
.
category
in
block
_id
:
usage_id
=
usage
_id
[
location
.
category
]
block_id
=
block
_id
[
location
.
category
]
elif
add_entry_if_missing
:
elif
add_entry_if_missing
:
usage
_id
=
self
.
_add_to_block_map
(
location
,
location_id
,
entry
[
'block_map'
])
block
_id
=
self
.
_add_to_block_map
(
location
,
location_id
,
entry
[
'block_map'
])
else
:
else
:
raise
ItemNotFoundError
()
raise
ItemNotFoundError
()
else
:
else
:
raise
InvalidLocationError
()
raise
InvalidLocationError
()
published_usage
=
BlockUsageLocator
(
published_usage
=
BlockUsageLocator
(
course_id
=
entry
[
'course_id'
],
branch
=
entry
[
'prod_branch'
],
usage_id
=
usage
_id
)
course_id
=
entry
[
'course_id'
],
branch
=
entry
[
'prod_branch'
],
block_id
=
block
_id
)
draft_usage
=
BlockUsageLocator
(
draft_usage
=
BlockUsageLocator
(
course_id
=
entry
[
'course_id'
],
branch
=
entry
[
'draft_branch'
],
usage_id
=
usage
_id
)
course_id
=
entry
[
'course_id'
],
branch
=
entry
[
'draft_branch'
],
block_id
=
block
_id
)
if
published
:
if
published
:
result
=
published_usage
result
=
published_usage
else
:
else
:
...
@@ -191,7 +191,7 @@ class LocMapperStore(object):
...
@@ -191,7 +191,7 @@ class LocMapperStore(object):
Returns an old style Location for the given Locator if there's an appropriate entry in the
Returns an old style Location for the given Locator if there's an appropriate entry in the
mapping collection. Note, it requires that the course was previously mapped (a side effect of
mapping collection. Note, it requires that the course was previously mapped (a side effect of
translate_location or explicitly via create_map_entry) and
translate_location or explicitly via create_map_entry) and
the block's
usage
_id was previously stored in the
the block's
block
_id was previously stored in the
map (a side effect of translate_location or via add|update_block_location).
map (a side effect of translate_location or via add|update_block_location).
If get_course, then rather than finding the map for this locator, it finds the 'course' root
If get_course, then rather than finding the map for this locator, it finds the 'course' root
...
@@ -200,7 +200,7 @@ class LocMapperStore(object):
...
@@ -200,7 +200,7 @@ class LocMapperStore(object):
If there are no matches, it returns None.
If there are no matches, it returns None.
If there's more than one location to locator mapping to the same course_id, it looks for the first
If there's more than one location to locator mapping to the same course_id, it looks for the first
one with a mapping for the block
usage
_id and picks that arbitrary course location.
one with a mapping for the block
block
_id and picks that arbitrary course location.
:param locator: a BlockUsageLocator
:param locator: a BlockUsageLocator
"""
"""
...
@@ -214,14 +214,14 @@ class LocMapperStore(object):
...
@@ -214,14 +214,14 @@ class LocMapperStore(object):
# This does not require that the course exist in any modulestore
# This does not require that the course exist in any modulestore
# only that it has a mapping entry.
# only that it has a mapping entry.
maps
=
self
.
location_map
.
find
({
'course_id'
:
locator
.
course_id
})
maps
=
self
.
location_map
.
find
({
'course_id'
:
locator
.
course_id
})
# look for one which maps to this block
usage
_id
# look for one which maps to this block
block
_id
if
maps
.
count
()
==
0
:
if
maps
.
count
()
==
0
:
return
None
return
None
result
=
None
result
=
None
for
candidate
in
maps
:
for
candidate
in
maps
:
old_course_id
=
self
.
_generate_location_course_id
(
candidate
[
'_id'
])
old_course_id
=
self
.
_generate_location_course_id
(
candidate
[
'_id'
])
for
old_name
,
cat_to_usage
in
candidate
[
'block_map'
]
.
iteritems
():
for
old_name
,
cat_to_usage
in
candidate
[
'block_map'
]
.
iteritems
():
for
category
,
usage
_id
in
cat_to_usage
.
iteritems
():
for
category
,
block
_id
in
cat_to_usage
.
iteritems
():
# cache all entries and then figure out if we have the one we want
# cache all entries and then figure out if we have the one we want
# Always return revision=None because the
# Always return revision=None because the
# old draft module store wraps locations as draft before
# old draft module store wraps locations as draft before
...
@@ -234,16 +234,16 @@ class LocMapperStore(object):
...
@@ -234,16 +234,16 @@ class LocMapperStore(object):
self
.
_decode_from_mongo
(
old_name
),
self
.
_decode_from_mongo
(
old_name
),
None
)
None
)
published_locator
=
BlockUsageLocator
(
published_locator
=
BlockUsageLocator
(
candidate
[
'course_id'
],
branch
=
candidate
[
'prod_branch'
],
usage_id
=
usage
_id
candidate
[
'course_id'
],
branch
=
candidate
[
'prod_branch'
],
block_id
=
block
_id
)
)
draft_locator
=
BlockUsageLocator
(
draft_locator
=
BlockUsageLocator
(
candidate
[
'course_id'
],
branch
=
candidate
[
'draft_branch'
],
usage_id
=
usage
_id
candidate
[
'course_id'
],
branch
=
candidate
[
'draft_branch'
],
block_id
=
block
_id
)
)
self
.
_cache_location_map_entry
(
old_course_id
,
location
,
published_locator
,
draft_locator
)
self
.
_cache_location_map_entry
(
old_course_id
,
location
,
published_locator
,
draft_locator
)
if
get_course
and
category
==
'course'
:
if
get_course
and
category
==
'course'
:
result
=
location
result
=
location
elif
not
get_course
and
usage_id
==
locator
.
usage
_id
:
elif
not
get_course
and
block_id
==
locator
.
block
_id
:
result
=
location
result
=
location
if
result
is
not
None
:
if
result
is
not
None
:
return
result
return
result
...
@@ -256,13 +256,15 @@ class LocMapperStore(object):
...
@@ -256,13 +256,15 @@ class LocMapperStore(object):
# The downside is that if there's more than one course mapped to from the same org/course root
# The downside is that if there's more than one course mapped to from the same org/course root
# the block ids will likely be out of sync and collide from an id perspective. HOWEVER,
# the block ids will likely be out of sync and collide from an id perspective. HOWEVER,
# if there are few == org/course roots or their content is unrelated, this will work well.
# if there are few == org/course roots or their content is unrelated, this will work well.
usage
_id
=
self
.
_verify_uniqueness
(
location
.
category
+
location
.
name
[:
3
],
block_map
)
block
_id
=
self
.
_verify_uniqueness
(
location
.
category
+
location
.
name
[:
3
],
block_map
)
else
:
else
:
usage_id
=
location
.
name
# if 2 different category locations had same name, then they'll collide. Make the later
# mapped ones unique
block_id
=
self
.
_verify_uniqueness
(
location
.
name
,
block_map
)
encoded_location_name
=
self
.
_encode_for_mongo
(
location
.
name
)
encoded_location_name
=
self
.
_encode_for_mongo
(
location
.
name
)
block_map
.
setdefault
(
encoded_location_name
,
{})[
location
.
category
]
=
usage
_id
block_map
.
setdefault
(
encoded_location_name
,
{})[
location
.
category
]
=
block
_id
self
.
location_map
.
update
(
location_id
,
{
'$set'
:
{
'block_map'
:
block_map
}})
self
.
location_map
.
update
(
location_id
,
{
'$set'
:
{
'block_map'
:
block_map
}})
return
usage
_id
return
block
_id
def
_interpret_location_course_id
(
self
,
course_id
,
location
):
def
_interpret_location_course_id
(
self
,
course_id
,
location
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/locator.py
View file @
6c4aae73
...
@@ -257,7 +257,7 @@ class CourseLocator(Locator):
...
@@ -257,7 +257,7 @@ class CourseLocator(Locator):
Returns a copy of itself (downcasting) as a CourseLocator.
Returns a copy of itself (downcasting) as a CourseLocator.
The copy has the same CourseLocator fields as the original.
The copy has the same CourseLocator fields as the original.
The copy does not include subclass information, such as
The copy does not include subclass information, such as
a
usage
_id (a property of BlockUsageLocator).
a
block
_id (a property of BlockUsageLocator).
"""
"""
return
CourseLocator
(
course_id
=
self
.
course_id
,
return
CourseLocator
(
course_id
=
self
.
course_id
,
version_guid
=
self
.
version_guid
,
version_guid
=
self
.
version_guid
,
...
@@ -298,8 +298,8 @@ class CourseLocator(Locator):
...
@@ -298,8 +298,8 @@ class CourseLocator(Locator):
self
.
_set_value
(
self
.
_set_value
(
parse
,
'version_guid'
,
lambda
(
new_guid
):
self
.
set_version_guid
(
self
.
as_object_id
(
new_guid
))
parse
,
'version_guid'
,
lambda
(
new_guid
):
self
.
set_version_guid
(
self
.
as_object_id
(
new_guid
))
)
)
self
.
_set_value
(
parse
,
'course_id'
,
lambda
(
new_id
):
self
.
set_course_id
(
new_id
)
)
self
.
_set_value
(
parse
,
'course_id'
,
self
.
set_course_id
)
self
.
_set_value
(
parse
,
'branch'
,
lambda
(
new_branch
):
self
.
set_branch
(
new_branch
)
)
self
.
_set_value
(
parse
,
'branch'
,
self
.
set_branch
)
def
init_from_version_guid
(
self
,
version_guid
):
def
init_from_version_guid
(
self
,
version_guid
):
"""
"""
...
@@ -390,23 +390,23 @@ class BlockUsageLocator(CourseLocator):
...
@@ -390,23 +390,23 @@ class BlockUsageLocator(CourseLocator):
"""
"""
# Default value
# Default value
usage
_id
=
None
block
_id
=
None
def
__init__
(
self
,
url
=
None
,
version_guid
=
None
,
course_id
=
None
,
def
__init__
(
self
,
url
=
None
,
version_guid
=
None
,
course_id
=
None
,
branch
=
None
,
usage
_id
=
None
):
branch
=
None
,
block
_id
=
None
):
"""
"""
Construct a BlockUsageLocator
Construct a BlockUsageLocator
Caller may provide url, version_guid, or course_id, and optionally provide branch.
Caller may provide url, version_guid, or course_id, and optionally provide branch.
The
usage
_id may be specified, either explictly or as part of
The
block
_id may be specified, either explictly or as part of
the url or course_id. If omitted, the locator is created but it
the url or course_id. If omitted, the locator is created but it
has not yet been initialized.
has not yet been initialized.
Resulting BlockUsageLocator will have a
usage
_id property.
Resulting BlockUsageLocator will have a
block
_id property.
It will have either a version_guid property or a course_id (with optional branch) property, or both.
It will have either a version_guid property or a course_id (with optional branch) property, or both.
version_guid must be an instance of bson.objectid.ObjectId or None
version_guid must be an instance of bson.objectid.ObjectId or None
url, course_id, branch, and
usage
_id must be strings or None
url, course_id, branch, and
block
_id must be strings or None
"""
"""
self
.
_validate_args
(
url
,
version_guid
,
course_id
)
self
.
_validate_args
(
url
,
version_guid
,
course_id
)
...
@@ -414,8 +414,8 @@ class BlockUsageLocator(CourseLocator):
...
@@ -414,8 +414,8 @@ class BlockUsageLocator(CourseLocator):
self
.
init_block_ref_from_str
(
url
)
self
.
init_block_ref_from_str
(
url
)
if
course_id
:
if
course_id
:
self
.
init_block_ref_from_course_id
(
course_id
)
self
.
init_block_ref_from_course_id
(
course_id
)
if
usage
_id
:
if
block
_id
:
self
.
init_block_ref
(
usage
_id
)
self
.
init_block_ref
(
block
_id
)
super
(
BlockUsageLocator
,
self
)
.
__init__
(
super
(
BlockUsageLocator
,
self
)
.
__init__
(
url
=
url
,
url
=
url
,
version_guid
=
version_guid
,
version_guid
=
version_guid
,
...
@@ -425,9 +425,9 @@ class BlockUsageLocator(CourseLocator):
...
@@ -425,9 +425,9 @@ class BlockUsageLocator(CourseLocator):
def
is_initialized
(
self
):
def
is_initialized
(
self
):
"""
"""
Returns True if
usage
_id has been initialized, else returns False
Returns True if
block
_id has been initialized, else returns False
"""
"""
return
self
.
usage
_id
is
not
None
return
self
.
block
_id
is
not
None
def
version_agnostic
(
self
):
def
version_agnostic
(
self
):
"""
"""
...
@@ -442,58 +442,57 @@ class BlockUsageLocator(CourseLocator):
...
@@ -442,58 +442,57 @@ class BlockUsageLocator(CourseLocator):
if
self
.
version_guid
:
if
self
.
version_guid
:
return
BlockUsageLocator
(
version_guid
=
self
.
version_guid
,
return
BlockUsageLocator
(
version_guid
=
self
.
version_guid
,
branch
=
self
.
branch
,
branch
=
self
.
branch
,
usage_id
=
self
.
usage
_id
)
block_id
=
self
.
block
_id
)
else
:
else
:
return
BlockUsageLocator
(
course_id
=
self
.
course_id
,
return
BlockUsageLocator
(
course_id
=
self
.
course_id
,
branch
=
self
.
branch
,
branch
=
self
.
branch
,
usage_id
=
self
.
usage
_id
)
block_id
=
self
.
block
_id
)
def
set_
usage
_id
(
self
,
new
):
def
set_
block
_id
(
self
,
new
):
"""
"""
Initialize
usage
_id to new value.
Initialize
block
_id to new value.
If
usage
_id has already been initialized to a different value, raise an exception.
If
block
_id has already been initialized to a different value, raise an exception.
"""
"""
self
.
set_property
(
'
usage
_id'
,
new
)
self
.
set_property
(
'
block
_id'
,
new
)
def
init_block_ref
(
self
,
block_ref
):
def
init_block_ref
(
self
,
block_ref
):
if
isinstance
(
block_ref
,
LocalId
):
if
isinstance
(
block_ref
,
LocalId
):
self
.
set_
usage
_id
(
block_ref
)
self
.
set_
block
_id
(
block_ref
)
else
:
else
:
parse
=
parse_block_ref
(
block_ref
)
parse
=
parse_block_ref
(
block_ref
)
if
not
parse
:
if
not
parse
:
raise
ValueError
(
'Could not parse "
%
s" as a block_ref'
%
block_ref
)
raise
ValueError
(
'Could not parse "
%
s" as a block_ref'
%
block_ref
)
self
.
set_
usage
_id
(
parse
[
'block'
])
self
.
set_
block
_id
(
parse
[
'block'
])
def
init_block_ref_from_str
(
self
,
value
):
def
init_block_ref_from_str
(
self
,
value
):
"""
"""
Create a block locator from the given string which may be a url or just the repr (no tag)
Create a block locator from the given string which may be a url or just the repr (no tag)
"""
"""
if
hasattr
(
value
,
'
usage
_id'
):
if
hasattr
(
value
,
'
block
_id'
):
self
.
init_block_ref
(
value
.
usage
_id
)
self
.
init_block_ref
(
value
.
block
_id
)
return
return
if
not
isinstance
(
value
,
basestring
):
if
not
isinstance
(
value
,
basestring
):
return
None
return
None
parse
=
parse_url
(
value
,
tag_optional
=
True
)
parse
=
parse_url
(
value
,
tag_optional
=
True
)
if
parse
is
None
:
if
parse
is
None
:
raise
ValueError
(
'Could not parse "
%
s" as a url'
%
value
)
raise
ValueError
(
'Could not parse "
%
s" as a url'
%
value
)
self
.
_set_value
(
parse
,
'block'
,
lambda
(
new_block
):
self
.
set_usage_id
(
new_block
)
)
self
.
_set_value
(
parse
,
'block'
,
self
.
set_block_id
)
def
init_block_ref_from_course_id
(
self
,
course_id
):
def
init_block_ref_from_course_id
(
self
,
course_id
):
if
isinstance
(
course_id
,
CourseLocator
):
if
isinstance
(
course_id
,
CourseLocator
):
# FIXME the parsed course_id should never contain a block ref
course_id
=
course_id
.
course_id
course_id
=
course_id
.
course_id
assert
course_id
,
"
%
s does not have a valid course_id"
assert
course_id
,
"
%
s does not have a valid course_id"
parse
=
parse_course_id
(
course_id
)
parse
=
parse_course_id
(
course_id
)
if
parse
is
None
:
if
parse
is
None
:
raise
ValueError
(
'Could not parse "
%
s" as a course_id'
%
course_id
)
raise
ValueError
(
'Could not parse "
%
s" as a course_id'
%
course_id
)
self
.
_set_value
(
parse
,
'block'
,
lambda
(
new_block
):
self
.
set_usage_id
(
new_block
)
)
self
.
_set_value
(
parse
,
'block'
,
self
.
set_block_id
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
"""
"""
Return a string representing this location.
Return a string representing this location.
"""
"""
rep
=
super
(
BlockUsageLocator
,
self
)
.
__unicode__
()
rep
=
super
(
BlockUsageLocator
,
self
)
.
__unicode__
()
return
rep
+
'/'
+
BLOCK_PREFIX
+
unicode
(
self
.
usage
_id
)
return
rep
+
'/'
+
BLOCK_PREFIX
+
unicode
(
self
.
block
_id
)
class
DefinitionLocator
(
Locator
):
class
DefinitionLocator
(
Locator
):
...
...
common/lib/xmodule/xmodule/modulestore/split_migrator.py
View file @
6c4aae73
...
@@ -50,7 +50,7 @@ class SplitMigrator(object):
...
@@ -50,7 +50,7 @@ class SplitMigrator(object):
course_location
.
org
,
original_course
.
display_name
,
course_location
.
org
,
original_course
.
display_name
,
user_id
,
id_root
=
new_course_id
,
user_id
,
id_root
=
new_course_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_
usage_id
=
new_course_root_locator
.
usage
_id
,
root_
block_id
=
new_course_root_locator
.
block
_id
,
master_branch
=
new_course_root_locator
.
branch
master_branch
=
new_course_root_locator
.
branch
)
)
...
@@ -74,13 +74,13 @@ class SplitMigrator(object):
...
@@ -74,13 +74,13 @@ class SplitMigrator(object):
# don't copy the course again. No drafts should get here but check
# don't copy the course again. No drafts should get here but check
if
module
.
location
!=
old_course_loc
and
not
getattr
(
module
,
'is_draft'
,
False
):
if
module
.
location
!=
old_course_loc
and
not
getattr
(
module
,
'is_draft'
,
False
):
# create split_xblock using split.create_item
# create split_xblock using split.create_item
# where
usage
_id is computed by translate_location_to_locator
# where
block
_id is computed by translate_location_to_locator
new_locator
=
self
.
loc_mapper
.
translate_location
(
new_locator
=
self
.
loc_mapper
.
translate_location
(
old_course_id
,
module
.
location
,
True
,
add_entry_if_missing
=
True
old_course_id
,
module
.
location
,
True
,
add_entry_if_missing
=
True
)
)
_new_module
=
self
.
split_modulestore
.
create_item
(
_new_module
=
self
.
split_modulestore
.
create_item
(
course_version_locator
,
module
.
category
,
user_id
,
course_version_locator
,
module
.
category
,
user_id
,
usage_id
=
new_locator
.
usage
_id
,
block_id
=
new_locator
.
block
_id
,
fields
=
self
.
_get_json_fields_translate_children
(
module
,
old_course_id
,
True
),
fields
=
self
.
_get_json_fields_translate_children
(
module
,
old_course_id
,
True
),
continue_version
=
True
continue_version
=
True
)
)
...
@@ -130,18 +130,18 @@ class SplitMigrator(object):
...
@@ -130,18 +130,18 @@ class SplitMigrator(object):
# create a new course version just in case the current head is also the prod head
# create a new course version just in case the current head is also the prod head
_new_module
=
self
.
split_modulestore
.
create_item
(
_new_module
=
self
.
split_modulestore
.
create_item
(
new_draft_course_loc
,
module
.
category
,
user_id
,
new_draft_course_loc
,
module
.
category
,
user_id
,
usage_id
=
new_locator
.
usage
_id
,
block_id
=
new_locator
.
block
_id
,
fields
=
self
.
_get_json_fields_translate_children
(
module
,
old_course_id
,
True
)
fields
=
self
.
_get_json_fields_translate_children
(
module
,
old_course_id
,
True
)
)
)
awaiting_adoption
[
module
.
location
]
=
new_locator
.
usage
_id
awaiting_adoption
[
module
.
location
]
=
new_locator
.
block
_id
for
draft_location
,
new_
usage
_id
in
awaiting_adoption
.
iteritems
():
for
draft_location
,
new_
block
_id
in
awaiting_adoption
.
iteritems
():
for
parent_loc
in
self
.
draft_modulestore
.
get_parent_locations
(
draft_location
,
old_course_id
):
for
parent_loc
in
self
.
draft_modulestore
.
get_parent_locations
(
draft_location
,
old_course_id
):
old_parent
=
self
.
draft_modulestore
.
get_item
(
parent_loc
)
old_parent
=
self
.
draft_modulestore
.
get_item
(
parent_loc
)
new_parent
=
self
.
split_modulestore
.
get_item
(
new_parent
=
self
.
split_modulestore
.
get_item
(
self
.
loc_mapper
.
translate_location
(
old_course_id
,
old_parent
.
location
,
False
)
self
.
loc_mapper
.
translate_location
(
old_course_id
,
old_parent
.
location
,
False
)
)
)
# this only occurs if the parent was also awaiting adoption
# this only occurs if the parent was also awaiting adoption
if
new_
usage
_id
in
new_parent
.
children
:
if
new_
block
_id
in
new_parent
.
children
:
break
break
# find index for module: new_parent may be missing quite a few of old_parent's children
# find index for module: new_parent may be missing quite a few of old_parent's children
new_parent_cursor
=
0
new_parent_cursor
=
0
...
@@ -152,15 +152,15 @@ class SplitMigrator(object):
...
@@ -152,15 +152,15 @@ class SplitMigrator(object):
sibling_loc
=
self
.
loc_mapper
.
translate_location
(
old_course_id
,
Location
(
old_child_loc
),
False
)
sibling_loc
=
self
.
loc_mapper
.
translate_location
(
old_course_id
,
Location
(
old_child_loc
),
False
)
# sibling may move cursor
# sibling may move cursor
for
idx
in
range
(
new_parent_cursor
,
len
(
new_parent
.
children
)):
for
idx
in
range
(
new_parent_cursor
,
len
(
new_parent
.
children
)):
if
new_parent
.
children
[
idx
]
==
sibling_loc
.
usage
_id
:
if
new_parent
.
children
[
idx
]
==
sibling_loc
.
block
_id
:
new_parent_cursor
=
idx
+
1
new_parent_cursor
=
idx
+
1
break
break
new_parent
.
children
.
insert
(
new_parent_cursor
,
new_
usage
_id
)
new_parent
.
children
.
insert
(
new_parent_cursor
,
new_
block
_id
)
new_parent
=
self
.
split_modulestore
.
update_item
(
new_parent
,
user_id
)
new_parent
=
self
.
split_modulestore
.
update_item
(
new_parent
,
user_id
)
def
_get_json_fields_translate_children
(
self
,
xblock
,
old_course_id
,
published
):
def
_get_json_fields_translate_children
(
self
,
xblock
,
old_course_id
,
published
):
"""
"""
Return the json repr for explicitly set fields but convert all children to their
usage
_id's
Return the json repr for explicitly set fields but convert all children to their
block
_id's
"""
"""
fields
=
self
.
get_json_fields_explicitly_set
(
xblock
)
fields
=
self
.
get_json_fields_explicitly_set
(
xblock
)
# this will too generously copy the children even for ones that don't exist in the published b/c the old mongo
# this will too generously copy the children even for ones that don't exist in the published b/c the old mongo
...
@@ -169,7 +169,7 @@ class SplitMigrator(object):
...
@@ -169,7 +169,7 @@ class SplitMigrator(object):
fields
[
'children'
]
=
[
fields
[
'children'
]
=
[
self
.
loc_mapper
.
translate_location
(
self
.
loc_mapper
.
translate_location
(
old_course_id
,
Location
(
child
),
published
,
add_entry_if_missing
=
True
old_course_id
,
Location
(
child
),
published
,
add_entry_if_missing
=
True
)
.
usage
_id
)
.
block
_id
for
child
in
fields
[
'children'
]]
for
child
in
fields
[
'children'
]]
return
fields
return
fields
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py
View file @
6c4aae73
...
@@ -47,26 +47,26 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -47,26 +47,26 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
self
.
default_class
=
default_class
self
.
default_class
=
default_class
self
.
local_modules
=
{}
self
.
local_modules
=
{}
def
_load_item
(
self
,
usage
_id
,
course_entry_override
=
None
):
def
_load_item
(
self
,
block
_id
,
course_entry_override
=
None
):
if
isinstance
(
usage_id
,
BlockUsageLocator
)
and
isinstance
(
usage_id
.
usage
_id
,
LocalId
):
if
isinstance
(
block_id
,
BlockUsageLocator
)
and
isinstance
(
block_id
.
block
_id
,
LocalId
):
try
:
try
:
return
self
.
local_modules
[
usage
_id
]
return
self
.
local_modules
[
block
_id
]
except
KeyError
:
except
KeyError
:
raise
ItemNotFoundError
raise
ItemNotFoundError
json_data
=
self
.
module_data
.
get
(
usage
_id
)
json_data
=
self
.
module_data
.
get
(
block
_id
)
if
json_data
is
None
:
if
json_data
is
None
:
# deeper than initial descendant fetch or doesn't exist
# deeper than initial descendant fetch or doesn't exist
self
.
modulestore
.
cache_items
(
self
,
[
usage
_id
],
lazy
=
self
.
lazy
)
self
.
modulestore
.
cache_items
(
self
,
[
block
_id
],
lazy
=
self
.
lazy
)
json_data
=
self
.
module_data
.
get
(
usage
_id
)
json_data
=
self
.
module_data
.
get
(
block
_id
)
if
json_data
is
None
:
if
json_data
is
None
:
raise
ItemNotFoundError
(
usage
_id
)
raise
ItemNotFoundError
(
block
_id
)
class_
=
XModuleDescriptor
.
load_class
(
class_
=
XModuleDescriptor
.
load_class
(
json_data
.
get
(
'category'
),
json_data
.
get
(
'category'
),
self
.
default_class
self
.
default_class
)
)
return
self
.
xblock_from_json
(
class_
,
usage
_id
,
json_data
,
course_entry_override
)
return
self
.
xblock_from_json
(
class_
,
block
_id
,
json_data
,
course_entry_override
)
# xblock's runtime does not always pass enough contextual information to figure out
# xblock's runtime does not always pass enough contextual information to figure out
# which named container (course x branch) or which parent is requesting an item. Because split allows
# which named container (course x branch) or which parent is requesting an item. Because split allows
...
@@ -79,7 +79,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -79,7 +79,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
# low; thus, the course_entry is most likely correct. If the thread is looking at > 1 named container
# low; thus, the course_entry is most likely correct. If the thread is looking at > 1 named container
# pointing to the same structure, the access is likely to be chunky enough that the last known container
# pointing to the same structure, the access is likely to be chunky enough that the last known container
# is the intended one when not given a course_entry_override; thus, the caching of the last branch/course_id.
# is the intended one when not given a course_entry_override; thus, the caching of the last branch/course_id.
def
xblock_from_json
(
self
,
class_
,
usage
_id
,
json_data
,
course_entry_override
=
None
):
def
xblock_from_json
(
self
,
class_
,
block
_id
,
json_data
,
course_entry_override
=
None
):
if
course_entry_override
is
None
:
if
course_entry_override
is
None
:
course_entry_override
=
self
.
course_entry
course_entry_override
=
self
.
course_entry
else
:
else
:
...
@@ -91,12 +91,12 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -91,12 +91,12 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
definition_id
=
self
.
modulestore
.
definition_locator
(
definition
)
definition_id
=
self
.
modulestore
.
definition_locator
(
definition
)
# If no usage id is provided, generate an in-memory id
# If no usage id is provided, generate an in-memory id
if
usage
_id
is
None
:
if
block
_id
is
None
:
usage
_id
=
LocalId
()
block
_id
=
LocalId
()
block_locator
=
BlockUsageLocator
(
block_locator
=
BlockUsageLocator
(
version_guid
=
course_entry_override
[
'structure'
][
'_id'
],
version_guid
=
course_entry_override
[
'structure'
][
'_id'
],
usage_id
=
usage
_id
,
block_id
=
block
_id
,
course_id
=
course_entry_override
.
get
(
'course_id'
),
course_id
=
course_entry_override
.
get
(
'course_id'
),
branch
=
course_entry_override
.
get
(
'branch'
)
branch
=
course_entry_override
.
get
(
'branch'
)
)
)
...
@@ -121,7 +121,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -121,7 +121,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
self
,
self
,
BlockUsageLocator
(
BlockUsageLocator
(
version_guid
=
course_entry_override
[
'structure'
][
'_id'
],
version_guid
=
course_entry_override
[
'structure'
][
'_id'
],
usage_id
=
usage
_id
block_id
=
block
_id
),
),
error_msg
=
exc_info_to_str
(
sys
.
exc_info
())
error_msg
=
exc_info_to_str
(
sys
.
exc_info
())
)
)
...
@@ -136,7 +136,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
...
@@ -136,7 +136,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
module
.
save
()
module
.
save
()
# If this is an in-memory block, store it in this system
# If this is an in-memory block, store it in this system
if
isinstance
(
block_locator
.
usage
_id
,
LocalId
):
if
isinstance
(
block_locator
.
block
_id
,
LocalId
):
self
.
local_modules
[
block_locator
]
=
module
self
.
local_modules
[
block_locator
]
=
module
return
module
return
module
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
6c4aae73
...
@@ -11,7 +11,7 @@ Representation:
...
@@ -11,7 +11,7 @@ Representation:
** 'versions': versions_dict: {branch_id: structure_id, ...}
** 'versions': versions_dict: {branch_id: structure_id, ...}
* structure:
* structure:
** '_id': an ObjectId (guid),
** '_id': an ObjectId (guid),
** 'root': root_
usage
_id (string of key in 'blocks' for the root of this structure,
** 'root': root_
block
_id (string of key in 'blocks' for the root of this structure,
** 'previous_version': the structure from which this one was derived. For published courses, this
** 'previous_version': the structure from which this one was derived. For published courses, this
points to the previously published version of the structure not the draft published to this.
points to the previously published version of the structure not the draft published to this.
** 'original_version': the original structure id in the previous_version relation. Is a pseudo object
** 'original_version': the original structure id in the previous_version relation. Is a pseudo object
...
@@ -130,20 +130,20 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -130,20 +130,20 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# the split mongo store is used for item creation as well as item persistence
# the split mongo store is used for item creation as well as item persistence
self
.
mixologist
=
Mixologist
(
self
.
xblock_mixins
)
self
.
mixologist
=
Mixologist
(
self
.
xblock_mixins
)
def
cache_items
(
self
,
system
,
base_
usage
_ids
,
depth
=
0
,
lazy
=
True
):
def
cache_items
(
self
,
system
,
base_
block
_ids
,
depth
=
0
,
lazy
=
True
):
'''
'''
Handles caching of items once inheritance and any other one time
Handles caching of items once inheritance and any other one time
per course per fetch operations are done.
per course per fetch operations are done.
:param system: a CachingDescriptorSystem
:param system: a CachingDescriptorSystem
:param base_
usage_ids: list of usage
_ids to fetch
:param base_
block_ids: list of block
_ids to fetch
:param depth: how deep below these to prefetch
:param depth: how deep below these to prefetch
:param lazy: whether to fetch definitions or use placeholders
:param lazy: whether to fetch definitions or use placeholders
'''
'''
new_module_data
=
{}
new_module_data
=
{}
for
usage_id
in
base_usage
_ids
:
for
block_id
in
base_block
_ids
:
new_module_data
=
self
.
descendants
(
new_module_data
=
self
.
descendants
(
system
.
course_entry
[
'structure'
][
'blocks'
],
system
.
course_entry
[
'structure'
][
'blocks'
],
usage
_id
,
block
_id
,
depth
,
depth
,
new_module_data
new_module_data
)
)
...
@@ -167,7 +167,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -167,7 +167,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
system
.
module_data
.
update
(
new_module_data
)
system
.
module_data
.
update
(
new_module_data
)
return
system
.
module_data
return
system
.
module_data
def
_load_items
(
self
,
course_entry
,
usage
_ids
,
depth
=
0
,
lazy
=
True
):
def
_load_items
(
self
,
course_entry
,
block
_ids
,
depth
=
0
,
lazy
=
True
):
'''
'''
Load & cache the given blocks from the course. Prefetch down to the
Load & cache the given blocks from the course. Prefetch down to the
given depth. Load the definitions into each block if lazy is False;
given depth. Load the definitions into each block if lazy is False;
...
@@ -187,8 +187,8 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -187,8 +187,8 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
mixins
=
self
.
xblock_mixins
mixins
=
self
.
xblock_mixins
)
)
self
.
_add_cache
(
course_entry
[
'structure'
][
'_id'
],
system
)
self
.
_add_cache
(
course_entry
[
'structure'
][
'_id'
],
system
)
self
.
cache_items
(
system
,
usage
_ids
,
depth
,
lazy
)
self
.
cache_items
(
system
,
block
_ids
,
depth
,
lazy
)
return
[
system
.
load_item
(
usage_id
,
course_entry
)
for
usage_id
in
usage
_ids
]
return
[
system
.
load_item
(
block_id
,
course_entry
)
for
block_id
in
block
_ids
]
def
_get_cache
(
self
,
course_version_guid
):
def
_get_cache
(
self
,
course_version_guid
):
"""
"""
...
@@ -333,7 +333,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -333,7 +333,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
the course or the block w/in the course do not exist for the given version.
the course or the block w/in the course do not exist for the given version.
raises InsufficientSpecificationError if the locator does not id a block
raises InsufficientSpecificationError if the locator does not id a block
"""
"""
if
block_location
.
usage
_id
is
None
:
if
block_location
.
block
_id
is
None
:
raise
InsufficientSpecificationError
(
block_location
)
raise
InsufficientSpecificationError
(
block_location
)
try
:
try
:
course_structure
=
self
.
_lookup_course
(
block_location
)[
'structure'
]
course_structure
=
self
.
_lookup_course
(
block_location
)[
'structure'
]
...
@@ -341,7 +341,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -341,7 +341,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# this error only occurs if the course does not exist
# this error only occurs if the course does not exist
return
False
return
False
return
course_structure
[
'blocks'
]
.
get
(
block_location
.
usage
_id
)
is
not
None
return
course_structure
[
'blocks'
]
.
get
(
block_location
.
block
_id
)
is
not
None
def
get_item
(
self
,
location
,
depth
=
0
):
def
get_item
(
self
,
location
,
depth
=
0
):
"""
"""
...
@@ -365,7 +365,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -365,7 +365,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
if
not
location
.
is_initialized
():
if
not
location
.
is_initialized
():
raise
InsufficientSpecificationError
(
"Not yet initialized:
%
s"
%
location
)
raise
InsufficientSpecificationError
(
"Not yet initialized:
%
s"
%
location
)
course
=
self
.
_lookup_course
(
location
)
course
=
self
.
_lookup_course
(
location
)
items
=
self
.
_load_items
(
course
,
[
location
.
usage
_id
],
depth
,
lazy
=
True
)
items
=
self
.
_load_items
(
course
,
[
location
.
block
_id
],
depth
,
lazy
=
True
)
if
len
(
items
)
==
0
:
if
len
(
items
)
==
0
:
raise
ItemNotFoundError
(
location
)
raise
ItemNotFoundError
(
location
)
return
items
[
0
]
return
items
[
0
]
...
@@ -397,9 +397,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -397,9 +397,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
qualifiers
=
{}
qualifiers
=
{}
course
=
self
.
_lookup_course
(
locator
)
course
=
self
.
_lookup_course
(
locator
)
items
=
[]
items
=
[]
for
usage
_id
,
value
in
course
[
'structure'
][
'blocks'
]
.
iteritems
():
for
block
_id
,
value
in
course
[
'structure'
][
'blocks'
]
.
iteritems
():
if
self
.
_block_matches
(
value
,
qualifiers
):
if
self
.
_block_matches
(
value
,
qualifiers
):
items
.
append
(
usage
_id
)
items
.
append
(
block
_id
)
if
len
(
items
)
>
0
:
if
len
(
items
)
>
0
:
return
self
.
_load_items
(
course
,
items
,
0
,
lazy
=
True
)
return
self
.
_load_items
(
course
,
items
,
0
,
lazy
=
True
)
...
@@ -421,16 +421,16 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -421,16 +421,16 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
def
get_parent_locations
(
self
,
locator
,
course_id
=
None
):
def
get_parent_locations
(
self
,
locator
,
course_id
=
None
):
'''
'''
Return the locations (Locators w/
usage
_ids) for the parents of this location in this
Return the locations (Locators w/
block
_ids) for the parents of this location in this
course. Could use get_items(location, {'children':
usage
_id}) but this is slightly faster.
course. Could use get_items(location, {'children':
block
_id}) but this is slightly faster.
NOTE: the locator must contain the
usage_id, and this code does not actually ensure usage
_id exists
NOTE: the locator must contain the
block_id, and this code does not actually ensure block
_id exists
:param locator: BlockUsageLocator restricting search scope
:param locator: BlockUsageLocator restricting search scope
:param
usage_id: ignored. Only included for API compatibility. Specify the usag
e_id within the locator.
:param
course_id: ignored. Only included for API compatibility. Specify the cours
e_id within the locator.
'''
'''
course
=
self
.
_lookup_course
(
locator
)
course
=
self
.
_lookup_course
(
locator
)
items
=
self
.
_get_parents_from_structure
(
locator
.
usage
_id
,
course
[
'structure'
])
items
=
self
.
_get_parents_from_structure
(
locator
.
block
_id
,
course
[
'structure'
])
return
[
BlockUsageLocator
(
url
=
locator
.
as_course_locator
(),
usage
_id
=
parent_id
)
return
[
BlockUsageLocator
(
url
=
locator
.
as_course_locator
(),
block
_id
=
parent_id
)
for
parent_id
in
items
]
for
parent_id
in
items
]
def
get_orphans
(
self
,
course_id
,
detached_categories
,
branch
):
def
get_orphans
(
self
,
course_id
,
detached_categories
,
branch
):
...
@@ -447,7 +447,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -447,7 +447,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
if
block_data
[
'category'
]
in
detached_categories
:
if
block_data
[
'category'
]
in
detached_categories
:
items
.
discard
(
block_id
)
items
.
discard
(
block_id
)
return
[
return
[
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
usage
_id
=
block_id
)
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
block
_id
=
block_id
)
for
block_id
in
items
for
block_id
in
items
]
]
...
@@ -547,25 +547,25 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -547,25 +547,25 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
'''
'''
# version_agnostic means we don't care if the head and version don't align, trust the version
# version_agnostic means we don't care if the head and version don't align, trust the version
course_struct
=
self
.
_lookup_course
(
block_locator
.
version_agnostic
())[
'structure'
]
course_struct
=
self
.
_lookup_course
(
block_locator
.
version_agnostic
())[
'structure'
]
usage_id
=
block_locator
.
usage
_id
block_id
=
block_locator
.
block
_id
update_version_field
=
'blocks.{}.edit_info.update_version'
.
format
(
usage
_id
)
update_version_field
=
'blocks.{}.edit_info.update_version'
.
format
(
block
_id
)
all_versions_with_block
=
self
.
db_connection
.
find_matching_structures
({
'original_version'
:
course_struct
[
'original_version'
],
all_versions_with_block
=
self
.
db_connection
.
find_matching_structures
({
'original_version'
:
course_struct
[
'original_version'
],
update_version_field
:
{
'$exists'
:
True
}})
update_version_field
:
{
'$exists'
:
True
}})
# find (all) root versions and build map previous: [successors]
# find (all) root versions and build map previous: [successors]
possible_roots
=
[]
possible_roots
=
[]
result
=
{}
result
=
{}
for
version
in
all_versions_with_block
:
for
version
in
all_versions_with_block
:
if
version
[
'_id'
]
==
version
[
'blocks'
][
usage
_id
][
'edit_info'
][
'update_version'
]:
if
version
[
'_id'
]
==
version
[
'blocks'
][
block
_id
][
'edit_info'
][
'update_version'
]:
if
version
[
'blocks'
][
usage
_id
][
'edit_info'
]
.
get
(
'previous_version'
)
is
None
:
if
version
[
'blocks'
][
block
_id
][
'edit_info'
]
.
get
(
'previous_version'
)
is
None
:
possible_roots
.
append
(
version
[
'blocks'
][
usage
_id
][
'edit_info'
][
'update_version'
])
possible_roots
.
append
(
version
[
'blocks'
][
block
_id
][
'edit_info'
][
'update_version'
])
else
:
else
:
result
.
setdefault
(
version
[
'blocks'
][
usage
_id
][
'edit_info'
][
'previous_version'
],
set
())
.
add
(
result
.
setdefault
(
version
[
'blocks'
][
block
_id
][
'edit_info'
][
'previous_version'
],
set
())
.
add
(
version
[
'blocks'
][
usage
_id
][
'edit_info'
][
'update_version'
])
version
[
'blocks'
][
block
_id
][
'edit_info'
][
'update_version'
])
# more than one possible_root means usage was added and deleted > 1x.
# more than one possible_root means usage was added and deleted > 1x.
if
len
(
possible_roots
)
>
1
:
if
len
(
possible_roots
)
>
1
:
# find the history segment including block_locator's version
# find the history segment including block_locator's version
element_to_find
=
course_struct
[
'blocks'
][
usage
_id
][
'edit_info'
][
'update_version'
]
element_to_find
=
course_struct
[
'blocks'
][
block
_id
][
'edit_info'
][
'update_version'
]
if
element_to_find
in
possible_roots
:
if
element_to_find
in
possible_roots
:
possible_roots
=
[
element_to_find
]
possible_roots
=
[
element_to_find
]
for
possibility
in
possible_roots
:
for
possibility
in
possible_roots
:
...
@@ -576,9 +576,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -576,9 +576,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
return
None
return
None
# convert the results value sets to locators
# convert the results value sets to locators
for
k
,
versions
in
result
.
iteritems
():
for
k
,
versions
in
result
.
iteritems
():
result
[
k
]
=
[
BlockUsageLocator
(
version_guid
=
version
,
usage_id
=
usage
_id
)
result
[
k
]
=
[
BlockUsageLocator
(
version_guid
=
version
,
block_id
=
block
_id
)
for
version
in
versions
]
for
version
in
versions
]
return
VersionTree
(
BlockUsageLocator
(
version_guid
=
possible_roots
[
0
],
usage_id
=
usage
_id
),
result
)
return
VersionTree
(
BlockUsageLocator
(
version_guid
=
possible_roots
[
0
],
block_id
=
block
_id
),
result
)
def
get_definition_successors
(
self
,
definition_locator
,
version_history_depth
=
1
):
def
get_definition_successors
(
self
,
definition_locator
,
version_history_depth
=
1
):
'''
'''
...
@@ -646,7 +646,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -646,7 +646,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
else
:
else
:
return
definition_locator
,
False
return
definition_locator
,
False
def
_generate_
usage
_id
(
self
,
course_blocks
,
category
):
def
_generate_
block
_id
(
self
,
course_blocks
,
category
):
"""
"""
Generate a somewhat readable block id unique w/in this course using the category
Generate a somewhat readable block id unique w/in this course using the category
:param course_blocks: the current list of blocks.
:param course_blocks: the current list of blocks.
...
@@ -687,7 +687,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -687,7 +687,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# 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.
def
create_item
(
def
create_item
(
self
,
course_or_parent_locator
,
category
,
user_id
,
self
,
course_or_parent_locator
,
category
,
user_id
,
usage
_id
=
None
,
definition_locator
=
None
,
fields
=
None
,
block
_id
=
None
,
definition_locator
=
None
,
fields
=
None
,
force
=
False
,
continue_version
=
False
force
=
False
,
continue_version
=
False
):
):
"""
"""
...
@@ -712,7 +712,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -712,7 +712,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
to the existing definition. If fields contains Scope.content and definition_locator is not None, then
to the existing definition. If fields contains Scope.content and definition_locator is not None, then
the Scope.content fields are assumed to be a new payload for definition_locator.
the Scope.content fields are assumed to be a new payload for definition_locator.
:param
usage
_id: if provided, must not already exist in the structure. Provides the block id for the
:param
block
_id: if provided, must not already exist in the structure. Provides the block id for the
new item in this structure. Otherwise, one is computed using the category appended w/ a few digits.
new item in this structure. Otherwise, one is computed using the category appended w/ a few digits.
:param continue_version: continue changing the current structure at the head of the course. Very dangerous
:param continue_version: continue changing the current structure at the head of the course. Very dangerous
...
@@ -755,18 +755,18 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -755,18 +755,18 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
new_id
=
new_structure
[
'_id'
]
new_id
=
new_structure
[
'_id'
]
# generate usage id
# generate usage id
if
usage
_id
is
not
None
:
if
block
_id
is
not
None
:
if
usage
_id
in
new_structure
[
'blocks'
]:
if
block
_id
in
new_structure
[
'blocks'
]:
raise
DuplicateItemError
(
usage
_id
,
self
,
'structures'
)
raise
DuplicateItemError
(
block
_id
,
self
,
'structures'
)
else
:
else
:
new_
usage_id
=
usage
_id
new_
block_id
=
block
_id
else
:
else
:
new_
usage_id
=
self
.
_generate_usage
_id
(
new_structure
[
'blocks'
],
category
)
new_
block_id
=
self
.
_generate_block
_id
(
new_structure
[
'blocks'
],
category
)
block_fields
=
partitioned_fields
.
get
(
Scope
.
settings
,
{})
block_fields
=
partitioned_fields
.
get
(
Scope
.
settings
,
{})
if
Scope
.
children
in
partitioned_fields
:
if
Scope
.
children
in
partitioned_fields
:
block_fields
.
update
(
partitioned_fields
[
Scope
.
children
])
block_fields
.
update
(
partitioned_fields
[
Scope
.
children
])
new_structure
[
'blocks'
][
new_
usage
_id
]
=
{
new_structure
[
'blocks'
][
new_
block
_id
]
=
{
"category"
:
category
,
"category"
:
category
,
"definition"
:
definition_locator
.
definition_id
,
"definition"
:
definition_locator
.
definition_id
,
"fields"
:
block_fields
,
"fields"
:
block_fields
,
...
@@ -780,9 +780,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -780,9 +780,9 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# if given parent, add new block as child and update parent's version
# if given parent, add new block as child and update parent's version
parent
=
None
parent
=
None
if
isinstance
(
course_or_parent_locator
,
BlockUsageLocator
)
and
course_or_parent_locator
.
usage
_id
is
not
None
:
if
isinstance
(
course_or_parent_locator
,
BlockUsageLocator
)
and
course_or_parent_locator
.
block
_id
is
not
None
:
parent
=
new_structure
[
'blocks'
][
course_or_parent_locator
.
usage
_id
]
parent
=
new_structure
[
'blocks'
][
course_or_parent_locator
.
block
_id
]
parent
[
'fields'
]
.
setdefault
(
'children'
,
[])
.
append
(
new_
usage
_id
)
parent
[
'fields'
]
.
setdefault
(
'children'
,
[])
.
append
(
new_
block
_id
)
if
not
continue_version
or
parent
[
'edit_info'
][
'update_version'
]
!=
structure
[
'_id'
]:
if
not
continue_version
or
parent
[
'edit_info'
][
'update_version'
]
!=
structure
[
'_id'
]:
parent
[
'edit_info'
][
'edited_on'
]
=
datetime
.
datetime
.
now
(
UTC
)
parent
[
'edit_info'
][
'edited_on'
]
=
datetime
.
datetime
.
now
(
UTC
)
parent
[
'edit_info'
][
'edited_by'
]
=
user_id
parent
[
'edit_info'
][
'edited_by'
]
=
user_id
...
@@ -806,13 +806,13 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -806,13 +806,13 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# reconstruct the new_item from the cache
# reconstruct the new_item from the cache
return
self
.
get_item
(
BlockUsageLocator
(
course_id
=
course_parent
,
return
self
.
get_item
(
BlockUsageLocator
(
course_id
=
course_parent
,
usage_id
=
new_usage
_id
,
block_id
=
new_block
_id
,
version_guid
=
new_id
))
version_guid
=
new_id
))
def
create_course
(
def
create_course
(
self
,
org
,
prettyid
,
user_id
,
id_root
=
None
,
fields
=
None
,
self
,
org
,
prettyid
,
user_id
,
id_root
=
None
,
fields
=
None
,
master_branch
=
'draft'
,
versions_dict
=
None
,
root_category
=
'course'
,
master_branch
=
'draft'
,
versions_dict
=
None
,
root_category
=
'course'
,
root_
usage
_id
=
'course'
root_
block
_id
=
'course'
):
):
"""
"""
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
...
@@ -870,7 +870,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -870,7 +870,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
self
.
db_connection
.
insert_definition
(
definition_entry
)
self
.
db_connection
.
insert_definition
(
definition_entry
)
draft_structure
=
self
.
_new_structure
(
draft_structure
=
self
.
_new_structure
(
user_id
,
root_
usage
_id
,
root_category
,
block_fields
,
definition_id
user_id
,
root_
block
_id
,
root_category
,
block_fields
,
definition_id
)
)
new_id
=
draft_structure
[
'_id'
]
new_id
=
draft_structure
[
'_id'
]
...
@@ -944,10 +944,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -944,10 +944,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
descriptor
.
definition_locator
,
is_updated
=
self
.
update_definition_from_data
(
descriptor
.
definition_locator
,
is_updated
=
self
.
update_definition_from_data
(
descriptor
.
definition_locator
,
descriptor
.
get_explicitly_set_fields_by_scope
(
Scope
.
content
),
user_id
)
descriptor
.
definition_locator
,
descriptor
.
get_explicitly_set_fields_by_scope
(
Scope
.
content
),
user_id
)
# check children
# check children
original_entry
=
original_structure
[
'blocks'
][
descriptor
.
location
.
usage
_id
]
original_entry
=
original_structure
[
'blocks'
][
descriptor
.
location
.
block
_id
]
i
f
(
not
is_updated
and
descriptor
.
has_children
i
s_updated
=
is_updated
or
(
and
not
self
.
_xblock_lists_equal
(
original_entry
[
'fields'
][
'children'
],
descriptor
.
children
)):
descriptor
.
has_children
and
original_entry
[
'fields'
][
'children'
]
!=
descriptor
.
children
is_updated
=
True
)
# check metadata
# check metadata
if
not
is_updated
:
if
not
is_updated
:
is_updated
=
self
.
_compare_settings
(
is_updated
=
self
.
_compare_settings
(
...
@@ -958,12 +958,12 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -958,12 +958,12 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# if updated, rev the structure
# if updated, rev the structure
if
is_updated
:
if
is_updated
:
new_structure
=
self
.
_version_structure
(
original_structure
,
user_id
)
new_structure
=
self
.
_version_structure
(
original_structure
,
user_id
)
block_data
=
new_structure
[
'blocks'
][
descriptor
.
location
.
usage
_id
]
block_data
=
new_structure
[
'blocks'
][
descriptor
.
location
.
block
_id
]
block_data
[
"definition"
]
=
descriptor
.
definition_locator
.
definition_id
block_data
[
"definition"
]
=
descriptor
.
definition_locator
.
definition_id
block_data
[
"fields"
]
=
descriptor
.
get_explicitly_set_fields_by_scope
(
Scope
.
settings
)
block_data
[
"fields"
]
=
descriptor
.
get_explicitly_set_fields_by_scope
(
Scope
.
settings
)
if
descriptor
.
has_children
:
if
descriptor
.
has_children
:
block_data
[
'fields'
][
"children"
]
=
[
self
.
_usage_id
(
child
)
for
child
in
descriptor
.
children
]
block_data
[
'fields'
][
"children"
]
=
descriptor
.
children
new_id
=
new_structure
[
'_id'
]
new_id
=
new_structure
[
'_id'
]
block_data
[
'edit_info'
]
=
{
block_data
[
'edit_info'
]
=
{
...
@@ -990,7 +990,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -990,7 +990,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
create or update the xblock and all of its children. The xblock's location must specify a course.
create or update the xblock and all of its children. The xblock's location must specify a course.
If it doesn't specify a usage_id, then it's presumed to be new and need creation. This function
If it doesn't specify a usage_id, then it's presumed to be new and need creation. This function
descends the children performing the same operation for any that are xblocks. Any children which
descends the children performing the same operation for any that are xblocks. Any children which
are
usage
_ids just update the children pointer.
are
block
_ids just update the children pointer.
All updates go into the same course version (bulk updater).
All updates go into the same course version (bulk updater).
...
@@ -1020,7 +1020,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1020,7 +1020,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
return
self
.
get_item
(
return
self
.
get_item
(
BlockUsageLocator
(
BlockUsageLocator
(
course_id
=
xblock
.
location
.
course_id
,
course_id
=
xblock
.
location
.
course_id
,
usage_id
=
xblock
.
location
.
usage
_id
,
block_id
=
xblock
.
location
.
block
_id
,
branch
=
xblock
.
location
.
branch
,
branch
=
xblock
.
location
.
branch
,
version_guid
=
new_id
version_guid
=
new_id
)
)
...
@@ -1039,38 +1039,38 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1039,38 +1039,38 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
xblock
.
definition_locator
,
is_updated
=
self
.
update_definition_from_data
(
xblock
.
definition_locator
,
is_updated
=
self
.
update_definition_from_data
(
xblock
.
definition_locator
,
new_def_data
,
user_id
)
xblock
.
definition_locator
,
new_def_data
,
user_id
)
if
isinstance
(
xblock
.
scope_ids
.
usage_id
.
usage
_id
,
LocalId
):
if
isinstance
(
xblock
.
scope_ids
.
usage_id
.
block
_id
,
LocalId
):
# generate an id
# generate an id
is_new
=
True
is_new
=
True
is_updated
=
True
is_updated
=
True
usage_id
=
self
.
_generate_usage
_id
(
structure_blocks
,
xblock
.
category
)
block_id
=
self
.
_generate_block
_id
(
structure_blocks
,
xblock
.
category
)
xblock
.
scope_ids
.
usage_id
.
usage_id
=
usage
_id
xblock
.
scope_ids
.
usage_id
.
block_id
=
block
_id
else
:
else
:
is_new
=
False
is_new
=
False
usage_id
=
xblock
.
location
.
usage
_id
block_id
=
xblock
.
location
.
block
_id
i
f
(
not
is_updated
and
xblock
.
has_children
i
s_updated
=
is_updated
or
(
and
not
self
.
_xblock_lists_equal
(
structure_blocks
[
usage_id
][
'fields'
][
'children'
],
xblock
.
children
)):
xblock
.
has_children
and
structure_blocks
[
block_id
][
'fields'
][
'children'
]
!=
xblock
.
children
is_updated
=
True
)
children
=
[]
children
=
[]
if
xblock
.
has_children
:
if
xblock
.
has_children
:
for
child
in
xblock
.
children
:
for
child
in
xblock
.
children
:
if
isinstance
(
child
.
usage
_id
,
LocalId
):
if
isinstance
(
child
.
block
_id
,
LocalId
):
child_block
=
xblock
.
system
.
get_block
(
child
)
child_block
=
xblock
.
system
.
get_block
(
child
)
is_updated
=
self
.
_persist_subdag
(
child_block
,
user_id
,
structure_blocks
,
new_id
)
or
is_updated
is_updated
=
self
.
_persist_subdag
(
child_block
,
user_id
,
structure_blocks
,
new_id
)
or
is_updated
children
.
append
(
child_block
.
location
.
usage
_id
)
children
.
append
(
child_block
.
location
.
block
_id
)
else
:
else
:
children
.
append
(
child
)
children
.
append
(
child
)
block_fields
=
xblock
.
get_explicitly_set_fields_by_scope
(
Scope
.
settings
)
block_fields
=
xblock
.
get_explicitly_set_fields_by_scope
(
Scope
.
settings
)
if
not
is_new
and
not
is_updated
:
if
not
is_new
and
not
is_updated
:
is_updated
=
self
.
_compare_settings
(
block_fields
,
structure_blocks
[
usage
_id
][
'fields'
])
is_updated
=
self
.
_compare_settings
(
block_fields
,
structure_blocks
[
block
_id
][
'fields'
])
if
children
:
if
children
:
block_fields
[
'children'
]
=
children
block_fields
[
'children'
]
=
children
if
is_updated
:
if
is_updated
:
previous_version
=
None
if
is_new
else
structure_blocks
[
usage
_id
][
'edit_info'
]
.
get
(
'update_version'
)
previous_version
=
None
if
is_new
else
structure_blocks
[
block
_id
][
'edit_info'
]
.
get
(
'update_version'
)
structure_blocks
[
usage
_id
]
=
{
structure_blocks
[
block
_id
]
=
{
"category"
:
xblock
.
category
,
"category"
:
xblock
.
category
,
"definition"
:
xblock
.
definition_locator
.
definition_id
,
"definition"
:
xblock
.
definition_locator
.
definition_id
,
"fields"
:
block_fields
,
"fields"
:
block_fields
,
...
@@ -1214,7 +1214,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1214,7 +1214,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
"""
"""
assert
isinstance
(
usage_locator
,
BlockUsageLocator
)
and
usage_locator
.
is_initialized
()
assert
isinstance
(
usage_locator
,
BlockUsageLocator
)
and
usage_locator
.
is_initialized
()
original_structure
=
self
.
_lookup_course
(
usage_locator
)[
'structure'
]
original_structure
=
self
.
_lookup_course
(
usage_locator
)[
'structure'
]
if
original_structure
[
'root'
]
==
usage_locator
.
usage
_id
:
if
original_structure
[
'root'
]
==
usage_locator
.
block
_id
:
raise
ValueError
(
"Cannot delete the root of a course"
)
raise
ValueError
(
"Cannot delete the root of a course"
)
index_entry
=
self
.
_get_index_if_valid
(
usage_locator
,
force
)
index_entry
=
self
.
_get_index_if_valid
(
usage_locator
,
force
)
new_structure
=
self
.
_version_structure
(
original_structure
,
user_id
)
new_structure
=
self
.
_version_structure
(
original_structure
,
user_id
)
...
@@ -1222,22 +1222,24 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1222,22 +1222,24 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
new_id
=
new_structure
[
'_id'
]
new_id
=
new_structure
[
'_id'
]
parents
=
self
.
get_parent_locations
(
usage_locator
)
parents
=
self
.
get_parent_locations
(
usage_locator
)
for
parent
in
parents
:
for
parent
in
parents
:
parent_block
=
new_blocks
[
parent
.
usage
_id
]
parent_block
=
new_blocks
[
parent
.
block
_id
]
parent_block
[
'fields'
][
'children'
]
.
remove
(
usage_locator
.
usage
_id
)
parent_block
[
'fields'
][
'children'
]
.
remove
(
usage_locator
.
block
_id
)
parent_block
[
'edit_info'
][
'edited_on'
]
=
datetime
.
datetime
.
now
(
UTC
)
parent_block
[
'edit_info'
][
'edited_on'
]
=
datetime
.
datetime
.
now
(
UTC
)
parent_block
[
'edit_info'
][
'edited_by'
]
=
user_id
parent_block
[
'edit_info'
][
'edited_by'
]
=
user_id
parent_block
[
'edit_info'
][
'previous_version'
]
=
parent_block
[
'edit_info'
][
'update_version'
]
parent_block
[
'edit_info'
][
'previous_version'
]
=
parent_block
[
'edit_info'
][
'update_version'
]
parent_block
[
'edit_info'
][
'update_version'
]
=
new_id
parent_block
[
'edit_info'
][
'update_version'
]
=
new_id
# remove subtree
def
remove_subtree
(
block_id
):
def
remove_subtree
(
usage_id
):
"""
for
child
in
new_blocks
[
usage_id
][
'fields'
]
.
get
(
'children'
,
[]):
Remove the subtree rooted at block_id
"""
for
child
in
new_blocks
[
block_id
][
'fields'
]
.
get
(
'children'
,
[]):
remove_subtree
(
child
)
remove_subtree
(
child
)
del
new_blocks
[
usage
_id
]
del
new_blocks
[
block
_id
]
if
delete_children
:
if
delete_children
:
remove_subtree
(
usage_locator
.
usage
_id
)
remove_subtree
(
usage_locator
.
block
_id
)
else
:
else
:
del
new_blocks
[
usage_locator
.
usage
_id
]
del
new_blocks
[
usage_locator
.
block
_id
]
# update index if appropriate and structures
# update index if appropriate and structures
self
.
db_connection
.
insert_structure
(
new_structure
)
self
.
db_connection
.
insert_structure
(
new_structure
)
...
@@ -1307,22 +1309,22 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1307,22 +1309,22 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# migration where the old mongo published had pointers to privates
# migration where the old mongo published had pointers to privates
pass
pass
def
descendants
(
self
,
block_map
,
usage
_id
,
depth
,
descendent_map
):
def
descendants
(
self
,
block_map
,
block
_id
,
depth
,
descendent_map
):
"""
"""
adds block and its descendants out to depth to descendent_map
adds block and its descendants out to depth to descendent_map
Depth specifies the number of levels of descendants to return
Depth specifies the number of levels of descendants to return
(0 => this usage only, 1 => this usage and its children, etc...)
(0 => this usage only, 1 => this usage and its children, etc...)
A depth of None returns all descendants
A depth of None returns all descendants
"""
"""
if
usage
_id
not
in
block_map
:
if
block
_id
not
in
block_map
:
return
descendent_map
return
descendent_map
if
usage
_id
not
in
descendent_map
:
if
block
_id
not
in
descendent_map
:
descendent_map
[
usage_id
]
=
block_map
[
usage
_id
]
descendent_map
[
block_id
]
=
block_map
[
block
_id
]
if
depth
is
None
or
depth
>
0
:
if
depth
is
None
or
depth
>
0
:
depth
=
depth
-
1
if
depth
is
not
None
else
None
depth
=
depth
-
1
if
depth
is
not
None
else
None
for
child
in
block_map
[
usage
_id
][
'fields'
]
.
get
(
'children'
,
[]):
for
child
in
block_map
[
block
_id
][
'fields'
]
.
get
(
'children'
,
[]):
descendent_map
=
self
.
descendants
(
block_map
,
child
,
depth
,
descendent_map
=
self
.
descendants
(
block_map
,
child
,
depth
,
descendent_map
)
descendent_map
)
...
@@ -1343,7 +1345,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1343,7 +1345,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
def
internal_clean_children
(
self
,
course_locator
):
def
internal_clean_children
(
self
,
course_locator
):
"""
"""
Only intended for rather low level methods to use. Goes through the children attrs of
Only intended for rather low level methods to use. Goes through the children attrs of
each block removing any whose
usage
_id is not a member of the course. Does not generate
each block removing any whose
block
_id is not a member of the course. Does not generate
a new version of the course but overwrites the existing one.
a new version of the course but overwrites the existing one.
:param course_locator: the course to clean
:param course_locator: the course to clean
...
@@ -1352,7 +1354,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1352,7 +1354,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
for
block
in
original_structure
[
'blocks'
]
.
itervalues
():
for
block
in
original_structure
[
'blocks'
]
.
itervalues
():
if
'fields'
in
block
and
'children'
in
block
[
'fields'
]:
if
'fields'
in
block
and
'children'
in
block
[
'fields'
]:
block
[
'fields'
][
"children"
]
=
[
block
[
'fields'
][
"children"
]
=
[
usage_id
for
usage_id
in
block
[
'fields'
][
"children"
]
if
usage
_id
in
original_structure
[
'blocks'
]
block_id
for
block_id
in
block
[
'fields'
][
"children"
]
if
block
_id
in
original_structure
[
'blocks'
]
]
]
self
.
db_connection
.
update_structure
(
original_structure
)
self
.
db_connection
.
update_structure
(
original_structure
)
# clear cache again b/c inheritance may be wrong over orphans
# clear cache again b/c inheritance may be wrong over orphans
...
@@ -1390,32 +1392,6 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1390,32 +1392,6 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
else
:
else
:
return
criteria
==
target
return
criteria
==
target
def
_xblock_lists_equal
(
self
,
lista
,
listb
):
"""
Do the 2 lists refer to the same xblocks in the same order (presumes they're from the
same course)
:param lista:
:param listb:
"""
if
len
(
lista
)
!=
len
(
listb
):
return
False
for
ele_a
,
ele_b
in
zip
(
lista
,
listb
):
if
ele_a
!=
ele_b
:
if
self
.
_usage_id
(
ele_a
)
!=
self
.
_usage_id
(
ele_b
):
return
False
return
True
def
_usage_id
(
self
,
xblock_or_id
):
"""
arg is either an xblock or an id. If an xblock, get the usage_id from its location. Otherwise, return itself.
:param xblock_or_id:
"""
if
isinstance
(
xblock_or_id
,
XModuleDescriptor
):
return
xblock_or_id
.
location
.
usage_id
else
:
return
xblock_or_id
def
_get_index_if_valid
(
self
,
locator
,
force
=
False
,
continue_version
=
False
):
def
_get_index_if_valid
(
self
,
locator
,
force
=
False
,
continue_version
=
False
):
"""
"""
If the locator identifies a course and points to its draft (or plausibly its draft),
If the locator identifies a course and points to its draft (or plausibly its draft),
...
@@ -1523,7 +1499,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1523,7 +1499,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
"""
"""
return
SPLIT_MONGO_MODULESTORE_TYPE
return
SPLIT_MONGO_MODULESTORE_TYPE
def
_new_structure
(
self
,
user_id
,
root_
usage
_id
,
def
_new_structure
(
self
,
user_id
,
root_
block
_id
,
root_category
=
None
,
block_fields
=
None
,
definition_id
=
None
):
root_category
=
None
,
block_fields
=
None
,
definition_id
=
None
):
"""
"""
Internal function: create a structure element with no previous version. Must provide the root id
Internal function: create a structure element with no previous version. Must provide the root id
...
@@ -1533,13 +1509,13 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1533,13 +1509,13 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
new_id
=
ObjectId
()
new_id
=
ObjectId
()
if
root_category
is
not
None
:
if
root_category
is
not
None
:
blocks
=
{
blocks
=
{
root_
usage
_id
:
self
.
_new_block
(
user_id
,
root_category
,
block_fields
,
definition_id
,
new_id
)
root_
block
_id
:
self
.
_new_block
(
user_id
,
root_category
,
block_fields
,
definition_id
,
new_id
)
}
}
else
:
else
:
blocks
=
{}
blocks
=
{}
return
{
return
{
'_id'
:
new_id
,
'_id'
:
new_id
,
'root'
:
root_
usage
_id
,
'root'
:
root_
block
_id
,
'previous_version'
:
None
,
'previous_version'
:
None
,
'original_version'
:
new_id
,
'original_version'
:
new_id
,
'edited_by'
:
user_id
,
'edited_by'
:
user_id
,
...
@@ -1547,14 +1523,14 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
...
@@ -1547,14 +1523,14 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
'blocks'
:
blocks
'blocks'
:
blocks
}
}
def
_get_parents_from_structure
(
self
,
usage
_id
,
structure
):
def
_get_parents_from_structure
(
self
,
block
_id
,
structure
):
"""
"""
Given a structure, find all of
usage
_id's parents in that structure
Given a structure, find all of
block
_id's parents in that structure
"""
"""
items
=
[]
items
=
[]
for
parent_id
,
value
in
structure
[
'blocks'
]
.
iteritems
():
for
parent_id
,
value
in
structure
[
'blocks'
]
.
iteritems
():
for
child_id
in
value
[
'fields'
]
.
get
(
'children'
,
[]):
for
child_id
in
value
[
'fields'
]
.
get
(
'children'
,
[]):
if
usage
_id
==
child_id
:
if
block
_id
==
child_id
:
items
.
append
(
parent_id
)
items
.
append
(
parent_id
)
return
items
return
items
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_location_mapper.py
View file @
6c4aae73
...
@@ -75,10 +75,9 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -75,10 +75,9 @@ class TestLocationMapper(unittest.TestCase):
self
.
assertEqual
(
entry
[
'prod_branch'
],
'live'
)
self
.
assertEqual
(
entry
[
'prod_branch'
],
'live'
)
self
.
assertEqual
(
entry
[
'block_map'
],
block_map
)
self
.
assertEqual
(
entry
[
'block_map'
],
block_map
)
def
translate_n_check
(
self
,
location
,
old_style_course_id
,
new_style_course_id
,
block_id
,
branch
,
add_entry
=
False
):
def
translate_n_check
(
self
,
location
,
old_style_course_id
,
new_style_course_id
,
usage_id
,
branch
,
add_entry
=
False
):
"""
"""
Request translation, check course_id,
usage
_id, and branch
Request translation, check course_id,
block
_id, and branch
"""
"""
prob_locator
=
loc_mapper
()
.
translate_location
(
prob_locator
=
loc_mapper
()
.
translate_location
(
old_style_course_id
,
old_style_course_id
,
...
@@ -87,7 +86,7 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -87,7 +86,7 @@ class TestLocationMapper(unittest.TestCase):
add_entry_if_missing
=
add_entry
add_entry_if_missing
=
add_entry
)
)
self
.
assertEqual
(
prob_locator
.
course_id
,
new_style_course_id
)
self
.
assertEqual
(
prob_locator
.
course_id
,
new_style_course_id
)
self
.
assertEqual
(
prob_locator
.
usage_id
,
usage
_id
)
self
.
assertEqual
(
prob_locator
.
block_id
,
block
_id
)
self
.
assertEqual
(
prob_locator
.
branch
,
branch
)
self
.
assertEqual
(
prob_locator
.
branch
,
branch
)
def
test_translate_location_read_only
(
self
):
def
test_translate_location_read_only
(
self
):
...
@@ -243,7 +242,7 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -243,7 +242,7 @@ class TestLocationMapper(unittest.TestCase):
new_style_course_id
=
'{}.geek_dept.{}.baz_run'
.
format
(
org
,
course
)
new_style_course_id
=
'{}.geek_dept.{}.baz_run'
.
format
(
org
,
course
)
prob_locator
=
BlockUsageLocator
(
prob_locator
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
course_id
=
new_style_course_id
,
usage
_id
=
'problem2'
,
block
_id
=
'problem2'
,
branch
=
'published'
branch
=
'published'
)
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
...
@@ -267,21 +266,21 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -267,21 +266,21 @@ class TestLocationMapper(unittest.TestCase):
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'course'
,
'baz_run'
,
None
))
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'course'
,
'baz_run'
,
None
))
# explicit branch
# explicit branch
prob_locator
=
BlockUsageLocator
(
prob_locator
=
BlockUsageLocator
(
course_id
=
prob_locator
.
course_id
,
branch
=
'draft'
,
usage_id
=
prob_locator
.
usage
_id
course_id
=
prob_locator
.
course_id
,
branch
=
'draft'
,
block_id
=
prob_locator
.
block
_id
)
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
# Even though the problem was set as draft, we always return revision=None to work
# Even though the problem was set as draft, we always return revision=None to work
# with old mongo/draft modulestores.
# with old mongo/draft modulestores.
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
,
None
))
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
,
None
))
prob_locator
=
BlockUsageLocator
(
prob_locator
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
usage
_id
=
'problem2'
,
branch
=
'production'
course_id
=
new_style_course_id
,
block
_id
=
'problem2'
,
branch
=
'production'
)
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
,
None
))
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
,
None
))
# same for chapter except chapter cannot be draft in old system
# same for chapter except chapter cannot be draft in old system
chap_locator
=
BlockUsageLocator
(
chap_locator
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
course_id
=
new_style_course_id
,
usage
_id
=
'chapter48f'
,
block
_id
=
'chapter48f'
,
branch
=
'production'
branch
=
'production'
)
)
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
...
@@ -291,7 +290,7 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -291,7 +290,7 @@ class TestLocationMapper(unittest.TestCase):
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
self
.
assertEqual
(
chap_location
,
Location
(
'i4x'
,
org
,
course
,
'chapter'
,
'48f23a10395384929234'
))
self
.
assertEqual
(
chap_location
,
Location
(
'i4x'
,
org
,
course
,
'chapter'
,
'48f23a10395384929234'
))
chap_locator
=
BlockUsageLocator
(
chap_locator
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
usage
_id
=
'chapter48f'
,
branch
=
'production'
course_id
=
new_style_course_id
,
block
_id
=
'chapter48f'
,
branch
=
'production'
)
)
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
chap_location
=
loc_mapper
()
.
translate_locator_to_location
(
chap_locator
)
self
.
assertEqual
(
chap_location
,
Location
(
'i4x'
,
org
,
course
,
'chapter'
,
'48f23a10395384929234'
))
self
.
assertEqual
(
chap_location
,
Location
(
'i4x'
,
org
,
course
,
'chapter'
,
'48f23a10395384929234'
))
...
@@ -300,7 +299,7 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -300,7 +299,7 @@ class TestLocationMapper(unittest.TestCase):
prob_locator2
=
BlockUsageLocator
(
prob_locator2
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
course_id
=
new_style_course_id
,
branch
=
'draft'
,
branch
=
'draft'
,
usage
_id
=
'problem3'
block
_id
=
'problem3'
)
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator2
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator2
)
self
.
assertIsNone
(
prob_location
,
'Found non-existent problem'
)
self
.
assertIsNone
(
prob_location
,
'Found non-existent problem'
)
...
@@ -325,7 +324,7 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -325,7 +324,7 @@ class TestLocationMapper(unittest.TestCase):
prob_locator
=
BlockUsageLocator
(
prob_locator
=
BlockUsageLocator
(
course_id
=
new_style_course_id
,
course_id
=
new_style_course_id
,
branch
=
'production'
,
branch
=
'production'
,
usage
_id
=
'problem3'
block
_id
=
'problem3'
)
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
prob_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
))
self
.
assertEqual
(
prob_location
,
Location
(
'i4x'
,
org
,
course
,
'problem'
,
'abc123'
))
...
@@ -348,6 +347,25 @@ class TestLocationMapper(unittest.TestCase):
...
@@ -348,6 +347,25 @@ class TestLocationMapper(unittest.TestCase):
reverted_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
reverted_location
=
loc_mapper
()
.
translate_locator_to_location
(
prob_locator
)
self
.
assertEqual
(
location
,
reverted_location
)
self
.
assertEqual
(
location
,
reverted_location
)
def
test_name_collision
(
self
):
"""
Test dwim translation when the old name was not unique
"""
org
=
"myorg"
course
=
"another_course"
name
=
"running_again"
course_location
=
Location
(
'i4x'
,
org
,
course
,
'course'
,
name
)
course_xlate
=
loc_mapper
()
.
translate_location
(
None
,
course_location
,
add_entry_if_missing
=
True
)
self
.
assertEqual
(
course_location
,
loc_mapper
()
.
translate_locator_to_location
(
course_xlate
))
eponymous_block
=
course_location
.
replace
(
category
=
'chapter'
)
chapter_xlate
=
loc_mapper
()
.
translate_location
(
None
,
eponymous_block
,
add_entry_if_missing
=
True
)
self
.
assertEqual
(
course_location
,
loc_mapper
()
.
translate_locator_to_location
(
course_xlate
))
self
.
assertEqual
(
eponymous_block
,
loc_mapper
()
.
translate_locator_to_location
(
chapter_xlate
))
# and a non-existent one w/o add
eponymous_block
=
course_location
.
replace
(
category
=
'problem'
)
with
self
.
assertRaises
(
ItemNotFoundError
):
chapter_xlate
=
loc_mapper
()
.
translate_location
(
None
,
eponymous_block
,
add_entry_if_missing
=
False
)
#==================================
#==================================
# functions to mock existing services
# functions to mock existing services
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_locators.py
View file @
6c4aae73
...
@@ -255,9 +255,9 @@ class LocatorTest(TestCase):
...
@@ -255,9 +255,9 @@ class LocatorTest(TestCase):
"""
"""
course_id
=
'mit.eecs-1'
course_id
=
'mit.eecs-1'
branch
=
'foo'
branch
=
'foo'
usage
_id
=
'problem:with-colon~2'
block
_id
=
'problem:with-colon~2'
testobj
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
usage_id
=
usage
_id
)
testobj
=
BlockUsageLocator
(
course_id
=
course_id
,
branch
=
branch
,
block_id
=
block
_id
)
self
.
check_block_locn_fields
(
testobj
,
'Cannot handle colon'
,
course_id
=
course_id
,
branch
=
branch
,
block
=
usage
_id
)
self
.
check_block_locn_fields
(
testobj
,
'Cannot handle colon'
,
course_id
=
course_id
,
branch
=
branch
,
block
=
block
_id
)
def
test_repr
(
self
):
def
test_repr
(
self
):
testurn
=
'mit.eecs.6002x/'
+
BRANCH_PREFIX
+
'published/'
+
BLOCK_PREFIX
+
'HW3'
testurn
=
'mit.eecs.6002x/'
+
BRANCH_PREFIX
+
'published/'
+
BLOCK_PREFIX
+
'HW3'
...
@@ -275,7 +275,7 @@ class LocatorTest(TestCase):
...
@@ -275,7 +275,7 @@ class LocatorTest(TestCase):
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
list
(
location_tuple
)))
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
list
(
location_tuple
)))
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
location
.
dict
()))
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
location
.
dict
()))
locator
=
BlockUsageLocator
(
course_id
=
'foo.bar'
,
branch
=
'alpha'
,
usage
_id
=
'deep'
)
locator
=
BlockUsageLocator
(
course_id
=
'foo.bar'
,
branch
=
'alpha'
,
block
_id
=
'deep'
)
self
.
assertEqual
(
locator
,
Locator
.
to_locator_or_location
(
locator
))
self
.
assertEqual
(
locator
,
Locator
.
to_locator_or_location
(
locator
))
self
.
assertEqual
(
locator
.
as_course_locator
(),
Locator
.
to_locator_or_location
(
locator
.
as_course_locator
()))
self
.
assertEqual
(
locator
.
as_course_locator
(),
Locator
.
to_locator_or_location
(
locator
.
as_course_locator
()))
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
location
.
url
()))
self
.
assertEqual
(
location
,
Locator
.
to_locator_or_location
(
location
.
url
()))
...
@@ -347,4 +347,4 @@ class LocatorTest(TestCase):
...
@@ -347,4 +347,4 @@ class LocatorTest(TestCase):
"""
"""
self
.
check_course_locn_fields
(
testobj
,
msg
,
version_guid
,
course_id
,
self
.
check_course_locn_fields
(
testobj
,
msg
,
version_guid
,
course_id
,
branch
)
branch
)
self
.
assertEqual
(
testobj
.
usage
_id
,
block
)
self
.
assertEqual
(
testobj
.
block
_id
,
block
)
common/lib/xmodule/xmodule/modulestore/tests/test_orphan.py
View file @
6c4aae73
...
@@ -87,14 +87,14 @@ class TestOrphan(unittest.TestCase):
...
@@ -87,14 +87,14 @@ class TestOrphan(unittest.TestCase):
course_or_parent_locator
=
BlockUsageLocator
(
course_or_parent_locator
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
branch
=
'draft'
,
usage
_id
=
parent_name
block
_id
=
parent_name
)
)
else
:
else
:
course_or_parent_locator
=
CourseLocator
(
course_or_parent_locator
=
CourseLocator
(
course_id
=
'test_org.test_course.runid'
,
course_id
=
'test_org.test_course.runid'
,
branch
=
'draft'
,
branch
=
'draft'
,
)
)
self
.
split_mongo
.
create_item
(
course_or_parent_locator
,
category
,
self
.
userid
,
usage
_id
=
name
,
fields
=
fields
)
self
.
split_mongo
.
create_item
(
course_or_parent_locator
,
category
,
self
.
userid
,
block
_id
=
name
,
fields
=
fields
)
def
_create_course
(
self
):
def
_create_course
(
self
):
"""
"""
...
@@ -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_course_id
,
fields
=
fields
,
root_
usage
_id
=
'runid'
'test_org'
,
'my course'
,
self
.
userid
,
self
.
split_course_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
)
...
@@ -150,9 +150,9 @@ class TestOrphan(unittest.TestCase):
...
@@ -150,9 +150,9 @@ class TestOrphan(unittest.TestCase):
"""
"""
orphans
=
self
.
split_mongo
.
get_orphans
(
self
.
split_course_id
,
[
'static_tab'
,
'about'
,
'course_info'
],
'draft'
)
orphans
=
self
.
split_mongo
.
get_orphans
(
self
.
split_course_id
,
[
'static_tab'
,
'about'
,
'course_info'
],
'draft'
)
self
.
assertEqual
(
len
(
orphans
),
3
,
"Wrong # {}"
.
format
(
orphans
))
self
.
assertEqual
(
len
(
orphans
),
3
,
"Wrong # {}"
.
format
(
orphans
))
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
usage
_id
=
'OrphanChapter'
)
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
block
_id
=
'OrphanChapter'
)
self
.
assertIn
(
location
,
orphans
)
self
.
assertIn
(
location
,
orphans
)
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
usage
_id
=
'OrphanVert'
)
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
block
_id
=
'OrphanVert'
)
self
.
assertIn
(
location
,
orphans
)
self
.
assertIn
(
location
,
orphans
)
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
usage
_id
=
'OrphanHtml'
)
location
=
BlockUsageLocator
(
course_id
=
self
.
split_course_id
,
branch
=
'draft'
,
block
_id
=
'OrphanHtml'
)
self
.
assertIn
(
location
,
orphans
)
self
.
assertIn
(
location
,
orphans
)
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
View file @
6c4aae73
...
@@ -105,7 +105,7 @@ class SplitModuleTest(unittest.TestCase):
...
@@ -105,7 +105,7 @@ class SplitModuleTest(unittest.TestCase):
matches the _id.
matches the _id.
"""
"""
for
element
in
collection
:
for
element
in
collection
:
if
element
.
location
.
usage
_id
==
_id
:
if
element
.
location
.
block
_id
==
_id
:
return
element
return
element
...
@@ -235,6 +235,16 @@ class SplitModuleCourseTests(SplitModuleTest):
...
@@ -235,6 +235,16 @@ class SplitModuleCourseTests(SplitModuleTest):
modulestore
()
.
get_course
,
modulestore
()
.
get_course
,
CourseLocator
(
course_id
=
'GreekHero'
,
branch
=
'published'
))
CourseLocator
(
course_id
=
'GreekHero'
,
branch
=
'published'
))
def
test_cache
(
self
):
"""
Test that the mechanics of caching work.
"""
locator
=
CourseLocator
(
version_guid
=
self
.
GUID_D0
)
course
=
modulestore
()
.
get_course
(
locator
)
block_map
=
modulestore
()
.
cache_items
(
course
.
system
,
course
.
children
,
depth
=
3
)
self
.
assertIn
(
'chapter1'
,
block_map
)
self
.
assertIn
(
'problem3_2'
,
block_map
)
def
test_course_successors
(
self
):
def
test_course_successors
(
self
):
"""
"""
get_course_successors(course_locator, version_history_depth=1)
get_course_successors(course_locator, version_history_depth=1)
...
@@ -267,11 +277,11 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -267,11 +277,11 @@ class SplitModuleItemTests(SplitModuleTest):
'''
'''
course_id
=
'GreekHero'
course_id
=
'GreekHero'
# positive tests of various forms
# positive tests of various forms
locator
=
BlockUsageLocator
(
version_guid
=
self
.
GUID_D1
,
usage
_id
=
'head12345'
)
locator
=
BlockUsageLocator
(
version_guid
=
self
.
GUID_D1
,
block
_id
=
'head12345'
)
self
.
assertTrue
(
modulestore
()
.
has_item
(
course_id
,
locator
),
self
.
assertTrue
(
modulestore
()
.
has_item
(
course_id
,
locator
),
"couldn't find in
%
s"
%
self
.
GUID_D1
)
"couldn't find in
%
s"
%
self
.
GUID_D1
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
usage
_id
=
'head12345'
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
block
_id
=
'head12345'
,
branch
=
'draft'
)
self
.
assertTrue
(
self
.
assertTrue
(
modulestore
()
.
has_item
(
locator
.
course_id
,
locator
),
modulestore
()
.
has_item
(
locator
.
course_id
,
locator
),
"couldn't find in 12345"
"couldn't find in 12345"
...
@@ -280,7 +290,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -280,7 +290,7 @@ class SplitModuleItemTests(SplitModuleTest):
modulestore
()
.
has_item
(
locator
.
course_id
,
BlockUsageLocator
(
modulestore
()
.
has_item
(
locator
.
course_id
,
BlockUsageLocator
(
course_id
=
locator
.
course_id
,
course_id
=
locator
.
course_id
,
branch
=
'draft'
,
branch
=
'draft'
,
usage_id
=
locator
.
usage
_id
block_id
=
locator
.
block
_id
)),
)),
"couldn't find in draft 12345"
"couldn't find in draft 12345"
)
)
...
@@ -288,7 +298,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -288,7 +298,7 @@ class SplitModuleItemTests(SplitModuleTest):
modulestore
()
.
has_item
(
locator
.
course_id
,
BlockUsageLocator
(
modulestore
()
.
has_item
(
locator
.
course_id
,
BlockUsageLocator
(
course_id
=
locator
.
course_id
,
course_id
=
locator
.
course_id
,
branch
=
'published'
,
branch
=
'published'
,
usage_id
=
locator
.
usage
_id
)),
block_id
=
locator
.
block
_id
)),
"found in published 12345"
"found in published 12345"
)
)
locator
.
branch
=
'draft'
locator
.
branch
=
'draft'
...
@@ -298,18 +308,18 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -298,18 +308,18 @@ class SplitModuleItemTests(SplitModuleTest):
)
)
# not a course obj
# not a course obj
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
usage
_id
=
'chapter1'
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
block
_id
=
'chapter1'
,
branch
=
'draft'
)
self
.
assertTrue
(
self
.
assertTrue
(
modulestore
()
.
has_item
(
locator
.
course_id
,
locator
),
modulestore
()
.
has_item
(
locator
.
course_id
,
locator
),
"couldn't find chapter1"
"couldn't find chapter1"
)
)
# in published course
# in published course
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
usage
_id
=
"head23456"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
block
_id
=
"head23456"
,
branch
=
'draft'
)
self
.
assertTrue
(
self
.
assertTrue
(
modulestore
()
.
has_item
(
modulestore
()
.
has_item
(
locator
.
course_id
,
locator
.
course_id
,
BlockUsageLocator
(
course_id
=
locator
.
course_id
,
usage_id
=
locator
.
usage
_id
,
branch
=
'published'
)
BlockUsageLocator
(
course_id
=
locator
.
course_id
,
block_id
=
locator
.
block
_id
,
branch
=
'published'
)
),
"couldn't find in 23456"
),
"couldn't find in 23456"
)
)
locator
.
branch
=
'published'
locator
.
branch
=
'published'
...
@@ -319,9 +329,9 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -319,9 +329,9 @@ class SplitModuleItemTests(SplitModuleTest):
# negative tests--not found
# negative tests--not found
# no such course or block
# no such course or block
course_id
=
'GreekHero'
course_id
=
'GreekHero'
locator
=
BlockUsageLocator
(
course_id
=
"doesnotexist"
,
usage
_id
=
"head23456"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"doesnotexist"
,
block
_id
=
"head23456"
,
branch
=
'draft'
)
self
.
assertFalse
(
modulestore
()
.
has_item
(
course_id
,
locator
))
self
.
assertFalse
(
modulestore
()
.
has_item
(
course_id
,
locator
))
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
usage
_id
=
"doesnotexist"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
block
_id
=
"doesnotexist"
,
branch
=
'draft'
)
self
.
assertFalse
(
modulestore
()
.
has_item
(
course_id
,
locator
))
self
.
assertFalse
(
modulestore
()
.
has_item
(
course_id
,
locator
))
# negative tests--insufficient specification
# negative tests--insufficient specification
...
@@ -336,7 +346,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -336,7 +346,7 @@ class SplitModuleItemTests(SplitModuleTest):
get_item(blocklocator)
get_item(blocklocator)
'''
'''
# positive tests of various forms
# positive tests of various forms
locator
=
BlockUsageLocator
(
version_guid
=
self
.
GUID_D1
,
usage
_id
=
'head12345'
)
locator
=
BlockUsageLocator
(
version_guid
=
self
.
GUID_D1
,
block
_id
=
'head12345'
)
block
=
modulestore
()
.
get_item
(
locator
)
block
=
modulestore
()
.
get_item
(
locator
)
self
.
assertIsInstance
(
block
,
CourseDescriptor
)
self
.
assertIsInstance
(
block
,
CourseDescriptor
)
# get_instance just redirects to get_item, ignores course_id
# get_instance just redirects to get_item, ignores course_id
...
@@ -355,7 +365,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -355,7 +365,7 @@ class SplitModuleItemTests(SplitModuleTest):
block
.
grade_cutoffs
,
{
"Pass"
:
0.45
},
block
.
grade_cutoffs
,
{
"Pass"
:
0.45
},
)
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
usage
_id
=
'head12345'
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
block
_id
=
'head12345'
,
branch
=
'draft'
)
verify_greek_hero
(
modulestore
()
.
get_item
(
locator
))
verify_greek_hero
(
modulestore
()
.
get_item
(
locator
))
# get_instance just redirects to get_item, ignores course_id
# get_instance just redirects to get_item, ignores course_id
verify_greek_hero
(
modulestore
()
.
get_instance
(
"course_id"
,
locator
))
verify_greek_hero
(
modulestore
()
.
get_instance
(
"course_id"
,
locator
))
...
@@ -364,7 +374,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -364,7 +374,7 @@ class SplitModuleItemTests(SplitModuleTest):
self
.
assertRaises
(
ItemNotFoundError
,
self
.
assertRaises
(
ItemNotFoundError
,
modulestore
()
.
get_item
,
modulestore
()
.
get_item
,
BlockUsageLocator
(
course_id
=
locator
.
as_course_locator
(),
BlockUsageLocator
(
course_id
=
locator
.
as_course_locator
(),
usage_id
=
locator
.
usage
_id
,
block_id
=
locator
.
block
_id
,
branch
=
'published'
))
branch
=
'published'
))
locator
.
branch
=
'draft'
locator
.
branch
=
'draft'
self
.
assertIsInstance
(
self
.
assertIsInstance
(
...
@@ -374,7 +384,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -374,7 +384,7 @@ class SplitModuleItemTests(SplitModuleTest):
def
test_get_non_root
(
self
):
def
test_get_non_root
(
self
):
# not a course obj
# not a course obj
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
usage
_id
=
'chapter1'
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
'GreekHero'
,
block
_id
=
'chapter1'
,
branch
=
'draft'
)
block
=
modulestore
()
.
get_item
(
locator
)
block
=
modulestore
()
.
get_item
(
locator
)
self
.
assertEqual
(
block
.
location
.
course_id
,
"GreekHero"
)
self
.
assertEqual
(
block
.
location
.
course_id
,
"GreekHero"
)
self
.
assertEqual
(
block
.
category
,
'chapter'
)
self
.
assertEqual
(
block
.
category
,
'chapter'
)
...
@@ -383,7 +393,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -383,7 +393,7 @@ class SplitModuleItemTests(SplitModuleTest):
self
.
assertEqual
(
block
.
edited_by
,
"testassist@edx.org"
)
self
.
assertEqual
(
block
.
edited_by
,
"testassist@edx.org"
)
# in published course
# in published course
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
usage
_id
=
"head23456"
,
branch
=
'published'
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
block
_id
=
"head23456"
,
branch
=
'published'
)
self
.
assertIsInstance
(
self
.
assertIsInstance
(
modulestore
()
.
get_item
(
locator
),
modulestore
()
.
get_item
(
locator
),
CourseDescriptor
CourseDescriptor
...
@@ -391,10 +401,10 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -391,10 +401,10 @@ class SplitModuleItemTests(SplitModuleTest):
# negative tests--not found
# negative tests--not found
# no such course or block
# no such course or block
locator
=
BlockUsageLocator
(
course_id
=
"doesnotexist"
,
usage
_id
=
"head23456"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"doesnotexist"
,
block
_id
=
"head23456"
,
branch
=
'draft'
)
with
self
.
assertRaises
(
ItemNotFoundError
):
with
self
.
assertRaises
(
ItemNotFoundError
):
modulestore
()
.
get_item
(
locator
)
modulestore
()
.
get_item
(
locator
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
usage
_id
=
"doesnotexist"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
block
_id
=
"doesnotexist"
,
branch
=
'draft'
)
with
self
.
assertRaises
(
ItemNotFoundError
):
with
self
.
assertRaises
(
ItemNotFoundError
):
modulestore
()
.
get_item
(
locator
)
modulestore
()
.
get_item
(
locator
)
...
@@ -457,22 +467,22 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -457,22 +467,22 @@ class SplitModuleItemTests(SplitModuleTest):
matches
=
modulestore
()
.
get_items
(
locator
,
qualifiers
=
{
'fields'
:
{
'children'
:
'chapter2'
}})
matches
=
modulestore
()
.
get_items
(
locator
,
qualifiers
=
{
'fields'
:
{
'children'
:
'chapter2'
}})
self
.
assertEqual
(
len
(
matches
),
1
)
self
.
assertEqual
(
len
(
matches
),
1
)
self
.
assertEqual
(
matches
[
0
]
.
location
.
usage
_id
,
'head12345'
)
self
.
assertEqual
(
matches
[
0
]
.
location
.
block
_id
,
'head12345'
)
def
test_get_parents
(
self
):
def
test_get_parents
(
self
):
'''
'''
get_parent_locations(locator, [
usage
_id], [branch]): [BlockUsageLocator]
get_parent_locations(locator, [
block
_id], [branch]): [BlockUsageLocator]
'''
'''
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
branch
=
'draft'
,
usage
_id
=
'chapter1'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
branch
=
'draft'
,
block
_id
=
'chapter1'
)
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
self
.
assertEqual
(
len
(
parents
),
1
)
self
.
assertEqual
(
len
(
parents
),
1
)
self
.
assertEqual
(
parents
[
0
]
.
usage
_id
,
'head12345'
)
self
.
assertEqual
(
parents
[
0
]
.
block
_id
,
'head12345'
)
self
.
assertEqual
(
parents
[
0
]
.
course_id
,
"GreekHero"
)
self
.
assertEqual
(
parents
[
0
]
.
course_id
,
"GreekHero"
)
locator
.
usage
_id
=
'chapter2'
locator
.
block
_id
=
'chapter2'
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
self
.
assertEqual
(
len
(
parents
),
1
)
self
.
assertEqual
(
len
(
parents
),
1
)
self
.
assertEqual
(
parents
[
0
]
.
usage
_id
,
'head12345'
)
self
.
assertEqual
(
parents
[
0
]
.
block
_id
,
'head12345'
)
locator
.
usage
_id
=
'nosuchblock'
locator
.
block
_id
=
'nosuchblock'
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
parents
=
modulestore
()
.
get_parent_locations
(
locator
)
self
.
assertEqual
(
len
(
parents
),
0
)
self
.
assertEqual
(
len
(
parents
),
0
)
...
@@ -480,7 +490,7 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -480,7 +490,7 @@ class SplitModuleItemTests(SplitModuleTest):
"""
"""
Test the existing get_children method on xdescriptors
Test the existing get_children method on xdescriptors
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"head12345"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"head12345"
,
branch
=
'draft'
)
block
=
modulestore
()
.
get_item
(
locator
)
block
=
modulestore
()
.
get_item
(
locator
)
children
=
block
.
get_children
()
children
=
block
.
get_children
()
expected_ids
=
[
expected_ids
=
[
...
@@ -488,8 +498,8 @@ class SplitModuleItemTests(SplitModuleTest):
...
@@ -488,8 +498,8 @@ class SplitModuleItemTests(SplitModuleTest):
]
]
for
child
in
children
:
for
child
in
children
:
self
.
assertEqual
(
child
.
category
,
"chapter"
)
self
.
assertEqual
(
child
.
category
,
"chapter"
)
self
.
assertIn
(
child
.
location
.
usage
_id
,
expected_ids
)
self
.
assertIn
(
child
.
location
.
block
_id
,
expected_ids
)
expected_ids
.
remove
(
child
.
location
.
usage
_id
)
expected_ids
.
remove
(
child
.
location
.
block
_id
)
self
.
assertEqual
(
len
(
expected_ids
),
0
)
self
.
assertEqual
(
len
(
expected_ids
),
0
)
...
@@ -551,7 +561,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -551,7 +561,7 @@ class TestItemCrud(SplitModuleTest):
# check that block does not exist in previous version
# check that block does not exist in previous version
locator
=
BlockUsageLocator
(
locator
=
BlockUsageLocator
(
version_guid
=
premod_course
.
location
.
version_guid
,
version_guid
=
premod_course
.
location
.
version_guid
,
usage_id
=
new_module
.
location
.
usage
_id
block_id
=
new_module
.
location
.
block
_id
)
)
self
.
assertRaises
(
ItemNotFoundError
,
modulestore
()
.
get_item
,
locator
)
self
.
assertRaises
(
ItemNotFoundError
,
modulestore
()
.
get_item
,
locator
)
...
@@ -559,7 +569,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -559,7 +569,7 @@ class TestItemCrud(SplitModuleTest):
"""
"""
Test create_item w/ specifying the parent of the new item
Test create_item w/ specifying the parent of the new item
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
usage
_id
=
"head23456"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"wonderful"
,
block
_id
=
"head23456"
,
branch
=
'draft'
)
premod_course
=
modulestore
()
.
get_course
(
locator
)
premod_course
=
modulestore
()
.
get_course
(
locator
)
category
=
'chapter'
category
=
'chapter'
new_module
=
modulestore
()
.
create_item
(
new_module
=
modulestore
()
.
create_item
(
...
@@ -570,16 +580,16 @@ class TestItemCrud(SplitModuleTest):
...
@@ -570,16 +580,16 @@ class TestItemCrud(SplitModuleTest):
# check that course version changed and course's previous is the other one
# check that course version changed and course's previous is the other one
self
.
assertNotEqual
(
new_module
.
location
.
version_guid
,
premod_course
.
location
.
version_guid
)
self
.
assertNotEqual
(
new_module
.
location
.
version_guid
,
premod_course
.
location
.
version_guid
)
parent
=
modulestore
()
.
get_item
(
locator
)
parent
=
modulestore
()
.
get_item
(
locator
)
self
.
assertIn
(
new_module
.
location
.
usage
_id
,
parent
.
children
)
self
.
assertIn
(
new_module
.
location
.
block
_id
,
parent
.
children
)
self
.
assertEqual
(
str
(
new_module
.
definition_locator
.
definition_id
),
"cd00000000000000dddd0022"
)
self
.
assertEqual
(
str
(
new_module
.
definition_locator
.
definition_id
),
"cd00000000000000dddd0022"
)
def
test_unique_naming
(
self
):
def
test_unique_naming
(
self
):
"""
"""
Check that 2 modules of same type get unique
usage
_ids. Also check that if creation provides
Check that 2 modules of same type get unique
block
_ids. Also check that if creation provides
a definition id and new def data that it branches the definition in the db.
a definition id and new def data that it branches the definition in the db.
Actually, this tries to test all create_item features not tested above.
Actually, this tries to test all create_item features not tested above.
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"contender"
,
usage
_id
=
"head345679"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"contender"
,
block
_id
=
"head345679"
,
branch
=
'draft'
)
category
=
'problem'
category
=
'problem'
premod_time
=
datetime
.
datetime
.
now
(
UTC
)
-
datetime
.
timedelta
(
seconds
=
1
)
premod_time
=
datetime
.
datetime
.
now
(
UTC
)
-
datetime
.
timedelta
(
seconds
=
1
)
new_payload
=
"<problem>empty</problem>"
new_payload
=
"<problem>empty</problem>"
...
@@ -595,9 +605,9 @@ class TestItemCrud(SplitModuleTest):
...
@@ -595,9 +605,9 @@ class TestItemCrud(SplitModuleTest):
)
)
# check that course version changed and course's previous is the other one
# check that course version changed and course's previous is the other one
parent
=
modulestore
()
.
get_item
(
locator
)
parent
=
modulestore
()
.
get_item
(
locator
)
self
.
assertNotEqual
(
new_module
.
location
.
usage_id
,
another_module
.
location
.
usage
_id
)
self
.
assertNotEqual
(
new_module
.
location
.
block_id
,
another_module
.
location
.
block
_id
)
self
.
assertIn
(
new_module
.
location
.
usage
_id
,
parent
.
children
)
self
.
assertIn
(
new_module
.
location
.
block
_id
,
parent
.
children
)
self
.
assertIn
(
another_module
.
location
.
usage
_id
,
parent
.
children
)
self
.
assertIn
(
another_module
.
location
.
block
_id
,
parent
.
children
)
self
.
assertEqual
(
new_module
.
data
,
new_payload
)
self
.
assertEqual
(
new_module
.
data
,
new_payload
)
self
.
assertEqual
(
another_module
.
data
,
another_payload
)
self
.
assertEqual
(
another_module
.
data
,
another_payload
)
# check definition histories
# check definition histories
...
@@ -641,13 +651,13 @@ class TestItemCrud(SplitModuleTest):
...
@@ -641,13 +651,13 @@ class TestItemCrud(SplitModuleTest):
self
.
assertEqual
(
refetch_course
.
update_version
,
course_block_update_version
)
self
.
assertEqual
(
refetch_course
.
update_version
,
course_block_update_version
)
refetch_index_history_info
=
modulestore
()
.
get_course_history_info
(
refetch_course
.
location
)
refetch_index_history_info
=
modulestore
()
.
get_course_history_info
(
refetch_course
.
location
)
self
.
assertEqual
(
refetch_index_history_info
,
index_history_info
)
self
.
assertEqual
(
refetch_index_history_info
,
index_history_info
)
self
.
assertIn
(
new_ele
.
location
.
usage
_id
,
refetch_course
.
children
)
self
.
assertIn
(
new_ele
.
location
.
block
_id
,
refetch_course
.
children
)
# try to create existing item
# try to create existing item
with
self
.
assertRaises
(
DuplicateItemError
):
with
self
.
assertRaises
(
DuplicateItemError
):
_fail
=
modulestore
()
.
create_item
(
_fail
=
modulestore
()
.
create_item
(
new_course
.
location
,
'chapter'
,
user
,
new_course
.
location
,
'chapter'
,
user
,
usage_id
=
new_ele
.
location
.
usage
_id
,
block_id
=
new_ele
.
location
.
block
_id
,
fields
=
{
'display_name'
:
'chapter 2'
},
fields
=
{
'display_name'
:
'chapter 2'
},
continue_version
=
True
continue_version
=
True
)
)
...
@@ -678,7 +688,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -678,7 +688,7 @@ class TestItemCrud(SplitModuleTest):
# add new child to old parent in continued (leave off version_guid)
# add new child to old parent in continued (leave off version_guid)
course_module_locator
=
BlockUsageLocator
(
course_module_locator
=
BlockUsageLocator
(
course_id
=
new_course
.
location
.
course_id
,
course_id
=
new_course
.
location
.
course_id
,
usage_id
=
new_course
.
location
.
usage
_id
,
block_id
=
new_course
.
location
.
block
_id
,
branch
=
new_course
.
location
.
branch
branch
=
new_course
.
location
.
branch
)
)
new_ele
=
modulestore
()
.
create_item
(
new_ele
=
modulestore
()
.
create_item
(
...
@@ -691,7 +701,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -691,7 +701,7 @@ class TestItemCrud(SplitModuleTest):
# check children, previous_version
# check children, previous_version
refetch_course
=
modulestore
()
.
get_course
(
versionless_course_locator
)
refetch_course
=
modulestore
()
.
get_course
(
versionless_course_locator
)
self
.
assertIn
(
new_ele
.
location
.
usage
_id
,
refetch_course
.
children
)
self
.
assertIn
(
new_ele
.
location
.
block
_id
,
refetch_course
.
children
)
self
.
assertEqual
(
refetch_course
.
previous_version
,
course_block_update_version
)
self
.
assertEqual
(
refetch_course
.
previous_version
,
course_block_update_version
)
self
.
assertEqual
(
refetch_course
.
update_version
,
transaction_guid
)
self
.
assertEqual
(
refetch_course
.
update_version
,
transaction_guid
)
...
@@ -699,7 +709,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -699,7 +709,7 @@ class TestItemCrud(SplitModuleTest):
"""
"""
test updating an items metadata ensuring the definition doesn't version but the course does if it should
test updating an items metadata ensuring the definition doesn't version but the course does if it should
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"problem3_2"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"problem3_2"
,
branch
=
'draft'
)
problem
=
modulestore
()
.
get_item
(
locator
)
problem
=
modulestore
()
.
get_item
(
locator
)
pre_def_id
=
problem
.
definition_locator
.
definition_id
pre_def_id
=
problem
.
definition_locator
.
definition_id
pre_version_guid
=
problem
.
location
.
version_guid
pre_version_guid
=
problem
.
location
.
version_guid
...
@@ -718,7 +728,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -718,7 +728,7 @@ class TestItemCrud(SplitModuleTest):
# refetch to ensure original didn't change
# refetch to ensure original didn't change
original_location
=
BlockUsageLocator
(
original_location
=
BlockUsageLocator
(
version_guid
=
pre_version_guid
,
version_guid
=
pre_version_guid
,
usage_id
=
problem
.
location
.
usage
_id
block_id
=
problem
.
location
.
block
_id
)
)
problem
=
modulestore
()
.
get_item
(
original_location
)
problem
=
modulestore
()
.
get_item
(
original_location
)
self
.
assertNotEqual
(
problem
.
max_attempts
,
4
,
"original changed"
)
self
.
assertNotEqual
(
problem
.
max_attempts
,
4
,
"original changed"
)
...
@@ -737,7 +747,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -737,7 +747,7 @@ class TestItemCrud(SplitModuleTest):
"""
"""
test updating an item's children ensuring the definition doesn't version but the course does if it should
test updating an item's children ensuring the definition doesn't version but the course does if it should
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"chapter3"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"chapter3"
,
branch
=
'draft'
)
block
=
modulestore
()
.
get_item
(
locator
)
block
=
modulestore
()
.
get_item
(
locator
)
pre_def_id
=
block
.
definition_locator
.
definition_id
pre_def_id
=
block
.
definition_locator
.
definition_id
pre_version_guid
=
block
.
location
.
version_guid
pre_version_guid
=
block
.
location
.
version_guid
...
@@ -752,7 +762,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -752,7 +762,7 @@ class TestItemCrud(SplitModuleTest):
self
.
assertNotEqual
(
updated_problem
.
location
.
version_guid
,
pre_version_guid
)
self
.
assertNotEqual
(
updated_problem
.
location
.
version_guid
,
pre_version_guid
)
self
.
assertEqual
(
updated_problem
.
children
,
block
.
children
)
self
.
assertEqual
(
updated_problem
.
children
,
block
.
children
)
self
.
assertNotIn
(
moved_child
,
updated_problem
.
children
)
self
.
assertNotIn
(
moved_child
,
updated_problem
.
children
)
locator
.
usage
_id
=
"chapter1"
locator
.
block
_id
=
"chapter1"
other_block
=
modulestore
()
.
get_item
(
locator
)
other_block
=
modulestore
()
.
get_item
(
locator
)
other_block
.
children
.
append
(
moved_child
)
other_block
.
children
.
append
(
moved_child
)
other_block
.
save
()
# decache model changes
other_block
.
save
()
# decache model changes
...
@@ -763,7 +773,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -763,7 +773,7 @@ class TestItemCrud(SplitModuleTest):
"""
"""
test updating an item's definition: ensure it gets versioned as well as the course getting versioned
test updating an item's definition: ensure it gets versioned as well as the course getting versioned
"""
"""
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"head12345"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"head12345"
,
branch
=
'draft'
)
block
=
modulestore
()
.
get_item
(
locator
)
block
=
modulestore
()
.
get_item
(
locator
)
pre_def_id
=
block
.
definition_locator
.
definition_id
pre_def_id
=
block
.
definition_locator
.
definition_id
pre_version_guid
=
block
.
location
.
version_guid
pre_version_guid
=
block
.
location
.
version_guid
...
@@ -781,7 +791,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -781,7 +791,7 @@ class TestItemCrud(SplitModuleTest):
Test updating metadata, children, and definition in a single call ensuring all the versioning occurs
Test updating metadata, children, and definition in a single call ensuring all the versioning occurs
"""
"""
# first add 2 children to the course for the update to manipulate
# first add 2 children to the course for the update to manipulate
locator
=
BlockUsageLocator
(
course_id
=
"contender"
,
usage
_id
=
"head345679"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"contender"
,
block
_id
=
"head345679"
,
branch
=
'draft'
)
category
=
'problem'
category
=
'problem'
new_payload
=
"<problem>empty</problem>"
new_payload
=
"<problem>empty</problem>"
modulestore
()
.
create_item
(
modulestore
()
.
create_item
(
...
@@ -823,7 +833,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -823,7 +833,7 @@ class TestItemCrud(SplitModuleTest):
'deleting_user'
)
'deleting_user'
)
reusable_location
=
BlockUsageLocator
(
reusable_location
=
BlockUsageLocator
(
course_id
=
course
.
location
.
course_id
,
course_id
=
course
.
location
.
course_id
,
usage_id
=
course
.
location
.
usage
_id
,
block_id
=
course
.
location
.
block
_id
,
branch
=
'draft'
)
branch
=
'draft'
)
# delete a leaf
# delete a leaf
...
@@ -832,12 +842,12 @@ class TestItemCrud(SplitModuleTest):
...
@@ -832,12 +842,12 @@ class TestItemCrud(SplitModuleTest):
new_course_loc
=
modulestore
()
.
delete_item
(
locn_to_del
,
'deleting_user'
,
delete_children
=
False
)
new_course_loc
=
modulestore
()
.
delete_item
(
locn_to_del
,
'deleting_user'
,
delete_children
=
False
)
deleted
=
BlockUsageLocator
(
course_id
=
reusable_location
.
course_id
,
deleted
=
BlockUsageLocator
(
course_id
=
reusable_location
.
course_id
,
branch
=
reusable_location
.
branch
,
branch
=
reusable_location
.
branch
,
usage_id
=
locn_to_del
.
usage
_id
)
block_id
=
locn_to_del
.
block
_id
)
self
.
assertFalse
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
deleted
))
self
.
assertFalse
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
deleted
))
self
.
assertRaises
(
VersionConflictError
,
modulestore
()
.
has_item
,
reusable_location
.
course_id
,
locn_to_del
)
self
.
assertRaises
(
VersionConflictError
,
modulestore
()
.
has_item
,
reusable_location
.
course_id
,
locn_to_del
)
locator
=
BlockUsageLocator
(
locator
=
BlockUsageLocator
(
version_guid
=
locn_to_del
.
version_guid
,
version_guid
=
locn_to_del
.
version_guid
,
usage_id
=
locn_to_del
.
usage
_id
block_id
=
locn_to_del
.
block
_id
)
)
self
.
assertTrue
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
locator
))
self
.
assertTrue
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
locator
))
self
.
assertNotEqual
(
new_course_loc
.
version_guid
,
course
.
location
.
version_guid
)
self
.
assertNotEqual
(
new_course_loc
.
version_guid
,
course
.
location
.
version_guid
)
...
@@ -854,10 +864,10 @@ class TestItemCrud(SplitModuleTest):
...
@@ -854,10 +864,10 @@ class TestItemCrud(SplitModuleTest):
BlockUsageLocator
(
BlockUsageLocator
(
course_id
=
node_loc
.
course_id
,
course_id
=
node_loc
.
course_id
,
branch
=
node_loc
.
branch
,
branch
=
node_loc
.
branch
,
usage_id
=
node
.
location
.
usage
_id
)))
block_id
=
node
.
location
.
block
_id
)))
locator
=
BlockUsageLocator
(
locator
=
BlockUsageLocator
(
version_guid
=
node
.
location
.
version_guid
,
version_guid
=
node
.
location
.
version_guid
,
usage_id
=
node
.
location
.
usage
_id
)
block_id
=
node
.
location
.
block
_id
)
self
.
assertTrue
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
locator
))
self
.
assertTrue
(
modulestore
()
.
has_item
(
reusable_location
.
course_id
,
locator
))
if
node
.
has_children
:
if
node
.
has_children
:
for
sub
in
node
.
get_children
():
for
sub
in
node
.
get_children
():
...
@@ -868,7 +878,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -868,7 +878,7 @@ class TestItemCrud(SplitModuleTest):
course
=
modulestore
()
.
create_course
(
'nihilx'
,
'deletion'
,
'deleting_user'
)
course
=
modulestore
()
.
create_course
(
'nihilx'
,
'deletion'
,
'deleting_user'
)
root
=
BlockUsageLocator
(
root
=
BlockUsageLocator
(
course_id
=
course
.
location
.
course_id
,
course_id
=
course
.
location
.
course_id
,
usage_id
=
course
.
location
.
usage
_id
,
block_id
=
course
.
location
.
block
_id
,
branch
=
'draft'
)
branch
=
'draft'
)
for
_
in
range
(
4
):
for
_
in
range
(
4
):
self
.
create_subtree_for_deletion
(
root
,
[
'chapter'
,
'vertical'
,
'problem'
])
self
.
create_subtree_for_deletion
(
root
,
[
'chapter'
,
'vertical'
,
'problem'
])
...
@@ -878,7 +888,7 @@ class TestItemCrud(SplitModuleTest):
...
@@ -878,7 +888,7 @@ class TestItemCrud(SplitModuleTest):
if
not
category_queue
:
if
not
category_queue
:
return
return
node
=
modulestore
()
.
create_item
(
parent
,
category_queue
[
0
],
'deleting_user'
)
node
=
modulestore
()
.
create_item
(
parent
,
category_queue
[
0
],
'deleting_user'
)
node_loc
=
BlockUsageLocator
(
parent
.
as_course_locator
(),
usage_id
=
node
.
location
.
usage
_id
)
node_loc
=
BlockUsageLocator
(
parent
.
as_course_locator
(),
block_id
=
node
.
location
.
block
_id
)
for
_
in
range
(
4
):
for
_
in
range
(
4
):
self
.
create_subtree_for_deletion
(
node_loc
,
category_queue
[
1
:])
self
.
create_subtree_for_deletion
(
node_loc
,
category_queue
[
1
:])
...
@@ -971,7 +981,7 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -971,7 +981,7 @@ class TestCourseCreation(SplitModuleTest):
self
.
assertFalse
(
self
.
assertFalse
(
modulestore
()
.
has_item
(
new_draft_locator
.
course_id
,
BlockUsageLocator
(
modulestore
()
.
has_item
(
new_draft_locator
.
course_id
,
BlockUsageLocator
(
original_locator
,
original_locator
,
usage_id
=
new_item
.
location
.
usage
_id
block_id
=
new_item
.
location
.
block
_id
))
))
)
)
...
@@ -1051,9 +1061,9 @@ class TestCourseCreation(SplitModuleTest):
...
@@ -1051,9 +1061,9 @@ 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'
,
user
,
root_
usage
_id
=
'top'
,
root_category
=
'chapter'
root_
block
_id
=
'top'
,
root_category
=
'chapter'
)
)
self
.
assertEqual
(
new_course
.
location
.
usage
_id
,
'top'
)
self
.
assertEqual
(
new_course
.
location
.
block
_id
,
'top'
)
self
.
assertEqual
(
new_course
.
category
,
'chapter'
)
self
.
assertEqual
(
new_course
.
category
,
'chapter'
)
# look at db to verify
# look at db to verify
db_structure
=
modulestore
()
.
db_connection
.
get_structure
(
db_structure
=
modulestore
()
.
db_connection
.
get_structure
(
...
@@ -1076,11 +1086,11 @@ class TestInheritance(SplitModuleTest):
...
@@ -1076,11 +1086,11 @@ class TestInheritance(SplitModuleTest):
"""
"""
# Note, not testing value where defined (course) b/c there's no
# Note, not testing value where defined (course) b/c there's no
# defined accessor for it on CourseDescriptor.
# defined accessor for it on CourseDescriptor.
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"problem3_2"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"problem3_2"
,
branch
=
'draft'
)
node
=
modulestore
()
.
get_item
(
locator
)
node
=
modulestore
()
.
get_item
(
locator
)
# inherited
# inherited
self
.
assertEqual
(
node
.
graceperiod
,
datetime
.
timedelta
(
hours
=
2
))
self
.
assertEqual
(
node
.
graceperiod
,
datetime
.
timedelta
(
hours
=
2
))
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
usage
_id
=
"problem1"
,
branch
=
'draft'
)
locator
=
BlockUsageLocator
(
course_id
=
"GreekHero"
,
block
_id
=
"problem1"
,
branch
=
'draft'
)
node
=
modulestore
()
.
get_item
(
locator
)
node
=
modulestore
()
.
get_item
(
locator
)
# overridden
# overridden
self
.
assertEqual
(
node
.
graceperiod
,
datetime
.
timedelta
(
hours
=
4
))
self
.
assertEqual
(
node
.
graceperiod
,
datetime
.
timedelta
(
hours
=
4
))
...
@@ -1117,24 +1127,24 @@ class TestPublish(SplitModuleTest):
...
@@ -1117,24 +1127,24 @@ class TestPublish(SplitModuleTest):
expected
.
remove
(
"chapter1"
)
expected
.
remove
(
"chapter1"
)
# check that it's not in published course
# check that it's not in published course
with
self
.
assertRaises
(
ItemNotFoundError
):
with
self
.
assertRaises
(
ItemNotFoundError
):
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
usage
_id
))
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
block
_id
))
# publish it
# publish it
modulestore
()
.
xblock_publish
(
self
.
user
,
source_course
,
dest_course
,
[
new_module
.
location
.
usage
_id
],
None
)
modulestore
()
.
xblock_publish
(
self
.
user
,
source_course
,
dest_course
,
[
new_module
.
location
.
block
_id
],
None
)
expected
.
append
(
new_module
.
location
.
usage
_id
)
expected
.
append
(
new_module
.
location
.
block
_id
)
# check that it is in the published course and that its parent is the chapter
# check that it is in the published course and that its parent is the chapter
pub_module
=
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
usage
_id
))
pub_module
=
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
block
_id
))
self
.
assertEqual
(
self
.
assertEqual
(
modulestore
()
.
get_parent_locations
(
pub_module
.
location
)[
0
]
.
usage
_id
,
"chapter1"
modulestore
()
.
get_parent_locations
(
pub_module
.
location
)[
0
]
.
block
_id
,
"chapter1"
)
)
# ensure intentionally orphaned blocks work (e.g., course_info)
# ensure intentionally orphaned blocks work (e.g., course_info)
new_module
=
modulestore
()
.
create_item
(
new_module
=
modulestore
()
.
create_item
(
source_course
,
"course_info"
,
self
.
user
,
usage
_id
=
"handouts"
source_course
,
"course_info"
,
self
.
user
,
block
_id
=
"handouts"
)
)
# publish it
# publish it
modulestore
()
.
xblock_publish
(
self
.
user
,
source_course
,
dest_course
,
[
new_module
.
location
.
usage
_id
],
None
)
modulestore
()
.
xblock_publish
(
self
.
user
,
source_course
,
dest_course
,
[
new_module
.
location
.
block
_id
],
None
)
expected
.
append
(
new_module
.
location
.
usage
_id
)
expected
.
append
(
new_module
.
location
.
block
_id
)
# check that it is in the published course (no error means it worked)
# check that it is in the published course (no error means it worked)
pub_module
=
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
usage
_id
))
pub_module
=
modulestore
()
.
get_item
(
self
.
_usage
(
dest_course
,
new_module
.
location
.
block
_id
))
self
.
_check_course
(
self
.
_check_course
(
source_course
,
dest_course
,
expected
,
[
"chapter2"
,
"chapter3"
,
"problem1"
,
"problem3_2"
]
source_course
,
dest_course
,
expected
,
[
"chapter2"
,
"chapter3"
,
"problem1"
,
"problem3_2"
]
)
)
...
@@ -1200,7 +1210,7 @@ class TestPublish(SplitModuleTest):
...
@@ -1200,7 +1210,7 @@ class TestPublish(SplitModuleTest):
"""
"""
Generate a BlockUsageLocator for the combo of the course location and block id
Generate a BlockUsageLocator for the combo of the course location and block id
"""
"""
return
BlockUsageLocator
(
course_id
=
course_loc
.
course_id
,
branch
=
course_loc
.
branch
,
usage
_id
=
block_id
)
return
BlockUsageLocator
(
course_id
=
course_loc
.
course_id
,
branch
=
course_loc
.
branch
,
block
_id
=
block_id
)
def
_compare_children
(
self
,
source_children
,
dest_children
,
unexpected
):
def
_compare_children
(
self
,
source_children
,
dest_children
,
unexpected
):
"""
"""
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
6c4aae73
...
@@ -168,7 +168,7 @@ class XModuleMixin(XBlockMixin):
...
@@ -168,7 +168,7 @@ class XModuleMixin(XBlockMixin):
if
isinstance
(
self
.
location
,
Location
):
if
isinstance
(
self
.
location
,
Location
):
return
self
.
location
.
name
return
self
.
location
.
name
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
elif
isinstance
(
self
.
location
,
BlockUsageLocator
):
return
self
.
location
.
usage
_id
return
self
.
location
.
block
_id
else
:
else
:
raise
InsufficientSpecificationError
()
raise
InsufficientSpecificationError
()
...
...
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