web_updated_code/.venv/Lib/site-packages/mapbox/services/geocoding.py
2024-10-28 13:57:19 +05:30

134 lines
6.0 KiB
Python

# mapbox
from iso3166 import countries
from uritemplate import URITemplate
from mapbox.errors import InvalidCountryCodeError, InvalidPlaceTypeError
from mapbox.services.base import Service
class Geocoder(Service):
"""Access to the Geocoding API V5"""
api_name = 'geocoding'
api_version = 'v5'
precision = {'reverse': 5, 'proximity': 3}
def __init__(self, name='mapbox.places', access_token=None, cache=None,
host=None):
"""Constructs a Geocoding Service object.
:param name: name of a geocoding dataset.
:param access_token: Mapbox access token string.
:param cache: CacheControl cache instance (Dict or FileCache).
"""
self.name = name
super(Geocoder, self).__init__(access_token=access_token, cache=cache,
host=host)
def _validate_country_codes(self, ccs):
"""Validate country code filters for use in requests."""
for cc in ccs:
if cc not in self.country_codes:
raise InvalidCountryCodeError(cc)
return {'country': ",".join(ccs)}
def _validate_place_types(self, types):
"""Validate place types and return a mapping for use in requests."""
for pt in types:
if pt not in self.place_types:
raise InvalidPlaceTypeError(pt)
return {'types': ",".join(types)}
def forward(self, address, types=None, lon=None, lat=None,
country=None, bbox=None, limit=None, languages=None):
"""Returns a Requests response object that contains a GeoJSON
collection of places matching the given address.
`response.geojson()` returns the geocoding result as GeoJSON.
`response.status_code` returns the HTTP API status code.
Place results may be constrained to those of one or more types
or be biased toward a given longitude and latitude.
See: https://www.mapbox.com/api-documentation/search/#geocoding."""
uri = URITemplate(self.baseuri + '/{dataset}/{query}.json').expand(
dataset=self.name, query=address.encode('utf-8'))
params = {}
if country:
params.update(self._validate_country_codes(country))
if types:
params.update(self._validate_place_types(types))
if lon is not None and lat is not None:
params.update(proximity='{0},{1}'.format(
round(float(lon), self.precision.get('proximity', 3)),
round(float(lat), self.precision.get('proximity', 3))))
if languages:
params.update(language=','.join(languages))
if bbox is not None:
params.update(bbox='{0},{1},{2},{3}'.format(*bbox))
if limit is not None:
params.update(limit='{0}'.format(limit))
resp = self.session.get(uri, params=params)
self.handle_http_error(resp)
# for consistency with other services
def geojson():
return resp.json()
resp.geojson = geojson
return resp
def reverse(self, lon, lat, types=None, limit=None):
"""Returns a Requests response object that contains a GeoJSON
collection of places near the given longitude and latitude.
`response.geojson()` returns the geocoding result as GeoJSON.
`response.status_code` returns the HTTP API status code.
See: https://www.mapbox.com/api-documentation/search/#reverse-geocoding."""
uri = URITemplate(self.baseuri + '/{dataset}/{lon},{lat}.json').expand(
dataset=self.name,
lon=str(round(float(lon), self.precision.get('reverse', 5))),
lat=str(round(float(lat), self.precision.get('reverse', 5))))
params = {}
if types:
types = list(types)
params.update(self._validate_place_types(types))
if limit is not None:
if not types or len(types) != 1:
raise InvalidPlaceTypeError(
'Specify a single type when using limit with reverse geocoding')
params.update(limit='{0}'.format(limit))
resp = self.session.get(uri, params=params)
self.handle_http_error(resp)
# for consistency with other services
def geojson():
return resp.json()
resp.geojson = geojson
return resp
@property
def country_codes(self):
"""A list of valid country codes"""
return [c.alpha2.lower() for c in countries]
@property
def place_types(self):
"""A mapping of place type names to descriptions"""
return {
'address': "A street address with house number. Examples: 1600 Pennsylvania Ave NW, 1051 Market St, Oberbaumstrasse 7.",
'country': "Sovereign states and other political entities. Examples: United States, France, China, Russia.",
'place': "City, town, village or other municipality relevant to a country's address or postal system. Examples: Cleveland, Saratoga Springs, Berlin, Paris.",
'locality': "A smaller area within a place that possesses official status and boundaries. Examples: Oakleigh (Melbourne)",
'neighborhood': "A smaller area within a place, often without formal boundaries. Examples: Montparnasse, Downtown, Haight-Ashbury.",
'poi': "Places of interest including commercial venues, major landmarks, parks, and other features. Examples: Subway Restaurant, Yosemite National Park, Statue of Liberty.",
'poi.landmark': "Places of interest that are particularly notable or long-lived like parks, places of worship and museums. A strict subset of the poi place type. Examples: Yosemite National Park, Statue of Liberty.",
'postcode': "Postal code, varies by a country's postal system. Examples: 20009, CR0 3RL.",
'district': "Second order administrative division. Only used when necessary. Examples: Tianjin, Beijing",
'region': "First order administrative divisions within a country, usually provinces or states. Examples: California, Ontario, Essonne."}