jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/334908 )
Change subject: Support adding units to WbQuantity through ItemPage or entity url
......................................................................
Support adding units to WbQuantity through ItemPage or entity url
This is backwards compatible so either ItemPages or entity
urls may be provided as a unit.
Provided urls are not validated (outside of limiting it to the
http(s) protocols) since items need not be in the same repo as the
claim.
Bug: T143594
Change-Id: I0ef7249d7a8f31ab62aa57d4f661062e889d9585
---
M pywikibot/__init__.py
M tests/wikibase_edit_tests.py
M tests/wikibase_tests.py
3 files changed, 183 insertions(+), 53 deletions(-)
Approvals:
Dalba: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 42b93ec..0233583 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""The initialization file for the Pywikibot framework."""
#
-# (C) Pywikibot team, 2008-2016
+# (C) Pywikibot team, 2008-2017
#
# Distributed under the terms of the MIT license.
#
@@ -23,6 +23,7 @@
if sys.version_info[0] > 2:
from queue import Queue
long = int
+ basestring = str
else:
from Queue import Queue
@@ -256,7 +257,7 @@
@type dim: int
@param site: The Wikibase site
@type site: pywikibot.site.DataSite
- @param entity: The URL entity of a Wikibase item
+ @param entity: The URL entity of a Wikibase item for the globe
@type entity: str
"""
self.lat = lat
@@ -644,6 +645,16 @@
return None
return format(value, "+g")
+ def __eq__(self, other):
+ """Override equality to handle different unit
representations."""
+ if isinstance(other, self.__class__):
+ self_dict = self.__dict__.copy()
+ other_dict = other.__dict__.copy()
+ self_dict['_unit'] = self.unit
+ other_dict['_unit'] = other.unit
+ return self_dict == other_dict
+ return NotImplemented
+
def __init__(self, amount, unit=None, error=None, site=None):
u"""
Create a new WbQuantity object.
@@ -651,7 +662,9 @@
@param amount: number representing this quantity
@type amount: string or Decimal. Other types are accepted, and converted
via str to Decimal.
- @param unit: not used (only unit-less quantities are supported)
+ @param unit: the Wikibase item for the unit or the URL entity of this
+ Wikibase item.
+ @type unit: pywikibot.ItemPage, str or None
@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.
@@ -660,11 +673,14 @@
"""
if amount is None:
raise ValueError('no amount given')
- if unit is None:
- unit = '1'
self.amount = self._todecimal(amount)
- self.unit = unit
+ self._unit = unit
+
+ # also allow entity urls to be provided via unit parameter
+ if isinstance(unit, basestring) and \
+ unit.partition('://')[0] not in ('http',
'https'):
+ raise ValueError("'unit' must be an ItemPage or entity
url.")
if error is None and not self._require_errors(site):
self.upperBound = self.lowerBound = None
@@ -679,6 +695,13 @@
self.upperBound = self.amount + upperError
self.lowerBound = self.amount - lowerError
+
+ @property
+ def unit(self):
+ """Return _unit's entity url or '1' if _unit is
None."""
+ if isinstance(self._unit, ItemPage):
+ return self._unit.concept_url()
+ return self._unit or '1'
def toWikibase(self):
"""
@@ -709,7 +732,11 @@
error = None
if (upperBound and lowerBound) or cls._require_errors(site):
error = (upperBound - amount, amount - lowerBound)
- return cls(amount, wb['unit'], error, site)
+ if wb['unit'] == '1':
+ unit = None
+ else:
+ unit = wb['unit']
+ return cls(amount, unit, error, site)
class WbMonolingualText(_WbRepresentation):
diff --git a/tests/wikibase_edit_tests.py b/tests/wikibase_edit_tests.py
index 621146b..670eab9 100644
--- a/tests/wikibase_edit_tests.py
+++ b/tests/wikibase_edit_tests.py
@@ -6,7 +6,7 @@
class in edit_failiure_tests.py
"""
#
-# (C) Pywikibot team, 2014
+# (C) Pywikibot team, 2014-2017
#
# Distributed under the terms of the MIT license.
#
@@ -224,7 +224,7 @@
def test_WbMonolingualText_edit(self):
"""Attempt adding a monolingual text with valid
input."""
- # Clean the slate in preparation for test."""
+ # Clean the slate in preparation for test.
testsite = self.get_repo()
item = self._clean_item(testsite, 'P271')
@@ -245,7 +245,7 @@
testsite = self.get_repo()
item = self._clean_item(testsite, 'P69')
- # Make sure the wiki supports wikibase-conceptbaseuri
+ # Make sure the wiki supports unbound uncertainties
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.')
@@ -261,6 +261,29 @@
claim = item.claims['P69'][0]
self.assertEqual(claim.getTarget(), target)
+ def test_WbQuantity_edit(self):
+ """Attempt adding a quantity with valid input."""
+ # Clean the slate in preparation for test.
+ testsite = self.get_repo()
+ item = self._clean_item(testsite, 'P69')
+
+ # Make sure the wiki supports wikibase-conceptbaseuri
+ version = testsite.version()
+ if MediaWikiVersion(version) < MediaWikiVersion('1.28-wmf.23'):
+ raise unittest.SkipTest('Wiki version must be 1.28-wmf.23 or '
+ 'newer to expose wikibase-conceptbaseuri.')
+
+ # set new claim
+ claim = pywikibot.page.Claim(testsite, 'P69',
datatype='quantity')
+ target = pywikibot.WbQuantity(amount=1234, error=1, unit=item)
+ 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 8a18771..0bf0c54 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Tests for the Wikidata parts of the page module."""
#
-# (C) Pywikibot team, 2008-2016
+# (C) Pywikibot team, 2008-2017
#
# Distributed under the terms of the MIT license.
#
@@ -214,16 +214,6 @@
'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', error='0')
@@ -237,25 +227,6 @@
self.assertEqual("%r" % q,
"WbQuantity(amount=%(val)s, "
"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):
@@ -274,23 +245,29 @@
{'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,
error=1)
+
+ def test_WbQuantity_entity_unit(self):
+ """Test WbQuantity with entity url unit."""
+ q = pywikibot.WbQuantity(amount=1234, error=1,
+
unit='http://www.wikidata.org/entity/Q712226')
+ self.assertEqual(q.toWikibase(),
+ {'amount': '+1234', 'lowerBound':
'+1233',
+ 'upperBound': '+1235',
+ 'unit':
'http://www.wikidata.org/entity/Q712226', })
+
+ def test_WbQuantity_unit_fromWikibase(self):
+ """Test WbQuantity recognising unit from Wikibase
output."""
+ q = pywikibot.WbQuantity.fromWikibase({
+ 'amount': '+1234', 'lowerBound': '+1233',
'upperBound': '+1235',
+ 'unit': 'http://www.wikidata.org/entity/Q712226', })
+ self.assertEqual(q.toWikibase(),
+ {'amount': '+1234', 'lowerBound':
'+1233',
+ 'upperBound': '+1235',
+ 'unit':
'http://www.wikidata.org/entity/Q712226', })
def test_WbMonolingualText_string(self):
"""Test WbMonolingualText string."""
@@ -324,6 +301,97 @@
text='Test this!', language='')
self.assertRaises(ValueError, pywikibot.WbMonolingualText,
text=None, language='sv')
+
+
+class TestWikibaseTypesNonDry(WikidataTestCase):
+
+ """
+ Test Wikibase data types (non-dry).
+
+ These can be moved to TestWikibaseTypes once DrySite has been bumped to
+ the appropriate version.
+ """
+
+ 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',
+ 'upperBound': None, 'lowerBound': None})
+
+ 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_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_ItemPage_unit(self):
+ """Test WbQuantity with ItemPage unit."""
+ repo = self.get_repo()
+ if MediaWikiVersion(repo.version()) <
MediaWikiVersion('1.28-wmf.23'):
+ raise unittest.SkipTest('Wiki version must be 1.28-wmf.23 or '
+ 'newer to expose wikibase-conceptbaseuri.')
+
+ q = pywikibot.WbQuantity(amount=1234, error=1,
+ unit=pywikibot.ItemPage(repo, 'Q712226'))
+ self.assertEqual(q.toWikibase(),
+ {'amount': '+1234', 'lowerBound':
'+1233',
+ 'upperBound': '+1235',
+ 'unit':
'http://www.wikidata.org/entity/Q712226', })
+
+ def test_WbQuantity_equality(self):
+ """Test WbQuantity equality with different unit
representations."""
+ repo = self.get_repo()
+ if MediaWikiVersion(repo.version()) <
MediaWikiVersion('1.28-wmf.23'):
+ raise unittest.SkipTest('Wiki version must be 1.28-wmf.23 or '
+ 'newer to expose wikibase-conceptbaseuri.')
+
+ a = pywikibot.WbQuantity(
+ amount=1234, error=1,
+ unit=pywikibot.ItemPage(repo, 'Q712226'))
+ b = pywikibot.WbQuantity(
+ amount=1234, error=1,
+
unit='http://www.wikidata.org/entity/Q712226')
+ c = pywikibot.WbQuantity(
+ amount=1234, error=1,
+
unit='http://test.wikidata.org/entity/Q712226')
+ d = pywikibot.WbQuantity(
+ amount=1234, error=2,
+
unit='http://www.wikidata.org/entity/Q712226')
+ self.assertEqual(a, b)
+ self.assertNotEqual(a, c)
+ self.assertNotEqual(b, c)
+ self.assertNotEqual(b, d)
class TestItemPageExtensibility(TestCase):
@@ -789,6 +857,16 @@
claim.setTarget(target)
self.assertEqual(claim.target, target)
+ def test_set_WbQuantity(self):
+ """Test setting claim of quantity type."""
+ wikidata = self.get_repo()
+ claim = pywikibot.Claim(wikidata, 'P1106')
+ self.assertEqual(claim.type, 'quantity')
+ target = pywikibot.WbQuantity(
+ amount=1234, error=1,
unit='http://www.wikidata.org/entity/Q11573')
+ claim.setTarget(target)
+ self.assertEqual(claim.target, target)
+
def test_set_math(self):
"""Test setting claim of math type."""
wikidata = self.get_repo()
@@ -824,6 +902,8 @@
self.assertRaises(ValueError, url_claim.setTarget, pywikibot.WbTime(2001,
site=wikidata))
mono_claim = pywikibot.Claim(wikidata, 'P1450')
self.assertRaises(ValueError, mono_claim.setTarget, 'foo')
+ quantity_claim = pywikibot.Claim(wikidata, 'P1106')
+ self.assertRaises(ValueError, quantity_claim.setTarget, 'foo')
class TestItemBasePageMethods(WikidataTestCase, BasePageMethodsTestBase):
--
To view, visit
https://gerrit.wikimedia.org/r/334908
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I0ef7249d7a8f31ab62aa57d4f661062e889d9585
Gerrit-PatchSet: 10
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: Dalba <dalba.wiki(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Lokal Profil <lokal.profil(a)gmail.com>
Gerrit-Reviewer: Magul <tomasz.magulski(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>