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)
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
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)
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
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
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)
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)
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)
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
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
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)
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
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)
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"}
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
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)
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)