jenkins-bot has submitted this change and it was merged.

Change subject: [Breaking]Make uncertainties in WbQuantity optional
......................................................................


[Breaking]Make uncertainties in WbQuantity optional

Per T115269/Idd62bdebaa066ba33c4005fa69501e0409adffbc uncertainties
should not be added unless explicitly set, also uncertainties cannot
be assumed to exist in the API responses.

This patch is [Breaking] in that it:
1. It no longer sets +/- 0 as default (which comes down to the
   breaking change in WikiBase)
2. It requires the WbQuantity be initialised with a site object (which
   is due to needing to support older WikiBase versions)

Bug: T150210
Change-Id: Ifbc3fc0f324c7483f0eba092529a05a8f617ec8c
---
M pywikibot/__init__.py
M pywikibot/page.py
M tests/wikibase_edit_tests.py
M tests/wikibase_tests.py
4 files changed, 121 insertions(+), 20 deletions(-)

Approvals:
  Ladsgroup: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 37f03bb..413b036 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -70,6 +70,7 @@
     deprecated as __deprecated,
     deprecate_arg as __deprecate_arg,
     normalize_username,
+    MediaWikiVersion,
     redirect_func,
     ModuleDeprecationWrapper as _ModuleDeprecationWrapper,
     PY2,
@@ -594,9 +595,29 @@
     _items = ('amount', 'upperBound', 'lowerBound', 'unit')
 
     @staticmethod
+    def _require_errors(site):
+        """
+        Check if the Wikibase site is so old it requires error bounds to be 
given.
+
+        If no site item is supplied it raises a warning and returns True.
+
+        @param site: The Wikibase site
+        @type site: pywikibot.site.DataSite
+        @rtype: bool
+        """
+        if not site:
+            warning(
+                "WbQuantity now expects a 'site' parameter. This is needed to "
+                "ensure correct handling of error bounds.")
+            return True
+        return MediaWikiVersion(site.version()) < 
MediaWikiVersion('1.29.0-wmf.2')
+
+    @staticmethod
     def _todecimal(value):
         """
         Convert a string to a Decimal for use in WbQuantity.
+
+        None value is returned as is.
 
         @param value: decimal number to convert
         @type value: str
@@ -604,6 +625,8 @@
         """
         if isinstance(value, Decimal):
             return value
+        elif value is None:
+            return None
         return Decimal(str(value))
 
     @staticmethod
@@ -611,13 +634,17 @@
         """
         Convert a Decimal to a string representation suitable for WikiBase.
 
+        None value is returned as is.
+
         @param value: decimal number to convert
         @type value: Decimal
         @rtype: str
         """
+        if value is None:
+            return None
         return format(value, "+g")
 
-    def __init__(self, amount, unit=None, error=None):
+    def __init__(self, amount, unit=None, error=None, site=None):
         u"""
         Create a new WbQuantity object.
 
@@ -628,6 +655,8 @@
         @param error: the uncertainty of the amount (e.g. ±1)
         @type error: same as amount, or tuple of two values, where the first 
value is
                      the upper error and the second is the lower error value.
+        @param site: The Wikibase site
+        @type site: pywikibot.site.DataSite
         """
         if amount is None:
             raise ValueError('no amount given')
@@ -637,16 +666,19 @@
         self.amount = self._todecimal(amount)
         self.unit = unit
 
-        if error is None:
-            upperError = lowerError = Decimal(0)
-        elif isinstance(error, tuple):
-            upperError = self._todecimal(error[0])
-            lowerError = self._todecimal(error[1])
+        if error is None and not self._require_errors(site):
+            self.upperBound = self.lowerBound = None
         else:
-            upperError = lowerError = self._todecimal(error)
+            if error is None:
+                self.upperBound = self.lowerBound = Decimal(0)
+            elif isinstance(error, tuple):
+                upperError = self._todecimal(error[0])
+                lowerError = self._todecimal(error[1])
+            else:
+                upperError = lowerError = self._todecimal(error)
 
-        self.upperBound = self.amount + upperError
-        self.lowerBound = self.amount - lowerError
+            self.upperBound = self.amount + upperError
+            self.lowerBound = self.amount - lowerError
 
     def toWikibase(self):
         """
@@ -663,7 +695,7 @@
         return json
 
     @classmethod
-    def fromWikibase(cls, wb):
+    def fromWikibase(cls, wb, site=None):
         """
         Create a WbQuanity from the JSON data given by the Wikibase API.
 
@@ -672,10 +704,12 @@
         @rtype: pywikibot.WbQuanity
         """
         amount = cls._todecimal(wb['amount'])
-        upperBound = cls._todecimal(wb['upperBound'])
-        lowerBound = cls._todecimal(wb['lowerBound'])
-        error = (upperBound - amount, amount - lowerBound)
-        return cls(amount, wb['unit'], error)
+        upperBound = cls._todecimal(wb.get('upperBound'))
+        lowerBound = cls._todecimal(wb.get('lowerBound'))
+        error = None
+        if (upperBound and lowerBound) or cls._require_errors(site):
+            error = (upperBound - amount, amount - lowerBound)
+        return cls(amount, wb['unit'], error, site)
 
 
 class WbMonolingualText(_WbRepresentation):
diff --git a/pywikibot/page.py b/pywikibot/page.py
index 165e7c8..30a1bb0 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -4279,7 +4279,7 @@
             FilePage(pywikibot.Site('commons', 'commons'), value),
         'globe-coordinate': pywikibot.Coordinate.fromWikibase,
         'time': lambda value, site: pywikibot.WbTime.fromWikibase(value),
-        'quantity': lambda value, site: 
pywikibot.WbQuantity.fromWikibase(value),
+        'quantity': pywikibot.WbQuantity.fromWikibase,
         'monolingualtext': lambda value, site:
             pywikibot.WbMonolingualText.fromWikibase(value)
     }
diff --git a/tests/wikibase_edit_tests.py b/tests/wikibase_edit_tests.py
index 59bcd29..a1e0f32 100644
--- a/tests/wikibase_edit_tests.py
+++ b/tests/wikibase_edit_tests.py
@@ -18,6 +18,7 @@
 import time
 
 import pywikibot
+from pywikibot.tools import MediaWikiVersion
 
 from tests.aspects import unittest, WikibaseTestCase
 
@@ -238,6 +239,28 @@
         claim = item.claims['P271'][0]
         self.assertEqual(claim.getTarget(), target)
 
+    def test_WbQuantity_edit_unbound(self):
+        """Attempt adding a quantity with unbound errors."""
+        # Clean the slate in preparation for test.
+        testsite = self.get_repo()
+        item = self._clean_item(testsite, 'P69')
+
+        # Make sure the wiki supports wikibase-conceptbaseuri
+        if MediaWikiVersion(testsite.version()) < 
MediaWikiVersion('1.29.0-wmf.2'):
+            raise unittest.SkipTest('Wiki version must be 1.29.0-wmf.2 or '
+                                    'newer to support unbound uncertainties.')
+
+        # set new claim
+        claim = pywikibot.page.Claim(testsite, 'P69', datatype='quantity')
+        target = pywikibot.WbQuantity(amount=1234)
+        claim.setTarget(target)
+        item.addClaim(claim)
+
+        # confirm new claim
+        item.get(force=True)
+        claim = item.claims['P69'][0]
+        self.assertEqual(claim.getTarget(), target)
+
     def test_identifier_edit(self):
         """Attempt adding a math claim with valid input."""
         testsite = self.get_repo()
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index f428475..c746c36 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -20,6 +20,7 @@
 from pywikibot import pagegenerators
 from pywikibot.page import WikibasePage, ItemPage
 from pywikibot.site import Namespace, NamespacesDict
+from pywikibot.tools import MediaWikiVersion
 
 from tests import join_pages_path
 from tests.aspects import (
@@ -186,7 +187,7 @@
 
     def test_WbQuantity_float_27(self):
         """Test WbQuantity for float value."""
-        q = pywikibot.WbQuantity(amount=0.044405586)
+        q = pywikibot.WbQuantity(amount=0.044405586, error=0.0)
         q_dict = {'amount': '+0.044405586', 'lowerBound': '+0.044405586',
                   'upperBound': '+0.044405586', 'unit': '1', }
         self.assertEqual(q.toWikibase(), q_dict)
@@ -200,21 +201,32 @@
 
     def test_WbQuantity_decimal(self):
         """Test WbQuantity for decimal value."""
-        q = pywikibot.WbQuantity(amount=Decimal('0.044405586'))
+        q = pywikibot.WbQuantity(amount=Decimal('0.044405586'),
+                                 error=Decimal('0.0'))
         q_dict = {'amount': '+0.044405586', 'lowerBound': '+0.044405586',
                   'upperBound': '+0.044405586', 'unit': '1', }
         self.assertEqual(q.toWikibase(), q_dict)
 
     def test_WbQuantity_string(self):
         """Test WbQuantity for decimal notation."""
-        q = pywikibot.WbQuantity(amount='0.044405586')
+        q = pywikibot.WbQuantity(amount='0.044405586', error='0')
         q_dict = {'amount': '+0.044405586', 'lowerBound': '+0.044405586',
                   'upperBound': '+0.044405586', 'unit': '1', }
         self.assertEqual(q.toWikibase(), q_dict)
 
+    def test_WbQuantity_unbound(self):
+        """Test WbQuantity for integer value without bounds."""
+        repo = self.get_repo()
+        if MediaWikiVersion(repo.version()) < MediaWikiVersion('1.29.0-wmf.2'):
+            raise unittest.SkipTest('Wiki version must be 1.29.0-wmf.2 or '
+                                    'newer to support unbound uncertainties.')
+        q = pywikibot.WbQuantity(amount=1234.5, site=repo)
+        self.assertEqual(q.toWikibase(),
+                         {'amount': '+1234.5', 'unit': '1', })
+
     def test_WbQuantity_formatting(self):
         """Test other WbQuantity methods."""
-        q = pywikibot.WbQuantity(amount='0.044405586')
+        q = pywikibot.WbQuantity(amount='0.044405586', error='0')
         self.assertEqual("%s" % q,
                          '{\n'
                          '    "amount": "+%(val)s",\n'
@@ -227,9 +239,28 @@
                          "upperBound=%(val)s, lowerBound=%(val)s, "
                          "unit=1)" % {'val': '0.044405586'})
 
+    def test_WbQuantity_formatting_unbound(self):
+        """Test WbQuantity formatting without bounds."""
+        repo = self.get_repo()
+        if MediaWikiVersion(repo.version()) < MediaWikiVersion('1.29.0-wmf.2'):
+            raise unittest.SkipTest('Wiki version must be 1.29.0-wmf.2 or '
+                                    'newer to support unbound uncertainties.')
+        q = pywikibot.WbQuantity(amount='0.044405586', site=repo)
+        self.assertEqual("%s" % q,
+                         '{\n'
+                         '    "amount": "+%(val)s",\n'
+                         '    "lowerBound": null,\n'
+                         '    "unit": "1",\n'
+                         '    "upperBound": null\n'
+                         '}' % {'val': '0.044405586'})
+        self.assertEqual("%r" % q,
+                         "WbQuantity(amount=%(val)s, "
+                         "upperBound=None, lowerBound=None, "
+                         "unit=1)" % {'val': '0.044405586'})
+
     def test_WbQuantity_equality(self):
         """Test WbQuantity equality."""
-        q = pywikibot.WbQuantity(amount='0.044405586')
+        q = pywikibot.WbQuantity(amount='0.044405586', error='0')
         self.assertEqual(q, q)
 
     def test_WbQuantity_fromWikibase(self):
@@ -243,6 +274,19 @@
                          {'amount': '+0.0229', 'lowerBound': '+0.0000',
                           'upperBound': '+1.0000', 'unit': '1', })
 
+    def test_WbQuantity_fromWikibase_unbound(self):
+        """Test WbQuantity.fromWikibase() instantiating without bounds."""
+        repo = self.get_repo()
+        if MediaWikiVersion(repo.version()) < MediaWikiVersion('1.29.0-wmf.2'):
+            raise unittest.SkipTest('Wiki version must be 1.29.0-wmf.2 or '
+                                    'newer to support unbound uncertainties.')
+        q = pywikibot.WbQuantity.fromWikibase({u'amount': u'+0.0229',
+                                               u'unit': u'1'},
+                                              site=repo)
+        self.assertEqual(q.toWikibase(),
+                         {'amount': '+0.0229', 'lowerBound': None,
+                          'upperBound': None, 'unit': '1', })
+
     def test_WbQuantity_errors(self):
         """Test WbQuantity error handling."""
         self.assertRaises(ValueError, pywikibot.WbQuantity, amount=None,

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ifbc3fc0f324c7483f0eba092529a05a8f617ec8c
Gerrit-PatchSet: 2
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Lokal Profil <[email protected]>
Gerrit-Reviewer: John Vandenberg <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Lokal Profil <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to