Skip to content
This repository has been archived by the owner on Sep 5, 2023. It is now read-only.

add autosuggest api #19

Merged
merged 5 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions here_location_services/autosuggest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"""This module contains classes for accessing `HERE Autosuggest API <https://developer.here.com/documentation/geocoding-search-api/dev_guide/topics/endpoint-autosuggest-brief.html>`_.
""" # noqa E501

from typing import Dict, List, Optional
from typing import Dict, List, Optional, Tuple

from here_location_services.config.autosuggest_config import SearchBox, SearchCircle
from here_location_services.config.autosuggest_config import SearchCircle
from here_location_services.platform.auth import Auth

from .apis import Api
Expand All @@ -28,36 +28,36 @@ def __init__(

def get_autosuggest(
self,
q: str,
query: str,
at: Optional[List] = None,
jain-aayush1123 marked this conversation as resolved.
Show resolved Hide resolved
search_in_circle: Optional[SearchCircle] = None,
search_in_box: Optional[SearchBox] = None,
in_country: Optional[List] = None,
limit: Optional[int] = None,
search_in_bbox: Optional[Tuple] = None,
in_country: Optional[List[str]] = None,
limit: Optional[int] = 20,
terms_limit: Optional[int] = None,
lang: Optional[List] = None,
lang: Optional[List[str]] = None,
political_view: Optional[str] = None,
show: Optional[List] = None,
show: Optional[List[str]] = None,
):
"""Suggest address or place candidates based on an incomplete or misspelled query

:param q: A string for free-text query. Example: res, rest
:param query: A string for free-text query. Example: res, rest
:param at: Specify the center of the search context expressed as coordinates
One of `at`, `search_in_circle` or `search_in_box` is required.
Parameters "at", "search_in_circle" and "search_in_box" are mutually exclusive. Only
One of `at`, `search_in_circle` or `search_in_bbox` is required.
Parameters "at", "search_in_circle" and "search_in_bbox" are mutually exclusive. Only
one of them is allowed.
:param search_in_circle: Search within a circular geographic area provided as
latitude, longitude, and radius (in meters)
:param search_in_box: Search within a rectangular bounding box geographic area provided
as west longitude, south latitude, east longitude, north latitude
:param search_in_bbox: Search within a rectangular bounding box geographic area provided
as tuple of west longitude, south latitude, east longitude, north latitude
:param in_country: Search within a specific or multiple countries provided as
comma-separated ISO 3166-1 alpha-3 country codes. The country codes are to be
provided in all uppercase. Must be accompanied by exactly one of
`at`, `search_in_circle` or `search_in_box`.
`at`, `search_in_circle` or `search_in_bbox`.
:param limit: An integer specifiying maximum number of results to be returned.
:param terms_limit: An integer specifiying maximum number of Query Terms Suggestions
to be returned.
:param lang: Array of string to select the language to be used for result rendering
:param lang: List of strings to select the language to be used for result rendering
from a list of BCP 47 compliant language codes.
:param political_view: Toggle the political view.
:param show: Select additional fields to be rendered in the response. Please note
Expand All @@ -70,7 +70,7 @@ def get_autosuggest(
path = "v1/autosuggest"
url = f"{self._base_url}/{path}"
params: Dict[str, str] = {
"q": q,
"q": query,
}
if at:
params["at"] = ",".join([str(i) for i in at])
Expand All @@ -95,16 +95,8 @@ def get_autosuggest(
params["politicalView"] = political_view
if show:
params["show"] = ",".join([str(i) for i in show])
if search_in_box:
params["in"] = "bbox:" + (
search_in_box.west
+ ","
+ search_in_box.south
+ ","
+ search_in_box.east
+ ","
+ search_in_box.north
)
if search_in_bbox:
params["in"] = "bbox:" + ",".join([str(i) for i in search_in_bbox])
resp = self.get(url, params=params, proxies=self.proxies)
if resp.status_code == 200:
return resp
Expand Down
14 changes: 0 additions & 14 deletions here_location_services/config/autosuggest_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@ def __init__(self, lat: str, lng: str, radius: int):
self.radius = radius


class SearchBox:
"""A class to define ``SearchBox``

Results will be returned if they are located within the specified rectangular
area defined by its west longitude, south latitude, east longitude, north latitude
"""

def __init__(self, westLng: str, southLat: str, eastLng: str, northLat: str):
self.west = westLng
self.south = southLat
self.east = eastLng
self.north = northLat


class PoliticalView(Bunch):
"""A Class to define constant values for political view

Expand Down
57 changes: 23 additions & 34 deletions here_location_services/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
import urllib.request
from datetime import datetime
from time import sleep
from typing import Dict, List, Optional, Union
from typing import Dict, List, Optional, Tuple, Union

from here_location_services.config.routing_config import Scooter, Via
from here_location_services.platform.apis.aaa_oauth2_api import AAAOauth2Api
from here_location_services.platform.auth import Auth
from here_location_services.platform.credentials import PlatformCredentials

from .autosuggest_api import AutosuggestApi
from .config.autosuggest_config import SearchBox, SearchCircle
from .config.autosuggest_config import SearchCircle
from .config.base_config import PlaceOptions, Truck, WayPointOptions
from .config.matrix_routing_config import (
AutoCircleRegion,
Expand Down Expand Up @@ -205,7 +205,7 @@ def calculate_isoline(
for ``destination``.
:param destination_waypoint_options: :class:`WayPointOptions` optional waypoint options
for ``destination``.
:raises ValueError: If ``start`` and ``destination`` are provided togrther.
:raises ValueError: If ``origin`` and ``destination`` are provided together.
:return: :class:`IsolineResponse` object.
"""

Expand Down Expand Up @@ -244,67 +244,56 @@ def calculate_isoline(

def autosuggest(
self,
q: str,
query: str,
at: Optional[List] = None,
search_in_circle: Optional[SearchCircle] = None,
search_in_box: Optional[SearchBox] = None,
in_country: Optional[List] = None,
limit: Optional[int] = None,
search_in_bbox: Optional[Tuple] = None,
in_country: Optional[List[str]] = None,
limit: Optional[int] = 20,
terms_limit: Optional[int] = None,
lang: Optional[List] = None,
lang: Optional[List[str]] = None,
political_view: Optional[str] = None,
show: Optional[List] = None,
show: Optional[List[str]] = None,
) -> AutosuggestResponse:
"""Suggest address or place candidates based on an incomplete or misspelled query

:param q: A string for free-text query. Example: res, rest
:param query: A string for free-text query. Example: res, rest
:param at: Specify the center of the search context expressed as coordinates
sackh marked this conversation as resolved.
Show resolved Hide resolved
One of `at`, `search_in_circle` or `search_in_box` is required.
Parameters "at", "search_in_circle" and "search_in_box" are mutually exclusive. Only
One of `at`, `search_in_circle` or `search_in_bbox` is required.
Parameters "at", "search_in_circle" and "search_in_bbox" are mutually exclusive. Only
one of them is allowed.
:param search_in_circle: Search within a circular geographic area provided as
latitude, longitude, and radius (in meters)
:param search_in_box: Search within a rectangular bounding box geographic area provided
as west longitude, south latitude, east longitude, north latitude
:param search_in_bbox: Search within a rectangular bounding box geographic area provided
as tuple of west longitude, south latitude, east longitude, north latitude
:param in_country: Search within a specific or multiple countries provided as
comma-separated ISO 3166-1 alpha-3 country codes. The country codes are to be
provided in all uppercase. Must be accompanied by exactly one of
`at`, `search_in_circle` or `search_in_box`.
`at`, `search_in_circle` or `search_in_bbox`.
:param limit: An integer specifiying maximum number of results to be returned.
:param terms_limit: An integer specifiying maximum number of Query Terms Suggestions
to be returned.
:param lang: Array of string to select the language to be used for result rendering
:param lang: List of strings to select the language to be used for result rendering
from a list of BCP 47 compliant language codes.
:param political_view: Toggle the political view.
:param show: Select additional fields to be rendered in the response. Please note
that some of the fields involve additional webservice calls and can increase
the overall response time.
:return: :class:`requests.Response` object.
:raises ValueError: If ``search_in_circle``,``search_in_box`` and ``destination``
are provided togrther.
:raises ValueError: If ``search_in_circle``,``search_in_bbox`` and ``destination``
are provided together.
"""

if search_in_circle and search_in_box and at:
raise ValueError(
"`search_in_circle` and `search_in_box` and `at` can not be provided together."
)
if search_in_circle and search_in_box:
i = iter([search_in_circle, search_in_bbox, at])
if not (any(i) and not any(i)):
raise ValueError(
"`search_in_circle` and `search_in_box` can not be provided together."
)
if search_in_box and at:
raise ValueError("`search_in_box` and `at` can not be provided together.")
if search_in_circle and at:
raise ValueError("`search_in_circle` and `at` can not be provided together.")
if search_in_circle is None and search_in_box is None and at is None:
raise ValueError(
"please provide either `search_in_circle` or `search_in_box` or `at`."
"Exactly one of `search_in_circle` or `search_in_bbox` or `at` must be provided."
)

resp = self.autosuggest_api.get_autosuggest(
q=q,
query=query,
at=at,
search_in_box=search_in_box,
search_in_bbox=search_in_bbox,
search_in_circle=search_in_circle,
in_country=in_country,
limit=limit,
Expand Down
30 changes: 11 additions & 19 deletions tests/test_ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@
from geojson import FeatureCollection

from here_location_services import LS
from here_location_services.config.autosuggest_config import (
POLITICAL_VIEW,
SHOW,
SearchBox,
SearchCircle,
)
from here_location_services.config.autosuggest_config import POLITICAL_VIEW, SHOW, SearchCircle
from here_location_services.config.base_config import (
ROUTING_MODE,
SHIPPED_HAZARDOUS_GOODS,
Expand Down Expand Up @@ -61,25 +56,22 @@
def test_ls_autosuggest():
"""Test autosuggest api."""
ls = LS(api_key=LS_API_KEY)
resp = ls.autosuggest(q="res", limit=5, at=["52.93175,12.77165"])
resp = ls.autosuggest(query="res", limit=5, at=["52.93175,12.77165"])
assert resp.items

search_in_circle1 = SearchCircle(lat=52.53, lng="13.38", radius="10000")
search_in_box1 = SearchBox(
westLng="13.08836", southLat="52.3381", eastLng="13.761", northLat="52.6755"
)
search_in_bbox1 = ("13.08836", "52.33812", "13.761", "52.6755")

# resp2 = ls.autosuggest(q="res", limit=5, search_in_box=search_in_box1)
resp2 = ls.autosuggest(q="res", limit=5, at=["-13.163068,-72.545128"], in_country=["USA"])
resp2 = ls.autosuggest(query="res", limit=5, at=["-13.163068,-72.545128"], in_country=["USA"])
assert resp2.items

resp3 = ls.autosuggest(q="res", limit=5, search_in_circle=search_in_circle1, lang=["en"])
resp3 = ls.autosuggest(query="res", limit=5, search_in_circle=search_in_circle1, lang=["en"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add assertion for limit parameter if results returned are limited to 5

assert resp3.items

resp4 = ls.autosuggest(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertions missing for resp4 can we verify change in results after passing, show and politcal_view ?

q="res",
query="res",
limit=5,
search_in_box=search_in_box1,
search_in_bbox=search_in_bbox1,
terms_limit=3,
sackh marked this conversation as resolved.
Show resolved Hide resolved
show=[SHOW.phonemes],
political_view=POLITICAL_VIEW.RUS,
Expand All @@ -88,21 +80,21 @@ def test_ls_autosuggest():

with pytest.raises(ValueError):
ls.autosuggest(
q="res",
query="res",
)

with pytest.raises(ValueError):
ls.autosuggest(
q="res",
query="res",
at=["-13.163068,-72.545128"],
search_in_box=search_in_box1,
search_in_bbox=search_in_bbox1,
search_in_circle=search_in_circle1,
)

with pytest.raises(ApiError):
ls2 = LS(api_key="dummy")
ls2.autosuggest(
q="res",
query="res",
at=["-13.163068,-72.545128"],
)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_ls_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@pytest.mark.skipif(not LS_API_KEY, reason="No api key found.")
def test_autosuggest(autosuggest_api):
"""Test autosuggest api."""
resp = autosuggest_api.get_autosuggest(q="res", limit=5, at=["52.93175,12.77165"])
resp = autosuggest_api.get_autosuggest(query="res", limit=5, at=["52.93175,12.77165"])
assert type(resp) == requests.Response
assert resp.status_code == 200

Expand Down