Exemplo n.º 1
0
    def _get_street_network_routing_matrix(
        self, instance, origins, destinations, street_network_mode, max_duration, request, request_id, **kwargs
    ):
        if street_network_mode != "bike":
            logging.getLogger(__name__).error('Geovelo, mode {} not implemented'.format(street_network_mode))
            raise InvalidArguments('Geovelo, mode {} not implemented'.format(street_network_mode))
        if len(origins) != 1 and len(destinations) != 1:
            logging.getLogger(__name__).error(
                'Geovelo, managing only 1-n in connector, requested {}-{}'.format(
                    len(origins), len(destinations)
                )
            )
            raise InvalidArguments(
                'Geovelo, managing only 1-n in connector, requested {}-{}'.format(
                    len(origins), len(destinations)
                )
            )

        data = self._make_request_arguments_isochrone(origins, destinations, request['bike_speed'])
        r = self._call_geovelo(
            '{}/{}'.format(self.service_url, 'api/v2/routes_m2m'), requests.post, ujson.dumps(data)
        )
        self._check_response(r)
        resp_json = ujson.loads(r.text)

        if len(resp_json) - 1 != len(data.get('starts', [])) * len(data.get('ends', [])):
            logging.getLogger(__name__).error('Geovelo nb response != nb requested')
            raise UnableToParse('Geovelo nb response != nb requested')

        return self._get_matrix(resp_json)
Exemplo n.º 2
0
def get_pt_object_coord(pt_object):
    """
    Given a PtObject, return the coord according to its embedded_type
    :param pt_object: type_pb2.PtObject
    :return: coord: type_pb2.GeographicalCoord

    >>> pt_object = type_pb2.PtObject()
    >>> pt_object.embedded_type = type_pb2.POI
    >>> pt_object.poi.coord.lon = 42.42
    >>> pt_object.poi.coord.lat = 41.41
    >>> coord = get_pt_object_coord(pt_object)
    >>> coord.lon
    42.42
    >>> coord.lat
    41.41
    """
    if not isinstance(pt_object, type_pb2.PtObject):
        logging.getLogger(__name__).error('Invalid pt_object')
        raise InvalidArguments('Invalid pt_object')

    map_coord = {
        type_pb2.STOP_POINT: "stop_point",
        type_pb2.STOP_AREA: "stop_area",
        type_pb2.ADDRESS: "address",
        type_pb2.ADMINISTRATIVE_REGION: "administrative_region",
        type_pb2.POI: "poi",
    }
    attr = getattr(pt_object, map_coord.get(pt_object.embedded_type, ""), None)
    coord = getattr(attr, "coord", None)

    if not coord:
        logging.getLogger(__name__).error('Invalid coord for ptobject type: {}'.format(pt_object.embedded_type))
        raise UnableToParse('Invalid coord for ptobject type: {}'.format(pt_object.embedded_type))
    return coord
Exemplo n.º 3
0
    def _format_url(self, mode, pt_object_origin, pt_object_destination):
        map_mode = {"walking": "pedestrian", "car": "auto", "bike": "bicycle"}
        if mode not in map_mode:
            logging.getLogger(__name__).error(
                'Valhalla, mode {} not implemented'.format(mode))
            raise InvalidArguments(
                'Valhalla, mode {} not implemented'.format(mode))
        valhalla_mode = map_mode.get(mode)
        args = {
            "locations": [
                self._format_coord(pt_object_origin),
                self._format_coord(pt_object_destination)
            ],
            "costing":
            valhalla_mode,
            "directions_options":
            self.directions_options
        }

        costing_options = self._get_costing_options(valhalla_mode)
        if costing_options and len(costing_options) > 0:
            args["costing_options"] = costing_options

        return '{}/route?json={}&api_key={}'.format(self.service_url,
                                                    json.dumps(args),
                                                    self.api_key)
Exemplo n.º 4
0
    def get(self, region=None, lon=None, lat=None):
        args = self.parsers["get"].parse_args()
        self._register_interpreted_parameters(args)
        if len(args['q']) == 0:
            abort(400, message="Search word absent")

        if args['disable_geojson']:
            g.disable_geojson = True

        user = authentication.get_user(token=authentication.get_token(), abort_if_no_token=False)

        if args['shape'] is None and user and user.shape:
            args['shape'] = json.loads(user.shape)

        if user and user.default_coord:
            if args['from'] is None:
                args['from'] = CoordFormat()(user.default_coord)
        else:
            if args['from'] == '':
                raise InvalidArguments("if 'from' is provided it cannot be null")

        # If a region or coords are asked, we do the search according
        # to the region, else, we do a word wide search

        if any([region, lon, lat]):
            self.region = i_manager.get_region(region, lon, lat)
            timezone.set_request_timezone(self.region)
            response = i_manager.dispatch(args, "places", instance_name=self.region)
        else:
            available_instances = get_all_available_instances(user)
            autocomplete = global_autocomplete.get('bragi')
            if not autocomplete:
                raise TechnicalError('world wide autocompletion service not available')
            response = autocomplete.get(args, instances=available_instances)
        return response, 200
Exemplo n.º 5
0
    def get(self, request, instances):
        if len(instances) != 1:
            raise InvalidArguments('kraken autocomplete works only for one (and only one) instance')
        instance = instances[0]
        req = request_pb2.Request()
        req.requested_api = type_pb2.places
        req.places.q = request['q']
        req.places.depth = request['depth']
        req.places.count = request['count']
        req.places.search_type = request['search_type']
        req._current_datetime = date_to_timestamp(request['_current_datetime'])
        if request["type[]"]:
            for type in request["type[]"]:
                if type not in places_type:
                    abort(422, message="{} is not an acceptable type".format(type))

                req.places.types.append(places_type[type])

        if request["admin_uri[]"]:
            for admin_uri in request["admin_uri[]"]:
                req.places.admin_uris.append(admin_uri)

        resp = instance.send_and_receive(req)

        if len(resp.places) == 0 and request['search_type'] == 0:
            req.places.search_type = 1
            resp = instance.send_and_receive(req)

        build_pagination(request, resp)
        return resp
Exemplo n.º 6
0
    def direct_path(self, mode, pt_object_origin, pt_object_destination,
                    fallback_extremity, request):
        if mode != "bike":
            logging.getLogger(__name__).error(
                'Geovelo, mode {} not implemented'.format(mode))
            raise InvalidArguments(
                'Geovelo, mode {} not implemented'.format(mode))

        data = self._make_request_arguments_direct_path(
            pt_object_origin, pt_object_destination)
        r = self._call_geovelo(
            '{}/{}'.format(
                self.service_url, 'api/v2/computedroutes?'
                'instructions=true&'
                'elevations=false&'
                'geometry=true&'
                'single_result=true&'
                'bike_stations=false&'
                'objects_as_ids=true&'), requests.post, json.dumps(data))
        self._check_response(r)
        resp_json = r.json()

        if len(resp_json) != 1:
            logging.getLogger(__name__).error(
                'Geovelo nb response != nb requested')
            raise UnableToParse('Geovelo nb response != nb requested')

        return self._get_response(resp_json, mode, pt_object_origin,
                                  pt_object_destination, fallback_extremity)
Exemplo n.º 7
0
 def _get_valhalla_mode(cls, kraken_mode):
     map_mode = {"walking": "pedestrian", "car": "auto", "bike": "bicycle"}
     if kraken_mode not in map_mode:
         logging.getLogger(__name__).error(
             'Valhalla, mode {} not implemented'.format(kraken_mode))
         raise InvalidArguments(
             'Valhalla, mode {} not implemented'.format(kraken_mode))
     return map_mode.get(kraken_mode)
Exemplo n.º 8
0
 def get_by_uri(self, uri, instances=None, current_datetime=None):
     if len(instances) != 1:
         raise InvalidArguments('kraken search by uri works only for one (and only one) instance')
     instance = instances[0]
     req = request_pb2.Request()
     req.requested_api = type_pb2.place_uri
     req.place_uri.uri = uri
     if current_datetime:
         req._current_datetime = date_to_timestamp(current_datetime)
     return instance.send_and_receive(req)
Exemplo n.º 9
0
    def get(self, region=None, lon=None, lat=None):
        args = self.parsers["get"].parse_args()
        self._register_interpreted_parameters(args)
        size_q = len(args['q'])
        if size_q == 0:
            abort(400, message="Search word absent")

        if size_q > 1024:
            abort(
                413,
                message="Number of characters allowed for the search is 1024")

        if args['disable_geojson']:
            g.disable_geojson = True

        user = authentication.get_user(token=authentication.get_token(),
                                       abort_if_no_token=False)

        if args['shape'] is None and user and user.shape:
            args['shape'] = json.loads(user.shape)

        if not args.get("shape_scope[]") and user:
            args.update({"shape_scope[]": user.shape_scope})

        if user and user.default_coord:
            if args['from'] is None:
                args['from'] = CoordFormat()(user.default_coord)
        else:
            if args['from'] == '':
                raise InvalidArguments(
                    "if 'from' is provided it cannot be null")

        # If a region or coords are asked, we do the search according
        # to the region, else, we do a word wide search
        args["request_id"] = args.get('request_id', flask.request.id)
        if any([region, lon, lat]):
            self.region = i_manager.get_region(region, lon, lat)

            # when autocompletion is done on a specific coverage we want to filter on its shape
            if not args['shape']:
                instance = i_manager.instances.get(self.region)
                args['shape'] = build_instance_shape(instance)
            timezone.set_request_timezone(self.region)
            response = i_manager.dispatch(args,
                                          "places",
                                          instance_name=self.region)
        else:
            available_instances = get_all_available_instances(user)
            autocomplete = global_autocomplete.get('bragi')
            if not autocomplete:
                raise TechnicalError(
                    'world wide autocompletion service not available')
            response = autocomplete.get(args, instances=available_instances)
        return response, 200
Exemplo n.º 10
0
 def _get_coord(self, pt_object):
     if not isinstance(pt_object, type_pb2.PtObject):
         logging.getLogger(__name__).error('Invalid pt_object')
         raise InvalidArguments('Invalid pt_object')
     coord = get_pt_object_coord(pt_object)
     if not coord:
         logging.getLogger(__name__).error(
             'Invalid coord for ptobject type: {}'.format(
                 pt_object.embedded_type))
         raise UnableToParse('Invalid coord for ptobject type: {}'.format(
             pt_object.embedded_type))
     return coord
Exemplo n.º 11
0
 def _find_coverage_by_object_id(self, object_id):
     if object_id.count(";") == 1 or object_id[:6] == "coord:":
         if object_id.count(";") == 1:
             lon, lat = object_id.split(";")
         else:
             lon, lat = object_id[6:].split(":")
         try:
             flon = float(lon)
             flat = float(lat)
         except:
             raise InvalidArguments(object_id)
         return self._all_keys_of_coord(flon, flat)
     return self._all_keys_of_id(object_id)
Exemplo n.º 12
0
 def _all_keys_of_id(self, object_id):
     if object_id.count(";") == 1 or object_id[:6] == "coord:":
         if object_id.count(";") == 1:
             lon, lat = object_id.split(";")
         else:
             lon, lat = object_id[6:].split(":")
         try:
             flon = float(lon)
             flat = float(lat)
         except:
             raise InvalidArguments(object_id)
         return self._all_keys_of_coord(flon, flat)
     instances = [i.name for i in self.instances.values() if i.has_id(object_id)]
     if not instances:
         raise RegionNotFound(object_id=object_id)
     return instances
Exemplo n.º 13
0
    def _direct_path(
        self,
        instance,
        mode,
        pt_object_origin,
        pt_object_destination,
        fallback_extremity,
        request,
        direct_path_type,
        request_id,
    ):
        if mode != "bike":
            logging.getLogger(__name__).error('Geovelo, mode {} not implemented'.format(mode))
            raise InvalidArguments('Geovelo, mode {} not implemented'.format(mode))

        data = self._make_request_arguments_direct_path(
            pt_object_origin, pt_object_destination, request['bike_speed']
        )
        single_result = True
        if (
            direct_path_type == StreetNetworkPathType.DIRECT
            and request['direct_path'] == 'only_with_alternatives'
        ):
            single_result = False
        r = self._call_geovelo(
            '{}/{}'.format(
                self.service_url,
                'api/v2/computedroutes?'
                'instructions=true&'
                'elevations=true&'
                'geometry=true&'
                'single_result={}&'
                'bike_stations=false&'
                'objects_as_ids=true&'.format(single_result),
            ),
            requests.post,
            ujson.dumps(data),
        )
        self._check_response(r)
        resp_json = ujson.loads(r.text)

        if len(resp_json) != 1 and single_result:
            logging.getLogger(__name__).error('Geovelo nb response != nb requested')
            raise UnableToParse('Geovelo nb response != nb requested')

        return self._get_response(resp_json, pt_object_origin, pt_object_destination, fallback_extremity)
Exemplo n.º 14
0
 def _format_coord(self, pt_object):
     if not isinstance(pt_object, type_pb2.PtObject):
         logging.getLogger(__name__).error('Invalid pt_object')
         raise InvalidArguments('Invalid pt_object')
     map_coord = {
         type_pb2.STOP_POINT: pt_object.stop_point.coord,
         type_pb2.STOP_AREA: pt_object.stop_area.coord,
         type_pb2.ADDRESS: pt_object.address.coord,
         type_pb2.ADMINISTRATIVE_REGION:
         pt_object.administrative_region.coord
     }
     coord = map_coord.get(pt_object.embedded_type, None)
     if not coord:
         logging.getLogger(__name__).error(
             'Invalid coord for ptobject type: {}'.format(
                 pt_object.embedded_type))
         raise UnableToParse('Invalid coord for ptobject type: {}'.format(
             pt_object.embedded_type))
     return {"lat": coord.lat, "lon": coord.lon, "type": "break"}
Exemplo n.º 15
0
    def _all_keys_of_id(self, object_id):
        if object_id.count(";") == 1 or object_id[:6] == "coord:":
            if object_id.count(";") == 1:
                lon, lat = object_id.split(";")
            else:
                lon, lat = object_id[6:].split(":")
            try:
                flon = float(lon)
                flat = float(lat)
            except:
                raise InvalidArguments(object_id)
            return self._all_keys_of_coord(flon, flat)
        instances = []
        futures = {}
        for name, instance in self.instances.items():
            futures[name] = gevent.spawn(instance.has_id, object_id)
        for name, future in futures.items():
            if future.get():
                instances.append(name)

        if not instances:
            raise RegionNotFound(object_id=object_id)
        return instances
Exemplo n.º 16
0
    def get(self, uri=None, region=None, lon=None, lat=None):
        args = self.parsers["get"].parse_args()

        # for retrocompatibility purpose
        for forbid_id in args['__temporary_forbidden_id[]']:
            args['forbidden_uris[]'].append(forbid_id)

        args["nb_stoptimes"] = args["count"]

        if args['disable_geojson']:
            g.disable_geojson = True

        # retrocompatibility
        if args['max_date_times'] is not None:
            args['items_per_schedule'] = args['max_date_times']

        if uri is None:
            if not args['filter']:
                raise InvalidArguments('filter')
            first_filter = args["filter"].lower().split("and")[0].strip()
            parts = first_filter.lower().split("=")
            if len(parts) != 2:
                error = "Unable to parse filter {filter}"
                return {"error": error.format(filter=args["filter"])}, 503
            else:
                self.region = i_manager.get_region(object_id=parts[1].strip())
        else:
            self.collection = 'schedules'
            args["filter"] = self.get_filter(split_uri(uri), args)
            self.region = i_manager.get_region(region, lon, lat)
        timezone.set_request_timezone(self.region)

        # create direction type filter
        if args['direction_type']:
            args['filter'] = self._add_direction_type_filter(
                args['direction_type'], args['filter'])
        logging.getLogger(__name__).debug("Schedule filter: %s",
                                          args["filter"])

        if not args["from_datetime"] and not args["until_datetime"]:
            # no datetime given, default is the current time, and we activate the realtime
            args['from_datetime'] = args['_current_datetime']
            if args["calendar"]:  # if we have a calendar, the dt is only used for sorting, so 00:00 is fine
                args['from_datetime'] = args['from_datetime'].replace(hour=0,
                                                                      minute=0)
        elif not args.get('calendar'):
            # if a calendar is given all times will be given in local (because the calendar might span over dst)
            if args['from_datetime']:
                args['from_datetime'] = self.convert_to_utc(
                    args['from_datetime'])
            if args['until_datetime']:
                args['until_datetime'] = self.convert_to_utc(
                    args['until_datetime'])

        # we save the original datetime for debugging purpose
        args['original_datetime'] = args['from_datetime']
        if args['from_datetime']:
            args['from_datetime'] = utils.date_to_timestamp(
                args['from_datetime'])
        if args['until_datetime']:
            args['until_datetime'] = utils.date_to_timestamp(
                args['until_datetime'])

        if not args['data_freshness']:
            args['data_freshness'] = self._get_default_freshness()

        if not args["from_datetime"] and args[
                "until_datetime"] and self.endpoint[:4] == "next":
            self.endpoint = "previous" + self.endpoint[4:]

        # Add timezone in request for availability in greenlet
        args['timezone'] = timezone.get_timezone()

        self._register_interpreted_parameters(args)
        return i_manager.dispatch(args,
                                  self.endpoint,
                                  instance_name=self.region)
Exemplo n.º 17
0
    def get(self, uri=None, region=None, lon=None, lat=None):
        args = self.parsers["get"].parse_args()

        # for retrocompatibility purpose
        for forbid_id in args['__temporary_forbidden_id[]']:
            args['forbidden_uris[]'].append(forbid_id)

        args["nb_stoptimes"] = args["count"]

        # retrocompatibility
        if args['max_date_times'] is not None:
            args['items_per_schedule'] = args['max_date_times']

        if uri is None:
            if not args['filter']:
                raise InvalidArguments('filter')
            first_filter = args["filter"].lower().split("and")[0].strip()
            parts = first_filter.lower().split("=")
            if len(parts) != 2:
                error = "Unable to parse filter {filter}"
                return {"error": error.format(filter=args["filter"])}, 503
            else:
                self.region = i_manager.get_region(object_id=parts[1].strip())
        else:
            self.collection = 'schedules'
            args["filter"] = self.get_filter(uri.split("/"), args)
            self.region = i_manager.get_region(region, lon, lat)
        timezone.set_request_timezone(self.region)

        if not args["from_datetime"] and not args["until_datetime"]:
            # no datetime given, default is the current time, and we activate the realtime
            args['from_datetime'] = args['_current_datetime']
            if args["calendar"]:  # if we have a calendar, the dt is only used for sorting, so 00:00 is fine
                args['from_datetime'] = args['from_datetime'].replace(hour=0,
                                                                      minute=0)

            if not args['data_freshness']:
                args['data_freshness'] = 'realtime'
        elif not args.get('calendar'):
            #if a calendar is given all times will be given in local (because the calendar might span over dst)
            if args['from_datetime']:
                args['from_datetime'] = self.convert_to_utc(
                    args['from_datetime'])
            if args['until_datetime']:
                args['until_datetime'] = self.convert_to_utc(
                    args['until_datetime'])

        # we save the original datetime for debuging purpose
        args['original_datetime'] = args['from_datetime']
        if args['from_datetime']:
            args['from_datetime'] = utils.date_to_timestamp(
                args['from_datetime'])
        if args['until_datetime']:
            args['until_datetime'] = utils.date_to_timestamp(
                args['until_datetime'])

        if not args['data_freshness']:
            # The data freshness depends on the API
            # for route_schedule, by default we want the base schedule
            if self.endpoint == 'route_schedules':
                args['data_freshness'] = 'base_schedule'
            # for stop_schedule and previous/next departure/arrival, we want the freshest data by default
            else:
                args['data_freshness'] = 'realtime'

        if not args["from_datetime"] and args["until_datetime"]\
                and self.endpoint[:4] == "next":
            self.endpoint = "previous" + self.endpoint[4:]

        self._register_interpreted_parameters(args)
        return i_manager.dispatch(args,
                                  self.endpoint,
                                  instance_name=self.region)