Merlijn van Deen has submitted this change and it was merged.
Change subject: Fix cache key for non-Latin sites ......................................................................
Fix cache key for non-Latin sites
Avoiding using Page.__repr__() as it uses the localized namespace name and encodes the title into the console encoding, which causes problems when _create_file_name() tries to encode it again.
Bug: 67488
Change-Id: If49039bac8e8347852c1a04963f678903621d2a9 --- M pywikibot/data/api.py M tests/dry_api_tests.py 2 files changed, 67 insertions(+), 19 deletions(-)
Approvals: John Vandenberg: Looks good to me, but someone else must approve Phe: Looks good to me, but someone else must approve Merlijn van Deen: Looks good to me, approved
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py index 33e46f6..7102074 100644 --- a/pywikibot/data/api.py +++ b/pywikibot/data/api.py @@ -483,14 +483,16 @@ if login_status > pywikibot.site.LoginStatus.NOT_LOGGED_IN and \ hasattr(self.site, '_userinfo') and \ 'name' in self.site._userinfo: - user_key = pywikibot.page.User(self.site, - self.site._userinfo['name']) + # This uses the format of Page.__repr__(), without the encoding + # it performs. This string cant be encoded otherwise it creates an + # exception when _create_file_name() tries to encode it again. + user_key = u'User(User:%s)' % self.site._userinfo['name'] else: user_key = pywikibot.site.LoginStatus( max(login_status, pywikibot.site.LoginStatus.NOT_LOGGED_IN)) + user_key = repr(user_key)
- return (repr(self.site) + repr(user_key) + - repr(sorted(self.iteritems()))) + return repr(self.site) + user_key + repr(sorted(self.iteritems()))
def _create_file_name(self): self.http_params() # normalize self.iteritems() diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py index 95870ff..1714b59 100644 --- a/tests/dry_api_tests.py +++ b/tests/dry_api_tests.py @@ -8,12 +8,13 @@ #
import datetime +import hashlib import pywikibot from pywikibot.data.api import CachedRequest, QueryGenerator from utils import unittest
-class DryAPITests(unittest.TestCase): +class DryCachedRequestTests(unittest.TestCase):
def setUp(self): self.basesite = pywikibot.Site('en', 'wikipedia') @@ -28,6 +29,10 @@
def test_expiry_formats(self): self.assertEqual(self.req.expiry, CachedRequest(datetime.timedelta(days=1), **self.parms).expiry) + + def test_expired(self): + self.assertFalse(self.req._expired(datetime.datetime.now())) + self.assertTrue(self.req._expired(datetime.datetime.now() - datetime.timedelta(days=2)))
def test_get_cache_dir(self): retval = self.req._get_cache_dir() @@ -44,16 +49,27 @@ self.assertNotEqual(self.req._cachefile_path(), self.diffreq._cachefile_path()) self.assertNotEqual(self.req._cachefile_path(), self.diffsite._cachefile_path())
- def test_cachefile_path_different_users(self): - # Mock basesite object to test this. + +class MockCachedRequestKeyTests(unittest.TestCase): + def setUp(self): + class MockFamily(pywikibot.family.Family): + + @property + def name(self): + return 'mock' + class MockSite(pywikibot.site.APISite):
_loginstatus = pywikibot.site.LoginStatus.NOT_ATTEMPTED
- _namespaces = {2: 'User'} + _namespaces = {2: ['User']}
def __init__(self): self._user = 'anon' + pywikibot.site.BaseSite.__init__(self, 'mock', MockFamily()) + + def languages(self): + return ['mock']
def user(self): return self._user @@ -74,33 +90,63 @@ def __getattr__(self, attr): raise Exception("Attribute %r not defined" % attr)
- site = MockSite() - req = CachedRequest(expiry=1, site=site, action='query', meta='siteinfo') + self.site = MockSite() + + def test_cachefile_path_different_users(self): + req = CachedRequest(expiry=1, site=self.site, + action='query', meta='siteinfo') anonpath = req._cachefile_path()
- site._userinfo = {'name': u'user'} - site._loginstatus = 0 - req = CachedRequest(expiry=1, site=site, action='query', meta='siteinfo') + self.site._userinfo = {'name': u'MyUser'} + self.site._loginstatus = 0 + req = CachedRequest(expiry=1, site=self.site, + action='query', meta='siteinfo') userpath = req._cachefile_path()
self.assertNotEqual(anonpath, userpath)
- site._userinfo = {'name': u'sysop'} - site._loginstatus = 1 - req = CachedRequest(expiry=1, site=site, action='query', meta='siteinfo') + self.site._userinfo = {'name': u'MySysop'} + self.site._loginstatus = 1 + req = CachedRequest(expiry=1, site=self.site, + action='query', meta='siteinfo') sysoppath = req._cachefile_path()
self.assertNotEqual(anonpath, sysoppath) self.assertNotEqual(userpath, sysoppath)
- def test_expired(self): - self.assertFalse(self.req._expired(datetime.datetime.now())) - self.assertTrue(self.req._expired(datetime.datetime.now() - datetime.timedelta(days=2))) + def test_unicode(self): + self.site._userinfo = {'name': u'محمد الفلسطيني'} + self.site._loginstatus = 0 + + req = CachedRequest(expiry=1, site=self.site, + action='query', meta='siteinfo') + en_user_path = req._cachefile_path() + + self.site._namespaces = {2: [u'مستخدم']} + + req = CachedRequest(expiry=1, site=self.site, + action='query', meta='siteinfo') + + expect = u'MockSite()User(User:محمد الفلسطيني)' + \ + "[('action', 'query'), ('meta', 'siteinfo')]" + + self.assertEqual(repr(req._uniquedescriptionstr()), repr(expect)) + + self.assertEqual(req._uniquedescriptionstr().encode('utf-8'), + expect.encode('utf-8')) + + ar_user_path = req._cachefile_path() + + self.assertEqual(en_user_path, ar_user_path) + + +class DryQueryGenTests(unittest.TestCase):
def test_query_constructor(self): qGen1 = QueryGenerator(action="query", meta="siteinfo") qGen2 = QueryGenerator(meta="siteinfo") self.assertEqual(str(qGen1.request), str(qGen2.request))
+ if __name__ == '__main__': unittest.main()