Commit d2b59cb6 by Nimisha Asthagiri

get_items API: have qualifiers be a separate parameter instead of assuming kwargs.

parent 775b50a7
...@@ -138,7 +138,7 @@ def xml_only_video(step): ...@@ -138,7 +138,7 @@ def xml_only_video(step):
course = world.scenario_dict['COURSE'] course = world.scenario_dict['COURSE']
store = modulestore() store = modulestore()
parent_location = store.get_items(course.id, category='vertical')[0].location parent_location = store.get_items(course.id, qualifiers={'category': 'vertical'})[0].location
youtube_id = 'ABCDEFG' youtube_id = 'ABCDEFG'
world.scenario_dict['YOUTUBE_ID'] = youtube_id world.scenario_dict['YOUTUBE_ID'] = youtube_id
......
...@@ -58,7 +58,7 @@ class Command(BaseCommand): ...@@ -58,7 +58,7 @@ class Command(BaseCommand):
discussion_items = _get_discussion_items(course) discussion_items = _get_discussion_items(course)
# now query all discussion items via get_items() and compare with the tree-traversal # now query all discussion items via get_items() and compare with the tree-traversal
queried_discussion_items = store.get_items(course_key=course_key, category='discussion',) queried_discussion_items = store.get_items(course_key=course_key, qualifiers={'category': 'discussion'})
for item in queried_discussion_items: for item in queried_discussion_items:
if item.location not in discussion_items: if item.location not in discussion_items:
......
...@@ -95,7 +95,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -95,7 +95,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
store.update_item(course, self.user.id) store.update_item(course, self.user.id)
# just pick one vertical # just pick one vertical
descriptor = store.get_items(course.id, category='vertical',) descriptor = store.get_items(course.id, qualifiers={'category': 'vertical'})
resp = self.client.get_html(get_url('container_handler', descriptor[0].location)) resp = self.client.get_html(get_url('container_handler', descriptor[0].location))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -128,7 +128,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -128,7 +128,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
"""Verifies the editing HTML in all the verticals in the given test course""" """Verifies the editing HTML in all the verticals in the given test course"""
_, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', [test_course_name]) _, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', [test_course_name])
items = self.store.get_items(course_items[0].id, category='vertical') items = self.store.get_items(course_items[0].id, qualifiers={'category': 'vertical'})
self._check_verticals(items) self._check_verticals(items)
def test_edit_unit_toy(self): def test_edit_unit_toy(self):
...@@ -290,7 +290,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -290,7 +290,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
_, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy']) _, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy'])
course_key = course_items[0].id course_key = course_items[0].id
items = self.store.get_items(course_key, category='poll_question') items = self.store.get_items(course_key, qualifiers={'category': 'poll_question'})
found = len(items) > 0 found = len(items) > 0
self.assertTrue(found) self.assertTrue(found)
...@@ -644,7 +644,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -644,7 +644,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
filesystem = OSFS(root_dir / 'test_export') filesystem = OSFS(root_dir / 'test_export')
self.assertTrue(filesystem.exists(dirname)) self.assertTrue(filesystem.exists(dirname))
items = store.get_items(course_id, category=category_name) items = store.get_items(course_id, qualifiers={'category': category_name})
for item in items: for item in items:
filesystem = OSFS(root_dir / ('test_export/' + dirname)) filesystem = OSFS(root_dir / ('test_export/' + dirname))
...@@ -743,7 +743,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -743,7 +743,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
# create a new video module and add it as a child to a vertical # create a new video module and add it as a child to a vertical
# this re-creates a bug whereby since the video template doesn't have # this re-creates a bug whereby since the video template doesn't have
# anything in 'data' field, the export was blowing up # anything in 'data' field, the export was blowing up
verticals = self.store.get_items(course_id, category='vertical') verticals = self.store.get_items(course_id, qualifiers={'category': 'vertical'})
self.assertGreater(len(verticals), 0) self.assertGreater(len(verticals), 0)
...@@ -769,7 +769,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -769,7 +769,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
import_from_xml(self.store, self.user.id, 'common/test/data/', ['word_cloud']) import_from_xml(self.store, self.user.id, 'common/test/data/', ['word_cloud'])
course_id = SlashSeparatedCourseKey('HarvardX', 'ER22x', '2013_Spring') course_id = SlashSeparatedCourseKey('HarvardX', 'ER22x', '2013_Spring')
verticals = self.store.get_items(course_id, category='vertical') verticals = self.store.get_items(course_id, qualifiers={'category': 'vertical'})
self.assertGreater(len(verticals), 0) self.assertGreater(len(verticals), 0)
...@@ -796,7 +796,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -796,7 +796,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy']) import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy'])
course_id = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall') course_id = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
verticals = self.store.get_items(course_id, category='vertical') verticals = self.store.get_items(course_id, qualifiers={'category': 'vertical'})
self.assertGreater(len(verticals), 0) self.assertGreater(len(verticals), 0)
...@@ -917,8 +917,10 @@ class ContentStoreToyCourseTest(ContentStoreTestCase): ...@@ -917,8 +917,10 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
items = self.store.get_items( items = self.store.get_items(
course_id, course_id,
category='sequential', qualifiers={
name='vertical_sequential' 'category': 'sequential',
'name': 'vertical_sequential',
}
) )
self.assertEqual(len(items), 1) self.assertEqual(len(items), 1)
...@@ -1401,7 +1403,7 @@ class ContentStoreTest(ContentStoreTestCase): ...@@ -1401,7 +1403,7 @@ class ContentStoreTest(ContentStoreTestCase):
_, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy']) _, course_items = import_from_xml(self.store, self.user.id, 'common/test/data/', ['toy'])
course = course_items[0] course = course_items[0]
verticals = self.store.get_items(course.id, category='vertical') verticals = self.store.get_items(course.id, qualifiers={'category': 'vertical'})
# let's assert on the metadata_inheritance on an existing vertical # let's assert on the metadata_inheritance on an existing vertical
for vertical in verticals: for vertical in verticals:
......
...@@ -413,7 +413,7 @@ class CourseGradingTest(CourseTestCase): ...@@ -413,7 +413,7 @@ class CourseGradingTest(CourseTestCase):
Populate the course, grab a section, get the url for the assignment type access Populate the course, grab a section, get the url for the assignment type access
""" """
self.populate_course() self.populate_course()
sections = modulestore().get_items(self.course.id, category="sequential") sections = modulestore().get_items(self.course.id, qualifiers={'category': "sequential"})
# see if test makes sense # see if test makes sense
self.assertGreater(len(sections), 0, "No sections found") self.assertGreater(len(sections), 0, "No sections found")
section = sections[0] # just take the first one section = sections[0] # just take the first one
......
...@@ -190,7 +190,7 @@ class CourseTestCase(ModuleStoreTestCase): ...@@ -190,7 +190,7 @@ class CourseTestCase(ModuleStoreTestCase):
""" """
items = self.store.get_items( items = self.store.get_items(
course_id, course_id,
category='vertical', qualifiers={'category': 'vertical'},
revision=ModuleStoreEnum.RevisionOption.published_only revision=ModuleStoreEnum.RevisionOption.published_only
) )
self.check_verticals(items) self.check_verticals(items)
......
...@@ -1135,7 +1135,7 @@ class GroupConfiguration(object): ...@@ -1135,7 +1135,7 @@ class GroupConfiguration(object):
} }
""" """
usage_info = {} usage_info = {}
descriptors = store.get_items(course.id, category='split_test') descriptors = store.get_items(course.id, qualifiers={'category': 'split_test'})
for split_test in descriptors: for split_test in descriptors:
if split_test.user_partition_id not in usage_info: if split_test.user_partition_id not in usage_info:
usage_info[split_test.user_partition_id] = [] usage_info[split_test.user_partition_id] = []
......
...@@ -202,9 +202,6 @@ class ModuleStoreRead(object): ...@@ -202,9 +202,6 @@ class ModuleStoreRead(object):
return True, field return True, field
for key, criteria in qualifiers.iteritems(): for key, criteria in qualifiers.iteritems():
if callable(criteria):
# skip over any optional fields that are functions
continue
is_set, value = _is_set_on(key) is_set, value = _is_set_on(key)
if not is_set: if not is_set:
return False return False
......
...@@ -26,7 +26,8 @@ log = logging.getLogger(__name__) ...@@ -26,7 +26,8 @@ log = logging.getLogger(__name__)
def strip_key(func): def strip_key(func):
""" """
A decorator for stripping version and branch information from return values that are, or contain, locations. A decorator for stripping version and branch information from return values that are, or contain, UsageKeys or
CourseKeys.
Additionally, the decorated function is called with an optional 'field_decorator' parameter that can be used 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. to strip any location(-containing) fields, which are not directly returned by the function.
...@@ -222,14 +223,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -222,14 +223,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
and rules as kwargs below and rules as kwargs below
content (dict): fields to look for which have content scope. Follows same syntax and content (dict): fields to look for which have content scope. Follows same syntax and
rules as kwargs below. rules as kwargs below.
additional kwargs (key=value): what to look for within the course. qualifiers (dict): what to look for within the course.
Common qualifiers are ``category`` or any field name. if the target field is a list, Common qualifiers are ``category`` or any field name. if the target field is a list,
then it searches for the given value in the list not list equivalence. then it searches for the given value in the list not list equivalence.
Substring matching pass a regex object. Substring matching pass a regex object.
For some modulestores, ``name`` is another commonly provided key (Location based stores) For some modulestores, ``name`` is another commonly provided key (Location based stores)
For some modulestores, For some modulestores,
you can search by ``edited_by``, ``edited_on`` providing either a datetime for == (probably you can search by ``edited_by``, ``edited_on`` providing either a datetime for == (probably
useless) or a function accepting one arg to do inequality useless) or a function accepting one arg to do inequality
""" """
if not isinstance(course_key, CourseKey): if not isinstance(course_key, CourseKey):
raise Exception("Must pass in a course_key when calling get_items()") raise Exception("Must pass in a course_key when calling get_items()")
......
...@@ -846,7 +846,15 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -846,7 +846,15 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
for key in ('tag', 'org', 'course', 'category', 'name', 'revision') for key in ('tag', 'org', 'course', 'category', 'name', 'revision')
]) ])
def get_items(self, course_id, settings=None, content=None, key_revision=MongoRevisionKey.published, **kwargs): def get_items(
self,
course_id,
settings=None,
content=None,
key_revision=MongoRevisionKey.published,
qualifiers=None,
**kwargs
):
""" """
Returns: Returns:
list of XModuleDescriptor instances for the matching items within the course with list of XModuleDescriptor instances for the matching items within the course with
...@@ -861,15 +869,15 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -861,15 +869,15 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
Args: Args:
course_id (CourseKey): the course identifier course_id (CourseKey): the course identifier
settings (dict): fields to look for which have settings scope. Follows same syntax settings (dict): fields to look for which have settings scope. Follows same syntax
and rules as kwargs below and rules as qualifiers below
content (dict): fields to look for which have content scope. Follows same syntax and content (dict): fields to look for which have content scope. Follows same syntax and
rules as kwargs below. rules as qualifiers below.
key_revision (str): the revision of the items you're looking for. key_revision (str): the revision of the items you're looking for.
MongoRevisionKey.draft - only returns drafts MongoRevisionKey.draft - only returns drafts
MongoRevisionKey.published (equates to None) - only returns published MongoRevisionKey.published (equates to None) - only returns published
If you want one of each matching xblock but preferring draft to published, call this same method If you want one of each matching xblock but preferring draft to published, call this same method
on the draft modulestore with ModuleStoreEnum.RevisionOption.draft_preferred. on the draft modulestore with ModuleStoreEnum.RevisionOption.draft_preferred.
kwargs (key=value): what to look for within the course. qualifiers (dict): what to look for within the course.
Common qualifiers are ``category`` or any field name. if the target field is a list, Common qualifiers are ``category`` or any field name. if the target field is a list,
then it searches for the given value in the list not list equivalence. then it searches for the given value in the list not list equivalence.
Substring matching pass a regex object. Substring matching pass a regex object.
...@@ -877,21 +885,19 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -877,21 +885,19 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
This modulestore does not allow searching dates by comparison or edited_by, previous_version, This modulestore does not allow searching dates by comparison or edited_by, previous_version,
update_version info. update_version info.
""" """
qualifiers = qualifiers.copy() if qualifiers else {} # copy the qualifiers (destructively manipulated here)
query = self._course_key_to_son(course_id) query = self._course_key_to_son(course_id)
query['_id.revision'] = key_revision query['_id.revision'] = key_revision
for field in ['category', 'name']: for field in ['category', 'name']:
if field in kwargs: if field in qualifiers:
query['_id.' + field] = kwargs.pop(field) query['_id.' + field] = qualifiers.pop(field)
for key, value in (settings or {}).iteritems(): for key, value in (settings or {}).iteritems():
query['metadata.' + key] = value query['metadata.' + key] = value
for key, value in (content or {}).iteritems(): for key, value in (content or {}).iteritems():
query['definition.data.' + key] = value query['definition.data.' + key] = value
if 'children' in kwargs: if 'children' in qualifiers:
query['definition.children'] = kwargs.pop('children') query['definition.children'] = qualifiers.pop('children')
# remove any callable kwargs for qualifiers
qualifiers = {key: val for key, val in kwargs.iteritems() if not callable(val)}
query.update(qualifiers) query.update(qualifiers)
items = self.collection.find( items = self.collection.find(
......
...@@ -331,11 +331,6 @@ class DraftModuleStore(MongoModuleStore): ...@@ -331,11 +331,6 @@ class DraftModuleStore(MongoModuleStore):
returns only Published items returns only Published items
if the branch setting is ModuleStoreEnum.Branch.draft_preferred, if the branch setting is ModuleStoreEnum.Branch.draft_preferred,
returns either Draft or Published, preferring Draft items. returns either Draft or Published, preferring Draft items.
kwargs (key=value): what to look for within the course.
Common qualifiers are ``category`` or any field name. if the target field is a list,
then it searches for the given value in the list not list equivalence.
Substring matching pass a regex object.
``name`` is another commonly provided key (Location based stores)
""" """
def base_get_items(key_revision): def base_get_items(key_revision):
return super(DraftModuleStore, self).get_items(course_key, key_revision=key_revision, **kwargs) return super(DraftModuleStore, self).get_items(course_key, key_revision=key_revision, **kwargs)
......
...@@ -451,7 +451,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): ...@@ -451,7 +451,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
log.debug("Found more than one item for '{}'".format(usage_key)) log.debug("Found more than one item for '{}'".format(usage_key))
return items[0] return items[0]
def get_items(self, course_locator, settings=None, content=None, **kwargs): def get_items(self, course_locator, settings=None, content=None, qualifiers=None, **kwargs):
""" """
Returns: Returns:
list of XModuleDescriptor instances for the matching items within the course with list of XModuleDescriptor instances for the matching items within the course with
...@@ -462,10 +462,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): ...@@ -462,10 +462,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
Args: Args:
course_locator (CourseLocator): the course identifier course_locator (CourseLocator): the course identifier
settings (dict): fields to look for which have settings scope. Follows same syntax settings (dict): fields to look for which have settings scope. Follows same syntax
and rules as kwargs below and rules as qualifiers below
content (dict): fields to look for which have content scope. Follows same syntax and content (dict): fields to look for which have content scope. Follows same syntax and
rules as kwargs below. rules as qualifiers below.
kwargs (key=value): what to look for within the course. qualifiers (dict): what to look for within the course.
Common qualifiers are ``category`` or any field name. if the target field is a list, Common qualifiers are ``category`` or any field name. if the target field is a list,
then it searches for the given value in the list not list equivalence. then it searches for the given value in the list not list equivalence.
For substring matching pass a regex object. For substring matching pass a regex object.
...@@ -474,6 +474,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): ...@@ -474,6 +474,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
""" """
course = self._lookup_course(course_locator) course = self._lookup_course(course_locator)
items = [] items = []
qualifiers = qualifiers.copy() if qualifiers else {} # copy the qualifiers (destructively manipulated here)
def _block_matches_all(block_json): def _block_matches_all(block_json):
""" """
...@@ -481,7 +482,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): ...@@ -481,7 +482,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
""" """
# do the checks which don't require loading any additional data # do the checks which don't require loading any additional data
if ( if (
self._block_matches(block_json, kwargs) and self._block_matches(block_json, qualifiers) and
self._block_matches(block_json.get('fields', {}), settings) self._block_matches(block_json.get('fields', {}), settings)
): ):
if content: if content:
...@@ -492,17 +493,17 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): ...@@ -492,17 +493,17 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
if settings is None: if settings is None:
settings = {} settings = {}
if 'name' in kwargs: if 'name' in qualifiers:
# odd case where we don't search just confirm # odd case where we don't search just confirm
block_id = kwargs.pop('name') block_id = qualifiers.pop('name')
block = course['structure']['blocks'].get(block_id) block = course['structure']['blocks'].get(block_id)
if _block_matches_all(block): if _block_matches_all(block):
return self._load_items(course, [block_id], lazy=True, **kwargs) return self._load_items(course, [block_id], lazy=True, **kwargs)
else: else:
return [] return []
# don't expect caller to know that children are in fields # don't expect caller to know that children are in fields
if 'children' in kwargs: if 'children' in qualifiers:
settings['children'] = kwargs.pop('children') settings['children'] = qualifiers.pop('children')
for block_id, value in course['structure']['blocks'].iteritems(): for block_id, value in course['structure']['blocks'].iteritems():
if _block_matches_all(value): if _block_matches_all(value):
items.append(block_id) items.append(block_id)
......
...@@ -171,18 +171,13 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS ...@@ -171,18 +171,13 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
usage_key = self._map_revision_to_branch(usage_key, revision=revision) usage_key = self._map_revision_to_branch(usage_key, revision=revision)
return super(DraftVersioningModuleStore, self).get_item(usage_key, depth=depth, **kwargs) return super(DraftVersioningModuleStore, self).get_item(usage_key, depth=depth, **kwargs)
def get_items(self, course_locator, settings=None, content=None, revision=None, **kwargs): def get_items(self, course_locator, revision=None, **kwargs):
""" """
Returns a list of XModuleDescriptor instances for the matching items within the course with Returns a list of XModuleDescriptor instances for the matching items within the course with
the given course_locator. the given course_locator.
""" """
course_locator = self._map_revision_to_branch(course_locator, revision=revision) course_locator = self._map_revision_to_branch(course_locator, revision=revision)
return super(DraftVersioningModuleStore, self).get_items( return super(DraftVersioningModuleStore, self).get_items(course_locator, **kwargs)
course_locator,
settings=settings,
content=content,
**kwargs
)
def get_parent_location(self, location, revision=None, **kwargs): def get_parent_location(self, location, revision=None, **kwargs):
''' '''
......
...@@ -326,7 +326,7 @@ class TestMixedModuleStore(unittest.TestCase): ...@@ -326,7 +326,7 @@ class TestMixedModuleStore(unittest.TestCase):
course_locn = self.course_locations[self.XML_COURSEID1] course_locn = self.course_locations[self.XML_COURSEID1]
# NOTE: use get_course if you just want the course. get_items is expensive # NOTE: use get_course if you just want the course. get_items is expensive
modules = self.store.get_items(course_locn.course_key, category='course') modules = self.store.get_items(course_locn.course_key, qualifiers={'category': 'course'})
self.assertEqual(len(modules), 1) self.assertEqual(len(modules), 1)
self.assertEqual(modules[0].location, course_locn) self.assertEqual(modules[0].location, course_locn)
...@@ -334,7 +334,7 @@ class TestMixedModuleStore(unittest.TestCase): ...@@ -334,7 +334,7 @@ class TestMixedModuleStore(unittest.TestCase):
course_locn = self.course_locations[self.MONGO_COURSEID] course_locn = self.course_locations[self.MONGO_COURSEID]
with check_mongo_calls(mongo_store, max_find, max_send): with check_mongo_calls(mongo_store, max_find, max_send):
# NOTE: use get_course if you just want the course. get_items is expensive # NOTE: use get_course if you just want the course. get_items is expensive
modules = self.store.get_items(course_locn.course_key, category='problem') modules = self.store.get_items(course_locn.course_key, qualifiers={'category': 'problem'})
self.assertEqual(len(modules), 6) self.assertEqual(len(modules), 6)
# verify that an error is raised when the revision is not valid # verify that an error is raised when the revision is not valid
......
...@@ -151,7 +151,7 @@ class TestMigration(SplitWMongoCourseBoostrapper): ...@@ -151,7 +151,7 @@ class TestMigration(SplitWMongoCourseBoostrapper):
# grab the detached items to compare they should be in both published and draft # grab the detached items to compare they should be in both published and draft
for category in ['conditional', 'about', 'course_info', 'static_tab']: for category in ['conditional', 'about', 'course_info', 'static_tab']:
for conditional in presplit.get_items(self.old_course_key, category=category): for conditional in presplit.get_items(self.old_course_key, qualifiers={'category': category}):
locator = new_course_key.make_usage_key(category, conditional.location.block_id) locator = new_course_key.make_usage_key(category, conditional.location.block_id)
self.compare_dags(presplit, conditional, self.split_mongo.get_item(locator), published) self.compare_dags(presplit, conditional, self.split_mongo.get_item(locator), published)
......
...@@ -895,18 +895,18 @@ class SplitModuleItemTests(SplitModuleTest): ...@@ -895,18 +895,18 @@ class SplitModuleItemTests(SplitModuleTest):
self.assertEqual(len(matches), 6) self.assertEqual(len(matches), 6)
matches = modulestore().get_items(locator) matches = modulestore().get_items(locator)
self.assertEqual(len(matches), 6) self.assertEqual(len(matches), 6)
matches = modulestore().get_items(locator, category='chapter') matches = modulestore().get_items(locator, qualifiers={'category': 'chapter'})
self.assertEqual(len(matches), 3) self.assertEqual(len(matches), 3)
matches = modulestore().get_items(locator, category='garbage') matches = modulestore().get_items(locator, qualifiers={'category': 'garbage'})
self.assertEqual(len(matches), 0) self.assertEqual(len(matches), 0)
matches = modulestore().get_items( matches = modulestore().get_items(
locator, locator,
category='chapter', qualifiers={'category': 'chapter'},
settings={'display_name': re.compile(r'Hera')}, settings={'display_name': re.compile(r'Hera')},
) )
self.assertEqual(len(matches), 2) self.assertEqual(len(matches), 2)
matches = modulestore().get_items(locator, children='chapter2') matches = modulestore().get_items(locator, qualifiers={'children': 'chapter2'})
self.assertEqual(len(matches), 1) self.assertEqual(len(matches), 1)
self.assertEqual(matches[0].location.block_id, 'head12345') self.assertEqual(matches[0].location.block_id, 'head12345')
...@@ -1324,7 +1324,7 @@ class TestItemCrud(SplitModuleTest): ...@@ -1324,7 +1324,7 @@ class TestItemCrud(SplitModuleTest):
reusable_location = course.id.version_agnostic().for_branch(BRANCH_NAME_DRAFT) reusable_location = course.id.version_agnostic().for_branch(BRANCH_NAME_DRAFT)
# delete a leaf # delete a leaf
problems = modulestore().get_items(reusable_location, category='problem') problems = modulestore().get_items(reusable_location, qualifiers={'category': 'problem'})
locn_to_del = problems[0].location locn_to_del = problems[0].location
new_course_loc = modulestore().delete_item(locn_to_del, self.user_id) new_course_loc = modulestore().delete_item(locn_to_del, self.user_id)
deleted = locn_to_del.version_agnostic() deleted = locn_to_del.version_agnostic()
...@@ -1336,7 +1336,7 @@ class TestItemCrud(SplitModuleTest): ...@@ -1336,7 +1336,7 @@ class TestItemCrud(SplitModuleTest):
self.assertNotEqual(new_course_loc.version_guid, course.location.version_guid) self.assertNotEqual(new_course_loc.version_guid, course.location.version_guid)
# delete a subtree # delete a subtree
nodes = modulestore().get_items(reusable_location, category='chapter') nodes = modulestore().get_items(reusable_location, qualifiers={'category': 'chapter'})
new_course_loc = modulestore().delete_item(nodes[0].location, self.user_id) new_course_loc = modulestore().delete_item(nodes[0].location, self.user_id)
# check subtree # check subtree
......
...@@ -717,7 +717,7 @@ class XMLModuleStore(ModuleStoreReadBase): ...@@ -717,7 +717,7 @@ class XMLModuleStore(ModuleStoreReadBase):
except KeyError: except KeyError:
raise ItemNotFoundError(usage_key) raise ItemNotFoundError(usage_key)
def get_items(self, course_id, settings=None, content=None, revision=None, **kwargs): def get_items(self, course_id, settings=None, content=None, revision=None, qualifiers=None, **kwargs):
""" """
Returns: Returns:
list of XModuleDescriptor instances for the matching items within the course with list of XModuleDescriptor instances for the matching items within the course with
...@@ -729,10 +729,10 @@ class XMLModuleStore(ModuleStoreReadBase): ...@@ -729,10 +729,10 @@ class XMLModuleStore(ModuleStoreReadBase):
Args: Args:
course_id (CourseKey): the course identifier course_id (CourseKey): the course identifier
settings (dict): fields to look for which have settings scope. Follows same syntax settings (dict): fields to look for which have settings scope. Follows same syntax
and rules as kwargs below and rules as qualifiers below
content (dict): fields to look for which have content scope. Follows same syntax and content (dict): fields to look for which have content scope. Follows same syntax and
rules as kwargs below. rules as qualifiers below.
kwargs (key=value): what to look for within the course. qualifiers (dict): what to look for within the course.
Common qualifiers are ``category`` or any field name. if the target field is a list, Common qualifiers are ``category`` or any field name. if the target field is a list,
then it searches for the given value in the list not list equivalence. then it searches for the given value in the list not list equivalence.
Substring matching pass a regex object. Substring matching pass a regex object.
...@@ -747,8 +747,9 @@ class XMLModuleStore(ModuleStoreReadBase): ...@@ -747,8 +747,9 @@ class XMLModuleStore(ModuleStoreReadBase):
items = [] items = []
category = kwargs.pop('category', None) qualifiers = qualifiers.copy() if qualifiers else {} # copy the qualifiers (destructively manipulated here)
name = kwargs.pop('name', None) category = qualifiers.pop('category', None)
name = qualifiers.pop('name', None)
def _block_matches_all(mod_loc, module): def _block_matches_all(mod_loc, module):
if category and mod_loc.category != category: if category and mod_loc.category != category:
...@@ -757,7 +758,7 @@ class XMLModuleStore(ModuleStoreReadBase): ...@@ -757,7 +758,7 @@ class XMLModuleStore(ModuleStoreReadBase):
return False return False
return all( return all(
self._block_matches(module, fields or {}) self._block_matches(module, fields or {})
for fields in [settings, content, kwargs] for fields in [settings, content, qualifiers]
) )
for mod_loc, module in self.modules[course_id].iteritems(): for mod_loc, module in self.modules[course_id].iteritems():
......
...@@ -106,7 +106,7 @@ def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir): ...@@ -106,7 +106,7 @@ def export_to_xml(modulestore, contentstore, course_key, root_dir, course_dir):
# and index here since the XML modulestore cannot load draft modules # and index here since the XML modulestore cannot load draft modules
draft_verticals = modulestore.get_items( draft_verticals = modulestore.get_items(
course_key, course_key,
category='vertical', qualifiers={'category': 'vertical'},
revision=ModuleStoreEnum.RevisionOption.draft_only revision=ModuleStoreEnum.RevisionOption.draft_only
) )
if len(draft_verticals) > 0: if len(draft_verticals) > 0:
...@@ -144,7 +144,7 @@ def _export_field_content(xblock_item, item_dir): ...@@ -144,7 +144,7 @@ def _export_field_content(xblock_item, item_dir):
def export_extra_content(export_fs, modulestore, course_key, category_type, dirname, file_suffix=''): def export_extra_content(export_fs, modulestore, course_key, category_type, dirname, file_suffix=''):
items = modulestore.get_items(course_key, category=category_type) items = modulestore.get_items(course_key, qualifiers={'category': category_type})
if len(items) > 0: if len(items) > 0:
item_dir = export_fs.makeopendir(dirname) item_dir = export_fs.makeopendir(dirname)
......
...@@ -13,7 +13,7 @@ class TestDraftModuleStore(TestCase): ...@@ -13,7 +13,7 @@ class TestDraftModuleStore(TestCase):
store = modulestore() store = modulestore()
# fix was to allow get_items() to take the course_id parameter # fix was to allow get_items() to take the course_id parameter
store.get_items(SlashSeparatedCourseKey('a', 'b', 'c'), category='vertical') store.get_items(SlashSeparatedCourseKey('a', 'b', 'c'), qualifiers={'category': 'vertical'})
# test success is just getting through the above statement. # test success is just getting through the above statement.
# The bug was that 'course_id' argument was # The bug was that 'course_id' argument was
......
...@@ -163,7 +163,7 @@ class TestDraftModuleStore(ModuleStoreTestCase): ...@@ -163,7 +163,7 @@ class TestDraftModuleStore(ModuleStoreTestCase):
store = modulestore() store = modulestore()
# fix was to allow get_items() to take the course_id parameter # fix was to allow get_items() to take the course_id parameter
store.get_items(SlashSeparatedCourseKey('abc', 'def', 'ghi'), category='vertical') store.get_items(SlashSeparatedCourseKey('abc', 'def', 'ghi'), qualifiers={'category': 'vertical'})
# test success is just getting through the above statement. # test success is just getting through the above statement.
# The bug was that 'course_id' argument was # The bug was that 'course_id' argument was
......
...@@ -463,7 +463,7 @@ def jump_to_id(request, course_id, module_id): ...@@ -463,7 +463,7 @@ def jump_to_id(request, course_id, module_id):
passed in. This assumes that id is unique within the course_id namespace passed in. This assumes that id is unique within the course_id namespace
""" """
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
items = modulestore().get_items(course_key, name=module_id) items = modulestore().get_items(course_key, qualifiers={'name': module_id})
if len(items) == 0: if len(items) == 0:
raise Http404( raise Http404(
...@@ -937,7 +937,7 @@ def get_course_lti_endpoints(request, course_id): ...@@ -937,7 +937,7 @@ def get_course_lti_endpoints(request, course_id):
anonymous_user = AnonymousUser() anonymous_user = AnonymousUser()
anonymous_user.known = False # make these "noauth" requests like module_render.handle_xblock_callback_noauth anonymous_user.known = False # make these "noauth" requests like module_render.handle_xblock_callback_noauth
lti_descriptors = modulestore().get_items(course.id, category='lti') lti_descriptors = modulestore().get_items(course.id, qualifiers={'category': 'lti'})
lti_noauth_modules = [ lti_noauth_modules = [
get_module_for_descriptor( get_module_for_descriptor(
......
...@@ -57,7 +57,7 @@ def has_forum_access(uname, course_id, rolename): ...@@ -57,7 +57,7 @@ def has_forum_access(uname, course_id, rolename):
def _get_discussion_modules(course): def _get_discussion_modules(course):
all_modules = modulestore().get_items(course.id, category='discussion') all_modules = modulestore().get_items(course.id, qualifiers={'category': 'discussion'})
def has_required_keys(module): def has_required_keys(module):
for key in ('discussion_id', 'discussion_category', 'discussion_target'): for key in ('discussion_id', 'discussion_category', 'discussion_target'):
......
...@@ -92,7 +92,7 @@ def find_peer_grading_module(course): ...@@ -92,7 +92,7 @@ def find_peer_grading_module(course):
problem_url = "" problem_url = ""
# Get the peer grading modules currently in the course. Explicitly specify the course id to avoid issues with different runs. # Get the peer grading modules currently in the course. Explicitly specify the course id to avoid issues with different runs.
items = modulestore().get_items(course.id, category='peergrading') items = modulestore().get_items(course.id, qualifiers={'category': 'peergrading'})
# See if any of the modules are centralized modules (ie display info from multiple problems) # See if any of the modules are centralized modules (ie display info from multiple problems)
items = [i for i in items if not getattr(i, "use_for_single_location", True)] items = [i for i in items if not getattr(i, "use_for_single_location", True)]
# Loop through all potential peer grading modules, and find the first one that has a path to it. # Loop through all potential peer grading modules, and find the first one that has a path to it.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment