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}
         """
+        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)))

-- 
To view, visit https://gerrit.wikimedia.org/r/155235
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I62d13dca5b592bddf72dbbdcc0b8edf77c0059ed
Gerrit-PatchSet: 6
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <[email protected]>
Gerrit-Reviewer: John Vandenberg <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Merlijn van Deen <[email protected]>
Gerrit-Reviewer: Mpaa <[email protected]>
Gerrit-Reviewer: XZise <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
Pywikibot-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/pywikibot-commits

Reply via email to