jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] http: Get revision/version if necessary ......................................................................
[FEAT] http: Get revision/version if necessary
This changes pywikibot.comms.http to always use the version number even if it's not cached. The pywikibot.version module is now always using a custom user-agent to avoid that {version} or {revision} appears in it and creating an infinite recursion.
To avoid defining the version and revision if they are not appearing in the user-agent it is using a custom formatter which handles those two special so that they don't have to appear in format's args and kwargs. Instead they will be only defined if the formatter finds those in the string.
Change-Id: Ia7a31cfba4d467118713fbb0122dad932b3a5c39 --- M pywikibot/comms/http.py M pywikibot/version.py M tests/http_tests.py 3 files changed, 29 insertions(+), 9 deletions(-)
Approvals: John Vandenberg: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/comms/http.py b/pywikibot/comms/http.py index 54549f1..e45c52b 100644 --- a/pywikibot/comms/http.py +++ b/pywikibot/comms/http.py @@ -27,6 +27,7 @@ import time
from distutils.version import StrictVersion +from string import Formatter from warnings import warn
# Verify that a working httplib2 is present. @@ -137,6 +138,22 @@ }
+class _UserAgentFormatter(Formatter): + + """User-agent formatter to load version/revision only if necessary.""" + + def get_value(self, key, args, kwargs): + """Get field as usual except for version and revision.""" + # This is the Pywikibot revision; also map it to {version} at present. + if key == 'version' or key == 'revision': + return pywikibot.version.getversiondict()['rev'] + else: + return super(_UserAgentFormatter, self).get_value(key, args, kwargs) + + +_USER_AGENT_FORMATTER = _UserAgentFormatter() + + def user_agent_username(username=None): """ Reduce username to a representation permitted in HTTP headers. @@ -180,13 +197,6 @@ """ values = USER_AGENT_PRODUCTS.copy()
- # This is the Pywikibot revision; also map it to {version} at present. - if pywikibot.version.cache: - values['revision'] = pywikibot.version.cache['rev'] - else: - values['revision'] = '' - values['version'] = values['revision'] - values['script'] = pywikibot.calledModuleName()
# TODO: script_product should add the script version, if known @@ -216,7 +226,7 @@ if not format_string: format_string = config.user_agent_format
- formatted = format_string.format(**values) + formatted = _USER_AGENT_FORMATTER.format(format_string, **values) # clean up after any blank components formatted = formatted.replace(u'()', u'').replace(u' ', u' ').strip() return formatted diff --git a/pywikibot/version.py b/pywikibot/version.py index b3ba9eb..8de383e 100644 --- a/pywikibot/version.py +++ b/pywikibot/version.py @@ -359,7 +359,8 @@ from pywikibot.comms import http
url = repo or 'https://git.wikimedia.org/feed/pywikibot/core' - buf = http.fetch(url).content.splitlines() + buf = http.fetch(uri=url, + headers={'user-agent': '{pwb}'}).content.splitlines() try: hsh = buf[13].split('/')[5][:-1] return hsh diff --git a/tests/http_tests.py b/tests/http_tests.py index 7692acb..a42557b 100644 --- a/tests/http_tests.py +++ b/tests/http_tests.py @@ -329,6 +329,15 @@
self.assertEqual('%E2%81%82', http.user_agent_username(u'⁂'))
+ def test_version(self): + pywikibot.version.cache = None + http.user_agent(format_string='version does not appear') + self.assertIsNone(pywikibot.version.cache) + pywikibot.version.cache = {'rev': 'dummy'} + self.assertEqual(http.user_agent(format_string='{version} does appear'), + 'dummy does appear') + self.assertIsNotNone(pywikibot.version.cache) +
class DefaultUserAgentTestCase(TestCase):