Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
edx-platform-release
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
1
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Hsin-Yu Chien
edx-platform-release
Commits
f10bcc1e
Commit
f10bcc1e
authored
10 years ago
by
Nimisha Asthagiri
Browse files
Options
Downloads
Patches
Plain Diff
Fix get_courses.
parent
abbfa95e
Loading
Loading
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
common/lib/xmodule/xmodule/modulestore/mixed.py
+45
-17
45 additions, 17 deletions
common/lib/xmodule/xmodule/modulestore/mixed.py
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+17
-21
17 additions, 21 deletions
...odule/xmodule/modulestore/tests/test_mixed_modulestore.py
with
62 additions
and
38 deletions
common/lib/xmodule/xmodule/modulestore/mixed.py
+
45
−
17
View file @
f10bcc1e
...
...
@@ -8,11 +8,11 @@ In this way, courses can be served up both - say - XMLModuleStore or MongoModule
import
logging
from
contextlib
import
contextmanager
import
itertools
import
functools
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locator
import
Locator
from
.
import
ModuleStoreWriteBase
from
.
import
ModuleStoreEnum
...
...
@@ -25,40 +25,63 @@ log = logging.getLogger(__name__)
def
strip_key
(
func
):
"""
A decorator for stripping version and branch information from return values that are, or contain, locations.
Additionally, the decorated function is called with an optional
'
field_decorator
'
parameter that can be used
to strip any location(-containing) fields, which are not directly returned by the function.
The behavior can be controlled by passing
'
remove_version
'
and
'
remove_branch
'
booleans to the decorated
function
'
s kwargs.
"""
@functools.wraps
(
func
)
def
inner
(
*
args
,
**
kwargs
):
"""
Supported kwargs:
remove_version - If True, calls
'
version_agnostic
'
on all return values, including those in lists and dicts.
remove_branch - If True, calls
'
for_branch(None)
'
on all return values, including those in lists and dicts.
Note: The
'
field_decorator
'
parameter passed to the decorated function is a function that honors the
values of these kwargs.
"""
# remove version and branch, by default
rem_vers
=
kwargs
.
pop
(
'
remove_version
'
,
True
)
rem_branch
=
kwargs
.
pop
(
'
remove_branch
'
,
False
)
# helper function for stripping individual values
def
strip_key_func
(
val
):
"""
Strips the version and branch information according to the settings of rem_vers and rem_branch.
Recursively calls this function if the given value has a
'
location
'
attribute.
"""
retval
=
val
if
isinstance
(
retval
,
Locator
):
if
rem_vers
:
retval
=
retval
.
version_agnostic
()
if
rem_branch
:
retval
=
retval
.
for_branch
(
None
)
if
rem_vers
and
hasattr
(
retval
,
'
version_agnostic
'
):
retval
=
retval
.
version_agnostic
()
if
rem_branch
and
hasattr
(
retval
,
'
for_branch
'
):
retval
=
retval
.
for_branch
(
None
)
if
hasattr
(
retval
,
'
location
'
):
retval
.
location
=
strip_key_func
(
retval
.
location
)
return
retval
# decorator for field values
def
strip_key_field_decorator
(
field_value
):
# function for stripping both, collection of, and individual, values
def
strip_key_collection
(
field_value
):
"""
Calls strip_key_func for each element in the given value.
"""
if
rem_vers
or
rem_branch
:
if
isinstance
(
field_value
,
list
):
field_value
=
[
strip_key_func
(
fv
)
for
fv
in
field_value
]
elif
isinstance
(
field_value
,
dict
):
for
key
,
val
in
field_value
.
iteritems
():
field_value
[
key
]
=
strip_key_func
(
val
)
elif
hasattr
(
field_value
,
'
location
'
):
field_value
.
location
=
strip_key_func
(
field_value
.
location
)
else
:
field_value
=
strip_key_func
(
field_value
)
return
field_value
# call the function
retval
=
func
(
field_decorator
=
strip_key_
field_decorator
,
*
args
,
**
kwargs
)
# call the
decorated
function
retval
=
func
(
field_decorator
=
strip_key_
collection
,
*
args
,
**
kwargs
)
#
return the "decorated"
value
return
strip_key_
field_decorator
(
retval
)
#
strip the return
value
return
strip_key_
collection
(
retval
)
return
inner
...
...
@@ -219,10 +242,15 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
'''
Returns a list containing the top level XModuleDescriptors of the courses in this modulestore.
'''
courses
=
[]
courses
=
{}
for
store
in
self
.
modulestores
:
courses
.
extend
(
store
.
get_courses
(
**
kwargs
))
return
courses
# filter out ones which were fetched from earlier stores but locations may not be ==
for
course
in
store
.
get_courses
(
**
kwargs
):
course_id
=
self
.
_clean_course_id_for_mapping
(
course
.
id
)
if
course_id
not
in
courses
:
# course is indeed unique. save it in result
courses
[
course_id
]
=
course
return
courses
.
values
()
def
make_course_key
(
self
,
org
,
course
,
run
):
"""
...
...
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+
17
−
21
View file @
f10bcc1e
...
...
@@ -91,7 +91,7 @@ class TestMixedModuleStore(unittest.TestCase):
"""
AssertEqual replacement for CourseLocator
"""
if
loc1
.
version_agnostic
()
!=
loc2
.
version_agnostic
(
):
if
loc1
.
for_branch
(
None
)
!=
loc2
.
for_branch
(
None
):
self
.
fail
(
self
.
_formatMessage
(
msg
,
u
"
{} != {}
"
.
format
(
unicode
(
loc1
),
unicode
(
loc2
))))
def
setUp
(
self
):
...
...
@@ -125,13 +125,13 @@ class TestMixedModuleStore(unittest.TestCase):
# create course
self
.
course
=
self
.
store
.
create_course
(
course_key
.
org
,
course_key
.
course
,
course_key
.
run
,
self
.
user_id
)
if
isinstance
(
self
.
course
.
id
,
CourseLocator
):
self
.
course_locations
[
self
.
MONGO_COURSEID
]
=
self
.
course
.
location
.
version_agnostic
()
self
.
course_locations
[
self
.
MONGO_COURSEID
]
=
self
.
course
.
location
else
:
self
.
assertEqual
(
self
.
course
.
id
,
course_key
)
# create chapter
chapter
=
self
.
store
.
create_child
(
self
.
user_id
,
self
.
course
.
location
,
'
chapter
'
,
block_id
=
'
Overview
'
)
self
.
writable_chapter_location
=
chapter
.
location
.
version_agnostic
()
self
.
writable_chapter_location
=
chapter
.
location
def
_create_block_hierarchy
(
self
):
"""
...
...
@@ -176,13 +176,13 @@ class TestMixedModuleStore(unittest.TestCase):
def
create_sub_tree
(
parent
,
block_info
):
block
=
self
.
store
.
create_child
(
self
.
user_id
,
parent
.
location
.
version_agnostic
()
,
self
.
user_id
,
parent
.
location
,
block_info
.
category
,
block_id
=
block_info
.
display_name
,
fields
=
{
'
display_name
'
:
block_info
.
display_name
},
)
for
tree
in
block_info
.
sub_tree
:
create_sub_tree
(
block
,
tree
)
setattr
(
self
,
block_info
.
field_name
,
block
.
location
.
version_agnostic
()
)
setattr
(
self
,
block_info
.
field_name
,
block
.
location
)
for
tree
in
trees
:
create_sub_tree
(
self
.
course
,
tree
)
...
...
@@ -386,7 +386,7 @@ class TestMixedModuleStore(unittest.TestCase):
# Create dummy direct only xblocks
chapter
=
self
.
store
.
create_item
(
self
.
user_id
,
test_course
.
id
.
version_agnostic
()
,
test_course
.
id
,
'
chapter
'
,
block_id
=
'
vertical_container
'
)
...
...
@@ -407,7 +407,7 @@ class TestMixedModuleStore(unittest.TestCase):
# Create a dummy component to test against
xblock
=
self
.
store
.
create_item
(
self
.
user_id
,
test_course
.
id
.
version_agnostic
()
,
test_course
.
id
,
'
vertical
'
,
block_id
=
'
test_vertical
'
)
...
...
@@ -522,7 +522,7 @@ class TestMixedModuleStore(unittest.TestCase):
revision
=
ModuleStoreEnum
.
RevisionOption
.
draft_preferred
)
self
.
store
.
publish
(
private_vert
.
location
.
version_agnostic
()
,
self
.
user_id
)
self
.
store
.
publish
(
private_vert
.
location
,
self
.
user_id
)
private_leaf
.
display_name
=
'
change me
'
private_leaf
=
self
.
store
.
update_item
(
private_leaf
,
self
.
user_id
)
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
...
...
@@ -538,11 +538,7 @@ class TestMixedModuleStore(unittest.TestCase):
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
courses
=
self
.
store
.
get_courses
()
course_ids
=
[
course
.
location
.
version_agnostic
()
if
hasattr
(
course
.
location
,
'
version_agnostic
'
)
else
course
.
location
for
course
in
courses
]
course_ids
=
[
course
.
location
for
course
in
courses
]
self
.
assertEqual
(
len
(
courses
),
3
,
"
Not 3 courses: {}
"
.
format
(
course_ids
))
self
.
assertIn
(
self
.
course_locations
[
self
.
MONGO_COURSEID
],
course_ids
)
self
.
assertIn
(
self
.
course_locations
[
self
.
XML_COURSEID1
],
course_ids
)
...
...
@@ -622,7 +618,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
_create_block_hierarchy
()
# publish the course
self
.
course
=
self
.
store
.
publish
(
self
.
course
.
location
.
version_agnostic
()
,
self
.
user_id
)
self
.
course
=
self
.
store
.
publish
(
self
.
course
.
location
,
self
.
user_id
)
# make drafts of verticals
self
.
store
.
convert_to_draft
(
self
.
vertical_x1a
,
self
.
user_id
)
...
...
@@ -648,7 +644,7 @@ class TestMixedModuleStore(unittest.TestCase):
])
# publish the course again
self
.
store
.
publish
(
self
.
course
.
location
.
version_agnostic
()
,
self
.
user_id
)
self
.
store
.
publish
(
self
.
course
.
location
,
self
.
user_id
)
self
.
verify_get_parent_locations_results
([
(
child_to_move_location
,
new_parent_location
,
None
),
(
child_to_move_location
,
new_parent_location
,
ModuleStoreEnum
.
RevisionOption
.
draft_preferred
),
...
...
@@ -888,7 +884,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
initdb
(
default_ms
)
block
=
self
.
store
.
create_item
(
self
.
user_id
,
self
.
course
.
location
.
version_agnostic
().
course_key
,
self
.
course
.
location
.
course_key
,
'
problem
'
)
self
.
assertEqual
(
self
.
user_id
,
block
.
edited_by
)
...
...
@@ -899,7 +895,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
initdb
(
default_ms
)
block
=
self
.
store
.
create_item
(
self
.
user_id
,
self
.
course
.
location
.
version_agnostic
().
course_key
,
self
.
course
.
location
.
course_key
,
'
problem
'
)
self
.
assertEqual
(
self
.
user_id
,
block
.
subtree_edited_by
)
...
...
@@ -944,7 +940,7 @@ class TestMixedModuleStore(unittest.TestCase):
self
.
_create_block_hierarchy
()
# publish
self
.
store
.
publish
(
self
.
course
.
location
.
version_agnostic
()
,
self
.
user_id
)
self
.
store
.
publish
(
self
.
course
.
location
,
self
.
user_id
)
published_xblock
=
self
.
store
.
get_item
(
self
.
vertical_x1a
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
...
...
@@ -980,7 +976,7 @@ class TestMixedModuleStore(unittest.TestCase):
# start off as Private
item
=
self
.
store
.
create_child
(
self
.
user_id
,
self
.
writable_chapter_location
,
'
problem
'
,
'
test_compute_publish_state
'
)
item_location
=
item
.
location
.
version_agnostic
()
item_location
=
item
.
location
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
private
)
...
...
@@ -1030,13 +1026,13 @@ class TestMixedModuleStore(unittest.TestCase):
test_course
=
self
.
store
.
create_course
(
'
testx
'
,
'
GreekHero
'
,
'
test_run
'
,
self
.
user_id
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
test_course
),
PublishState
.
public
)
test_course_key
=
test_course
.
id
.
version_agnostic
()
test_course_key
=
test_course
.
id
# test create_item of direct-only category to make sure we are autopublishing
chapter
=
self
.
store
.
create_item
(
self
.
user_id
,
test_course_key
,
'
chapter
'
,
'
Overview
'
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
chapter
),
PublishState
.
public
)
chapter_location
=
chapter
.
location
.
version_agnostic
()
chapter_location
=
chapter
.
location
# test create_child of direct-only category to make sure we are autopublishing
sequential
=
self
.
store
.
create_child
(
self
.
user_id
,
chapter_location
,
'
sequential
'
,
'
Sequence
'
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment