def _check_status(status): """ Validates error statuses. """ if status == 0: # When there are no results, just return. return if status == 1: raise GeocoderServiceError('Internal server error.') elif status == 2: raise GeocoderQueryError('Invalid request.') elif status == 3: raise GeocoderAuthenticationFailure('Authentication failure.') elif status == 4: raise GeocoderQuotaExceeded('Quota validate failure.') elif status == 5: raise GeocoderQueryError('AK Illegal or Not Exist.') elif status == 101: raise GeocoderAuthenticationFailure('No AK') elif status == 102: raise GeocoderAuthenticationFailure('MCODE Error') elif status == 200: raise GeocoderAuthenticationFailure('Invalid AK') elif status == 211: raise GeocoderAuthenticationFailure('Invalid SN') elif 200 <= status < 300: raise GeocoderAuthenticationFailure('Authentication Failure') elif 300 <= status < 500: raise GeocoderQuotaExceeded('Quota Error.') else: raise GeocoderQueryError('Unknown error. Status: %r' % status)
def _check_status(status): """ Validates error statuses. """ if status == 'OVER_QUERY_LIMIT': raise GeocoderQuotaExceeded( 'The given key has gone over the requests limit in the 24' ' hour period or has submitted too many requests in too' ' short a period of time.') elif status == 'REQUEST_DENIED': raise GeocoderQueryError('Your request was denied.') elif status == 'INVALID_REQUEST': raise GeocoderQueryError('Probably missing address or latlng.') else: raise GeocoderQueryError('Unknown error.')
def _check_status(self, status): # https://developers.google.com/maps/documentation/geocoding/overview#StatusCodes if status == 'ZERO_RESULTS': # When there are no results, just return. return if status in ('OVER_QUERY_LIMIT', 'OVER_DAILY_LIMIT'): raise GeocoderQuotaExceeded( 'The given key has gone over the requests limit in the 24' ' hour period or has submitted too many requests in too' ' short a period of time.') elif status == 'REQUEST_DENIED': raise GeocoderQueryError('Your request was denied.') elif status == 'INVALID_REQUEST': raise GeocoderQueryError('Probably missing address or latlng.') else: raise GeocoderQueryError('Unknown error.')
def _geocoder_exception_handler(self, error): """Custom exception handling for invalid queries and exceeded quotas. Geocod.io returns a ``422`` status code for invalid queries, which is not mapped in :const:`~geopy.geocoders.base.ERROR_CODE_MAP`. The service also returns a ``403`` status code for exceeded quotas instead of the ``429`` code mapped in :const:`~geopy.geocoders.base.ERROR_CODE_MAP` """ if not isinstance(error, AdapterHTTPError): return if error.status_code is None or error.text is None: return if error.status_code == 422: error_message = self._get_error_message(error) if ( 'could not geocode address' in error_message.lower() and 'postal code or city required' in error_message.lower() ): return NONE_RESULT raise GeocoderQueryError(error_message) from error if error.status_code == 403: error_message = self._get_error_message(error) quota_exceeded_snippet = "You can't make this request as it is " \ "above your daily maximum." if quota_exceeded_snippet in error_message: raise GeocoderQuotaExceeded(error_message) from error
def createLocator(api_key = None): """ Parameters ---------- api_key : string, optional Google Cloud API key for geocoding. The default is None. If an invalid key is given the function will raise an error. Raises ------ GeocoderQueryError geopy.exc.GeocoderQueryError if the request fails. Returns ------- locator : TYPE geocoding object using the GoogleV3 cloud API. """ locator = GoogleV3(api_key=api_key, user_agent="UoG_Medicine_Placement_Sorter") try: logging.info('Test request starting') locator.geocode('UK G1 Postcode') # test request logging.info('Test request complete') return locator except GeocoderQueryError: logging.info('Test request failed') raise GeocoderQueryError('Invalid API key.')
def _check_status(status): """ Validates error statuses. """ if status == 0: # When there are no results, just return. return if status == 110: raise GeocoderQueryError(u'请求来源未被授权.') elif status == 306: raise GeocoderQueryError(u'请求有护持信息请检查字符串.') elif status == 310: raise GeocoderAuthenticationFailure(u'请求参数信息有误.') elif status == 311: raise GeocoderQuotaExceeded(u'key格式错误.') else: raise GeocoderQueryError('Unknown error: %s' % status)
def timezone(self, location, at_time=None, timeout=None): """ **This is an unstable API.** Finds the timezone a `location` was in for a specified `at_time`, and returns a pytz timezone object. .. versionadded:: 1.2.0 :param location: The coordinates for which you want a timezone. :type location: :class:`geopy.point.Point`, list or tuple of (latitude, longitude), or string as "%(latitude)s, %(longitude)s" :param at_time: The time at which you want the timezone of this location. This is optional, and defaults to the time that the function is called in UTC. :type at_time integer, long, float, datetime: :rtype: pytz timezone """ if not pytz_available: raise ImportError( 'pytz must be installed in order to locate timezones. ' ' Install with `pip install geopy -e ".[timezone]"`.') location = self._coerce_point_to_string(location) if isinstance(at_time, Number): timestamp = at_time elif isinstance(at_time, datetime): timestamp = timegm(at_time.utctimetuple()) elif at_time is None: timestamp = timegm(datetime.utcnow().utctimetuple()) else: raise GeocoderQueryError("`at_time` must be an epoch integer or " "datetime.datetime object") params = { "location": location, "timestamp": timestamp, } if self.api_key: params['key'] = self.api_key url = "?".join((self.tz_api, urlencode(params))) logger.debug("%s.timezone: %s", self.__class__.__name__, url) response = self._call_geocoder(url, timeout=timeout) try: tz = timezone(response["timeZoneId"]) except UnknownTimeZoneError: raise GeocoderParseError( "pytz could not parse the timezone identifier (%s) " "returned by the service." % response["timeZoneId"]) except KeyError: raise GeocoderParseError( "geopy could not find a timezone in this response: %s" % response) return tz
def _check_status(status): """ Validates error statuses. """ if status == '0': # When there are no results, just return. return if status == '1': raise GeocoderQueryError('Internal server error.') elif status == '2': raise GeocoderQueryError('Invalid request.') elif status == '3': raise GeocoderAuthenticationFailure('Authentication failure.') elif status == '4': raise GeocoderQuotaExceeded('Quota validate failure.') elif status == '5': raise GeocoderQueryError('AK Illegal or Not Exist.') elif status == '101': raise GeocoderQueryError('Your request was denied.') elif status == '102': raise GeocoderQueryError('IP/SN/SCODE/REFERER Illegal:') elif status == '2xx': raise GeocoderQueryError('Has No Privilleges.') elif status == '3xx': raise GeocoderQuotaExceeded('Quota Error.') else: raise GeocoderQueryError('Unknown error')
def _check_status(self, status): """ Validates error statuses. """ status_code = status['code'] if status_code == 429: # Rate limit exceeded raise GeocoderQuotaExceeded( 'The given key has gone over the requests limit in the 24' ' hour period or has submitted too many requests in too' ' short a period of time.') if status_code == 200: # When there are no results, just return. return if status_code == 403: raise GeocoderQueryError('Your request was denied.') else: raise GeocoderQueryError('Unknown error.')
def geocode(self, query, *, max_results=25, set_back=0, location_descriptor='any', exactly_one=True, timeout=DEFAULT_SENTINEL): """ Return a location point by address. :param str query: The address or query you wish to geocode. :param int max_results: The maximum number of resutls to request. :param float set_back: The distance to move the accessPoint away from the curb (in meters) and towards the interior of the parcel. location_descriptor must be set to accessPoint for set_back to take effect. :param str location_descriptor: The type of point requested. It can be any, accessPoint, frontDoorPoint, parcelPoint, rooftopPoint and routingPoint. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ params = {'addressString': query} if set_back != 0: params['setBack'] = set_back if location_descriptor not in [ 'any', 'accessPoint', 'frontDoorPoint', 'parcelPoint', 'rooftopPoint', 'routingPoint' ]: raise GeocoderQueryError( "You did not provided a location_descriptor " "the webservice can consume. It should be any, accessPoint, " "frontDoorPoint, parcelPoint, rooftopPoint or routingPoint.") params['locationDescriptor'] = location_descriptor if exactly_one: max_results = 1 params['maxResults'] = max_results url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) callback = partial(self._parse_json, exactly_one=exactly_one) return self._call_geocoder(url, callback, timeout=timeout)
def _normalize_timezone_at_time(self, at_time): if at_time is None: timestamp = timegm(datetime.utcnow().utctimetuple()) elif isinstance(at_time, datetime): # Naive datetimes are silently treated as UTC. # Timezone-aware datetimes are handled correctly. timestamp = timegm(at_time.utctimetuple()) else: raise GeocoderQueryError( "`at_time` must be an instance of `datetime.datetime`") return timestamp
def _geocoder_exception_handler(self, error): """Custom exception handling for invalid queries and exceeded quotas. Geocod.io returns a ``422`` status code for invalid queries, which is not mapped in :const:`~geopy.geocoders.base.ERROR_CODE_MAP`. The service also returns a ``403`` status code for exceeded quotas instead of the ``429`` code mapped in :const:`~geopy.geocoders.base.ERROR_CODE_MAP` """ if error.status_code == 422: error_message = self._get_error_message(error) raise GeocoderQueryError(error_message) if error.status_code == 403: error_message = self._get_error_message(error) quota_exceeded_snippet = "You can't make this request as it is " \ "above your daily maximum." if quota_exceeded_snippet in error_message: raise GeocoderQuotaExceeded(error_message)
def _parse_json(self, places, exactly_one): if not places: return None if isinstance(places, collections.abc.Mapping) and 'error' in places: if places['error'] == 'Unable to geocode': # no results in reverse return None else: raise GeocoderQueryError(places['error']) if not isinstance(places, collections.abc.Sequence): places = [places] if exactly_one: return self._parse_code(places[0]) else: return [self._parse_code(place) for place in places]
def _normalize_timezone_at_time(self, at_time): if at_time is None: timestamp = timegm(datetime.utcnow().utctimetuple()) elif isinstance(at_time, Number): warnings.warn( 'Support for `at_time` as int/float is deprecated ' 'and will be removed in geopy 2.0. ' 'Pass a `datetime.datetime` instance instead.', DeprecationWarning, stacklevel=3) timestamp = at_time elif isinstance(at_time, datetime): # Naive datetimes are silently treated as UTC. # Timezone-aware datetimes are handled correctly. timestamp = timegm(at_time.utctimetuple()) else: raise GeocoderQueryError( "`at_time` must be an instance of `datetime.datetime`") return timestamp
def _format_bounding_box(bbox, output_format="%(lat1)s,%(lon1)s,%(lat2)s,%(lon2)s"): """ Transform bounding box boundaries to a string matching `output_format` from the following formats: - [Point(lat1, lon1), Point(lat2, lon2)] - [[lat1, lon1], [lat2, lon2]] - ["lat1,lon1", "lat2,lon2"] It is guaranteed that lat1 <= lat2 and lon1 <= lon2. """ if len(bbox) != 2: raise GeocoderQueryError("Unsupported format for a bounding box") p1, p2 = bbox p1, p2 = Point(p1), Point(p2) return output_format % dict(lat1=min(p1.latitude, p2.latitude), lon1=min(p1.longitude, p2.longitude), lat2=max(p1.latitude, p2.latitude), lon2=max(p1.longitude, p2.longitude))
def reverse(self, query, *, reverse_geocode_preference=('StreetAddress', ), maximum_responses=25, filtering='', exactly_one=True, timeout=DEFAULT_SENTINEL): """ Return an address by location point. :param query: The coordinates for which you wish to obtain the closest human-readable addresses. :type query: :class:`geopy.point.Point`, list or tuple of ``(latitude, longitude)``, or string as ``"%(latitude)s, %(longitude)s"``. :param list reverse_geocode_preference: Enable to set expected results type. It can be `StreetAddress` or `PositionOfInterest`. Default is set to `StreetAddress`. :param int maximum_responses: The maximum number of responses to ask to the API in the query body. :param str filtering: Provide string that help setting geocoder filter. It contains an XML string. See examples in documentation and ignfrance.py file in directory tests. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ sub_request = """ <ReverseGeocodeRequest> {reverse_geocode_preference} <Position> <gml:Point> <gml:pos>{query}</gml:pos> </gml:Point> {filtering} </Position> </ReverseGeocodeRequest> """ xml_request = self.xml_request.format( method_name='ReverseGeocodeRequest', sub_request=sub_request, maximum_responses=maximum_responses) for pref in reverse_geocode_preference: if pref not in ('StreetAddress', 'PositionOfInterest'): raise GeocoderQueryError( '`reverse_geocode_preference` must contain ' 'one or more of: StreetAddress, PositionOfInterest') point = self._coerce_point_to_string(query, "%(lat)s %(lon)s") reverse_geocode_preference = '\n'.join( ('<ReverseGeocodePreference>%s</ReverseGeocodePreference>' % pref for pref in reverse_geocode_preference)) request_string = xml_request.format( maximum_responses=maximum_responses, query=point, reverse_geocode_preference=reverse_geocode_preference, filtering=filtering) url = "?".join((self.api, urlencode({'xls': request_string}))) logger.debug("%s.reverse: %s", self.__class__.__name__, url) callback = partial(self._parse_xml, exactly_one=exactly_one, is_reverse=True, is_freeform='false') return self._request_raw_content(url, callback, timeout=timeout)
def geocode(self, query, *, query_type='StreetAddress', maximum_responses=25, is_freeform=False, filtering=None, exactly_one=True, timeout=DEFAULT_SENTINEL): """ Return a location point by address. :param str query: The query string to be geocoded. :param str query_type: The type to provide for geocoding. It can be `PositionOfInterest`, `StreetAddress` or `CadastralParcel`. `StreetAddress` is the default choice if none provided. :param int maximum_responses: The maximum number of responses to ask to the API in the query body. :param str is_freeform: Set if return is structured with freeform structure or a more structured returned. By default, value is False. :param str filtering: Provide string that help setting geocoder filter. It contains an XML string. See examples in documentation and ignfrance.py file in directory tests. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ # Check if acceptable query type if query_type not in [ 'PositionOfInterest', 'StreetAddress', 'CadastralParcel' ]: raise GeocoderQueryError("""You did not provided a query_type the webservice can consume. It should be PositionOfInterest, 'StreetAddress or CadastralParcel""") # Check query validity for CadastralParcel if query_type == 'CadastralParcel' and len(query.strip()) != 14: raise GeocoderQueryError("""You must send a string of fourteen characters long to match the cadastre required code""") sub_request = """ <GeocodeRequest returnFreeForm="{is_freeform}"> <Address countryCode="{query_type}"> <freeFormAddress>{query}</freeFormAddress> {filtering} </Address> </GeocodeRequest> """ xml_request = self.xml_request.format( method_name='LocationUtilityService', sub_request=sub_request, maximum_responses=maximum_responses) # Manage type change for xml case sensitive if is_freeform: is_freeform = 'true' else: is_freeform = 'false' # Manage filtering value if filtering is None: filtering = '' # Create query using parameters request_string = xml_request.format(is_freeform=is_freeform, query=query, query_type=query_type, filtering=filtering) params = {'xls': request_string} url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) callback = partial(self._parse_xml, is_freeform=is_freeform, exactly_one=exactly_one) return self._request_raw_content(url, callback, timeout=timeout)
def geocode(self, query, *, exactly_one=True, timeout=DEFAULT_SENTINEL, limit=None, addressdetails=False, language=False, geometry=None, extratags=False, country_codes=None, viewbox=None, bounded=False, featuretype=None, namedetails=False): """ Return a location point by address. :param query: The address, query or a structured query you wish to geocode. For a structured query, provide a dictionary whose keys are one of: `street`, `city`, `county`, `state`, `country`, or `postalcode`. For more information, see Nominatim's documentation for `structured requests`: https://nominatim.org/release-docs/develop/api/Search :type query: dict or str :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param int limit: Maximum amount of results to return from Nominatim. Unless exactly_one is set to False, limit will always be 1. :param bool addressdetails: If you want in *Location.raw* to include address details such as house_number, city_district, postcode, etc (in a structured form) set it to True :param str language: Preferred language in which to return results. Either uses standard `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`_ accept-language string or a simple comma-separated list of language codes. :param str geometry: If present, specifies whether the geocoding service should return the result's geometry in `wkt`, `svg`, `kml`, or `geojson` formats. This is available via the `raw` attribute on the returned :class:`geopy.location.Location` object. :param bool extratags: Include additional information in the result if available, e.g. wikipedia link, opening hours. :param country_codes: Limit search results to a specific country (or a list of countries). A country_code should be the ISO 3166-1alpha2 code, e.g. ``gb`` for the United Kingdom, ``de`` for Germany, etc. :type country_codes: str or list :type viewbox: list or tuple of 2 items of :class:`geopy.point.Point` or ``(latitude, longitude)`` or ``"%(latitude)s, %(longitude)s"``. :param viewbox: Coordinates to restrict search within. Example: ``[Point(22, 180), Point(-22, -180)]``. :param bool bounded: Restrict the results to only items contained within the bounding view_box. :param str featuretype: If present, restrict results to certain type of features. Allowed values: `country`, `state`, `city`, `settlement`. :param bool namedetails: If you want in *Location.raw* to include namedetails, set it to True. This will be a list of alternative names, including language variants, etc. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if isinstance(query, collections.abc.Mapping): params = { key: val for key, val in query.items() if key in self.structured_query_params } else: params = {'q': query} params.update({'format': 'json'}) if exactly_one: params['limit'] = 1 elif limit is not None: limit = int(limit) if limit < 1: raise ValueError("Limit cannot be less than 1") params['limit'] = limit if viewbox: params['viewbox'] = self._format_bounding_box( viewbox, "%(lon1)s,%(lat1)s,%(lon2)s,%(lat2)s") if bounded: params['bounded'] = 1 if not country_codes: country_codes = [] if isinstance(country_codes, str): country_codes = [country_codes] if country_codes: params['countrycodes'] = ",".join(country_codes) if addressdetails: params['addressdetails'] = 1 if namedetails: params['namedetails'] = 1 if language: params['accept-language'] = language if extratags: params['extratags'] = True if geometry is not None: geometry = geometry.lower() if geometry == 'wkt': params['polygon_text'] = 1 elif geometry == 'svg': params['polygon_svg'] = 1 elif geometry == 'kml': params['polygon_kml'] = 1 elif geometry == 'geojson': params['polygon_geojson'] = 1 else: raise GeocoderQueryError( "Invalid geometry format. Must be one of: " "wkt, svg, kml, geojson.") if featuretype: params['featuretype'] = featuretype url = self._construct_url(self.api, params) logger.debug("%s.geocode: %s", self.__class__.__name__, url) callback = partial(self._parse_json, exactly_one=exactly_one) return self._call_geocoder(url, callback, timeout=timeout)
def reverse(self, query, *, exactly_one=True, timeout=DEFAULT_SENTINEL, feature_code=None, lang=None, find_nearby_type='findNearbyPlaceName'): """ Return an address by location point. :param query: The coordinates for which you wish to obtain the closest human-readable addresses. :type query: :class:`geopy.point.Point`, list or tuple of ``(latitude, longitude)``, or string as ``"%(latitude)s, %(longitude)s"``. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param str feature_code: A GeoNames feature code :param str lang: language of the returned ``name`` element (the pseudo language code 'local' will return it in local language) Full list of supported languages can be found here: https://www.geonames.org/countries/ :param str find_nearby_type: A flag to switch between different GeoNames API endpoints. The default value is ``findNearbyPlaceName`` which returns the closest populated place. Another currently implemented option is ``findNearby`` which returns the closest toponym for the lat/lng query. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ try: lat, lng = self._coerce_point_to_string(query).split(',') except ValueError: raise ValueError("Must be a coordinate pair or Point") if find_nearby_type == 'findNearbyPlaceName': # default if feature_code: raise ValueError( "find_nearby_type=findNearbyPlaceName doesn't support " "the `feature_code` param") params = self._reverse_find_nearby_place_name_params( lat=lat, lng=lng, lang=lang, ) url = "?".join((self.api_reverse, urlencode(params))) elif find_nearby_type == 'findNearby': if lang: raise ValueError( "find_nearby_type=findNearby doesn't support the `lang` param" ) params = self._reverse_find_nearby_params( lat=lat, lng=lng, feature_code=feature_code, ) url = "?".join((self.api_reverse_nearby, urlencode(params))) else: raise GeocoderQueryError( '`%s` find_nearby_type is not supported by geopy' % find_nearby_type) logger.debug("%s.reverse: %s", self.__class__.__name__, url) callback = partial(self._parse_json, exactly_one=exactly_one) return self._call_geocoder(url, callback, timeout=timeout)
def geocode(self, query=None, *, limit=None, exactly_one=True, timeout=DEFAULT_SENTINEL, street=None, city=None, state=None, postal_code=None, country=None): """Return a location point by address. You may either provide a single address string as a ``query`` argument or individual address components using the ``street``, ``city``, ``state``, ``postal_code``, and ``country`` arguments. :param str query: The address or query you wish to geocode. You must either provide this argument or a valid combination of ``street``, ``city``, ``state``, and ``postal_code`` and you may not provide those arguments if also providing ``query``. :param int limit: The maximum number of matches to return. This will be reset to 1 if ``exactly_one`` is ``True``. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param str street: The street address to geocode. If providing this argument you must provide at least one of ``city``, ``state``, or ``postal_code``, and you must *not* provide a ``query`` argument. :param str city: The city of the address to geocode. If providing this argument you must *not* provide a ``query`` argument. :param str state: The state of the address to geocode. If providing this argument you must *not* provide a ``query`` argument. :param str postal_code: The postal code of the address to geocode. If providing this argument you must *not* provide a ``query`` argument. :param str country: The country of the address to geocode. If providing this argument you must *not* provide a ``query`` argument. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if query is not None and \ any(p is not None for p in (city, state, postal_code, country)): raise GeocoderQueryError( 'Address component must not be provided if ' 'query argument is used.') if street is not None and \ not any(p is not None for p in (city, state, postal_code)): raise GeocoderQueryError( 'If street is provided must also provide city, ' 'state, and/or postal_code.') if exactly_one: limit = 1 params = dict(api_key=self.api_key, q=query, street=street, city=city, state=state, postal_code=postal_code, country=country, limit=limit) params = {k: v for k, v in params.items() if v is not None} api = '%s://%s%s' % (self.scheme, self.domain, self.geocode_path) url = "?".join((api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) callback = partial(self._parse_json, exactly_one=exactly_one) return self._call_geocoder(url, callback, timeout=timeout)
def reverse( self, query, exactly_one=DEFAULT_SENTINEL, timeout=DEFAULT_SENTINEL, feature_code=None, lang=None, find_nearby_type='findNearbyPlaceName', ): """ Return an address by location point. .. versionadded:: 1.2.0 :param query: The coordinates for which you wish to obtain the closest human-readable addresses. :type query: :class:`geopy.point.Point`, list or tuple of ``(latitude, longitude)``, or string as ``"%(latitude)s, %(longitude)s"``. :param bool exactly_one: Return one result or a list of results, if available. .. versionchanged:: 1.14.0 Default value for ``exactly_one`` was ``False``, which differs from the conventional default across geopy. Please always pass this argument explicitly, otherwise you would get a warning. In geopy 2.0 the default value will become ``True``. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param str feature_code: A GeoNames feature code .. versionadded:: 1.18.0 :param str lang: language of the returned ``name`` element (the pseudo language code 'local' will return it in local language) Full list of supported languages can be found here: https://www.geonames.org/countries/ .. versionadded:: 1.18.0 :param str find_nearby_type: A flag to switch between different GeoNames API endpoints. The default value is ``findNearbyPlaceName`` which returns the closest populated place. Another currently implemented option is ``findNearby`` which returns the closest toponym for the lat/lng query. .. versionadded:: 1.18.0 :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if exactly_one is DEFAULT_SENTINEL: warnings.warn('%s.reverse: default value for `exactly_one` ' 'argument will become True in geopy 2.0. ' 'Specify `exactly_one=False` as the argument ' 'explicitly to get rid of this warning.' % type(self).__name__, DeprecationWarning, stacklevel=2) exactly_one = False try: lat, lng = self._coerce_point_to_string(query).split(',') except ValueError: raise ValueError("Must be a coordinate pair or Point") if find_nearby_type == 'findNearbyPlaceName': # default if feature_code: raise ValueError( "find_nearby_type=findNearbyPlaceName doesn't support " "the `feature_code` param") params = self._reverse_find_nearby_place_name_params( lat=lat, lng=lng, lang=lang, ) url = "?".join((self.api_reverse, urlencode(params))) elif find_nearby_type == 'findNearby': if lang: raise ValueError( "find_nearby_type=findNearby doesn't support the `lang` param" ) params = self._reverse_find_nearby_params( lat=lat, lng=lng, feature_code=feature_code, ) url = "?".join((self.api_reverse_nearby, urlencode(params))) else: raise GeocoderQueryError( '`%s` find_nearby_type is not supported by geopy' % find_nearby_type) logger.debug("%s.reverse: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), exactly_one)
def geocode(self, query, exactly_one=True, timeout=None, addressdetails=False, language=False, geometry=None): # pylint: disable=R0913,W0221 """ Geocode a location query. :param query: The address, query or structured query to geocode you wish to geocode. For a structured query, provide a dictionary whose keys are one of: `street`, `city`, `county`, `state`, `country`, or `postalcode`. For more information, see Nominatim's documentation for "structured requests": https://wiki.openstreetmap.org/wiki/Nominatim :type query: dict or string .. versionchanged:: 1.0.0 :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. .. versionadded:: 0.97 :param addressdetails: If you want in *Location.raw* to include addressdetails such as city_district, etc set it to True :type addressdetails: bool :param string language: Preferred language in which to return results. Either uses standard `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`_ accept-language string or a simple comma-separated list of language codes. :type language: string .. versionadded:: 1.0.0 :param string geometry: If present, specifies whether the geocoding service should return the result's geometry in `wkt`, `svg`, `kml`, or `geojson` formats. This is available via the `raw` attribute on the returned :class:`geopy.location.Location` object. .. versionadded:: 1.3.0 """ if isinstance(query, dict): params = { key: val for key, val in query.items() if key in self.structured_query_params } else: params = {'q': self.format_string % query} params.update({'format': 'json'}) # `viewbox` apparently replaces `view_box` if self.view_box: params['viewbox'] = ','.join(self.view_box) if self.country_bias: params['countrycodes'] = self.country_bias if addressdetails: params['addressdetails'] = 1 if language: params['accept-language'] = language if geometry is not None: geometry = geometry.lower() if geometry == 'wkt': params['polygon_text'] = 1 elif geometry == 'svg': params['polygon_svg'] = 1 elif geometry == 'kml': params['polygon_kml'] = 1 elif geometry == 'geojson': params['polygon_geojson'] = 1 else: raise GeocoderQueryError( "Invalid geometry format. Must be one of: " "wkt, svg, kml, geojson.") url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), exactly_one)
def geocode( self, query=None, exactly_one=True, timeout=DEFAULT_SENTINEL, bounds=None, region=None, components=None, language=None, sensor=False, ): """ Return a location point by address. :param str query: The address or query you wish to geocode. Optional, if ``components`` param is set:: >>> g = GoogleV3() >>> g.geocode(components={"city": "Paris", "country": "FR"}) Location(France, (46.227638, 2.213749, 0.0)) .. versionchanged:: 1.14.0 Now ``query`` is optional if ``components`` param is set. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param bounds: The bounding box of the viewport within which to bias geocode results more prominently. :type bounds: list or tuple :param str region: The region code, specified as a ccTLD ("top-level domain") two-character value. :param dict components: Restricts to an area. Can use any combination of: route, locality, administrative_area, postal_code, country. :param str language: The language in which to return results. :param bool sensor: Whether the geocoding request comes from a device with a location sensor. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ params = {'sensor': str(sensor).lower()} if query is None and not components: raise ValueError('Either `query` or `components` must be set.`') if query is not None: params['address'] = self.format_string % query if self.api_key: params['key'] = self.api_key if bounds: if len(bounds) != 4: raise GeocoderQueryError( "bounds must be a four-item iterable of lat,lon,lat,lon") params['bounds'] = self._format_bounds_param(bounds) if region: params['region'] = region if components: params['components'] = self._format_components_param(components) if language: params['language'] = language if self.premier: url = self._get_signed_url(params) else: url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), exactly_one)
def geocode( self, query, max_results=25, set_back=0, location_descriptor='any', exactly_one=True, timeout=None, ): """ Geocode a location query. :param string query: The address or query you wish to geocode. :param int max_results: The maximum number of resutls to request. :param float set_back: The distance to move the accessPoint away from the curb (in meters) and towards the interior of the parcel. location_descriptor must be set to accessPoint for set_back to take effect. :param string location_descriptor: The type of point requested. It can be any, accessPoint, frontDoorPoint, parcelPoint, rooftopPoint and routingPoint. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. """ params = {'addressString': query} if set_back != 0: params['setBack'] = set_back if location_descriptor not in ['any', 'accessPoint', 'frontDoorPoint', 'parcelPoint', 'rooftopPoint', 'routingPoint']: raise GeocoderQueryError( "You did not provided a location_descriptor " "the webservice can consume. It should be any, accessPoint, " "frontDoorPoint, parcelPoint, rooftopPoint or routingPoint." ) params['locationDescriptor'] = location_descriptor if exactly_one is True: max_results = 1 params['maxResults'] = max_results url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) response = self._call_geocoder(url, timeout=timeout) # Success; convert from GeoJSON if not len(response['features']): return None geocoded = [] for feature in response['features']: geocoded.append(self._parse_feature(feature)) if exactly_one is True: return geocoded[0] return geocoded
def geocode(self, query, exactly_one=True, timeout=None, bounds=None, region=None, components=None, language=None, sensor=False, userlocation=None): # pylint: disable=W0221,R0913 """ Geocode a location query. :param string query: The address or query you wish to geocode. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. .. versionadded:: 0.97 :param bounds: The bounding box of the viewport within which to bias geocode results more prominently. :type bounds: list or tuple :param string region: The region code, specified as a ccTLD ("top-level domain") two-character value. :param dict components: Restricts to an area. Can use any combination of: route, locality, administrative_area, postal_code, country. .. versionadded:: 0.97.1 :param string language: The language in which to return results. :param bool sensor: Whether the geocoding request comes from a device with a location sensor. """ params = { 'address': self.format_string % query, 'sensor': str(sensor).lower() } if self.api_key: params['key'] = self.api_key if bounds: if len(bounds) != 4: raise GeocoderQueryError( "bounds must be a four-item iterable of lat,lon,lat,lon") params['bounds'] = self._format_bounds_param(bounds) if region: params['region'] = region if components: params['components'] = self._format_components_param(components) if language: params['language'] = language if self.premier is False: url = "?".join((self.api, urlencode(params))) else: url = self._get_signed_url(params) logger.debug("%s.geocode: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), userlocation, exactly_one)
def geocode(self, query=None, *, components=None, at=None, countries=None, language=None, limit=None, exactly_one=True, timeout=DEFAULT_SENTINEL): """ Return a location point by address. :param str query: The address or query you wish to geocode. Optional, if ``components`` param is set. :param dict components: A structured query. Can be used along with the free-text ``query``. Should be a dictionary whose keys are one of: `country`, `state`, `county`, `city`, `district`, `street`, `houseNumber`, `postalCode`. :param at: The center of the search context. :type at: :class:`geopy.point.Point`, list or tuple of ``(latitude, longitude)``, or string as ``"%(latitude)s, %(longitude)s"``. :param list countries: A list of country codes specified in `ISO 3166-1 alpha-3 <https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3>`_ format, e.g. ``['USA', 'CAN']``. This is a hard filter. :param str language: Affects the language of the response, must be a BCP 47 compliant language code, e.g. ``en-US``. :param int limit: Defines the maximum number of items in the response structure. If not provided and there are multiple results the HERE API will return 20 results by default. This will be reset to one if ``exactly_one`` is True. :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ params = { 'apiKey': self.apikey, } if query: params['q'] = query if components: parts = [ "{}={}".format(key, val) for key, val in components.items() if key in self.structured_query_params ] if not parts: raise GeocoderQueryError("`components` dict must not be empty") for pair in parts: if ';' in pair: raise GeocoderQueryError( "';' must not be used in values of the structured query. " "Offending pair: {!r}".format(pair)) params['qq'] = ';'.join(parts) if at: point = self._coerce_point_to_string( at, output_format="%(lat)s,%(lon)s") params['at'] = point if countries: params['in'] = 'countryCode:' + ','.join(countries) if language: params['lang'] = language if limit: params['limit'] = limit if exactly_one: params['limit'] = 1 url = "?".join((self.api, urlencode(params))) logger.debug("%s.geocode: %s", self.__class__.__name__, url) callback = partial(self._parse_json, exactly_one=exactly_one) return self._call_geocoder(url, callback, timeout=timeout)
def geocode(self, query, exactly_one=True, timeout=DEFAULT_SENTINEL, limit=None, addressdetails=False, language=False, geometry=None): """ Return a location point by address. :param query: The address, query or a structured query you wish to geocode. .. versionchanged:: 1.0.0 For a structured query, provide a dictionary whose keys are one of: `street`, `city`, `county`, `state`, `country`, or `postalcode`. For more information, see Nominatim's documentation for `structured requests`: https://wiki.openstreetmap.org/wiki/Nominatim :type query: dict or str :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param int limit: Maximum amount of results to return from Nominatim. Unless exactly_one is set to False, limit will always be 1. .. versionadded:: 1.13.0 :param bool addressdetails: If you want in *Location.raw* to include addressdetails such as city_district, etc set it to True :param str language: Preferred language in which to return results. Either uses standard `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`_ accept-language string or a simple comma-separated list of language codes. .. versionadded:: 1.0.0 :param str geometry: If present, specifies whether the geocoding service should return the result's geometry in `wkt`, `svg`, `kml`, or `geojson` formats. This is available via the `raw` attribute on the returned :class:`geopy.location.Location` object. .. versionadded:: 1.3.0 :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if isinstance(query, dict): params = { key: val for key, val in query.items() if key in self.structured_query_params } else: params = {'q': self.format_string % query} params.update({'format': 'json'}) if exactly_one: params['limit'] = 1 elif limit: limit = int(limit) if limit < 1: raise ValueError("Limit cannot be less than 1") params['limit'] = limit # `viewbox` apparently replaces `view_box` if self.view_box: if all(isinstance(point, Point) for point in self.view_box): p1, p2 = self.view_box params['viewbox'] = ','.join( str(p) for p in chain(p1[1::-1], p2[1::-1])) else: params['viewbox'] = ','.join( str(coord) for coord in self.view_box) if self.country_bias: params['countrycodes'] = self.country_bias if addressdetails: params['addressdetails'] = 1 if language: params['accept-language'] = language if geometry is not None: geometry = geometry.lower() if geometry == 'wkt': params['polygon_text'] = 1 elif geometry == 'svg': params['polygon_svg'] = 1 elif geometry == 'kml': params['polygon_kml'] = 1 elif geometry == 'geojson': params['polygon_geojson'] = 1 else: raise GeocoderQueryError( "Invalid geometry format. Must be one of: " "wkt, svg, kml, geojson.") url = self._construct_url(self.api, params) logger.debug("%s.geocode: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), exactly_one)
def reverse( self, query, reverse_geocode_preference=('StreetAddress', ), maximum_responses=25, filtering='', exactly_one=DEFAULT_SENTINEL, timeout=DEFAULT_SENTINEL, ): """ Return an address by location point. :param query: The coordinates for which you wish to obtain the closest human-readable addresses. :type query: :class:`geopy.point.Point`, list or tuple of ``(latitude, longitude)``, or string as ``"%(latitude)s, %(longitude)s"``. :param list reverse_geocode_preference: Enable to set expected results type. It can be `StreetAddress` or `PositionOfInterest`. Default is set to `StreetAddress`. :param int maximum_responses: The maximum number of responses to ask to the API in the query body. :param str filtering: Provide string that help setting geocoder filter. It contains an XML string. See examples in documentation and ignfrance.py file in directory tests. :param bool exactly_one: Return one result or a list of results, if available. .. versionchanged:: 1.14.0 Default value for ``exactly_one`` was ``False``, which differs from the conventional default across geopy. Please always pass this argument explicitly, otherwise you would get a warning. In geopy 2.0 the default value will become ``True``. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if exactly_one is DEFAULT_SENTINEL: warnings.warn( '%s.reverse: default value for `exactly_one` ' 'argument will become True in geopy 2.0. ' 'Specify `exactly_one=False` as the argument ' 'explicitly to get rid of this warning.' % type(self).__name__, DeprecationWarning) exactly_one = False sub_request = """ <ReverseGeocodeRequest> {reverse_geocode_preference} <Position> <gml:Point> <gml:pos>{query}</gml:pos> </gml:Point> {filtering} </Position> </ReverseGeocodeRequest> """ xml_request = self.xml_request.format( method_name='ReverseGeocodeRequest', sub_request=sub_request, maximum_responses=maximum_responses) for pref in reverse_geocode_preference: if pref not in ('StreetAddress', 'PositionOfInterest'): raise GeocoderQueryError( '`reverse_geocode_preference` must contain ' 'one or more of: StreetAddress, PositionOfInterest') point = self._coerce_point_to_string(query).replace(',', ' ') reverse_geocode_preference = '\n'.join( ('<ReverseGeocodePreference>%s</ReverseGeocodePreference>' % pref for pref in reverse_geocode_preference)) request_string = xml_request.format( maximum_responses=maximum_responses, query=point, reverse_geocode_preference=reverse_geocode_preference, filtering=filtering) url = "?".join((self.api, urlencode({'xls': request_string}))) logger.debug("%s.reverse: %s", self.__class__.__name__, url) raw_xml = self._request_raw_content(url, timeout) return self._parse_xml(raw_xml, exactly_one=exactly_one, is_reverse=True, is_freeform='false')
def geocode( self, query, exactly_one=True, timeout=DEFAULT_SENTINEL, limit=None, addressdetails=False, language=False, geometry=None, extratags=False, country_codes=None, viewbox=None, bounded=None, # TODO: change default value to `False` in geopy 2.0 ): """ Return a location point by address. :param query: The address, query or a structured query you wish to geocode. .. versionchanged:: 1.0.0 For a structured query, provide a dictionary whose keys are one of: `street`, `city`, `county`, `state`, `country`, or `postalcode`. For more information, see Nominatim's documentation for `structured requests`: https://wiki.openstreetmap.org/wiki/Nominatim :type query: dict or str :param bool exactly_one: Return one result or a list of results, if available. :param int timeout: Time, in seconds, to wait for the geocoding service to respond before raising a :class:`geopy.exc.GeocoderTimedOut` exception. Set this only if you wish to override, on this call only, the value set during the geocoder's initialization. :param int limit: Maximum amount of results to return from Nominatim. Unless exactly_one is set to False, limit will always be 1. .. versionadded:: 1.13.0 :param bool addressdetails: If you want in *Location.raw* to include addressdetails such as city_district, etc set it to True :param str language: Preferred language in which to return results. Either uses standard `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`_ accept-language string or a simple comma-separated list of language codes. .. versionadded:: 1.0.0 :param str geometry: If present, specifies whether the geocoding service should return the result's geometry in `wkt`, `svg`, `kml`, or `geojson` formats. This is available via the `raw` attribute on the returned :class:`geopy.location.Location` object. .. versionadded:: 1.3.0 :param bool extratags: Include additional information in the result if available, e.g. wikipedia link, opening hours. .. versionadded:: 1.17.0 :param country_codes: Limit search results to a specific country (or a list of countries). A country_code should be the ISO 3166-1alpha2 code, e.g. ``gb`` for the United Kingdom, ``de`` for Germany, etc. .. versionadded:: 1.19.0 :type country_codes: str or list :type viewbox: list or tuple of 2 items of :class:`geopy.point.Point` or ``(latitude, longitude)`` or ``"%(latitude)s, %(longitude)s"``. :param viewbox: Coordinates to restrict search within. Example: ``[Point(22, 180), Point(-22, -180)]``. .. versionadded:: 1.19.0 :param bool bounded: Restrict the results to only items contained within the bounding view_box. Defaults to `False`. .. versionadded:: 1.19.0 :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if ``exactly_one=False``. """ if isinstance(query, dict): params = { key: val for key, val in query.items() if key in self.structured_query_params } else: params = {'q': self.format_string % query} params.update({'format': 'json'}) if exactly_one: params['limit'] = 1 elif limit is not None: limit = int(limit) if limit < 1: raise ValueError("Limit cannot be less than 1") params['limit'] = limit if viewbox is None: viewbox = self.view_box if viewbox: if len(viewbox) == 4: warnings.warn( '%s `viewbox` format of ' '`[longitude, latitude, longitude, latitude]` is now ' 'deprecated and will not be supported in geopy 2.0. ' 'Use `[Point(latitude, longitude), Point(latitude, longitude)]` ' 'instead.' % type(self).__name__, DeprecationWarning, stacklevel=2) lon1, lat1, lon2, lat2 = viewbox viewbox = [[lat1, lon1], [lat2, lon2]] params['viewbox'] = self._format_bounding_box( viewbox, "%(lon1)s,%(lat1)s,%(lon2)s,%(lat2)s") if bounded is None: bounded = self.bounded if bounded: params['bounded'] = 1 if country_codes is None: country_codes = self.country_bias if not country_codes: country_codes = [] if isinstance(country_codes, string_compare): country_codes = [country_codes] if country_codes: params['countrycodes'] = ",".join(country_codes) if addressdetails: params['addressdetails'] = 1 if language: params['accept-language'] = language if extratags: params['extratags'] = True if geometry is not None: geometry = geometry.lower() if geometry == 'wkt': params['polygon_text'] = 1 elif geometry == 'svg': params['polygon_svg'] = 1 elif geometry == 'kml': params['polygon_kml'] = 1 elif geometry == 'geojson': params['polygon_geojson'] = 1 else: raise GeocoderQueryError( "Invalid geometry format. Must be one of: " "wkt, svg, kml, geojson.") url = self._construct_url(self.api, params) logger.debug("%s.geocode: %s", self.__class__.__name__, url) return self._parse_json(self._call_geocoder(url, timeout=timeout), exactly_one)
def _check_status(status): """ Validates error statuses. """ if status == '10000': # When there are no results, just return. return if status == '10001': raise GeocoderAuthenticationFailure('Invalid user key.') elif status == '10002': raise GeocoderAuthenticationFailure('Service not available.') elif status == '10003': raise GeocoderQuotaExceeded('Daily query over limit.') elif status == '10004': raise GeocoderQuotaExceeded('Access too frequent.') elif status == '10005': raise GeocoderQueryError('Invalid user IP.') elif status == '10006': raise GeocoderQueryError('Invalid user domain.') elif status == '10007': raise GeocoderQueryError('Invalid user signature') elif status == '10008': raise GeocoderQueryError('Invalid user scode.') elif status == '10009': raise GeocoderQuotaExceeded('Userkey plat nomatch.') elif status == '10010': raise GeocoderQuotaExceeded('IP query over limit.') elif status == '10011': raise GeocoderQuotaExceeded('Not support https.') elif status == '10012': raise GeocoderQuotaExceeded('Insufficient privileges.') elif status == '10013': raise GeocoderQuotaExceeded('User key recycled.') elif status == '10014': raise GeocoderQuotaExceeded('QPS has exceeded the limit.') elif status == '10015': raise GeocoderQuotaExceeded('Gateway timeout.') elif status == '10016': raise GeocoderQuotaExceeded('Server is busy.') elif status == '10017': raise GeocoderQuotaExceeded('Resource unavailable.') elif status == '20000': raise GeocoderQuotaExceeded('Invalid params.') elif status == '20001': raise GeocoderQuotaExceeded('Missing required params.') elif status == '20002': raise GeocoderQuotaExceeded('Illegal request.') elif status == '20003': raise GeocoderQuotaExceeded('Unknown error.') elif status == '20800': raise GeocoderQuotaExceeded('Out of service.') elif status == '20801': raise GeocoderQuotaExceeded('No roads nearby.') elif status == '20802': raise GeocoderQuotaExceeded('Route fail.') elif status == '20803': raise GeocoderQuotaExceeded('Over direction range.') elif status == '300**': raise GeocoderQuotaExceeded('Engine response data error.') else: raise GeocoderQueryError('Unknown error')