def setup_database(): """ we create two realtime_updates with the same vj but for different date and return a vj for navitia """ with app.app_context(): vj1 = model.VehicleJourney({'trip': {'id': 'vj:1'}}, date(2015, 11, 4)) vj2 = model.VehicleJourney({'trip': {'id': 'vj:2'}}, date(2015, 11, 4)) vj3 = model.VehicleJourney({'trip': {'id': 'vj:3'}}, date(2015, 11, 4)) tu1 = model.TripUpdate(vj1, contributor='realtime.ire') tu2 = model.TripUpdate(vj2, contributor='realtime.ire') tu3 = model.TripUpdate(vj3, contributor='realtime.timeo') rtu1 = model.RealTimeUpdate(None, 'ire') rtu1.created_at = datetime(2015, 11, 4, 6, 32) rtu1.trip_updates.append(tu1) model.db.session.add(rtu1) rtu2 = model.RealTimeUpdate(None, 'ire') rtu2.created_at = datetime(2015, 11, 4, 7, 32) rtu2.trip_updates.append(tu2) model.db.session.add(rtu2) rtu3 = model.RealTimeUpdate(None, 'ire') rtu3.created_at = datetime(2015, 11, 4, 7, 42) rtu3.trip_updates.append(tu3) model.db.session.add(rtu3) model.db.session.commit()
def _get_navitia_vj(self, trip_id, since_dt, until_dt): filter = "vehicle_journey.has_code({}, {})".format(self.stop_code_key, trip_id) navitia_vjs = self._request_navitia_vehicle_journeys(filter, since_dt, until_dt, depth=2) if not navitia_vjs: self.log.info("impossible to find vj {t} on [{s}, {u}]".format(t=trip_id, s=since_dt, u=until_dt)) record_internal_failure("missing vj", contributor=self.contributor.id) return None if len(navitia_vjs) > 1: vj_ids = [vj.get("id") for vj in navitia_vjs] self.log.info( "too many vjs found for {t} on [{s}, {u}]: {ids}".format( t=trip_id, s=since_dt, u=until_dt, ids=vj_ids ) ) record_internal_failure("duplicate vjs", contributor=self.contributor.id) return None nav_vj = navitia_vjs[0] vj = None try: vj = model.VehicleJourney(nav_vj, since_dt, until_dt) except Exception as e: self.log.exception("Error while creating kirin VJ of {}: {}".format(nav_vj.get("id"), e)) record_internal_failure("Error while creating kirin VJ", contributor=self.contributor.id) return vj
def _get_navitia_vj(self, piv_key, train_date, ads, is_trip_addition): self.log.debug("searching for vj {} in navitia".format(piv_key)) # large filter on date mostly to ensure only base-schedule VJ are requested filter = 'vehicle_journey.has_code("rt_piv", "{}")'.format(piv_key) train_datetime = datetime.datetime.combine(train_date, datetime.time(0, 0, 0)) since_dt = train_datetime - datetime.timedelta(days=1) until_dt = train_datetime + datetime.timedelta(days=2) navitia_vjs = self._request_navitia_vehicle_journeys(filter, since_dt, until_dt, depth=2, show_codes=True) if not navitia_vjs: # Last PIV information is always right, so if the VJ doesn't exist, it's an ADD (no matter feed content) navitia_vjs = [_make_navitia_empty_vj(piv_key)] vj = None if len(navitia_vjs) != 1: self.log.info( "Can not match a unique train for key {}".format(piv_key)) record_internal_failure("no unique train", contributor=self.contributor.id) else: navitia_vj = navitia_vjs[0] try: base_vs_rt_error_margin = datetime.timedelta(hours=1) vj_base_start = _get_first_stop_base_datetime( ads, "depart", skip_fully_added_stops=not is_trip_addition) # not even a single stop is a base-schedule stop if not vj_base_start: raise InvalidArguments( "Whole trip is specified as pre-existing, but no stop is specified as pre-existing" ) vj = model.VehicleJourney( navitia_vj, vj_base_start - base_vs_rt_error_margin, vj_base_start + base_vs_rt_error_margin, vj_start_dt=vj_base_start, ) except InvalidArguments as i: raise i except Exception as e: self.log.exception( "Error while creating kirin VJ of {}: {}".format( navitia_vjs[0].get("id"), e)) record_internal_failure("Error while creating kirin VJ", contributor=self.contributor.id) if not vj: raise ObjectNotFound("no train found for key {}".format(piv_key)) return vj
def _make_db_vj(self, vj_source_code, since_dt, until_dt): """ Search for navitia's vehicle journeys with given code, in the period provided :param vj_source_code: the code to search for :param since_dt: naive UTC datetime that starts the search period. Typically the supposed datetime of first base-schedule stop_time. :param until_dt: naive UTC datetime that ends the search period. Typically the supposed datetime of last base-schedule stop_time. """ if since_dt.tzinfo is not None or until_dt.tzinfo is not None: raise InternalException( "Invalid datetime provided: must be naive (and UTC)") navitia_vjs = self.navitia.vehicle_journeys( q={ "filter": "vehicle_journey.has_code({}, {})".format( self.stop_code_key, vj_source_code), "since": to_navitia_utc_str(since_dt), "until": to_navitia_utc_str(until_dt), "depth": "2", # we need this depth to get the stoptime's stop_area }) if not navitia_vjs: self.log.info("impossible to find vj {t} on [{s}, {u}]".format( t=vj_source_code, s=since_dt, u=until_dt)) record_internal_failure("missing vj", contributor=self.contributor.id) return [] if len(navitia_vjs) > 1: vj_ids = [vj.get("id") for vj in navitia_vjs] self.log.info( "too many vjs found for {t} on [{s}, {u}]: {ids}".format( t=vj_source_code, s=since_dt, u=until_dt, ids=vj_ids)) record_internal_failure("duplicate vjs", contributor=self.contributor.id) return [] nav_vj = navitia_vjs[0] try: vj = model.VehicleJourney(nav_vj, since_dt, until_dt) return [vj] except Exception as e: self.log.exception( "Error while creating kirin VJ of {}: {}".format( nav_vj.get("id"), e)) record_internal_failure("Error while creating kirin VJ", contributor=self.contributor.id) return []
def _get_navitia_vjs(self, headsign_str, since_dt, until_dt): """ Search for navitia's vehicle journeys with given headsigns, in the period provided """ log = logging.getLogger(__name__) vjs = {} # to get the date of the vj we use the start/end of the vj + some tolerance # since the SNCF data and navitia data might not be synchronized extended_since_dt = since_dt - timedelta(hours=1) extended_until_dt = until_dt + timedelta(hours=1) # using a set to deduplicate # one headsign_str (ex: "96320/1") can lead to multiple headsigns (ex: ["96320", "96321"]) # but most of the time (if not always) they refer to the same VJ # (the VJ switches headsign along the way). # So we do one VJ search for each headsign to ensure we get it, then deduplicate VJs for train_number in headsigns(headsign_str): log.debug('searching for vj {} on {} in navitia'.format( train_number, since_dt)) navitia_vjs = self.navitia.vehicle_journeys( q={ 'headsign': train_number, 'since': to_navitia_str(extended_since_dt), 'until': to_navitia_str(extended_until_dt), 'depth': '2', # we need this depth to get the stoptime's stop_area 'show_codes': 'true' # we need the stop_points CRCICH codes }) if not navitia_vjs: logging.getLogger(__name__).info( 'impossible to find train {t} on [{s}, {u}['.format( t=train_number, s=extended_since_dt, u=extended_until_dt)) record_internal_failure('missing train', contributor=self.contributor) for nav_vj in navitia_vjs: vj = model.VehicleJourney(nav_vj, since_dt.date()) vjs[nav_vj['id']] = vj if not vjs: raise ObjectNotFound( 'no train found for headsign(s) {}'.format(headsign_str)) return vjs.values()
def _get_vjs(self, xml_train): log = logging.getLogger(__name__) train_numbers = headsigns(get_value(xml_train, 'NumeroTrain')) # to get the date of the vj we use the start/end of the vj + some tolerance # since the ire data and navitia data might not be synchronized vj_start = as_date( get_value(xml_train, 'OrigineTheoriqueTrain/DateHeureDepart')) since = vj_start - timedelta(hours=1) vj_end = as_date( get_value(xml_train, 'TerminusTheoriqueTrain/DateHeureTerminus')) until = vj_end + timedelta(hours=1) vjs = {} for train_number in train_numbers: log.debug('searching for vj {} on {} in navitia'.format( train_number, vj_start)) navitia_vjs = self.navitia.vehicle_journeys( q={ 'headsign': train_number, 'since': to_str(since), 'until': to_str(until), 'depth': '2', # we need this depth to get the stoptime's stop_area 'show_codes': 'true' # we need the stop_points CRCICH codes }) if not navitia_vjs: logging.getLogger(__name__).info( 'impossible to find train {t} on [{s}, {u}['.format( t=train_number, s=since, u=until)) record_internal_failure('missing train', contributor=self.contributor) for nav_vj in navitia_vjs: vj = model.VehicleJourney(nav_vj, vj_start.date()) vjs[nav_vj['id']] = vj if not vjs: raise ObjectNotFound( 'no train found for headsigns {}'.format(train_numbers)) return vjs.values()
def _make_db_vj(self, vj_source_code, since_dt, until_dt): """ Search for navitia's vehicle journeys with given code, in the period provided :param vj_source_code: the code to search for :param since_dt: naive UTC datetime that starts the search period. Typically the supposed datetime of first base-schedule stop_time. :param until_dt: naive UTC datetime that ends the search period. Typically the supposed datetime of last base-schedule stop_time. """ filter = "vehicle_journey.has_code({}, {})".format( self.stop_code_key, vj_source_code) navitia_vjs = self._request_navitia_vehicle_journeys(filter, since_dt, until_dt, depth=2) if not navitia_vjs: self.log.info("impossible to find vj {t} on [{s}, {u}]".format( t=vj_source_code, s=since_dt, u=until_dt)) record_internal_failure("missing vj", contributor=self.contributor.id) return [] if len(navitia_vjs) > 1: vj_ids = [vj.get("id") for vj in navitia_vjs] self.log.info( "too many vjs found for {t} on [{s}, {u}]: {ids}".format( t=vj_source_code, s=since_dt, u=until_dt, ids=vj_ids)) record_internal_failure("duplicate vjs", contributor=self.contributor.id) return [] nav_vj = navitia_vjs[0] try: vj = model.VehicleJourney(nav_vj, since_dt, until_dt) return [vj] except Exception as e: self.log.exception( "Error while creating kirin VJ of {}: {}".format( nav_vj.get("id"), e)) record_internal_failure("Error while creating kirin VJ", contributor=self.contributor.id) return []
def _make_db_vj(self, vj_source_code, utc_since_dt, utc_until_dt): navitia_vjs = self.navitia.vehicle_journeys( q={ 'filter': 'vehicle_journey.has_code({}, {})'.format( self.stop_code_key, vj_source_code), 'since': to_str(utc_since_dt), 'until': to_str(utc_until_dt), 'depth': '2', # we need this depth to get the stoptime's stop_area }) if not navitia_vjs: self.log.info('impossible to find vj {t} on [{s}, {u}]'.format( t=vj_source_code, s=utc_since_dt, u=utc_until_dt)) record_internal_failure('missing vj', contributor=self.contributor) return [] if len(navitia_vjs) > 1: vj_ids = [vj.get('id') for vj in navitia_vjs] self.log.info( 'too many vjs found for {t} on [{s}, {u}]: {ids}'.format( t=vj_source_code, s=utc_since_dt, u=utc_until_dt, ids=vj_ids)) record_internal_failure('duplicate vjs', contributor=self.contributor) return [] nav_vj = navitia_vjs[0] try: vj = model.VehicleJourney(nav_vj, utc_since_dt, utc_until_dt) return [vj] except Exception as e: self.log.exception( 'Error while creating kirin VJ of {}: {}'.format( nav_vj.get('id'), e)) record_internal_failure('Error while creating kirin VJ', contributor=self.contributor) return []
def _get_navitia_vjs(self, trip, data_time): vj_source_code = trip.trip_id since = data_time - self.period_filter_tolerance until = data_time + self.period_filter_tolerance self.log.debug('searching for vj {} on [{}, {}[ in navitia'.format(vj_source_code, since, until)) navitia_vjs = self.navitia.vehicle_journeys(q={ 'filter': 'vehicle_journey.has_code({}, {})'.format(self.stop_code_key, vj_source_code), 'since': to_str(since), 'until': to_str(until), 'depth': '2', # we need this depth to get the stoptime's stop_area }) if not navitia_vjs: logging.getLogger(__name__).info('impossible to find vj {t} on [{s}, {u}[' .format(t=vj_source_code, s=since, u=until)) return [model.VehicleJourney(nav_vj, since.date()) for nav_vj in navitia_vjs]
def _make_db_vj(self, vj_source_code, since, until): navitia_vjs = self.navitia.vehicle_journeys( q={ 'filter': 'vehicle_journey.has_code({}, {})'.format( self.stop_code_key, vj_source_code), 'since': to_str(since), 'until': to_str(until), 'depth': '2', # we need this depth to get the stoptime's stop_area }) if not navitia_vjs: self.log.info('impossible to find vj {t} on [{s}, {u}]'.format( t=vj_source_code, s=since, u=until)) record_internal_failure('missing vj', contributor=self.contributor) return [] if len(navitia_vjs) > 1: vj_ids = [vj.get('id') for vj in navitia_vjs] self.log.info( 'too many vjs found for {t} on [{s}, {u}]: {ids}'.format( t=vj_source_code, s=since, u=until, ids=vj_ids)) record_internal_failure('duplicate vjs', contributor=self.contributor) return [] nav_vj = navitia_vjs[0] # Now we compute the real circulate_date of VJ from since, until and vj's first stop_time # We do this to prevent cases like pass midnight when [since, until] is too large # we need local timezone circulate_date (and it's sometimes different from UTC date) first_stop_time = nav_vj.get('stop_times', [{}])[0] tzinfo = get_timezone(first_stop_time) # 'since' and 'until' must have a timezone before being converted to local timezone local_since = pytz.utc.localize(since).astimezone(tzinfo) local_until = pytz.utc.localize(until).astimezone(tzinfo) circulate_date = None if local_since.date() == local_until.date(): circulate_date = local_since.date() else: arrival_time = first_stop_time['arrival_time'] # At first, we suppose that the circulate_date is local_since's date if local_since <= tzinfo.localize( datetime.datetime.combine(local_since.date(), arrival_time)) <= local_until: circulate_date = local_since.date() elif local_since <= tzinfo.localize( datetime.datetime.combine(local_until.date(), arrival_time)) <= local_until: circulate_date = local_until.date() if circulate_date is None: self.log.error( 'impossible to calculate the circulate date (local) of vj: {}'. format(nav_vj.get('id'))) record_internal_failure( 'impossible to calculate the circulate date of vj', contributor=self.contributor) return [] try: vj = model.VehicleJourney(nav_vj, circulate_date) return [vj] except Exception as e: self.log.exception( 'Error while creating kirin VJ of {}: {}'.format( nav_vj.get('id'), e)) record_internal_failure('Error while creating kirin VJ', contributor=self.contributor) return []
def setup_database(): """ we create two realtime_updates with the same vj but for different date and return a vj for navitia """ with app.app_context(): vj1 = model.VehicleJourney( { 'trip': { 'id': 'vj:1' }, 'stop_times': [{ 'utc_arrival_time': time(9, 0), 'stop_point': { 'stop_area': { 'timezone': 'Europe/Paris' } } }] }, utc.localize(datetime(2015, 11, 4, 8, 0, 0)), utc.localize(datetime(2015, 11, 4, 10, 0, 0))) vj2 = model.VehicleJourney( { 'trip': { 'id': 'vj:2' }, 'stop_times': [{ 'utc_arrival_time': time(9, 0), 'stop_point': { 'stop_area': { 'timezone': 'Europe/Paris' } } }] }, utc.localize(datetime(2015, 11, 4, 8, 0, 0)), utc.localize(datetime(2015, 11, 4, 10, 0, 0))) vj3 = model.VehicleJourney( { 'trip': { 'id': 'vj:3' }, 'stop_times': [{ 'utc_arrival_time': time(9, 0), 'stop_point': { 'stop_area': { 'timezone': 'Europe/Paris' } } }] }, utc.localize(datetime(2015, 11, 4, 8, 0, 0)), utc.localize(datetime(2015, 11, 4, 10, 0, 0))) tu1 = model.TripUpdate(vj1, contributor='realtime.cots') tu2 = model.TripUpdate(vj2, contributor='realtime.cots') tu3 = model.TripUpdate(vj3, contributor='realtime.sherbrooke') rtu1 = model.RealTimeUpdate(None, 'cots', 'realtime.cots') rtu1.created_at = datetime(2015, 11, 4, 6, 32) rtu1.trip_updates.append(tu1) model.db.session.add(rtu1) rtu2 = model.RealTimeUpdate(None, 'cots', contributor='realtime.cots') rtu2.created_at = datetime(2015, 11, 4, 7, 32) rtu2.trip_updates.append(tu2) model.db.session.add(rtu2) rtu3 = model.RealTimeUpdate(None, 'gtfs-rt', contributor='realtime.sherbrooke') rtu3.created_at = datetime(2015, 11, 4, 7, 42) rtu3.trip_updates.append(tu3) model.db.session.add(rtu3) rtu4 = model.RealTimeUpdate( None, connector='gtfs-rt', contributor='realtime.sherbrooke', status='KO', error='No new information destinated to navitia for this gtfs-rt') rtu4.created_at = datetime(2015, 11, 4, 7, 52) model.db.session.add(rtu4) model.db.session.commit()
def _get_navitia_vjs(self, headsign_str, since_dt, until_dt, action_on_trip=ActionOnTrip.NOT_ADDED.name): """ Search for navitia's vehicle journeys with given headsigns, in the period provided :param headsign_str: the headsigns to search for (can be multiple expressed in one string, like "2512/3") :param since_dt: naive UTC datetime that starts the search period. Typically the supposed datetime of first base-schedule stop_time. :param until_dt: naive UTC datetime that ends the search period. Typically the supposed datetime of last base-schedule stop_time. :param action_on_trip: action to be performed on trip. This param is used to do consistency check """ if (since_dt is None) or (until_dt is None): return [] if since_dt.tzinfo is not None or until_dt.tzinfo is not None: raise InternalException( "Invalid datetime provided: must be naive (and UTC)") vjs = {} # to get the date of the vj we use the start/end of the vj + some tolerance # since the SNCF data and navitia data might not be synchronized extended_since_dt = since_dt - SNCF_SEARCH_MARGIN extended_until_dt = until_dt + SNCF_SEARCH_MARGIN # using a set to deduplicate # one headsign_str (ex: "96320/1") can lead to multiple headsigns (ex: ["96320", "96321"]) # but most of the time (if not always) they refer to the same VJ # (the VJ switches headsign along the way). # So we do one VJ search for each headsign to ensure we get it, then deduplicate VJs for train_number in headsigns(headsign_str): self.log.debug( "searching for vj {} during period [{} - {}] in navitia". format(train_number, extended_since_dt, extended_until_dt)) navitia_vjs = self.navitia.vehicle_journeys( q={ "headsign": train_number, "since": to_navitia_utc_str(extended_since_dt), "until": to_navitia_utc_str(extended_until_dt), "data_freshness": "base_schedule", "depth": "2", # we need this depth to get the stoptime's stop_area "show_codes": "true", # we need the stop_points CRCICH codes }) # Consistency check on action applied to trip if action_on_trip == ActionOnTrip.NOT_ADDED.name: if not navitia_vjs: self.log.info( "impossible to find train {t} on [{s}, {u}[".format( t=train_number, s=extended_since_dt, u=extended_until_dt)) record_internal_failure("missing train", contributor=self.contributor.id) else: if action_on_trip == ActionOnTrip.FIRST_TIME_ADDED.name and navitia_vjs: raise InvalidArguments( "Invalid action, trip {} already present in navitia". format(train_number)) navitia_vjs = [make_navitia_empty_vj(train_number)] for nav_vj in navitia_vjs: try: vj = model.VehicleJourney(nav_vj, extended_since_dt, extended_until_dt, vj_start_dt=since_dt) vjs[nav_vj["id"]] = vj except Exception as e: self.log.exception( "Error while creating kirin VJ of {}: {}".format( nav_vj.get("id"), e)) record_internal_failure("Error while creating kirin VJ", contributor=self.contributor.id) if not vjs: raise ObjectNotFound( "no train found for headsign(s) {}".format(headsign_str)) return vjs.values()
def setup_database(): """ we create two realtime_updates with the same vj but for different date and return a vj for navitia """ with app.app_context(): vj1 = model.VehicleJourney( { "trip": { "id": "vj:1" }, "stop_times": [{ "utc_arrival_time": time(9, 0), "stop_point": { "stop_area": { "timezone": "Europe/Paris" } } }], }, datetime(2015, 11, 4, 8, 0, 0), datetime(2015, 11, 4, 10, 0, 0), ) vj2 = model.VehicleJourney( { "trip": { "id": "vj:2" }, "stop_times": [{ "utc_arrival_time": time(9, 0), "stop_point": { "stop_area": { "timezone": "Europe/Paris" } } }], }, datetime(2015, 11, 4, 8, 0, 0), datetime(2015, 11, 4, 10, 0, 0), ) vj3 = model.VehicleJourney( { "trip": { "id": "vj:3" }, "stop_times": [{ "utc_arrival_time": time(9, 0), "stop_point": { "stop_area": { "timezone": "Europe/Paris" } } }], }, datetime(2015, 11, 4, 8, 0, 0), datetime(2015, 11, 4, 10, 0, 0), ) tu1 = model.TripUpdate(vj1, contributor_id=COTS_CONTRIBUTOR_ID) tu2 = model.TripUpdate(vj2, contributor_id=COTS_CONTRIBUTOR_ID) tu3 = model.TripUpdate(vj3, contributor_id=GTFS_CONTRIBUTOR_ID) rtu1 = make_rt_update(None, COTS_CONTRIBUTOR_ID, status="OK") rtu1.created_at = datetime(2015, 11, 4, 6, 32) rtu1.updated_at = datetime(2015, 11, 4, 6, 32) # mock creation, no update done rtu1.trip_updates.append(tu1) model.db.session.add(rtu1) rtu2 = make_rt_update(None, contributor_id=COTS_CONTRIBUTOR_ID, status="OK") rtu2.created_at = datetime(2015, 11, 4, 7, 32) rtu2.updated_at = datetime(2015, 11, 4, 7, 32) rtu2.trip_updates.append(tu2) model.db.session.add(rtu2) rtu3 = make_rt_update(None, contributor_id=GTFS_CONTRIBUTOR_ID, status="OK") rtu3.created_at = datetime(2015, 11, 4, 7, 42) rtu3.updated_at = datetime(2015, 11, 4, 7, 42) rtu3.trip_updates.append(tu3) model.db.session.add(rtu3) rtu4 = save_rt_data_with_error( None, contributor_id=GTFS_CONTRIBUTOR_ID, error="No new information destined for navitia on rt.vroumvroum", is_reprocess_same_data_allowed=False, ) rtu4.created_at = datetime(2015, 11, 4, 7, 52) rtu4.updated_at = datetime(2015, 11, 4, 7, 52) model.db.session.add(rtu4) rtu5 = make_rt_update(None, contributor_id=GTFS_CONTRIBUTOR_DB_ID, status="OK") rtu5.created_at = datetime(2015, 11, 4, 8, 2) rtu5.updated_at = datetime(2015, 11, 4, 8, 2) model.db.session.add(rtu5) rtu6 = make_rt_update(None, contributor_id=COTS_CONTRIBUTOR_DB_ID, status="OK") rtu6.created_at = datetime(2015, 11, 4, 8, 12) rtu6.updated_at = datetime(2015, 11, 4, 8, 12) model.db.session.add(rtu6) rtu_piv = make_rt_update(None, contributor_id=PIV_CONTRIBUTOR_ID, status="OK") rtu_piv.created_at = datetime(2015, 11, 4, 8, 17) rtu_piv.updated_at = datetime(2015, 11, 4, 8, 17) model.db.session.add(rtu_piv) model.db.session.commit()
def _get_navitia_vjs(self, headsign_str, utc_since_dt, utc_until_dt, action_on_trip=ActionOnTrip.NOT_ADDED.name): """ Search for navitia's vehicle journeys with given headsigns, in the period provided :param utc_since_dt: UTC datetime that starts the search period. Typically the supposed datetime of first base-schedule stop_time. :param utc_until_dt: UTC datetime that ends the search period. Typically the supposed datetime of last base-schedule stop_time. """ log = logging.getLogger(__name__) if (utc_since_dt is None) or (utc_until_dt is None): return [] vjs = {} # to get the date of the vj we use the start/end of the vj + some tolerance # since the SNCF data and navitia data might not be synchronized extended_since_dt = utc_since_dt - SNCF_SEARCH_MARGIN extended_until_dt = utc_until_dt + SNCF_SEARCH_MARGIN # using a set to deduplicate # one headsign_str (ex: "96320/1") can lead to multiple headsigns (ex: ["96320", "96321"]) # but most of the time (if not always) they refer to the same VJ # (the VJ switches headsign along the way). # So we do one VJ search for each headsign to ensure we get it, then deduplicate VJs for train_number in headsigns(headsign_str): log.debug('searching for vj {} during period [{} - {}] in navitia'. format(train_number, extended_since_dt, extended_until_dt)) navitia_vjs = self.navitia.vehicle_journeys( q={ 'headsign': train_number, 'since': to_navitia_str(extended_since_dt), 'until': to_navitia_str(extended_until_dt), 'depth': '2', # we need this depth to get the stoptime's stop_area 'show_codes': 'true' # we need the stop_points CRCICH codes }) if action_on_trip == ActionOnTrip.NOT_ADDED.name: if not navitia_vjs: logging.getLogger(__name__).info( 'impossible to find train {t} on [{s}, {u}['.format( t=train_number, s=extended_since_dt, u=extended_until_dt)) record_internal_failure('missing train', contributor=self.contributor) else: if action_on_trip == ActionOnTrip.FIRST_TIME_ADDED.name and navitia_vjs: raise InvalidArguments( 'Invalid action, trip {} already present in navitia'. format(train_number)) navitia_vjs = [make_navitia_empty_vj(train_number)] for nav_vj in navitia_vjs: try: vj = model.VehicleJourney(nav_vj, extended_since_dt, extended_until_dt, vj_start_dt=utc_since_dt) vjs[nav_vj['id']] = vj except Exception as e: logging.getLogger(__name__).exception( 'Error while creating kirin VJ of {}: {}'.format( nav_vj.get('id'), e)) record_internal_failure('Error while creating kirin VJ', contributor=self.contributor) if not vjs: raise ObjectNotFound( 'no train found for headsign(s) {}'.format(headsign_str)) return vjs.values()