Example #1
0
    def _request_raw_content(self, url, timeout):
        """
        Send the request to get raw content.
        """

        request = Request(url)

        if self.referer is not None:
            request.add_header("Referer", self.referer)

        raw_xml = self._call_geocoder(request, timeout=timeout, deserializer=None)

        return raw_xml
    def _request_raw_content(self, url, timeout):
        """
        Send the request to get raw content.
        """

        request = Request(url)

        if self.referer is not None:
            request.add_header('Referer', self.referer)

        raw_xml = self._call_geocoder(request,
                                      timeout=timeout,
                                      deserializer=None)

        return raw_xml
Example #3
0
 def _refresh_authentication_token_broken(self):
     """
     POST to ArcGIS requesting a new token.
     """
     if self.retry == self._MAX_RETRIES:
         raise GeocoderAuthenticationFailure(
             'Too many retries for auth: %s' % self.retry)
     token_request_arguments = {
         'username': self.username,
         'password': self.password,
         'client': 'requestip',
         #'referer': 'requestip',
         'expiration': self.token_lifetime,
         'f': 'json'
     }
     self.token_expiry = int(time()) + self.token_lifetime
     data = urlencode(token_request_arguments)
     print(data)
     data = data.encode("utf-8")
     print(data)
     req = Request(url=self.auth_api, headers=self.headers)
     print(req)
     page = urlopen(req, data=data, timeout=self.timeout)
     print(page)
     page = page.read()
     print(page)
     response = json.loads(page.decode('unicode_escape'))
     if not 'token' in response:
         raise GeocoderAuthenticationFailure(
             'Missing token in auth request. '
             'Request URL: %s?%s. '
             'Response JSON: %s. ' %
             (self.auth_api, data, json.dumps(response)))
     self.retry = 0
     self.token = response['token']
Example #4
0
 def _authenticated_call_geocoder(self, url, timeout=DEFAULT_SENTINEL):
     """
     Wrap self._call_geocoder, handling tokens.
     """
     if self.token is None or int(time()) > self.token_expiry:
         self._refresh_authentication_token()
     request = Request("&".join((url, urlencode({"token": self.token}))),
                       headers={"Referer": self.referer})
     return self._base_call_geocoder(request, timeout=timeout)
Example #5
0
 def _authenticated_call_geocoder(self, url, timeout=None):
     """
     Wrap self._call_geocoder, handling tokens.
     """
     if self.token is None or int(time()) > self.token_expiry:
         self._refresh_authentication_token()
     request = Request(
         "&token=".join((url, self.token)),  # no urlencoding
         headers={"Referer": self.referer})
     return self._base_call_geocoder(request, timeout=timeout)
Example #6
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.

            .. versionadded:: 0.97
        """
        query_str = self.format_string % query

        url = "?".join((self.api, urlencode({'address':query_str})))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        if self.authenticated is True:
            auth = " ".join((
                "Basic",
                encodestring(":".join((self.username, self.password))\
                    .encode('utf-8')).strip().decode('utf-8')
            ))
            url = Request(url, headers={"Authorization": auth})
        page = self._call_geocoder(url, timeout=timeout, raw=True)
        content = page.read().decode("utf-8") if py3k else page.read() # pylint: disable=E1101,E1103
        places = [
            r for r in csv.reader(
                [content, ] if not isinstance(content, list)
                else content
            )
        ]
        if not len(places):
            return None
        if exactly_one is True:
            return self._parse_result(places[0])
        else:
            result = [self._parse_result(res) for res in places]
            if None in result: # todo
                return None
            return result
Example #7
0
    def _request_raw_content(self, url, timeout):
        """
        Send the request to get raw content.
        """

        request = Request(url)

        if self.referer is not None:
            request.add_header('Referer', self.referer)

        if self.username and self.password and self.referer is None:
            credentials = '{0}:{1}'.format(self.username, self.password).encode()
            auth_str = base64.standard_b64encode(credentials).decode()
            request.add_unredirected_header(
                'Authorization',
                'Basic {}'.format(auth_str.strip()))

        raw_xml = self._call_geocoder(
            request,
            timeout=timeout,
            deserializer=None
        )

        return raw_xml
Example #8
0
    def _call_geocoder(self,
                       url,
                       timeout=DEFAULT_SENTINEL,
                       raw=False,
                       requester=None,
                       deserializer=json.loads,
                       **kwargs):
        """
        For a generated query URL, get the results.
        """

        if requester:
            req = url  # Don't construct an urllib's Request for a custom requester.

            # `requester` might be anything which can issue an HTTP request.
            # Assume that `requester` is a method of the `requests` library.
            # Requests, however, doesn't accept SSL context in its HTTP
            # request methods. A custom HTTP adapter has to be created for that.
            # So the current usage is not directly compatible with `requests`.
            requester = functools.partial(requester,
                                          context=self.ssl_context,
                                          proxies=self.proxies,
                                          headers=self.headers)
        else:
            if isinstance(url, Request):
                # copy Request
                headers = self.headers.copy()
                headers.update(url.header_items())
                req = Request(url=url.get_full_url(), headers=headers)
            else:
                req = Request(url=url, headers=self.headers)

        requester = requester or self.urlopen

        if timeout is None:
            warnings.warn(
                ('`timeout=None` has been passed to a geocoder call. Using '
                 'default geocoder timeout. In geopy 2.0 the '
                 'behavior will be different: None will mean "no timeout" '
                 'instead of "default geocoder timeout". Pass '
                 'geopy.geocoders.base.DEFAULT_SENTINEL instead of None '
                 'to get rid of this warning.'), DeprecationWarning)
            timeout = DEFAULT_SENTINEL

        timeout = (timeout
                   if timeout is not DEFAULT_SENTINEL else self.timeout)

        try:
            page = requester(req, timeout=timeout, **kwargs)
        except Exception as error:
            message = (str(error) if not py3k else
                       (str(error.args[0]) if len(error.args) else str(error)))
            self._geocoder_exception_handler(error, message)
            if isinstance(error, HTTPError):
                code = error.getcode()
                try:
                    raise ERROR_CODE_MAP[code](message)
                except KeyError:
                    raise GeocoderServiceError(message)
            elif isinstance(error, URLError):
                if "timed out" in message:
                    raise GeocoderTimedOut('Service timed out')
                elif "unreachable" in message:
                    raise GeocoderUnavailable('Service not available')
            elif isinstance(error, SocketTimeout):
                raise GeocoderTimedOut('Service timed out')
            elif isinstance(error, SSLError):
                if "timed out" in message:
                    raise GeocoderTimedOut('Service timed out')
            raise GeocoderServiceError(message)

        if hasattr(page, 'getcode'):
            status_code = page.getcode()
        elif hasattr(page, 'status_code'):
            status_code = page.status_code
        else:
            status_code = None
        if status_code in ERROR_CODE_MAP:
            raise ERROR_CODE_MAP[page.status_code]("\n%s" % decode_page(page))

        if raw:
            return page

        page = decode_page(page)

        if deserializer is not None:
            try:
                return deserializer(page)
            except ValueError:
                raise GeocoderParseError(
                    "Could not deserialize using deserializer:\n%s" % page)
        else:
            return page
Example #9
0
    def _call_geocoder(self,
                       url,
                       timeout=None,
                       raw=False,
                       requester=None,
                       deserializer=json.loads,
                       **kwargs):
        """
        For a generated query URL, get the results.
        """
        requester = requester or self.urlopen

        req = Request(url=url, headers=self.headers)

        try:
            page = requester(req, timeout=(timeout or self.timeout), **kwargs)
        except Exception as error:  # pylint: disable=W0703
            message = (str(error) if not py3k else
                       (str(error.args[0]) if len(error.args) else str(error)))
            if hasattr(self, '_geocoder_exception_handler'):
                self._geocoder_exception_handler(error, message)  # pylint: disable=E1101
            if isinstance(error, HTTPError):
                code = error.getcode()
                try:
                    raise ERROR_CODE_MAP[code](message)
                except KeyError:
                    raise GeocoderServiceError(message)
            elif isinstance(error, URLError):
                if "timed out" in message:
                    raise GeocoderTimedOut('Service timed out')
                elif "unreachable" in message:
                    raise GeocoderUnavailable('Service not available')
            elif isinstance(error, SocketTimeout):
                raise GeocoderTimedOut('Service timed out')
            elif isinstance(error, SSLError):
                if "timed out" in message:
                    raise GeocoderTimedOut('Service timed out')
            raise GeocoderServiceError(message)

        if hasattr(page, 'getcode'):
            status_code = page.getcode()
        elif hasattr(page, 'status_code'):
            status_code = page.status_code
        else:
            status_code = None
        if status_code in ERROR_CODE_MAP:
            raise ERROR_CODE_MAP[page.status_code]("\n%s" % decode_page(page))

        if raw:
            return page

        page = decode_page(page)

        if deserializer is not None:
            try:
                return deserializer(page)
            except ValueError:
                raise GeocoderParseError(
                    "Could not deserialize using deserializer:\n%s" % page)
        else:
            return page
Example #10
0
    def geocode(
        self,
        query,
        exactly_one=True,
        timeout=DEFAULT_SENTINEL,
        type=None,
        restrict_searchable_attributes=None,
        limit=None,
        language=None,
        countries=None,
        around=None,
        around_via_ip=None,
        around_radius=None,
        x_forwarded_for=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 str type: Restrict the search results to a specific type.
            Available types are defined in documentation:
            https://community.algolia.com/places/api-clients.html#api-options-type

        :param str restrict_searchable_attributes: Restrict the fields in which
            the search is done.

        :param int limit: Limit the maximum number of items in the
            response. If not provided and there are multiple results
            Algolia API will return 20 results by default. This will be
            reset to one if ``exactly_one`` is True.

        :param str language: If specified, restrict the search results
            to a single language. You can pass two letters country
            codes (ISO 639-1).

        :param list countries: If specified, restrict the search results
            to a specific list of countries. You can pass two letters
            country codes (ISO 3166-1).

        :param around: Force to first search around a specific
            latitude longitude.
        :type around: :class:`geopy.point.Point`, list or tuple of
            ``(latitude, longitude)``, or string as ``"%(latitude)s,
            %(longitude)s"``.

        :param bool around_via_ip: Whether or not to first search
            around the geolocation of the user found via his IP address.
            This is true by default.

        :param around_radius: Radius in meters to search around the
            latitude/longitude. Otherwise a default radius is
            automatically computed given the area density.

        :param str x_forwarded_for: Override the HTTP header X-Forwarded-For.
            With this you can control the source IP address used to resolve
            the geo-location of the user. This is particularly useful when
            you want to use the API from your backend as if it was from your
            end-users' locations.

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

        """

        params = {
            'query': self.format_string % query,
        }

        if type is not None:
            params['type'] = type

        if restrict_searchable_attributes is not None:
            params[
                'restrictSearchableAttributes'] = restrict_searchable_attributes

        if limit is not None:
            params['hitsPerPage'] = limit

        if exactly_one:
            params["hitsPerPage"] = 1

        if language is not None:
            params['language'] = language.lower()

        if countries is not None:
            params['countries'] = ','.join([c.lower() for c in countries])

        if around is not None:
            p = Point(around)
            params['aroundLatLng'] = "%s,%s" % (p.latitude, p.longitude)

        if around_via_ip is not None:
            params['aroundLatLngViaIP'] = \
                'true' if around_via_ip else 'false'

        if around_radius is not None:
            params['aroundRadius'] = around_radius

        url = '?'.join((self.geocode_api, urlencode(params)))
        request = Request(url)

        if x_forwarded_for is not None:
            request.add_header('X-Forwarded-For', x_forwarded_for)

        if self.app_id is not None and self.api_key is not None:
            request.add_header('X-Algolia-Application-Id', self.app_id)
            request.add_header('X-Algolia-API-Key', self.api_key)

        logger.debug('%s.geocode: %s', self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(request, timeout=timeout),
            exactly_one,
            language=language,
        )
Example #11
0
    def reverse(
        self,
        query,
        exactly_one=True,
        timeout=DEFAULT_SENTINEL,
        limit=None,
        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 int limit: Limit the maximum number of items in the
            response. If not provided and there are multiple results
            Algolia API will return 20 results by default. This will be
            reset to one if ``exactly_one`` is True.

        :param str language: If specified, restrict the search results
            to a single language. You can pass two letters country
            codes (ISO 639-1).

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

        params = {
            'aroundLatLng': location,
        }

        if limit is not None:
            params['hitsPerPage'] = limit

        if language is not None:
            params['language'] = language

        url = '?'.join((self.reverse_api, urlencode(params)))
        request = Request(url)

        if self.app_id is not None and self.api_key is not None:
            request.add_header('X-Algolia-Application-Id', self.app_id)
            request.add_header('X-Algolia-API-Key', self.api_key)

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(request, timeout=timeout),
            exactly_one,
            language=language,
        )