Commit f3070e67 by Ben McMorran Committed by cahrens

Reduce mongo calls on course outline and container pages

parent 4b6035ba
...@@ -11,7 +11,7 @@ from django.conf import settings ...@@ -11,7 +11,7 @@ from django.conf import settings
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
from edxmako.shortcuts import render_to_response from edxmako.shortcuts import render_to_response
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import PublishState
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xblock.core import XBlock from xblock.core import XBlock
...@@ -97,7 +97,7 @@ def subsection_handler(request, usage_key_string): ...@@ -97,7 +97,7 @@ def subsection_handler(request, usage_key_string):
can_view_live = False can_view_live = False
subsection_units = item.get_children() subsection_units = item.get_children()
for unit in subsection_units: for unit in subsection_units:
has_published = modulestore().has_item(unit.location, revision=ModuleStoreEnum.RevisionOption.published_only) has_published = modulestore().compute_publish_state(unit) != PublishState.private
if has_published: if has_published:
can_view_live = True can_view_live = True
break break
......
...@@ -211,7 +211,8 @@ def course_handler(request, course_key_string=None): ...@@ -211,7 +211,8 @@ def course_handler(request, course_key_string=None):
response_format = request.REQUEST.get('format', 'html') response_format = request.REQUEST.get('format', 'html')
if response_format == 'json' or 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'): if response_format == 'json' or 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'):
if request.method == 'GET': if request.method == 'GET':
return JsonResponse(_course_outline_json(request, CourseKey.from_string(course_key_string))) course_module = _get_course_module(CourseKey.from_string(course_key_string), request.user, depth=None)
return JsonResponse(_course_outline_json(request, course_module))
elif request.method == 'POST': # not sure if this is only post. If one will have ids, it goes after access elif request.method == 'POST': # not sure if this is only post. If one will have ids, it goes after access
return _create_or_rerun_course(request) return _create_or_rerun_course(request)
elif not has_course_access(request.user, CourseKey.from_string(course_key_string)): elif not has_course_access(request.user, CourseKey.from_string(course_key_string)):
...@@ -231,11 +232,10 @@ def course_handler(request, course_key_string=None): ...@@ -231,11 +232,10 @@ def course_handler(request, course_key_string=None):
return HttpResponseNotFound() return HttpResponseNotFound()
def _course_outline_json(request, course_key): def _course_outline_json(request, course_module):
""" """
Returns a JSON representation of the course module and recursively all of its children. Returns a JSON representation of the course module and recursively all of its children.
""" """
course_module = _get_course_module(course_key, request.user, depth=None)
return create_xblock_info( return create_xblock_info(
course_module, course_module,
include_child_info=True, include_child_info=True,
...@@ -369,10 +369,12 @@ def course_index(request, course_key): ...@@ -369,10 +369,12 @@ def course_index(request, course_key):
org, course, name: Attributes of the Location for the item to edit org, course, name: Attributes of the Location for the item to edit
""" """
course_module = _get_course_module(course_key, request.user, depth=3) # A depth of None implies the whole course. The course outline needs this in order to compute has_changes.
# A unit may not have a draft version, but one of its components could, and hence the unit itself has changes.
course_module = _get_course_module(course_key, request.user, depth=None)
lms_link = get_lms_link_for_item(course_module.location) lms_link = get_lms_link_for_item(course_module.location)
sections = course_module.get_children() sections = course_module.get_children()
course_structure = _course_outline_json(request, course_key) course_structure = _course_outline_json(request, course_module)
locator_to_show = request.REQUEST.get('show', None) locator_to_show = request.REQUEST.get('show', None)
try: try:
......
...@@ -24,7 +24,7 @@ from xblock.fragment import Fragment ...@@ -24,7 +24,7 @@ from xblock.fragment import Fragment
import xmodule import xmodule
from xmodule.tabs import StaticTab, CourseTabList from xmodule.tabs import StaticTab, CourseTabList
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum, PublishState
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError
from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.inheritance import own_metadata
...@@ -380,7 +380,7 @@ def _save_xblock(user, xblock, data=None, children=None, metadata=None, nullout= ...@@ -380,7 +380,7 @@ def _save_xblock(user, xblock, data=None, children=None, metadata=None, nullout=
# new item should be republished. This is used by staff locking to ensure that changing the draft # new item should be republished. This is used by staff locking to ensure that changing the draft
# value of the staff lock will also update the published version. # value of the staff lock will also update the published version.
if publish == 'republish': if publish == 'republish':
published = modulestore().has_item(xblock.location, revision=ModuleStoreEnum.RevisionOption.published_only) published = modulestore().compute_publish_state(xblock) != PublishState.private
if published: if published:
publish = 'make_public' publish = 'make_public'
...@@ -624,7 +624,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F ...@@ -624,7 +624,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
return None return None
is_xblock_unit = is_unit(xblock, parent_xblock) is_xblock_unit = is_unit(xblock, parent_xblock)
is_unit_with_changes = is_xblock_unit and modulestore().has_changes(xblock.location) is_unit_with_changes = is_xblock_unit and modulestore().has_changes(xblock)
if graders is None: if graders is None:
graders = CourseGradingModel.fetch(xblock.location.course_key).graders graders = CourseGradingModel.fetch(xblock.location.course_key).graders
...@@ -643,7 +643,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F ...@@ -643,7 +643,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
# Treat DEFAULT_START_DATE as a magic number that means the release date has not been set # Treat DEFAULT_START_DATE as a magic number that means the release date has not been set
release_date = get_default_time_display(xblock.start) if xblock.start != DEFAULT_START_DATE else None release_date = get_default_time_display(xblock.start) if xblock.start != DEFAULT_START_DATE else None
published = modulestore().has_item(xblock.location, revision=ModuleStoreEnum.RevisionOption.published_only) published = modulestore().compute_publish_state(xblock) != PublishState.private
xblock_info = { xblock_info = {
"id": unicode(xblock.location), "id": unicode(xblock.location),
......
...@@ -541,14 +541,14 @@ class TestEditItem(ItemTest): ...@@ -541,14 +541,14 @@ class TestEditItem(ItemTest):
Verifies the item with given location has a published version and no draft (unpublished changes). Verifies the item with given location has a published version and no draft (unpublished changes).
""" """
self.assertTrue(self._is_location_published(location)) self.assertTrue(self._is_location_published(location))
self.assertFalse(modulestore().has_changes(location)) self.assertFalse(modulestore().has_changes(modulestore().get_item(location)))
def _verify_published_with_draft(self, location): def _verify_published_with_draft(self, location):
""" """
Verifies the item with given location has a published version and also a draft version (unpublished changes). Verifies the item with given location has a published version and also a draft version (unpublished changes).
""" """
self.assertTrue(self._is_location_published(location)) self.assertTrue(self._is_location_published(location))
self.assertTrue(modulestore().has_changes(location)) self.assertTrue(modulestore().has_changes(modulestore().get_item(location)))
def test_make_public(self): def test_make_public(self):
""" Test making a private problem public (publishing it). """ """ Test making a private problem public (publishing it). """
......
...@@ -80,7 +80,7 @@ class ModuleStoreDraftAndPublished(BranchSettingMixin): ...@@ -80,7 +80,7 @@ class ModuleStoreDraftAndPublished(BranchSettingMixin):
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def has_changes(self, usage_key): def has_changes(self, xblock):
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
......
...@@ -474,14 +474,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): ...@@ -474,14 +474,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
store = self._verify_modulestore_support(location.course_key, 'convert_to_draft') store = self._verify_modulestore_support(location.course_key, 'convert_to_draft')
return store.convert_to_draft(location, user_id) return store.convert_to_draft(location, user_id)
def has_changes(self, usage_key): def has_changes(self, xblock):
""" """
Checks if the given block has unpublished changes Checks if the given block has unpublished changes
:param usage_key: the block to check :param xblock: the block to check
:return: True if the draft and published versions differ :return: True if the draft and published versions differ
""" """
store = self._verify_modulestore_support(usage_key.course_key, 'has_changes') store = self._verify_modulestore_support(xblock.location.course_key, 'has_changes')
return store.has_changes(usage_key) return store.has_changes(xblock)
def _verify_modulestore_support(self, course_key, method): def _verify_modulestore_support(self, course_key, method):
""" """
......
...@@ -297,6 +297,19 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -297,6 +297,19 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
value[key] = self._convert_reference_to_key(subvalue) value[key] = self._convert_reference_to_key(subvalue)
return jsonfields return jsonfields
def lookup_item(self, location):
"""
Returns the JSON payload of the xblock at location.
"""
try:
json = self.module_data[location]
except KeyError:
json = self.modulestore._find_one(location)
self.module_data[location] = json
return json
# The only thing using this w/ wildcards is contentstore.mongo for asset retrieval # The only thing using this w/ wildcards is contentstore.mongo for asset retrieval
def location_to_query(location, wildcard=True, tag='i4x'): def location_to_query(location, wildcard=True, tag='i4x'):
......
...@@ -599,25 +599,19 @@ class DraftModuleStore(MongoModuleStore): ...@@ -599,25 +599,19 @@ class DraftModuleStore(MongoModuleStore):
_internal([root_usage.to_deprecated_son() for root_usage in root_usages]) _internal([root_usage.to_deprecated_son() for root_usage in root_usages])
self.collection.remove({'_id': {'$in': to_be_deleted}}, safe=self.collection.safe) self.collection.remove({'_id': {'$in': to_be_deleted}}, safe=self.collection.safe)
def has_changes(self, location): def has_changes(self, xblock):
""" """
Check if the xblock or its children have been changed since the last publish. Check if the xblock or its children have been changed since the last publish.
:param location: location to check :param xblock: xblock to check
:return: True if the draft and published versions differ :return: True if the draft and published versions differ
""" """
try:
item = self.get_item(location)
# defensively check that the parent's child actually exists
except ItemNotFoundError:
return False
# don't check children if this block has changes (is not public) # don't check children if this block has changes (is not public)
if self.compute_publish_state(item) != PublishState.public: if self.compute_publish_state(xblock) != PublishState.public:
return True return True
# if this block doesn't have changes, then check its children # if this block doesn't have changes, then check its children
elif item.has_children: elif xblock.has_children:
return any([self.has_changes(child) for child in item.children]) return any([self.has_changes(child) for child in xblock.get_children()])
# otherwise there are no changes # otherwise there are no changes
else: else:
return False return False
...@@ -799,13 +793,11 @@ class DraftModuleStore(MongoModuleStore): ...@@ -799,13 +793,11 @@ class DraftModuleStore(MongoModuleStore):
""" """
if getattr(xblock, 'is_draft', False): if getattr(xblock, 'is_draft', False):
published_xblock_location = as_published(xblock.location) published_xblock_location = as_published(xblock.location)
published_item = self.collection.find_one( try:
{'_id': published_xblock_location.to_deprecated_son()} xblock.runtime.lookup_item(published_xblock_location)
) except ItemNotFoundError:
if published_item is None:
return PublishState.private return PublishState.private
else: return PublishState.draft
return PublishState.draft
else: else:
return PublishState.public return PublishState.public
......
...@@ -194,16 +194,16 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS ...@@ -194,16 +194,16 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
location = self._map_revision_to_branch(location, revision=revision) location = self._map_revision_to_branch(location, revision=revision)
return SplitMongoModuleStore.get_parent_location(self, location, **kwargs) return SplitMongoModuleStore.get_parent_location(self, location, **kwargs)
def has_changes(self, usage_key): def has_changes(self, xblock):
""" """
Checks if the given block has unpublished changes Checks if the given block has unpublished changes
:param usage_key: the block to check :param xblock: the block to check
:return: True if the draft and published versions differ :return: True if the draft and published versions differ
""" """
# TODO for better performance: lookup the courses and get the block entry, don't create the instances # TODO for better performance: lookup the courses and get the block entry, don't create the instances
draft = self.get_item(usage_key.for_branch(ModuleStoreEnum.BranchName.draft)) draft = self.get_item(xblock.location.for_branch(ModuleStoreEnum.BranchName.draft))
try: try:
published = self.get_item(usage_key.for_branch(ModuleStoreEnum.BranchName.published)) published = self.get_item(xblock.location.for_branch(ModuleStoreEnum.BranchName.published))
except ItemNotFoundError: except ItemNotFoundError:
return True return True
......
...@@ -374,8 +374,8 @@ class TestMixedModuleStore(unittest.TestCase): ...@@ -374,8 +374,8 @@ class TestMixedModuleStore(unittest.TestCase):
) )
# Check that neither xblock has changes # Check that neither xblock has changes
self.assertFalse(self.store.has_changes(test_course.location)) self.assertFalse(self.store.has_changes(test_course))
self.assertFalse(self.store.has_changes(chapter.location)) self.assertFalse(self.store.has_changes(chapter))
@ddt.data('draft', 'split') @ddt.data('draft', 'split')
def test_has_changes(self, default_ms): def test_has_changes(self, default_ms):
...@@ -395,22 +395,22 @@ class TestMixedModuleStore(unittest.TestCase): ...@@ -395,22 +395,22 @@ class TestMixedModuleStore(unittest.TestCase):
) )
# Not yet published, so changes are present # Not yet published, so changes are present
self.assertTrue(self.store.has_changes(xblock.location)) self.assertTrue(self.store.has_changes(xblock))
# Publish and verify that there are no unpublished changes # Publish and verify that there are no unpublished changes
self.store.publish(xblock.location, self.user_id) newXBlock = self.store.publish(xblock.location, self.user_id)
self.assertFalse(self.store.has_changes(xblock.location)) self.assertFalse(self.store.has_changes(newXBlock))
# Change the component, then check that there now are changes # Change the component, then check that there now are changes
component = self.store.get_item(xblock.location) component = self.store.get_item(xblock.location)
component.display_name = 'Changed Display Name' component.display_name = 'Changed Display Name'
component = self.store.update_item(component, self.user_id) component = self.store.update_item(component, self.user_id)
self.assertTrue(self.store.has_changes(component.location)) self.assertTrue(self.store.has_changes(component))
# Publish and verify again # Publish and verify again
self.store.publish(component.location, self.user_id) component = self.store.publish(component.location, self.user_id)
self.assertFalse(self.store.has_changes(component.location)) self.assertFalse(self.store.has_changes(component))
@ddt.data(('draft', 7, 2), ('split', 13, 4)) @ddt.data(('draft', 7, 2), ('split', 13, 4))
@ddt.unpack @ddt.unpack
...@@ -994,7 +994,7 @@ class TestMixedModuleStore(unittest.TestCase): ...@@ -994,7 +994,7 @@ class TestMixedModuleStore(unittest.TestCase):
# Draft WITH changes # Draft WITH changes
item.display_name = 'new name' item.display_name = 'new name'
item = self.store.update_item(item, self.user_id) item = self.store.update_item(item, self.user_id)
self.assertTrue(self.store.has_changes(item.location)) self.assertTrue(self.store.has_changes(item))
self.assertEquals(self.store.compute_publish_state(item), PublishState.draft) self.assertEquals(self.store.compute_publish_state(item), PublishState.draft)
@ddt.data('draft', 'split') @ddt.data('draft', 'split')
......
...@@ -515,10 +515,10 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -515,10 +515,10 @@ class TestMongoModuleStore(unittest.TestCase):
block_id=location.block_id block_id=location.block_id
) )
parent.children += [Location('edX', 'toy', '2012_Fall', 'vertical', 'does_not_exist')] parent.children += [Location('edX', 'toy', '2012_Fall', 'vertical', 'does_not_exist')]
self.draft_store.update_item(parent, self.dummy_user) parent = self.draft_store.update_item(parent, self.dummy_user)
# Check the parent for changes should return False and not throw an exception # Check the parent for changes should return False and not throw an exception
self.assertFalse(self.draft_store.has_changes(location)) self.assertFalse(self.draft_store.has_changes(parent))
def _create_test_tree(self, name, user_id=None): def _create_test_tree(self, name, user_id=None):
""" """
...@@ -569,6 +569,11 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -569,6 +569,11 @@ class TestMongoModuleStore(unittest.TestCase):
return locations return locations
def _has_changes(self, location):
""" Helper that returns True if location has changes, False otherwise """
store = self.draft_store
return store.has_changes(store.get_item(location))
def test_has_changes_ancestors(self): def test_has_changes_ancestors(self):
""" """
Tests that has_changes() returns true on ancestors when a child is changed Tests that has_changes() returns true on ancestors when a child is changed
...@@ -577,7 +582,7 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -577,7 +582,7 @@ class TestMongoModuleStore(unittest.TestCase):
# Verify that there are no unpublished changes # Verify that there are no unpublished changes
for key in locations: for key in locations:
self.assertFalse(self.draft_store.has_changes(locations[key])) self.assertFalse(self._has_changes(locations[key]))
# Change the child # Change the child
child = self.draft_store.get_item(locations['child']) child = self.draft_store.get_item(locations['child'])
...@@ -585,18 +590,18 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -585,18 +590,18 @@ class TestMongoModuleStore(unittest.TestCase):
self.draft_store.update_item(child, user_id=self.dummy_user) self.draft_store.update_item(child, user_id=self.dummy_user)
# All ancestors should have changes, but not siblings # All ancestors should have changes, but not siblings
self.assertTrue(self.draft_store.has_changes(locations['grandparent'])) self.assertTrue(self._has_changes(locations['grandparent']))
self.assertTrue(self.draft_store.has_changes(locations['parent'])) self.assertTrue(self._has_changes(locations['parent']))
self.assertTrue(self.draft_store.has_changes(locations['child'])) self.assertTrue(self._has_changes(locations['child']))
self.assertFalse(self.draft_store.has_changes(locations['parent_sibling'])) self.assertFalse(self._has_changes(locations['parent_sibling']))
self.assertFalse(self.draft_store.has_changes(locations['child_sibling'])) self.assertFalse(self._has_changes(locations['child_sibling']))
# Publish the unit with changes # Publish the unit with changes
self.draft_store.publish(locations['parent'], self.dummy_user) self.draft_store.publish(locations['parent'], self.dummy_user)
# Verify that there are no unpublished changes # Verify that there are no unpublished changes
for key in locations: for key in locations:
self.assertFalse(self.draft_store.has_changes(locations[key])) self.assertFalse(self._has_changes(locations[key]))
def test_has_changes_publish_ancestors(self): def test_has_changes_publish_ancestors(self):
""" """
...@@ -606,7 +611,7 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -606,7 +611,7 @@ class TestMongoModuleStore(unittest.TestCase):
# Verify that there are no unpublished changes # Verify that there are no unpublished changes
for key in locations: for key in locations:
self.assertFalse(self.draft_store.has_changes(locations[key])) self.assertFalse(self._has_changes(locations[key]))
# Change both children # Change both children
child = self.draft_store.get_item(locations['child']) child = self.draft_store.get_item(locations['child'])
...@@ -617,22 +622,22 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -617,22 +622,22 @@ class TestMongoModuleStore(unittest.TestCase):
self.draft_store.update_item(child_sibling, user_id=self.dummy_user) self.draft_store.update_item(child_sibling, user_id=self.dummy_user)
# Verify that ancestors have changes # Verify that ancestors have changes
self.assertTrue(self.draft_store.has_changes(locations['grandparent'])) self.assertTrue(self._has_changes(locations['grandparent']))
self.assertTrue(self.draft_store.has_changes(locations['parent'])) self.assertTrue(self._has_changes(locations['parent']))
# Publish one child # Publish one child
self.draft_store.publish(locations['child_sibling'], self.dummy_user) self.draft_store.publish(locations['child_sibling'], self.dummy_user)
# Verify that ancestors still have changes # Verify that ancestors still have changes
self.assertTrue(self.draft_store.has_changes(locations['grandparent'])) self.assertTrue(self._has_changes(locations['grandparent']))
self.assertTrue(self.draft_store.has_changes(locations['parent'])) self.assertTrue(self._has_changes(locations['parent']))
# Publish the other child # Publish the other child
self.draft_store.publish(locations['child'], self.dummy_user) self.draft_store.publish(locations['child'], self.dummy_user)
# Verify that ancestors now have no changes # Verify that ancestors now have no changes
self.assertFalse(self.draft_store.has_changes(locations['grandparent'])) self.assertFalse(self._has_changes(locations['grandparent']))
self.assertFalse(self.draft_store.has_changes(locations['parent'])) self.assertFalse(self._has_changes(locations['parent']))
def test_has_changes_add_remove_child(self): def test_has_changes_add_remove_child(self):
""" """
...@@ -642,8 +647,8 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -642,8 +647,8 @@ class TestMongoModuleStore(unittest.TestCase):
locations = self._create_test_tree('has_changes_add_remove_child') locations = self._create_test_tree('has_changes_add_remove_child')
# Test that the ancestors don't have changes # Test that the ancestors don't have changes
self.assertFalse(self.draft_store.has_changes(locations['grandparent'])) self.assertFalse(self._has_changes(locations['grandparent']))
self.assertFalse(self.draft_store.has_changes(locations['parent'])) self.assertFalse(self._has_changes(locations['parent']))
# Create a new child and attach it to parent # Create a new child and attach it to parent
new_child_location = Location('edX', 'tree', 'has_changes_add_remove_child', 'vertical', 'new_child') new_child_location = Location('edX', 'tree', 'has_changes_add_remove_child', 'vertical', 'new_child')
...@@ -655,8 +660,8 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -655,8 +660,8 @@ class TestMongoModuleStore(unittest.TestCase):
) )
# Verify that the ancestors now have changes # Verify that the ancestors now have changes
self.assertTrue(self.draft_store.has_changes(locations['grandparent'])) self.assertTrue(self._has_changes(locations['grandparent']))
self.assertTrue(self.draft_store.has_changes(locations['parent'])) self.assertTrue(self._has_changes(locations['parent']))
# Remove the child from the parent # Remove the child from the parent
parent = self.draft_store.get_item(locations['parent']) parent = self.draft_store.get_item(locations['parent'])
...@@ -664,8 +669,8 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -664,8 +669,8 @@ class TestMongoModuleStore(unittest.TestCase):
self.draft_store.update_item(parent, user_id=self.dummy_user) self.draft_store.update_item(parent, user_id=self.dummy_user)
# Verify that ancestors now have no changes # Verify that ancestors now have no changes
self.assertFalse(self.draft_store.has_changes(locations['grandparent'])) self.assertFalse(self._has_changes(locations['grandparent']))
self.assertFalse(self.draft_store.has_changes(locations['parent'])) self.assertFalse(self._has_changes(locations['parent']))
def test_has_changes_non_direct_only_children(self): def test_has_changes_non_direct_only_children(self):
""" """
...@@ -689,16 +694,16 @@ class TestMongoModuleStore(unittest.TestCase): ...@@ -689,16 +694,16 @@ class TestMongoModuleStore(unittest.TestCase):
self.draft_store.publish(parent_location, self.dummy_user) self.draft_store.publish(parent_location, self.dummy_user)
# Verify that there are no changes # Verify that there are no changes
self.assertFalse(self.draft_store.has_changes(parent_location)) self.assertFalse(self._has_changes(parent_location))
self.assertFalse(self.draft_store.has_changes(child_location)) self.assertFalse(self._has_changes(child_location))
# Change the child # Change the child
child.display_name = 'Changed Display Name' child.display_name = 'Changed Display Name'
self.draft_store.update_item(child, user_id=self.dummy_user) self.draft_store.update_item(child, user_id=self.dummy_user)
# Verify that both parent and child have changes # Verify that both parent and child have changes
self.assertTrue(self.draft_store.has_changes(parent_location)) self.assertTrue(self._has_changes(parent_location))
self.assertTrue(self.draft_store.has_changes(child_location)) self.assertTrue(self._has_changes(child_location))
def test_update_edit_info_ancestors(self): def test_update_edit_info_ancestors(self):
""" """
......
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