jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/512049 )
Change subject: Validate IndexPage contents before saving it ......................................................................
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(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
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()
pywikibot-commits@lists.wikimedia.org