Source code for here_location_services.routing_api

# Copyright (C) 2019-2021 HERE Europe B.V.
# SPDX-License-Identifier: Apache-2.0

"""This module contains classes for accessing `HERE Routing API <https://developer.here.com/documentation/routing-api/8.17.0/dev_guide/index.html>`_.
"""  # noqa E501

from datetime import datetime
from typing import Dict, List, Optional

from here_location_services.config.base_config import PlaceOptions, Truck, WayPointOptions
from here_location_services.config.matrix_routing_config import AvoidBoundingBox
from here_location_services.config.routing_config import Scooter, Via
from here_location_services.platform.auth import Auth

from .apis import Api
from .exceptions import ApiError


[docs]class RoutingApi(Api): """A class for accessing HERE routing APIs."""
[docs] def __init__( self, api_key: Optional[str] = None, auth: Optional[Auth] = None, proxies: Optional[dict] = None, country: str = "row", ): super().__init__(api_key, auth=auth, proxies=proxies, country=country) self._base_url = f"https://router.{self._get_url_string()}"
[docs] def route( self, transport_mode: str, origin: List, destination: List, via: Optional[List[Via]] = None, origin_place_options: Optional[PlaceOptions] = None, origin_waypoint_options: Optional[WayPointOptions] = None, destination_place_options: Optional[PlaceOptions] = None, destination_waypoint_options: Optional[WayPointOptions] = None, scooter: Optional[Scooter] = None, departure_time: Optional[datetime] = None, routing_mode: str = "fast", alternatives: int = 0, units: str = "metric", lang: str = "en-US", return_results: Optional[List] = None, spans: Optional[List] = None, truck: Optional[Truck] = None, avoid_features: Optional[List[str]] = None, avoid_areas: Optional[List[AvoidBoundingBox]] = None, exclude: Optional[List[str]] = None, ): """Calculate route between two endpoints. See further information `here <https://developer.here.com/documentation/routing-api/8.16.0/api-reference-swagger.html>_`. :param transport_mode: A string to represent mode of transport. :param origin: A list of ``latitude`` and ``longitude`` of origin point of route. :param destination: A list of ``latitude`` and ``longitude`` of destination point of route. :param via: A list of tuples of ``latitude`` and ``longitude`` of via points. :param origin_place_options: :class:`PlaceOptions` optinal place options for ``origin``. :param origin_waypoint_options: :class:`WayPointOptions` optional waypoint options for ``origin``. :param destination_place_options: :class:`PlaceOptions` optinal place options for ``destination``. :param destination_waypoint_options: :class:`WayPointOptions` optional waypoint options for ``destination``. :param scooter: Additional attributes for scooter route. :param departure_time: :class:`datetime.datetime` object. :param routing_mode: A string to represent routing mode. :param alternatives: Number of alternative routes to return aside from the optimal route. default value is ``0`` and maximum is ``6``. :param units: A string representing units of measurement used in guidance instructions. The default is metric. :param lang: A string representing preferred language of the response. The value should comply with the IETF BCP 47. :param return_results: A list of strings. :param spans: A list of strings to define which attributes are included in the response spans. :param truck: Different truck options to use during route calculation. use object of :class:`Truck here_location_services.config.matrix_routing_config.Truck>` :param avoid_features: Avoid routes that violate these properties. Avoid features are defined in :attr:`AVOID_FEATURES <here_location_services.config.routing_config.AVOID_FEATURES>` :param avoid_areas: A list of areas to avoid during route calculation. To define avoid area use object of :class:`AvoidBoundingBox here_location_services.config.matrix_routing_config.AvoidBoundingBox>`. :param exclude: A comma separated list of three-letter country codes (ISO-3166-1 alpha-3 code) that routes will exclude. :return: :class:`requests.Response` object. :raises ApiError: If ``status_code`` of API response is not 200. """ # noqa E501 path = "v8/routes" url = f"{self._base_url}/{path}" params: Dict[str, str] = { "origin": ",".join([str(i) for i in origin]), "destination": ",".join([str(i) for i in destination]), "transportMode": transport_mode, } if via: vias = [] for v in via: via_str = f"via={v.lat},{v.lng}" if v.place_options: place_optns_str = ";".join( key + "=" + str(val) for key, val in vars(v.place_options).items() if val is not None ) via_str = via_str + ";" + place_optns_str if v.waypoint_options: waypoint_optns_str = "!".join( key + "=" + str(val) for key, val in vars(v.waypoint_options).items() if val is not None ) via_str = via_str + "!" + waypoint_optns_str vias.append(via_str) url = url + "?" + "&".join(vias) if departure_time: params["departureTime"] = departure_time.isoformat(timespec="seconds") params["routingMode"] = routing_mode params["alternatives"] = str(alternatives) params["units"] = units params["lang"] = lang if return_results: params["return"] = ",".join(return_results) if spans: params["spans"] = ",".join(spans) if origin_place_options: origin_place_opt = ";".join( key + "=" + str(val) for key, val in vars(origin_place_options).items() if val is not None ) params["origin"] = ";".join([params["origin"], origin_place_opt]) if origin_waypoint_options: origin_way_opt = "!".join( key + "=" + str(val) for key, val in vars(origin_waypoint_options).items() if val is not None ) params["origin"] = "!".join([params["origin"], origin_way_opt]) if destination_place_options: dest_place_opt = ";".join( key + "=" + str(val) for key, val in vars(destination_place_options).items() if val is not None ) params["destination"] = ";".join([params["destination"], dest_place_opt]) if destination_waypoint_options: dest_way_opt = "!".join( key + "=" + str(val) for key, val in vars(destination_waypoint_options).items() if val is not None ) params["destination"] = "!".join([params["destination"], dest_way_opt]) if scooter: if scooter.allowHighway is True: params["scooter[allowHighway]"] = "true" else: params["scooter[allowHighway]"] = "false" if truck: for key, val in vars(truck).items(): if key == "shippedHazardousGoods" and val: params[f"truck[{key}]"] = ",".join(val) elif val is not None: params[f"truck[{key}]"] = val if avoid_features: params["avoid[features]"] = ",".join(avoid_features) if avoid_areas: bbox_areas = [] for area in avoid_areas: area_attrs = vars(area) bbox_areas.append( "bbox:{west},{south},{east},{north}".format( west=area_attrs["west"], south=area_attrs["south"], east=area_attrs["east"], north=area_attrs["north"], ) ) params["avoid[areas]"] = "|".join(bbox_areas) if exclude: params["exclude"] = ",".join(exclude) resp = self.get(url, params=params, proxies=self.proxies) if resp.status_code == 200: return resp else: raise ApiError(resp)