http://www.mediawiki.org/wiki/Special:Code/pywikipedia/11653
Revision: 11653 Author: legoktm Date: 2013-06-16 07:49:27 +0000 (Sun, 16 Jun 2013) Log Message: ----------- Overhaul Coordinate support, implement GeoData extension * Added support for fetching a page's coordinates * Wikidata globes are now stored in the family file * Conversion between GeoData's "dim" to Wikibase's "precision" needs work
Modified Paths: -------------- branches/rewrite/pywikibot/__init__.py branches/rewrite/pywikibot/data/api.py branches/rewrite/pywikibot/families/wikidata_family.py branches/rewrite/pywikibot/page.py branches/rewrite/pywikibot/site.py
Modified: branches/rewrite/pywikibot/__init__.py =================================================================== --- branches/rewrite/pywikibot/__init__.py 2013-06-16 07:39:06 UTC (rev 11652) +++ branches/rewrite/pywikibot/__init__.py 2013-06-16 07:49:27 UTC (rev 11653) @@ -93,60 +93,90 @@ For now its just being used for DataSite, but in the future we can use it for the GeoData extension. """ - def __init__(self, lat, lon, alt=None, precision=0.1, globe='earth'): + def __init__(self, lat, lon, alt=None, precision=None, globe='earth', + typ="", name="", dim=None, site=None): """ @param lat: Latitude @type lat: float @param lon: Longitute - @param lon: float + @type lon: float @param alt: Altitute? TODO FIXME @param precision: precision @type precision: float - @param globe: Which Wikidata globe to use + @param globe: Which globe the point is on @type globe: str + @param typ: The type of coordinate point + @type typ: str + @param name: The name + @type name: str + @param dim: Dimension (in meters) + @type dim: int """ self.lat = lat self.lon = lon self.alt = alt self.precision = precision - self.globe = globe + self.globe = globe.lower() + self.type = typ + self.name = name + self.dim = dim + if not site: + self.site = Site().data_repository() + else: + self.site = site #Copied from [[mw:Extension:GeoData]] - if not globe in ['earth', 'mercury', 'venus', 'moon', - 'mars', 'phobos', 'deimos', 'ganymede', - 'callisto', 'io', 'europa', 'mimas', - 'enceladus', 'tethys', 'dione', - 'rhea', 'titan', 'hyperion', 'iapetus', - 'phoebe', 'miranda', 'ariel', 'umbriel', - 'titania', 'oberon', 'triton', 'pluto']: - raise ValueError(u"%s is not a supported globe." % globe) + if not self.globe in ['earth', 'mercury', 'venus', 'moon', + 'mars', 'phobos', 'deimos', 'ganymede', + 'callisto', 'io', 'europa', 'mimas', + 'enceladus', 'tethys', 'dione', + 'rhea', 'titan', 'hyperion', 'iapetus', + 'phoebe', 'miranda', 'ariel', 'umbriel', + 'titania', 'oberon', 'triton', 'pluto']: + raise ValueError(u"%s is not a supported globe." % self.globe)
+ def __repr__(self): + string = 'Coordinate(%s, %s' % (self.lat, self.lon) + if self.globe != 'earth': + string += ', globe="%s"' % self.globe + string += ')' + return string + def toWikibase(self): """ Function which converts the data to a JSON object for the Wikibase API. FIXME Should this be in the DataSite object? """ - globes = {'earth': 'http://www.wikidata.org/entity/Q2%27%7D - if not self.globe in globes: + if not self.globe in self.site.globes(): raise NotImplementedError(u"%s is not supported in Wikibase yet." % self.globe) return {'latitude': self.lat, 'longitude': self.lon, 'altitude': self.alt, - 'globe': globes[self.globe], + 'globe': self.site.globes()[self.globe], 'precision': self.precision, }
@staticmethod - def fromWikibase(data): + def fromWikibase(data, site): """Constructor to create an object from Wikibase's JSON output""" - globes = {'http://www.wikidata.org/entity/Q2': 'earth'} - # TODO FIXME ^ + globes = {} + for k in site.globes(): + globes[site.globes()[k]] = k + return Coordinate(data['latitude'], data['longitude'], - data['altitude'], data['precision'], - globes[data['globe']]) + data['altitude'], data['precision'], + globes[data['globe']], site=site)
+ def dimToPrecision(self): + """Convert dim from GeoData to Wikibase's Precision""" + raise NotImplementedError
+ def precisionToDim(self): + """Convert precision from Wikibase to GeoData's dim""" + raise NotImplementedError
+ + def deprecated(instead=None): """Decorator to output a method deprecation warning.
Modified: branches/rewrite/pywikibot/data/api.py =================================================================== --- branches/rewrite/pywikibot/data/api.py 2013-06-16 07:39:06 UTC (rev 11652) +++ branches/rewrite/pywikibot/data/api.py 2013-06-16 07:49:27 UTC (rev 11653) @@ -971,7 +971,20 @@ links.append(link) page._langlinks = links
+ if "coordinates" in pagedict: + coords = [] + for co in pagedict['coordinates']: + coord = pywikibot.Coordinate(lat=co['lat'], + lon=co['lon'], + typ=co['type'], + name=co['name'], + dim=co['dim'], + globe=co.get('globe', 'earth'), # See [[gerrit:67886]] + ) + coords.append(coord) + page._coords = coords
+ if __name__ == "__main__": from pywikibot import Site, logging logging.getLogger("pywiki.data.api").setLevel(logging.DEBUG)
Modified: branches/rewrite/pywikibot/families/wikidata_family.py =================================================================== --- branches/rewrite/pywikibot/families/wikidata_family.py 2013-06-16 07:39:06 UTC (rev 11652) +++ branches/rewrite/pywikibot/families/wikidata_family.py 2013-06-16 07:49:27 UTC (rev 11653) @@ -26,3 +26,7 @@ else: return ('wikidata', 'wikidata') if code == 'wikidata' else ('repo', 'wikidata') + + def globes(self, code): + """Supported globes for Coordinate datatype""" + return {'earth': 'http://www.wikidata.org/entity/Q2%27%7D
Modified: branches/rewrite/pywikibot/page.py =================================================================== --- branches/rewrite/pywikibot/page.py 2013-06-16 07:39:06 UTC (rev 11652) +++ branches/rewrite/pywikibot/page.py 2013-06-16 07:49:27 UTC (rev 11653) @@ -1088,6 +1088,20 @@ """ return self.site.page_extlinks(self, step=step, total=total)
+ def coordinates(self, primary_only=False): + """Return a list of Coordinate objects for points + on the page using [[mw:Extension:GeoData]] + + @param primary_only: Only return the coordinate indicated to be primary + @return: A list of Coordinate objects + """ + if not hasattr(self, '_coords'): + self.site.loadcoordinfo(self) + if primary_only: + return self._coords[0] + else: + return self._coords + def getRedirectTarget(self): """Return a Page object for the target this Page redirects to.
@@ -2624,7 +2638,7 @@ claim.target = ImagePage(site.image_repository(), 'File:' + data['mainsnak']['datavalue']['value']) elif claim.getType() == 'globecoordinate': - claim.target = pywikibot.Coordinate.fromWikibase(data['mainsnak']['datavalue']['value']) + claim.target = pywikibot.Coordinate.fromWikibase(data['mainsnak']['datavalue']['value'], site) else: #This covers string type claim.target = data['mainsnak']['datavalue']['value']
Modified: branches/rewrite/pywikibot/site.py =================================================================== --- branches/rewrite/pywikibot/site.py 2013-06-16 07:39:06 UTC (rev 11652) +++ branches/rewrite/pywikibot/site.py 2013-06-16 07:49:27 UTC (rev 11653) @@ -1182,6 +1182,24 @@ continue api.update_page(page, pageitem)
+ def loadcoordinfo(self, page): + """Load [[mw:Extension:GeoData]] info""" + #prop=coordinates&titles=Wikimedia Foundation&format=jsonfm&coprop=type|name|dim|country|region&coprimary=all + title = page.title(withSection=False) + query = self._generator(api.PropertyGenerator, + type_arg="coordinates", + titles=title.encode(self.encoding()), + coprop=['type', 'name', 'dim', + 'country', 'region'], + coprimary='all') + for pageitem in query: + if not self.sametitle(pageitem['title'], title): + pywikibot.warning( + u"loadcoordinfo: Query on %s returned data on '%s'" + % (page, pageitem['title'])) + continue + api.update_page(page, pageitem) + def loadimageinfo(self, page, history=False): """Load image info from api and save in page attributes