예제 #1
0
    def geocode(self, query, *, exactly_one=True, timeout=DEFAULT_SENTINEL):
        """
        Return a location point for a `3 words` query. If the `3 words` address
        doesn't exist, a :class:`geopy.exc.GeocoderQueryError` exception will be
        thrown.

        :param str query: The 3-word address you wish to geocode.

        :param bool exactly_one: Return one result or a list of results, if
            available. Due to the address scheme there is always exactly one
            result for each `3 words` address, so this parameter is rather
            useless for this geocoder.

        :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: :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """

        if not _check_query(query):
            raise exc.GeocoderQueryError(
                "Search string must be 'word.word.word'")

        params = {
            'words': query,
            'key': self.api_key,
        }

        url = "?".join((self.geocode_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)
예제 #2
0
    def geocode(self, query, lang='en', exactly_one=True, timeout=None):
        """
        Geocode a "3 words" or "OneWord" query.

        :param string query: The 3-word or OneWord-address you wish to geocode.

        :param string lang: two character language codes as supported by
            the API (http://what3words.com/api/reference/languages).

        :param bool exactly_one: Parameter has no effect for this geocoder.
            Due to the address scheme there is always exactly one result.

        :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
        """

        if not self._check_query(query):
            raise exc.GeocoderQueryError("Search string must be either like "
                                         "'word.word.word' or '*word' ")

        params = {
            'string': self.format_string % query,
            'lang': self.format_string % lang.lower(),
            'key': self.api_key,
        }

        url = "?".join(((self.api + "w3w"), urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(self._call_geocoder(url, timeout=timeout),
                                exactly_one)
예제 #3
0
    def _parse_reverse_json(self, resources, exactly_one=True):
        """
        Parses a location from a single-result reverse API call.
        """

        if resources.get('error') == "21":
            raise exc.GeocoderQueryError("Invalid coordinates")

        def parse_resource(resource):
            """
            Parse resource to return Geopy Location object
            """
            words = resource['words']
            words = join_filter(".", [words[0], words[1], words[2]])
            position = resource['position']
            latitude, longitude = position[0], position[1]

            if latitude and longitude:
                latitude = float(latitude)
                longitude = float(longitude)

            return Location(words, (latitude, longitude), resource)

        location = parse_resource(resources)
        if exactly_one:
            return location
        else:
            return [location]
예제 #4
0
    def _parse_json(self, resources, exactly_one=True):
        """
        Parse type, words, latitude, and longitude and language from a
        JSON response.
        """
        if resources.get('error') == "X1":
            raise exc.GeocoderAuthenticationFailure()

        if resources.get('error') == "11":
            raise exc.GeocoderQueryError(
                "Address (Word(s)) not recognised by What3Words.")

        def parse_resource(resource):
            """
            Parse record.
            """

            if resource['type'] == '3 words':
                words = resource['words']
                words = join_filter(".", [words[0], words[1], words[2]])
                position = resource['position']
                latitude, longitude = position[0], position[1]

                if latitude and longitude:
                    latitude = float(latitude)
                    longitude = float(longitude)

                return Location(words, (latitude, longitude), resource)
            elif resource['type'] == 'OneWord':
                # TODO this branch probably needs to be removed, as OneWord
                # addresses have been canceled.
                words = resource['words']
                words = join_filter(".", [words[0], words[1], words[2]])
                oneword = resource['oneword']
                info = resource['info']

                address = join_filter(", ", [
                    oneword, words, info['name'], info['address1'],
                    info['address2'], info['address3'], info['city'],
                    info['county'], info['postcode'], info['country_id']
                ])

                position = resource['position']
                latitude, longitude = position[0], position[1]

                if latitude and longitude:
                    latitude = float(latitude)
                    longitude = float(longitude)

                return Location(address, (latitude, longitude), resource)
            else:
                raise exc.GeocoderParseError('Error parsing result.')

        location = parse_resource(resources)
        if exactly_one:
            return location
        else:
            return [location]
예제 #5
0
    def geocode(self,
                query,
                lang='en',
                exactly_one=True,
                timeout=DEFAULT_SENTINEL):

        """
        Return a location point for a `3 words` query. If the `3 words` address
        doesn't exist, a :class:`geopy.exc.GeocoderQueryError` exception will be
        thrown.

        :param str query: The 3-word address you wish to geocode.

        :param str lang: two character language codes as supported by
            the API (https://docs.what3words.com/api/v2/#lang).

        :param bool exactly_one: Return one result or a list of results, if
            available. Due to the address scheme there is always exactly one
            result for each `3 words` address, so this parameter is rather
            useless for this geocoder.

            .. versionchanged:: 1.14.0
               ``exactly_one=False`` now returns a list of a single location.
               This option wasn't respected before.

        :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: :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """

        if not self._check_query(query):
            raise exc.GeocoderQueryError(
                "Search string must be 'word.word.word'"
            )

        params = {
            'addr': self.format_string % query,
            'lang': lang.lower(),
            'key': self.api_key,
        }

        url = "?".join(((self.api + "forward"), urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one=exactly_one
        )
예제 #6
0
    def _parse_json(self, resources, exactly_one=True):
        """
        Parse type, words, latitude, and longitude and language from a
        JSON response.
        """

        error = resources.get('error')

        if error is not None:
            # https://developer.what3words.com/public-api/docs#error-handling
            exc_msg = "Error returned by What3Words: %s" % resources["error"][
                "message"]
            exc_code = error.get('code')
            if exc_code in ['MissingKey', 'InvalidKey']:
                raise exc.GeocoderAuthenticationFailure(exc_msg)

            raise exc.GeocoderQueryError(exc_msg)

        def parse_resource(resource):
            """
            Parse record.
            """

            if 'coordinates' in resource:
                words = resource['words']
                position = resource['coordinates']
                latitude, longitude = position['lat'], position['lng']
                if latitude and longitude:
                    latitude = float(latitude)
                    longitude = float(longitude)

                return Location(words, (latitude, longitude), resource)
            else:
                raise exc.GeocoderParseError('Error parsing result.')

        location = parse_resource(resources)
        if exactly_one:
            return location
        else:
            return [location]
예제 #7
0
파일: what3words.py 프로젝트: aalbina/geopy
    def _parse_json(self, resources, exactly_one=True):
        """
        Parse type, words, latitude, and longitude and language from a
        JSON response.
        """

        code = resources['status'].get('code')

        if code:
            # https://docs.what3words.com/api/v2/#errors
            exc_msg = "Error returned by What3Words: %s" % resources['status'][
                'message']
            if code == 401:
                raise exc.GeocoderAuthenticationFailure(exc_msg)

            raise exc.GeocoderQueryError(exc_msg)

        def parse_resource(resource):
            """
            Parse record.
            """

            if 'geometry' in resource:
                words = resource['words']
                position = resource['geometry']
                latitude, longitude = position['lat'], position['lng']
                if latitude and longitude:
                    latitude = float(latitude)
                    longitude = float(longitude)

                return Location(words, (latitude, longitude), resource)
            else:
                raise exc.GeocoderParseError('Error parsing result.')

        location = parse_resource(resources)
        if exactly_one:
            return location
        else:
            return [location]
예제 #8
0
    def _parse_reverse_json(resources):
        """
        Parses a location from a single-result reverse API call.
        """

        if resources.get('error') == "21":
            raise exc.GeocoderQueryError("Invalid coordinates")

        def parse_resource(resource):

            words = resource['words']
            words = join_filter(".", [words[0], words[1], words[2]])
            position = resource['position']
            latitude, longitude = position[0], position[1]

            if latitude and longitude:
                latitude = float(latitude)
                longitude = float(longitude)

            return Location(words, (latitude, longitude), resource)

        return parse_resource(resources)