jenkins-bot has submitted this change and it was merged.
Change subject: Lock and unlock Flow topics ......................................................................
Lock and unlock Flow topics
This patch allows bots to lock and unlock Flow topics using the API. It also includes a property for Topic objects showing whether that topic is locked or not. Post.reply() now raises a LockedPage exception if the topic is locked. Two tests have been included, one to test locking and unlocking and the other to test error handling in Post.reply().
Bug: T108288 Change-Id: I4afb6c0fff6bf541a1a05aa2a5f9b0715e67541e --- M pywikibot/flow.py M pywikibot/site.py M tests/flow_edit_tests.py 3 files changed, 100 insertions(+), 3 deletions(-)
Approvals: Merlijn van Deen: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/flow.py b/pywikibot/flow.py index 1580edb..1c7f117 100644 --- a/pywikibot/flow.py +++ b/pywikibot/flow.py @@ -11,7 +11,7 @@
import logging
-from pywikibot.exceptions import NoPage, UnknownExtension +from pywikibot.exceptions import NoPage, UnknownExtension, LockedPage from pywikibot.page import BasePage from pywikibot.tools import PY2
@@ -213,6 +213,11 @@ self._root = Post.fromJSON(self, self.uuid, self._data) return self._root
+ @property + def is_locked(self): + """Whether this topic is locked.""" + return self.root._current_revision['isLocked'] + def replies(self, format='wikitext', force=False): """A list of replies to this topic's root post.
@@ -236,6 +241,24 @@ @rtype: Post """ return self.root.reply(content, format) + + def lock(self, reason='Closed'): + """Lock this topic. + + @param reason: The reason for locking this topic + @type reason: unicode + """ + self.site.lock_topic(self, True, reason) + self.root._load(load_from_topic=True) + + def unlock(self, reason='Reopened'): + """Unlock this topic. + + @param reason: The reason for unlocking this topic + @type reason: unicode + """ + self.site.lock_topic(self, False, reason) + self.root._load(load_from_topic=True)
# Flow non-page-like objects @@ -408,6 +431,9 @@ @rtype: Post """ self._load() + if self.page.is_locked: + raise LockedPage(self.page, 'Topic %s is locked.') + reply_url = self._current_revision['actions']['reply']['url'] parsed_url = urlparse(reply_url) params = parse_qs(parsed_url.query) diff --git a/pywikibot/site.py b/pywikibot/site.py index 4e87cb6..27d2ba0 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -5941,6 +5941,29 @@ data = req.submit() return data['flow']['reply']['committed']['topic']
+ @must_be('user') + @need_extension('Flow') + def lock_topic(self, page, lock, reason): + """Lock or unlock a Flow topic. + + @param page: A Flow topic + @type page: Topic + @param lock: Whether to lock or unlock the topic + @type lock: bool (True corresponds to locking the topic.) + @param reason: The reason to lock or unlock the topic + @type reason: unicode + @return: Metadata returned by the API + @rtype: dict + """ + status = 'lock' if lock else 'unlock' + token = self.tokens['csrf'] + params = {'action': 'flow', 'page': page, 'token': token, + 'submodule': 'lock-topic', 'cotreason': reason, + 'cotmoderationState': status} + req = self._request(parameters=params, use_get=False) + data = req.submit() + return data['flow']['lock-topic']['committed']['topic'] + def watched_pages(self, sysop=False, force=False, step=None, total=None): """ Return watchlist. diff --git a/tests/flow_edit_tests.py b/tests/flow_edit_tests.py index 9844f5d..4a3ce11 100644 --- a/tests/flow_edit_tests.py +++ b/tests/flow_edit_tests.py @@ -9,6 +9,7 @@
__version__ = '$Id$'
+from pywikibot.exceptions import LockedPage from pywikibot.flow import Board, Topic, Post from pywikibot.tools import PY2
@@ -30,9 +31,8 @@
def test_create_topic(self): """Test creation of topic.""" - site = self.get_site() content = 'If you can read this, the Flow code in Pywikibot works!' - board = Board(site, 'Talk:Pywikibot test') + board = Board(self.site, 'Talk:Pywikibot test') topic = board.new_topic('Pywikibot test', content, 'wikitext') first_post = topic.replies()[0] wikitext = first_post.get(format='wikitext') @@ -149,3 +149,51 @@ self.assertListEqual(old_nested_replies, []) more_root_replies = topic_root.replies(force=True) self.assertEqual(len(more_root_replies), len(new_root_replies) + 1) + + +class TestFlowLockTopic(TestCase): + + """Locking and unlocking topics.""" + + family = 'test' + code = 'test' + + user = True + write = True + + def test_lock_unlock_topic(self): + """Lock and unlock a test topic.""" + # Setup + topic = Topic(self.site, 'Topic:Sn12rdih4iducjsd') + if topic.is_locked: + topic.unlock() + self.assertFalse(topic.is_locked) + # Lock topic + topic.lock('Pywikibot test') + self.assertTrue(topic.is_locked) + # Unlock topic + topic.unlock('Pywikibot test') + self.assertFalse(topic.is_locked) + + +class TestFlowEditFailure(TestCase): + + """Flow-related edit failure tests.""" + + family = 'test' + code = 'test' + + user = True + write = -1 + + def test_reply_to_locked_topic(self): + """Test replying to locked topic (should raise exception).""" + # Setup + content = 'I am a reply to a locked topic. This is not good!' + topic = Topic(self.site, 'Topic:Smxnipjfs8umm1wt') + # Reply (should raise a LockedPage exception) + self.assertRaises(LockedPage, topic.reply, content, 'wikitext') + topic_root = topic.root + self.assertRaises(LockedPage, topic_root.reply, content, 'wikitext') + topic_reply = topic.root.replies(force=True)[0] + self.assertRaises(LockedPage, topic_reply.reply, content, 'wikitext')
pywikibot-commits@lists.wikimedia.org