Example #1
0
    def reverse(self, query, exactly_one=True, timeout=None):
        """
        Returns a reverse geocoded location.

        :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. GeocodeFarm's API will always return at most 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.
        """
        lat, lon = self._coerce_point_to_string(query).split(',')
        url = "".join((
            self.reverse_api,
            "?lat=%s" % quote(lat).encode('utf8'),
            "&lon=%s" % quote(lon).encode('utf8'),
        ))
        if self.api_key:
            url += "&key=%s" % self.api_key
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #2
0
    def geocode(
        self,
        query,
        exactly_one=True,
        timeout=DEFAULT_SENTINEL,
        proximity=None,
        country=None,
        bbox=None,
    ):
        """
        Return a location point by address

        :param str 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.

        :param proximity: A coordinate to bias local results based on a provided
            location.
        :type proximity: :class:`geopy.point.Point`, list or tuple of ``(latitude,
            longitude)``, or string as ``"%(latitude)s, %(longitude)s"``.

        :param string country: Country to filter result in form of
            ISO 3166-1 alpha-2 country code.

        :param bbox: The bounding box of the viewport within which
            to bias geocode results more prominently.
            Example: ``[Point(22, 180), Point(-22, -180)]``.
        :type bbox: list or tuple of 2 items of :class:`geopy.point.Point` or
            ``(latitude, longitude)`` or ``"%(latitude)s, %(longitude)s"``.

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        params = {}

        params['access_token'] = self.api_key
        query = self.format_string % query
        if bbox:
            params['bbox'] = self._format_bounding_box(
                bbox, "%(lon1)s,%(lat1)s,%(lon2)s,%(lat2)s")

        if country:
            params['country'] = country

        if proximity:
            p = Point(proximity)
            params['proximity'] = "%s,%s" % (p.longitude, p.latitude)

        quoted_query = quote(query.encode('utf-8'))
        url = "?".join(
            (self.api % dict(query=quoted_query), urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)

        return self._parse_json(self._call_geocoder(url, timeout=timeout))
Example #3
0
    def reverse(self, query, exactly_one=True, timeout=None):
        """
        Returns a reverse geocoded location.

        :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. GeocodeFarm's API will always return at most 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.
        """
        lat, lon = self._coerce_point_to_string(query).split(',')
        url = "".join((
            self.reverse_api,
            quote(("%s/%s" % (lat, lon)).encode('utf8'))
        ))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #4
0
    def reverse(
        self,
        query,
        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 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``.
        """
        position = self._coerce_point_to_string(query)
        params = self._reverse_params(position)

        quoted_position = quote(position.encode('utf-8'))
        url = "?".join((self.api_reverse % dict(position=quoted_position),
                        urlencode(params)))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)

        return self._parse_reverse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one)
Example #5
0
    def geocode(self, query, exactly_one=True, timeout=None):
        """
        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.
        """
        url = "".join((
            self.api,
            "?addr=",
            quote((self.format_string % query).encode('utf8'))
        ))
        if self.api_key:
            url += "&key=%s" % self.api_key
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #6
0
    def _build_request(self, string, reverse):
        """
        Returns a signed oauth request for the given query
        """
        request = oauth2.Request(
            method='GET',
            parameters={
                'oauth_nonce': oauth2.generate_nonce(),
                'oauth_timestamp': int(time.time()),
                'oauth_version': '1.0',
            },
            url='%s?location=%s&flags=J%s' % (
                self.api,
                quote(string.encode('utf-8')),
                '&gflags=R' if reverse else '', # todo refactor
            ),
        )

        request.sign_request(
            oauth2.SignatureMethod_HMAC_SHA1(),
            oauth2.Consumer(self.consumer_key, self.consumer_secret),
            None,
        )

        return request
Example #7
0
File: tomtom.py Project: jmb/geopy
    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            limit=None,
            typeahead=False,
            language=None,
    ):
        """
        Return a location point by address.

        :param str 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.

        :param int limit: Maximum amount of results to return from the service.
            Unless exactly_one is set to False, limit will always be 1.

        :param bool typeahead: If the "typeahead" flag is set, the query
            will be interpreted as a partial input and the search will
            enter predictive mode.

        :param str language: Language in which search results should be
            returned. When data in specified language is not
            available for a specific field, default language is used.
            List of supported languages (case-insensitive):
            https://developer.tomtom.com/online-search/online-search-documentation/supported-languages

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        query = self.format_string % query
        params = self._geocode_params(query)
        params['typeahead'] = self._boolean_value(typeahead)

        if limit:
            params['limit'] = str(int(limit))
        if exactly_one:
            params['limit'] = '1'

        if language:
            params['language'] = language

        quoted_query = quote(query.encode('utf-8'))
        url = "?".join((self.api % dict(query=quoted_query),
                        urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)

        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #8
0
    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            limit=None,
            typeahead=False,
            language=None,
    ):
        """
        Return a location point by address.

        :param str 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.

        :param int limit: Maximum amount of results to return from the service.
            Unless exactly_one is set to False, limit will always be 1.

        :param bool typeahead: If the "typeahead" flag is set, the query
            will be interpreted as a partial input and the search will
            enter predictive mode.

        :param str language: Language in which search results should be
            returned. When data in specified language is not
            available for a specific field, default language is used.
            List of supported languages (case-insensitive):
            https://developer.tomtom.com/online-search/online-search-documentation/supported-languages

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        query = self.format_string % query
        params = self._geocode_params(query)
        params['typeahead'] = self._boolean_value(typeahead)

        if limit:
            params['limit'] = str(int(limit))
        if exactly_one:
            params['limit'] = '1'

        if language:
            params['language'] = language

        quoted_query = quote(query.encode('utf-8'))
        url = "?".join((self.api % dict(query=quoted_query),
                        urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)

        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #9
0
File: bing.py Project: jmb/geopy
    def reverse(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            culture=None,
            include_country_code=False
    ):
        """
        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 culture: Affects the language of the response,
            must be a two-letter country code.

        :param bool include_country_code: Sets whether to include the
            two-letter ISO code of the country in the response (field name
            'countryRegionIso2').

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        point = self._coerce_point_to_string(query)
        params = {'key': self.api_key}
        if culture:
            params['culture'] = culture
        if include_country_code:
            params['include'] = 'ciso2'  # the only acceptable value

        quoted_point = quote(point.encode('utf-8'))
        url = "?".join((self.reverse_api % dict(point=quoted_point),
                        urlencode(params)))

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )
Example #10
0
    def reverse(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            language=None,
    ):
        """
        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 language: Language in which search results should be
            returned. When data in specified language is not
            available for a specific field, default language is used.
            List of supported languages (case-insensitive):
            https://developer.tomtom.com/online-search/online-search-documentation/supported-languages

            .. versionadded:: 1.18.0

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        position = self._coerce_point_to_string(query)
        params = self._reverse_params(position)

        if language:
            params['language'] = language

        quoted_position = quote(position.encode('utf-8'))
        url = "?".join((self.api_reverse % dict(position=quoted_position),
                        urlencode(params)))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)

        return self._parse_reverse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #11
0
    def reverse(self,
                query,
                exactly_one=True,
                timeout=DEFAULT_SENTINEL,
                culture=None,
                include_country_code=False):
        """
        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 culture: Affects the language of the response,
            must be a two-letter country code.

        :param bool include_country_code: Sets whether to include the
            two-letter ISO code of the country in the response (field name
            'countryRegionIso2').

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        point = self._coerce_point_to_string(query)
        params = {'key': self.api_key}
        if culture:
            params['culture'] = culture
        if include_country_code:
            params['include'] = 'ciso2'  # the only acceptable value

        quoted_point = quote(point.encode('utf-8'))
        url = "?".join(
            (self.reverse_api % dict(point=quoted_point), urlencode(params)))

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(self._call_geocoder(url, timeout=timeout),
                                exactly_one)
Example #12
0
    def reverse(
        self,
        query,
        exactly_one=True,
        timeout=DEFAULT_SENTINEL,
        language=None,
    ):
        """
        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 language: Prefer results in specific languages. Accepts
            a single string like ``"en"`` or a list like ``["de", "en"]``.
        :type language: str or list

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        params = {'key': self.api_key}

        if isinstance(language, string_compare):
            language = [language]
        if language:
            params['language'] = ','.join(language)

        point = self._coerce_point_to_string(query, "%(lon)s,%(lat)s")
        quoted_query = quote(point.encode('utf-8'))
        url = "?".join(
            (self.api % dict(query=quoted_query), urlencode(params)))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(self._call_geocoder(url, timeout=timeout),
                                exactly_one)
Example #13
0
    def reverse(self, query, 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 bool exactly_one: Return one result or a list of results, if
            available. Baidu's API will always return at most one result.

            .. versionadded:: 1.14.0

        :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 = {
            'ak': self.api_key,
            'output': 'json',
            'location': quote(
                self._coerce_point_to_string(query),
                safe="!*'();:@&=+$,/?#[]"
                ),
        }
        params = "&".join(["{}={}".format(k, v) for k, v in params.items()])

        if self.security_key is None:
            url = "?".join((self.api, params))
        else:
            url = self._url_with_signature(params)

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_reverse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one=exactly_one
        )
Example #14
0
    def _call_yahoo(self, query, reverse, exactly_one, timeout):
        """
        Returns a response for the given query
        """
        # we quote the location, because spaces must be encoded as "%20"
        # instead of "+". this also means we can't later call urlencode on
        # this value.
        params = {'location': quote(query), 'flags': 'J'}

        if reverse is True:
            params['gflags'] = 'R'
        if exactly_one is True:
            params['count'] = '1'

        auth = requests_oauthlib.OAuth1(self.consumer_key,
                                        self.consumer_secret)

        url = u'?'.join(
            (self.api, u'&'.join(u'='.join(item) for item in params.items())))

        return requests.get(url, auth=auth, timeout=timeout)
Example #15
0
    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
    ):
        """
        Return a location point by address.

        :param str 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.

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.

        """
        params = {
            'ak': self.api_key,
            'output': 'json',
            'address': quote(self.format_string % query, safe="!*'();:@&=+$,/?#[]"),
        }
        params = "&".join(["{}={}".format(k, v) for k, v in params.items()])

        if self.security_key is None:
            url = "?".join((self.api, params))
        else:
            url = self._url_with_signature(params)

        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one=exactly_one
        )
Example #16
0
    def _call_yahoo(self, query, reverse, exactly_one, timeout):
        """
        Returns a response for the given query
        """
        # we quote the location, because spaces must be encoded as "%20"
        # instead of "+". this also means we can't later call urlencode on
        # this value.
        params = {'location': quote(query), 'flags': 'J'}

        if reverse is True:
            params['gflags'] = 'R'
        if exactly_one is True:
            params['count'] = '1'

        auth = requests_oauthlib.OAuth1(
            self.consumer_key, self.consumer_secret)

        url = u'?'.join((
            self.api,
            u'&'.join(u'='.join(item) for item in params.items())
        ))

        return requests.get(url, auth=auth, timeout=timeout)
Example #17
0
    def geocode(self, query, exactly_one=True, timeout=None):
        """
        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. GeocodeFarm's API will always return at most 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.
        """
        url = "".join((
            self.api,
            quote((self.format_string % query).encode('utf8'))
        ))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #18
0
File: mapbox.py Project: jmb/geopy
    def reverse(
            self,
            query,
            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 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 = {}
        params['access_token'] = self.api_key

        point = self._coerce_point_to_string(query, "%(lon)s,%(lat)s")
        quoted_query = quote(point.encode('utf-8'))
        url = "?".join((self.api % dict(query=quoted_query),
                        urlencode(params)))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)

        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )
Example #19
0
File: mapbox.py Project: jmb/geopy
    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            proximity=None,
            country=None,
            bbox=None,
    ):
        """
        Return a location point by address

        :param str 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.

        :param proximity: A coordinate to bias local results based on a provided
            location.
        :type proximity: :class:`geopy.point.Point`, list or tuple of ``(latitude,
            longitude)``, or string as ``"%(latitude)s, %(longitude)s"``.

        :param string country: Country to filter result in form of
            ISO 3166-1 alpha-2 country code.

        :param bbox: The bounding box of the viewport within which
            to bias geocode results more prominently.
            Example: ``[Point(22, 180), Point(-22, -180)]``.
        :type bbox: list or tuple of 2 items of :class:`geopy.point.Point` or
            ``(latitude, longitude)`` or ``"%(latitude)s, %(longitude)s"``.

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        params = {}

        params['access_token'] = self.api_key
        query = self.format_string % query
        if bbox:
            params['bbox'] = self._format_bounding_box(
                bbox, "%(lon1)s,%(lat1)s,%(lon2)s,%(lat2)s")

        if country:
            params['country'] = country

        if proximity:
            p = Point(proximity)
            params['proximity'] = "%s,%s" % (p.longitude, p.latitude)

        quoted_query = quote(query.encode('utf-8'))
        url = "?".join((self.api % dict(query=quoted_query),
                        urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)

        return self._parse_json(
            self._call_geocoder(url, timeout=timeout)
        )
Example #20
0
    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=DEFAULT_SENTINEL,
            proximity=None,
            country=None,
            bbox=None,
    ):
        """
        Return a location point by address

        .. versionchanged:: 1.20.0
            Previously due to a bug the resulting :class:`geopy.location.Location`'s
            ``raw`` attribute contained a single string instead of a full
            service response.

        :param str query: The address or query you wish to geocode.

        :param bool exactly_one: Return one result or a list of results, if
            available.

            .. versionchanged:: 1.20.0
                Previously due to a bug this parameter wasn't respected.

        :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 proximity: A coordinate to bias local results based on a provided
            location.
        :type proximity: :class:`geopy.point.Point`, list or tuple of ``(latitude,
            longitude)``, or string as ``"%(latitude)s, %(longitude)s"``.

        :param country: Country to filter result in form of
            ISO 3166-1 alpha-2 country code (e.g. ``FR``).
            Might be a Python list of strings.

            .. versionchanged:: 1.19.0
                Previously only a single string could be specified.
                Now a Python list of individual countries is supported.

        :type country: str or list

        :param bbox: The bounding box of the viewport within which
            to bias geocode results more prominently.
            Example: ``[Point(22, 180), Point(-22, -180)]``.
        :type bbox: list or tuple of 2 items of :class:`geopy.point.Point` or
            ``(latitude, longitude)`` or ``"%(latitude)s, %(longitude)s"``.

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        """
        params = {}

        params['access_token'] = self.api_key
        query = self.format_string % query
        if bbox:
            params['bbox'] = self._format_bounding_box(
                bbox, "%(lon1)s,%(lat1)s,%(lon2)s,%(lat2)s")

        if not country:
            country = []
        if isinstance(country, string_compare):
            country = [country]
        if country:
            params['country'] = ",".join(country)

        if proximity:
            p = Point(proximity)
            params['proximity'] = "%s,%s" % (p.longitude, p.latitude)

        quoted_query = quote(query.encode('utf-8'))
        url = "?".join((self.api % dict(query=quoted_query),
                        urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)

        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )