jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/346700 )
Change subject: Add support for geo-shape Wikibase data type
......................................................................
Add support for geo-shape Wikibase data type
Introduces the WbGeoShape class to provide handling of geo-shape
data and do some basic validation on indata.
Also add a comment to commonsMedia to the task explaining how
come site is hard-coded to Wikimedia Commons for all Wikibase
installations (which is not the case for geo-shapes).
Bug:T161726
Change-Id: Ia96d35519163307227159ccece5981783ce8b558
---
M pywikibot/__init__.py
M pywikibot/families/wikidata_family.py
M pywikibot/page.py
M pywikibot/site.py
M tests/wikibase_edit_tests.py
M tests/wikibase_tests.py
6 files changed, 171 insertions(+), 3 deletions(-)
Approvals:
jenkins-bot: Verified
Xqt: Looks good to me, approved
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index eff852a..1b6ce51 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -812,6 +812,73 @@
return cls(wb['text'], wb['language'])
+class WbGeoShape(_WbRepresentation):
+ """
+ A Wikibase geo-shape representation.
+
+ A temporary implementation until T162336 has been resolved.
+ """
+
+ _items = ('page', )
+
+ def __init__(self, page, site=None):
+ """
+ Create a new WbGeoShape object.
+
+ @param page: page containing the map data
+ @type text: pywikibot.Page
+ @param site: The Wikibase site
+ @type site: pywikibot.site.DataSite
+ """
+ site = site or Site().data_repository()
+ if not isinstance(page, Page):
+ raise ValueError('page must be a pywikibot.Page object.')
+
+ # validate page exists
+ if not page.exists():
+ raise ValueError('page must exist.')
+
+ # validate page is on the right site, and that site supports geo-shapes
+ geo_shape_site = site.geo_shape_repository()
+ if not geo_shape_site:
+ raise ValueError('the provided site does not support geo-shapes.')
+ if page.site != geo_shape_site:
+ raise ValueError('page must be on the image repository site.')
+
+ # validate page title fulfills hard-coded Wikibase requirement
+ # pcre regexp: '/^Data:[^\\[\\]#\\\:{|}]+\.map$/u'
+ # As we have already checked for existence the following simplified
+ # check should be enough.
+ if not page.title().startswith('Data:') or \
+ not page.title().endswith('.map'):
+ raise ValueError(
+ "page must be a '.map' page in the 'Data:'
namespace.")
+
+ self.page = page
+
+ def toWikibase(self):
+ """
+ Convert the data to the value required by the Wikibase API.
+
+ @return: title of the geo-shape page incl. namespace
+ @rtype: str
+ """
+ return self.page.title()
+
+ @classmethod
+ def fromWikibase(cls, page_name, site):
+ """
+ Create a WbGeoShape from the JSON data given by the Wikibase API.
+
+ @param page_name: page name from Wikibase value
+ @type page_name: str
+ @rtype: pywikibot.WbGeoShape
+ """
+ geo_shape_site = site.geo_shape_repository()
+ page = Page(geo_shape_site, page_name)
+ return cls(page, site)
+
+
_sites = {}
_url_cache = {} # The code/fam pair for each URL
diff --git a/pywikibot/families/wikidata_family.py
b/pywikibot/families/wikidata_family.py
index f695a20..4b30106 100644
--- a/pywikibot/families/wikidata_family.py
+++ b/pywikibot/families/wikidata_family.py
@@ -50,6 +50,11 @@
"""Default calendar model for WbTime datatype."""
return 'http://www.wikidata.org/entity/Q1985727'
+ def shared_geo_shape_repository(self, code):
+ """Return Wikimedia Commons as the repository for
geo-shapes."""
+ # Per geoShapeStorageFrontendUrl settings in Wikibase
+ return ('commons', 'commons')
+
def globes(self, code):
"""Supported globes for Coordinate datatype."""
return {
diff --git a/pywikibot/page.py b/pywikibot/page.py
index 1885aef..e95bab3 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -4318,6 +4318,7 @@
'monolingualtext': pywikibot.WbMonolingualText,
'math': basestring,
'external-id': basestring,
+ 'geo-shape': pywikibot.WbGeoShape,
}
value_types = {'wikibase-item': 'wikibase-entityid',
@@ -4327,6 +4328,7 @@
'globe-coordinate': 'globecoordinate',
'math': 'string',
'external-id': 'string',
+ 'geo-shape': 'string',
}
def __init__(self, site, id, datatype=None):
@@ -4457,8 +4459,9 @@
'wikibase-property': lambda value, site:
PropertyPage(site, 'P' + str(value['numeric-id'])),
'commonsMedia': lambda value, site:
- FilePage(pywikibot.Site('commons', 'commons'), value),
+ FilePage(pywikibot.Site('commons', 'commons'), value), #
T90492
'globe-coordinate': pywikibot.Coordinate.fromWikibase,
+ 'geo-shape': pywikibot.WbGeoShape.fromWikibase,
'time': lambda value, site: pywikibot.WbTime.fromWikibase(value),
'quantity': pywikibot.WbQuantity.fromWikibase,
'monolingualtext': lambda value, site:
@@ -4884,7 +4887,8 @@
elif self.type == 'commonsMedia':
value = self.getTarget().title(withNamespace=False)
elif self.type in ('globe-coordinate', 'time',
- 'quantity', 'monolingualtext'):
+ 'quantity', 'monolingualtext',
+ 'geo-shape'):
value = self.getTarget().toWikibase()
else:
raise NotImplementedError('%s datatype is not supported yet.'
diff --git a/pywikibot/site.py b/pywikibot/site.py
index c715902..7c04551 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -7231,6 +7231,13 @@
"""
return self
+ def geo_shape_repository(self):
+ """Return Site object for the geo-shapes repository e.g.
commons."""
+ # Do this via API instead if T162561 is implemented.
+ code, fam = self.shared_geo_shape_repository()
+ if bool(code or fam):
+ return pywikibot.Site(code, fam, self.username())
+
def loadcontent(self, identification, *props):
"""
Fetch the current content of a Wikibase item.
diff --git a/tests/wikibase_edit_tests.py b/tests/wikibase_edit_tests.py
index 670eab9..1361c98 100644
--- a/tests/wikibase_edit_tests.py
+++ b/tests/wikibase_edit_tests.py
@@ -300,6 +300,25 @@
claim = item.claims['P718'][0]
self.assertEqual(claim.getTarget(), target)
+ def test_WbGeoShape_edit(self):
+ """Attempt adding a geo-shape with valid input."""
+ # Clean the slate in preparation for test.
+ testsite = self.get_repo()
+ item = self._clean_item(testsite, 'P27199')
+
+ # set new claim
+ claim = pywikibot.page.Claim(testsite, 'P27199',
datatype='geo-shape')
+ commons_site = pywikibot.Site('commons', 'commons')
+ page = pywikibot.Page(commons_site, 'Data:Lyngby Hovedgade.map')
+ target = pywikibot.WbGeoShape(page)
+ claim.setTarget(target)
+ item.addClaim(claim)
+
+ # confirm new claim
+ item.get(force=True)
+ claim = item.claims['P27199'][0]
+ self.assertEqual(claim.getTarget(), target)
+
class TestWikibaseRemoveQualifier(WikibaseTestCase):
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index 0006172..98c542d 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -18,7 +18,7 @@
import pywikibot
from pywikibot import pagegenerators
-from pywikibot.page import WikibasePage, ItemPage, PropertyPage
+from pywikibot.page import WikibasePage, ItemPage, PropertyPage, Page
from pywikibot.site import Namespace, NamespacesDict
from pywikibot.tools import MediaWikiVersion
@@ -490,6 +490,72 @@
text=None, language='sv')
+class TestWbGeoShapeNonDry(WikidataTestCase):
+
+ """
+ Test Wikibase WbGeoShape data type (non-dry).
+
+ These require non dry tests due to the page.exists() call.
+ """
+
+ def setUp(self):
+ """Setup tests."""
+ self.commons = pywikibot.Site('commons', 'commons')
+ self.page = Page(self.commons, 'Data:Lyngby Hovedgade.map')
+ super(TestWbGeoShapeNonDry, self).setUp()
+
+ def test_WbGeoShape_page(self):
+ """Test WbGeoShape page."""
+ q = pywikibot.WbGeoShape(self.page)
+ q_val = u'Data:Lyngby Hovedgade.map'
+ self.assertEqual(q.toWikibase(), q_val)
+
+ def test_WbGeoShape_page_and_site(self):
+ """Test WbGeoShape from page and site."""
+ q = pywikibot.WbGeoShape(self.page, self.get_repo())
+ q_val = u'Data:Lyngby Hovedgade.map'
+ self.assertEqual(q.toWikibase(), q_val)
+
+ def test_WbGeoShape_equality(self):
+ """Test WbGeoShape equality."""
+ q = pywikibot.WbGeoShape(self.page, self.get_repo())
+ self.assertEqual(q, q)
+
+ def test_WbGeoShape_fromWikibase(self):
+ """Test WbGeoShape.fromWikibase()
instantiating."""
+ repo = self.get_repo()
+ q = pywikibot.WbGeoShape.fromWikibase(
+ 'Data:Lyngby Hovedgade.map', repo)
+ self.assertEqual(q.toWikibase(), 'Data:Lyngby Hovedgade.map')
+
+ def test_WbGeoShape_error_on_non_page(self):
+ """Test WbGeoShape error handling when given a
non-page."""
+ self.assertRaises(ValueError, pywikibot.WbGeoShape,
+ 'A string', self.get_repo())
+
+ def test_WbGeoShape_error_on_non_exitant_page(self):
+ """Test WbGeoShape error handling of a non-existant
page."""
+ page = Page(self.commons, 'Non-existant page... really')
+ self.assertRaises(ValueError, pywikibot.WbGeoShape,
+ page, self.get_repo())
+
+ def test_WbGeoShape_error_on_wrong_site(self):
+ """Test WbGeoShape error handling of a page on non-filerepo
site."""
+ repo = self.get_repo()
+ page = Page(repo, 'Q123')
+ self.assertRaises(ValueError, pywikibot.WbGeoShape,
+ page, self.get_repo())
+
+ def test_WbGeoShape_error_on_wrong_page_type(self):
+ """Test WbGeoShape error handling of a non-map
page."""
+ non_data_page = Page(self.commons, 'File:Foo.jpg')
+ non_map_page = Page(self.commons, 'Data:Templatedata/Graph:Lines.tab')
+ self.assertRaises(ValueError, pywikibot.WbGeoShape,
+ non_data_page, self.get_repo())
+ self.assertRaises(ValueError, pywikibot.WbGeoShape,
+ non_map_page, self.get_repo())
+
+
class TestItemPageExtensibility(TestCase):
"""Test ItemPage extensibility."""
--
To view, visit
https://gerrit.wikimedia.org/r/346700
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ia96d35519163307227159ccece5981783ce8b558
Gerrit-PatchSet: 6
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Lokal Profil <lokal.profil(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: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>