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