jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/571927 )
Change subject: [IMPR] Provide mediawiki_messages for foreign language codes ......................................................................
[IMPR] Provide mediawiki_messages for foreign language codes
mediawiki_messages can be retrieved with language code. This patch enables messages to be independend from site.lang by giving a lang parameter to mediawiki message methods.
- use a new site._mw_msg_cache cache which holds all messages independend from a special Site object - remove the all message fetching behaviour of '*' key which was deprecated 5 years ago due to T111479 - add some test for the new behaviour - use subTest for the test method - remove tests for deprcated all message fetching with '*'
Change-Id: I24863cbf369a007404509a7bee19b4a36f9df881 --- M pywikibot/site.py M tests/site_tests.py 2 files changed, 90 insertions(+), 63 deletions(-)
Approvals: Mpaa: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/site.py b/pywikibot/site.py index c2d20cb..c725868 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -30,7 +30,7 @@ from collections.abc import Iterable, Container, Mapping except ImportError: # Python 2.7 from collections import Iterable, Container, Mapping -from collections import namedtuple +from collections import defaultdict, namedtuple from enum import IntEnum from warnings import warn
@@ -1845,6 +1845,9 @@ super(RemovedSite, self).__init__(code, fam, user)
+_mw_msg_cache = defaultdict(dict) + + class APISite(BaseSite):
""" @@ -2376,81 +2379,86 @@ except KeyError: return False
- def mediawiki_messages(self, keys): + def mediawiki_messages(self, keys, lang=None): """Fetch the text of a set of MediaWiki messages.
- If keys is '*' or ['*'], all messages will be fetched. (deprecated) - The returned dict uses each key to store the associated message.
@see: U{https://www.mediawiki.org/wiki/API:Allmessages%7D
@param keys: MediaWiki messages to fetch - @type keys: set of str, '*' or ['*'] + @type keys: iterable of str + @param lang: a language code, default is self.lang + @type lang: str or None
@rtype dict """ - if keys == '*' or keys == ['*']: - issue_deprecation_warning('mediawiki_messages("*")', - 'specific messages', since='20150905') - - if not all(_key in self._msgcache for _key in keys): + amlang = lang or self.lang + if not all(amlang in _mw_msg_cache + and _key in _mw_msg_cache[amlang] for _key in keys): parameters = {'meta': 'allmessages', 'ammessages': keys, - 'amlang': self.lang, + 'amlang': amlang, } msg_query = api.QueryGenerator(site=self, parameters=parameters)
for msg in msg_query: if 'missing' not in msg: - self._msgcache[msg['name']] = msg['*'] + _mw_msg_cache[amlang][msg['name']] = msg['*']
- # Return all messages - if keys == '*' or keys == ['*']: - return self._msgcache + # Check requested keys + result = {} + for key in keys: + try: + result[key] = _mw_msg_cache[amlang][key] + except KeyError: + raise KeyError("No message '{}' found for lang '{}'" + .format(key, amlang)) else: - # Check requested keys - for key in keys: - if key not in self._msgcache: - raise KeyError("Site %s has no message '%s'" - % (self, key)) + return result
- return {_key: self._msgcache[_key] for _key in keys} + return {_key: _mw_msg_cache[amlang][_key] for _key in keys}
@deprecated_args(forceReload=None) - def mediawiki_message(self, key): + def mediawiki_message(self, key, lang=None): """Fetch the text for a MediaWiki message.
@param key: name of MediaWiki message @type key: str + @param lang: a language code, default is self.lang + @type lang: str or None
@rtype unicode """ - return self.mediawiki_messages([key])[key] + return self.mediawiki_messages([key], lang=lang)[key]
- def has_mediawiki_message(self, key): + def has_mediawiki_message(self, key, lang=None): """Determine if the site defines a MediaWiki message.
@param key: name of MediaWiki message @type key: str + @param lang: a language code, default is self.lang + @type lang: str or None
@rtype: bool """ - return self.has_all_mediawiki_messages([key]) + return self.has_all_mediawiki_messages([key], lang=lang)
- def has_all_mediawiki_messages(self, keys): + def has_all_mediawiki_messages(self, keys, lang=None): """Confirm that the site defines a set of MediaWiki messages.
@param keys: names of MediaWiki messages - @type keys: set of str + @type keys: iterable of str + @param lang: a language code, default is self.lang + @type lang: str or None
@rtype: bool """ try: - self.mediawiki_messages(keys) - return True + self.mediawiki_messages(keys, lang=lang) except KeyError: return False + return True
@property def months_names(self): diff --git a/tests/site_tests.py b/tests/site_tests.py index 279b0f8..6fabc24 100644 --- a/tests/site_tests.py +++ b/tests/site_tests.py @@ -186,17 +186,6 @@ self.assertOneDeprecationParts('Calling the namespaces property', 'it directly')
- def test_messages_star(self): - """Test that fetching all messages is deprecated.""" - # Load all messages and check that '*' is not a valid key. - self.assertEqual(self.site.mediawiki_messages('*'), - {'*': 'dummy entry'}) - self.assertOneDeprecationParts('mediawiki_messages("*")', - 'specific messages') - self.assertEqual(self.site.mediawiki_messages(['hello']), - {'hello': 'world'}) - self.assertNoDeprecation() -
class TestBaseSiteProperties(TestCase):
@@ -397,37 +386,67 @@ """Test MediaWiki: messages.""" mysite = self.get_site() for msg in ('about', 'aboutpage', 'aboutsite', 'accesskey-n-portal'): - self.assertTrue(mysite.has_mediawiki_message(msg)) - self.assertIsInstance(mysite.mediawiki_message(msg), basestring) - self.assertFalse(mysite.has_mediawiki_message('nosuchmessage')) - self.assertRaises(KeyError, mysite.mediawiki_message, 'nosuchmessage') + with self.subTest(message=msg, lang=mysite.lang): + self.assertTrue(mysite.has_mediawiki_message(msg)) + self.assertIsInstance(mysite.mediawiki_message(msg), + basestring) + self.assertEqual( + mysite.mediawiki_message(msg), + mysite.mediawiki_message(msg, lang=mysite.lang)) + + with self.subTest(message=msg, lang='de'): + self.assertTrue(mysite.has_mediawiki_message(msg, lang='de')) + self.assertIsInstance(mysite.mediawiki_message(msg, lang='de'), + basestring) + + with self.subTest(message='nosuchmessage'): + self.assertFalse(mysite.has_mediawiki_message('nosuchmessage')) + self.assertRaises(KeyError, mysite.mediawiki_message, + 'nosuchmessage')
msg = ('about', 'aboutpage') - about_msgs = self.site.mediawiki_messages(msg) - self.assertIsInstance(mysite.mediawiki_messages(msg), dict) - self.assertTrue(mysite.mediawiki_messages(msg)) - self.assertLength(about_msgs, 2) - self.assertIn(msg[0], about_msgs) + with self.subTest(messages=msg): + about_msgs = self.site.mediawiki_messages(msg) + self.assertIsInstance(mysite.mediawiki_messages(msg), dict) + self.assertTrue(mysite.mediawiki_messages(msg)) + self.assertLength(about_msgs, 2) + self.assertIn(msg[0], about_msgs) + + months = ['january', 'february', 'march', 'april', 'may_long', + 'june', 'july', 'august', 'september', 'october', + 'november', 'december'] + with self.subTest(messages=months, lang1='af', lang2='an'): + self.assertLength(mysite.mediawiki_messages(months, 'af'), 12) + self.assertLength(mysite.mediawiki_messages(months, 'an'), 12) + self.assertNotEqual(mysite.mediawiki_messages(months, 'af'), + mysite.mediawiki_messages(months, 'an'))
# mediawiki_messages must be given a list; using a string will split it - self.assertRaises(KeyError, self.site.mediawiki_messages, 'about') + with self.subTest(messages='about'): + self.assertRaises(KeyError, self.site.mediawiki_messages, 'about')
msg = ('nosuchmessage1', 'about', 'aboutpage', 'nosuchmessage') - self.assertFalse(mysite.has_all_mediawiki_messages(msg)) - self.assertRaises(KeyError, mysite.mediawiki_messages, msg) + with self.subTest(messages=msg): + self.assertFalse(mysite.has_all_mediawiki_messages(msg)) + self.assertRaises(KeyError, mysite.mediawiki_messages, msg)
- self.assertIsInstance(mysite.server_time(), pywikibot.Timestamp) - ts = mysite.getcurrenttimestamp() - self.assertIsInstance(ts, basestring) - self.assertRegex(ts, r'(19|20)\d\d[0-1]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d') + with self.subTest(test='server_time'): + self.assertIsInstance(mysite.server_time(), pywikibot.Timestamp) + ts = mysite.getcurrenttimestamp() + self.assertIsInstance(ts, basestring) + self.assertRegex( + ts, r'(19|20)\d\d[0-1]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d')
- self.assertIsInstance(mysite.months_names, list) - self.assertLength(mysite.months_names, 12) - self.assertTrue(all(isinstance(month, tuple) - for month in mysite.months_names)) - for month in mysite.months_names: - self.assertLength(month, 2) - self.assertEqual(mysite.list_to_text(('pywikibot',)), 'pywikibot') + with self.subTest(test='months_names'): + self.assertIsInstance(mysite.months_names, list) + self.assertLength(mysite.months_names, 12) + self.assertTrue(all(isinstance(month, tuple) + for month in mysite.months_names)) + for month in mysite.months_names: + self.assertLength(month, 2) + + with self.subTest(test='list_to_text'): + self.assertEqual(mysite.list_to_text(('pywikibot',)), 'pywikibot')
def test_english_specific_methods(self): """Test Site methods using English specific inputs and outputs."""
pywikibot-commits@lists.wikimedia.org