compute_publish_state -> has_published_version

LMS-11213
This commit is contained in:
Don Mitchell
2014-08-26 15:45:08 -04:00
parent 12e2d442e9
commit ee8fc41b62
10 changed files with 61 additions and 159 deletions

View File

@@ -90,16 +90,6 @@ class ModuleStoreEnum(object):
test = -3
class PublishState(object):
"""
The legacy publish state for a given xblock-- either 'draft', 'private', or 'public'. These states
are no longer used in Studio, but they are still referenced in a few places in LMS.
"""
draft = 'draft'
private = 'private'
public = 'public'
class ModuleStoreRead(object):
"""
An abstract interface for a database backend that stores XModuleDescriptor
@@ -307,15 +297,9 @@ class ModuleStoreRead(object):
pass
@abstractmethod
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
"""
Returns whether this xblock is draft, public, or private.
Returns:
PublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
PublishState.public - content is locked and deployed to LMS
PublishState.private - content is editable and not deployed to LMS
Returns true if this xblock exists in the published course regardless of whether it's up to date
"""
pass
@@ -529,11 +513,11 @@ class ModuleStoreReadBase(ModuleStoreRead):
None
)
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
"""
Returns PublishState.public since this is a read-only store.
Returns True since this is a read-only store.
"""
return PublishState.public
return True
def heartbeat(self):
"""

View File

@@ -96,7 +96,7 @@ class ModuleStoreDraftAndPublished(BranchSettingMixin):
raise NotImplementedError
@abstractmethod
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
raise NotImplementedError
@abstractmethod

View File

@@ -540,7 +540,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
)
)
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
"""
Returns whether this xblock is draft, public, or private.
@@ -552,7 +552,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
"""
course_id = xblock.scope_ids.usage_id.course_key
store = self._get_modulestore_for_courseid(course_id)
return store.compute_publish_state(xblock)
return store.has_published_version(xblock)
@strip_key
def publish(self, location, user_id, **kwargs):

View File

@@ -11,7 +11,7 @@ import logging
from opaque_keys.edx.locations import Location
from xmodule.exceptions import InvalidVersionError
from xmodule.modulestore import PublishState, ModuleStoreEnum
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateItemError, DuplicateCourseError
from xmodule.modulestore.mongo.base import (
MongoModuleStore, MongoRevisionKey, as_draft, as_published,
@@ -591,13 +591,13 @@ class DraftModuleStore(MongoModuleStore):
def has_changes(self, xblock):
"""
Check if the xblock or its children have been changed since the last publish.
Check if the subtree rooted at xblock has any drafts and thus may possibly have changes
:param xblock: xblock to check
:return: True if the draft and published versions differ
:return: True if there are any drafts anywhere in the subtree under xblock (a weaker
condition than for other stores)
"""
# don't check children if this block has changes (is not public)
if self.compute_publish_state(xblock) != PublishState.public:
if getattr(xblock, 'is_draft', False):
return True
# if this block doesn't have changes, then check its children
elif xblock.has_children:
@@ -771,25 +771,18 @@ class DraftModuleStore(MongoModuleStore):
return queried_children
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
"""
Returns whether this xblock is draft, public, or private.
Returns:
PublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
PublishState.public - content is locked and deployed to LMS
PublishState.private - content is editable and not deployed to LMS
Returns True if this xblock has an existing published version regardless of whether the
published version is up to date.
"""
if getattr(xblock, 'is_draft', False):
published_xblock_location = as_published(xblock.location)
try:
xblock.runtime.lookup_item(published_xblock_location)
except ItemNotFoundError:
return PublishState.private
return PublishState.draft
else:
return PublishState.public
return False
return True
def _verify_branch_setting(self, expected_branch_setting):
"""

View File

@@ -3,7 +3,7 @@ Module for the dual-branch fall-back Draft->Published Versioning ModuleStore
"""
from split import SplitMongoModuleStore, EXCLUDE_ALL
from xmodule.modulestore import ModuleStoreEnum, PublishState
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.exceptions import InsufficientSpecificationError
from xmodule.modulestore.draft_and_published import (
ModuleStoreDraftAndPublished, DIRECT_ONLY_CATEGORIES, UnsupportedRevisionError
@@ -302,27 +302,11 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
block_locator = self._map_revision_to_branch(block_locator)
return super(DraftVersioningModuleStore, self).get_block_generations(block_locator)
def compute_publish_state(self, xblock):
def has_published_version(self, xblock):
"""
Returns whether this xblock is draft, public, or private.
Returns:
PublishState.draft - published exists and is different from draft
PublishState.public - published exists and is the same as draft
PublishState.private - no published version exists
Returns whether this xblock has a published version (whether it's up to date or not).
"""
draft_head = self._get_head(xblock, ModuleStoreEnum.BranchName.draft)
published_head = self._get_head(xblock, ModuleStoreEnum.BranchName.published)
if not published_head:
# published version does not exist
return PublishState.private
elif self._get_version(draft_head) == self._get_version(published_head):
# published and draft versions are equal
return PublishState.public
else:
# published and draft versions differ
return PublishState.draft
return self._get_head(xblock, ModuleStoreEnum.BranchName.published) is not None
def convert_to_draft(self, location, user_id):
"""

View File

@@ -9,7 +9,7 @@ import datetime
from pytz import UTC
from xmodule.tests import DATA_DIR
from xmodule.modulestore import ModuleStoreEnum, PublishState
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.exceptions import InvalidVersionError
@@ -988,11 +988,11 @@ class TestMixedModuleStore(unittest.TestCase):
)
self.assertIsNotNone(draft_xblock)
@ddt.data(('draft', 1, 0), ('split', 4, 0))
@ddt.data(('draft', 1, 0), ('split', 2, 0))
@ddt.unpack
def test_compute_publish_state(self, default_ms, max_find, max_send):
def test_has_published_version(self, default_ms, max_find, max_send):
"""
Test the compute_publish_state method
Test the has_published_version method
"""
self.initdb(default_ms)
self._create_block_hierarchy()
@@ -1002,37 +1002,33 @@ class TestMixedModuleStore(unittest.TestCase):
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)
self.assertFalse(self.store.has_published_version(item))
# Private -> Public
self.store.publish(item_location, self.user_id)
item = self.store.get_item(item_location)
self.assertEquals(self.store.compute_publish_state(item), PublishState.public)
self.assertTrue(self.store.has_published_version(item))
# Public -> Private
self.store.unpublish(item_location, self.user_id)
item = self.store.get_item(item_location)
self.assertEquals(self.store.compute_publish_state(item), PublishState.private)
self.assertFalse(self.store.has_published_version(item))
# Private -> Public
self.store.publish(item_location, self.user_id)
item = self.store.get_item(item_location)
self.assertEquals(self.store.compute_publish_state(item), PublishState.public)
self.assertTrue(self.store.has_published_version(item))
# Public -> Draft with NO changes
# Note: This is where Split and Mongo differ
self.store.convert_to_draft(item_location, self.user_id)
item = self.store.get_item(item_location)
self.assertEquals(
self.store.compute_publish_state(item),
PublishState.draft if default_ms == 'draft' else PublishState.public
)
self.assertTrue(self.store.has_published_version(item))
# Draft WITH changes
item.display_name = 'new name'
item = self.store.update_item(item, self.user_id)
self.assertTrue(self.store.has_changes(item))
self.assertEquals(self.store.compute_publish_state(item), PublishState.draft)
self.assertTrue(self.store.has_published_version(item))
@ddt.data('draft', 'split')
def test_auto_publish(self, default_ms):
@@ -1047,47 +1043,47 @@ class TestMixedModuleStore(unittest.TestCase):
# test create_course to make sure we are autopublishing
test_course = self.store.create_course('testx', 'GreekHero', 'test_run', self.user_id)
self.assertEqual(self.store.compute_publish_state(test_course), PublishState.public)
self.assertTrue(self.store.has_published_version(test_course))
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)
self.assertTrue(self.store.has_published_version(chapter))
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')
self.assertEqual(self.store.compute_publish_state(sequential), PublishState.public)
self.assertTrue(self.store.has_published_version(sequential))
# test update_item of direct-only category to make sure we are autopublishing
sequential.display_name = 'sequential1'
sequential = self.store.update_item(sequential, self.user_id)
self.assertEqual(self.store.compute_publish_state(sequential), PublishState.public)
self.assertTrue(self.store.has_published_version(sequential))
# test delete_item of direct-only category to make sure we are autopublishing
self.store.delete_item(sequential.location, self.user_id, revision=ModuleStoreEnum.RevisionOption.all)
chapter = self.store.get_item(chapter.location.for_branch(None))
self.assertEqual(self.store.compute_publish_state(chapter), PublishState.public)
self.assertTrue(self.store.has_published_version(chapter))
# test create_child of NOT direct-only category to make sure we aren't autopublishing
problem_child = self.store.create_child(self.user_id, chapter_location, 'problem', 'Problem_Child')
self.assertEqual(self.store.compute_publish_state(problem_child), PublishState.private)
self.assertFalse(self.store.has_published_version(problem_child))
# test create_item of NOT direct-only category to make sure we aren't autopublishing
problem_item = self.store.create_item(self.user_id, test_course_key, 'problem', 'Problem_Item')
self.assertEqual(self.store.compute_publish_state(problem_item), PublishState.private)
self.assertFalse(self.store.has_published_version(problem_item))
# test update_item of NOT direct-only category to make sure we aren't autopublishing
problem_item.display_name = 'Problem_Item1'
problem_item = self.store.update_item(problem_item, self.user_id)
self.assertEqual(self.store.compute_publish_state(problem_item), PublishState.private)
self.assertFalse(self.store.has_published_version(problem_item))
# test delete_item of NOT direct-only category to make sure we aren't autopublishing
self.store.delete_item(problem_child.location, self.user_id)
chapter = self.store.get_item(chapter.location.for_branch(None))
self.assertEqual(self.store.compute_publish_state(chapter), PublishState.public)
self.assertTrue(self.store.has_published_version(chapter))
@ddt.data('draft', 'split')
def test_get_courses_for_wiki_shared(self, default_ms):

View File

@@ -23,7 +23,7 @@ from xmodule.modulestore.inheritance import InheritanceMixin, own_metadata
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.mako_module import MakoDescriptorSystem
from xmodule.error_module import ErrorDescriptor
from xmodule.modulestore import PublishState, ModuleStoreEnum
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.mongo.draft import DraftModuleStore
from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES