jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] Handle API warnings ......................................................................
[FEAT] Handle API warnings
Some code parses the warnings returned by the API separately like Siteinfo. This option adds the possibility to handle warnings returned by the api via "_warning_handler". If it's not a method or that method returns not True the warning is still output like before (and is by default). The method must accept two parameters and is executed for each warning.
This also shows warnings when CachedRequest are used and not only for the first actually submitted request.
Change-Id: I62d13dca5b592bddf72dbbdcc0b8edf77c0059ed --- M pywikibot/data/api.py M pywikibot/site.py 2 files changed, 44 insertions(+), 24 deletions(-)
Approvals: John Vandenberg: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py index c36f88e..56c42c0 100644 --- a/pywikibot/data/api.py +++ b/pywikibot/data/api.py @@ -160,6 +160,7 @@ if "action" not in kwargs: raise ValueError("'action' specification missing from Request.") self.update(**kwargs) + self._warning_handler = None # Actions that imply database updates on the server, used for various # things like throttling or skipping actions when we're in simulation # mode @@ -342,6 +343,25 @@ submsg.set_payload(content) return submsg
+ def _handle_warnings(self, result): + if 'warnings' in result: + for mod, warning in result['warnings'].items(): + if mod == 'info': + continue + if '*' in warning: + text = warning['*'] + elif 'html' in warning: + # Bugzilla 49978 + text = warning['html']['*'] + else: + pywikibot.warning( + u'API warning ({0})of unknown format: {1}'. + format(mod, warning)) + continue + if (not callable(self._warning_handler) or + not self._warning_handler(mod, text)): + pywikibot.warning(u"API warning (%s): %s" % (mod, text)) + def submit(self): """Submit a query and parse the response.
@@ -470,21 +490,7 @@ self.site.login(status) # retry the previous query continue - if "warnings" in result: - modules = [k for k in result["warnings"] if k != "info"] - for mod in modules: - if '*' in result["warnings"][mod]: - text = result["warnings"][mod]['*'] - elif 'html' in result["warnings"][mod]: - # Bugzilla 49978 - text = result["warnings"][mod]['html']['*'] - else: - # This is just a warning, we shouldn't raise an - # exception because of it - continue - pywikibot.warning( - u"API warning (%s): %s" - % (mod, text)) + self._handle_warnings(result) if "error" not in result: return result if "*" in result["error"]: @@ -639,6 +645,8 @@ if not cached_available: self._data = super(CachedRequest, self).submit() self._write_cache(self._data) + else: + self._handle_warnings(self._data) return self._data
diff --git a/pywikibot/site.py b/pywikibot/site.py index 46995af..4b4848d 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -907,6 +907,9 @@ All values of the siteinfo property 'general' are directly available. """
+ WARNING_REGEX = re.compile(u"^Unrecognized values? for parameter " + u"'siprop': ([^,]+(?:, [^,]+)*)$") + def __init__(self, site): """Initialise it with an empty cache.""" self._site = site @@ -957,19 +960,33 @@ @rtype: dict (the values) @see: U{https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si%7D """ + def warn_handler(mod, message): + """Return True if the warning is handled.""" + matched = Siteinfo.WARNING_REGEX.match(message) + if mod == 'siteinfo' and matched: + invalid_properties.extend( + prop.strip() for prop in matched.group(1).split(',')) + return True + else: + return False + if isinstance(prop, basestring): props = [prop] else: props = prop if len(props) == 0: raise ValueError('At least one property name must be provided.') + invalid_properties = [] try: - data = pywikibot.data.api.CachedRequest( + request = pywikibot.data.api.CachedRequest( expiry=pywikibot.config.API_config_expiry if expiry is False else expiry, site=self._site, action='query', meta='siteinfo', - siprop='|'.join(props)).submit() + siprop='|'.join(props)) + # warnings are handled later + request._warning_handler = warn_handler + data = request.submit() except api.APIError as e: if e.code == 'siunknown_siprop': if len(props) == 1: @@ -987,13 +1004,8 @@ raise else: result = {} - if 'warnings' in data and 'siteinfo' in data['warnings']: - invalid_properties = [] - for prop in re.match(u"^Unrecognized values? for parameter " - u"'siprop': ([^,]+(?:, [^,]+)*)$", - data['warnings']['siteinfo']['*']).group(1).split(','): - prop = prop.strip() - invalid_properties += [prop] + if invalid_properties: + for prop in invalid_properties: result[prop] = (Siteinfo._get_default(prop), False) pywikibot.log(u"Unable to get siprop(s) '{0}'".format( u"', '".join(invalid_properties)))