Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Table of releases
* added bing batch forward & reverse geocoding
* added mapquest batch geocoding
* fixed google ratelimits
* added geocode.xyz support

## [1.32.1] - 2017-09-16

Expand Down
2 changes: 1 addition & 1 deletion geocoder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from geocoder.api import nokia, osm, tomtom, geolytica, arcgis, opencage, locationiq # noqa
from geocoder.api import maxmind, ipinfo, freegeoip, ottawa, here, baidu, gaode, w3w # noqa
from geocoder.api import yandex, mapzen, komoot, tamu, geocodefarm, tgos, uscensus # noqa
from geocoder.api import gisgraphy # noqa
from geocoder.api import gisgraphy, geocodexyz # noqa

# EXTRAS
from geocoder.api import timezone, elevation, places, ip, canadapost, reverse, distance, location # noqa
Expand Down
12 changes: 12 additions & 0 deletions geocoder/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from geocoder.freegeoip import FreeGeoIPQuery
from geocoder.gaode import GaodeQuery
from geocoder.geocodefarm import GeocodeFarmQuery
from geocoder.geocodexyz import GeocodeXYZQuery
from geocoder.geolytica import GeolyticaQuery
from geocoder.gisgraphy import GisgraphyQuery
from geocoder.here import HereQuery
Expand Down Expand Up @@ -173,6 +174,9 @@
'geocode': GisgraphyQuery,
'reverse': GisgraphyReverse,
},
'geocodexyz': {
'geocode': GeocodeXYZQuery,
},
}


Expand Down Expand Up @@ -381,6 +385,14 @@ def geolytica(location, **kwargs):
return get(location, provider='geolytica', **kwargs)


def geocodexyz(location, **kwargs):
"""Geocode.xyz Provider

:param ``location``: Your search location you want geocoded.
"""
return get(location, provider='geocodexyz', **kwargs)


def opencage(location, **kwargs):
"""Opencage Provider

Expand Down
126 changes: 126 additions & 0 deletions geocoder/geocodexyz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/python
# coding: utf8
from __future__ import absolute_import

import logging

from geocoder.base import OneResult, MultipleResultsQuery
from geocoder.keys import geocodexyz_key


class GeocodeXYZResult(OneResult):

def _get_value(self, json_obj, key, type=None):
value = json_obj.get(key, {})
if value:
value = value.strip()
if type and value:
return type(value)
return value

def __init__(self, json_content):
# create safe shortcuts
self._standard = json_content.get('standard', {})

# proceed with super.__init__
super(GeocodeXYZResult, self).__init__(json_content)

@property
def lat(self):
return self._get_value(self.raw, 'latt', float)

@property
def lng(self):
return self._get_value(self.raw, 'longt', float)

@property
def remaining_credits(self):
return self._get_value(self.raw, 'remaining_credits', int)

@property
def confidence(self):
return self._get_value(self._standard, 'confidence', float)

@property
def country(self):
return self._get_value(self._standard, 'countryname')

@property
def country_code(self):
return self._get_value(self._standard, 'prov')

@property
def city(self):
return self._get_value(self._standard, 'city')

@property
def region(self):
return self._get_value(self._standard, 'region')

@property
def street(self):
return self._get_value(self._standard, 'addresst')

@property
def postal(self):
return self._get_value(self._standard, 'postal')

@property
def housenumber(self):
return self._get_value(self._standard, 'stnumber')

@property
def address(self):
if self.street_number:
return u'{0} {1}, {2}'.format(
self.street_number, self.route, self.locality)
elif self.route and self.route != 'un-known':
return u'{0}, {1}'.format(self.route, self.locality)
else:
return self.locality


class GeocodeXYZQuery(MultipleResultsQuery):
"""API to retrieve data from geocode.xyz

Geocode.xyz uses only open data sources, including but not limited to
OpenStreetMap, Geonames, Osmnames, openaddresses.io, UK Ordnance Survey,
www.dati.gov.it, data.europa.eu/euodp/en/data, PSMA Geocoded National
Address File (Australia), etc.

"""
provider = 'geocodexyz'
method = 'geocode'

_URL = 'https://geocode.xyz/'
_RESULT_CLASS = GeocodeXYZResult
_KEY = geocodexyz_key
_KEY_MANDATORY = False

def _build_params(self, location, provider_key, **kwargs):
params = {
'json': 1,
'locate': location,
}
if 'region' in kwargs:
region = kwargs.pop('region')
if region:
params.update({'region': region})
if 'strictmode' in kwargs:
params.update({'strictmode': kwargs.pop('strictmode')})
if 'strict' in kwargs:
params.update({'strict': kwargs.pop('strict')})
if 'auth' in kwargs:
params.update({'auth': kwargs.pop('auth')})
else:
params.update({'auth': provider_key})
return params

def _adapt_results(self, json_response):
return [json_response]


if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
g = GeocodeXYZQuery('1552 Payette dr., Ottawa')
g.debug()
1 change: 1 addition & 0 deletions geocoder/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
baidu_key = os.environ.get('BAIDU_API_KEY')
baidu_security_key = os.environ.get('BAIDU_SECURITY_KEY')
gaode_key = os.environ.get('GAODE_API_KEY')
geocodexyz_key = os.environ.get('GEOCODEXYZ_API_KEY')
w3w_key = os.environ.get('W3W_API_KEY')
mapbox_access_token = os.environ.get('MAPBOX_ACCESS_TOKEN')
google_key = os.environ.get('GOOGLE_API_KEY')
Expand Down
1 change: 1 addition & 0 deletions tests/test_geocoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def test_entry_points():
geocoder.tamu
geocoder.geocodefarm
geocoder.uscensus
geocoder.geocodexyz


def test_location():
Expand Down
16 changes: 16 additions & 0 deletions tests/test_geocodexyz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/python
# coding: utf8

import geocoder

location = '1552 Payette dr., Ottawa'


def test_geocodexyz():
g = geocoder.geocodexyz(location)
assert g.ok
osm_count, fields_count = g.debug()[0]
assert osm_count >= 5
assert fields_count >= 11
assert isinstance(g.confidence, float)
assert isinstance(g.remaining_credits, int)