jenkins-bot merged this change.

View Change

Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
Validate IndexPage contents before saving it

Trying to save any other content than a {{:MediaWiki:Proofreadpage_index_template}}
template fails silently with a parameterless template being saved
instead.

Change-Id: I371e0dc2d365224edc8cbf9796408464694cc398
---
M pywikibot/proofreadpage.py
M tests/proofreadpage_tests.py
2 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py
index d05f932..39dbd28 100644
--- a/pywikibot/proofreadpage.py
+++ b/pywikibot/proofreadpage.py
@@ -53,6 +53,7 @@
import pywikibot
from pywikibot.comms import http
from pywikibot.data.api import Request
+from pywikibot.exceptions import OtherPageSaveError
from pywikibot.tools import ModuleDeprecationWrapper

_logger = 'proofreadpage'
@@ -750,6 +751,8 @@

"""Index Page page used in Mediawiki ProofreadPage extension."""

+ INDEX_TEMPLATE = ':MediaWiki:Proofreadpage_index_template'
+
def __init__(self, source, title=''):
"""Instantiate a IndexPage object.

@@ -809,6 +812,36 @@
else:
return None

+ def save(self, *args, **kwargs): # See Page.save().
+ """
+ Save page after validating the content.
+
+ Trying to save any other content fails silently with a parameterless
+ INDEX_TEMPLATE being saved.
+ """
+ if not self.has_valid_content():
+ raise OtherPageSaveError(
+ self, 'An IndexPage must consist only of a single call to '
+ '{{%s}}.' % self.INDEX_TEMPLATE)
+ kwargs['contentformat'] = 'text/x-wiki'
+ kwargs['contentmodel'] = 'proofread-index'
+ super(IndexPage, self).save(*args, **kwargs)
+
+ def has_valid_content(self):
+ """Test page only contains a single call to the index template."""
+ if (not self.text.startswith('{{' + self.INDEX_TEMPLATE)
+ or not self.text.endswith('}}')):
+ return False
+
+ # Discard all inner templates as only top-level ones matter
+ tmplts = pywikibot.textlib.extract_templates_and_params_regex_simple(
+ self.text)
+ if len(tmplts) != 1 or tmplts[0][0] != self.INDEX_TEMPLATE:
+ # Only a single call to the INDEX_TEMPLATE is allowed
+ return False
+
+ return True
+
def purge(self):
"""Overwrite purge method.

diff --git a/tests/proofreadpage_tests.py b/tests/proofreadpage_tests.py
index ebabb93..efa1518 100644
--- a/tests/proofreadpage_tests.py
+++ b/tests/proofreadpage_tests.py
@@ -769,6 +769,80 @@
self.assertEqual(list(gen), self.pages)


+class TestIndexPageHasValidContent(IndexPageTestCase):
+
+ """Unit tests for has_valid_content()."""
+
+ family = 'wikisource'
+ code = 'en'
+
+ index_name = 'Index:Phosphor (1888).djvu'
+ valid_template = '{{%s|foo=bar}}' % IndexPage.INDEX_TEMPLATE
+ other_template = '{{PoTM|bar=foobar}}'
+
+ @classmethod
+ def setUpClass(cls):
+ """Prepare tests by creating an IndexPage instance."""
+ super(TestIndexPageHasValidContent, cls).setUpClass()
+ cls.index = IndexPage(cls.site, cls.index_name)
+
+ def test_has_valid_content_empty(self):
+ """Test empty page is invalid."""
+ self.index.text = ''
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_non_template(self):
+ """Test non-template is invalid."""
+ self.index.text = 'foobar'
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_valid(self):
+ """Test correct Index template is valid."""
+ self.index.text = self.valid_template
+ self.assertTrue(self.index.has_valid_content())
+
+ def test_has_valid_content_prefixed(self):
+ """Test prefixing Index template is invalid."""
+ self.index.text = 'pre {}'.format(self.valid_template)
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_postfixed(self):
+ """Test postfixing Index template is invalid."""
+ self.index.text = '{}post'.format(self.valid_template)
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_pre_and_postfixed(self):
+ """Test pre- and postfixing Index template is invalid."""
+ self.index.text = 'pre{}post'.format(self.valid_template)
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_second_template(self):
+ """Test postfixing a second template is invalid."""
+ self.index.text = self.valid_template + self.other_template
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_wrong_template(self):
+ """Test incorrect template is invalid."""
+ self.index.text = self.other_template
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_missnamed_template(self):
+ """Test nested templates is valid."""
+ self.index.text = '{{%s_bar|foo=bar}}' % IndexPage.INDEX_TEMPLATE
+ self.assertFalse(self.index.has_valid_content())
+
+ def test_has_valid_content_nested_template(self):
+ """Test nested templates is valid."""
+ self.index.text = ('{{%s|foo=%s}}'
+ % (IndexPage.INDEX_TEMPLATE, self.other_template))
+ self.assertTrue(self.index.has_valid_content())
+
+ def test_has_valid_content_multiple_valid(self):
+ """Test multiple Index templates is invalid."""
+ self.index.text = self.valid_template * 2
+ self.assertFalse(self.index.has_valid_content())
+
+
if __name__ == '__main__': # pragma: no cover
try:
unittest.main()

To view, visit change 512049. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I371e0dc2d365224edc8cbf9796408464694cc398
Gerrit-Change-Number: 512049
Gerrit-PatchSet: 3
Gerrit-Owner: Lokal Profil <andre.costa@wikimedia.se>
Gerrit-Reviewer: Dvorapa <dvorapa@seznam.cz>
Gerrit-Reviewer: John Vandenberg <jayvdb@gmail.com>
Gerrit-Reviewer: Lokal Profil <andre.costa@wikimedia.se>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97@gmail.com>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: jenkins-bot (75)