Beispiel #1
0
 def ValidateRouteShortAndLongNamesAreNotBlank(self, problems):
     if util.IsEmpty(self.route_short_name) and \
         util.IsEmpty(self.route_long_name):
         problems.InvalidValue(
             'route_short_name', self.route_short_name,
             'Both route_short_name and '
             'route_long name are blank.')
Beispiel #2
0
 def ValidateRouteNames(self, problems, validate_children):
   # Check for multiple routes using same short + long name
   route_names = {}
   for route in self.routes.values():
     if validate_children:
       route.Validate(problems)
     short_name = ''
     if not util.IsEmpty(route.route_short_name):
       short_name = route.route_short_name.lower().strip()
     long_name = ''
     if not util.IsEmpty(route.route_long_name):
       long_name = route.route_long_name.lower().strip()
     name = (short_name, long_name)
     if name in route_names:
       problems.InvalidValue('route_long_name',
                             long_name,
                             'The same combination of '
                             'route_short_name and route_long_name '
                             'shouldn\'t be used for more than one '
                             'route, as it is for the for the two routes '
                             'with IDs "%s" and "%s".' %
                             (route.route_id, route_names[name].route_id),
                             type=problems_module.TYPE_WARNING)
     else:
       route_names[name] = route
Beispiel #3
0
 def ValidateStopTimezone(self, problems):
   # Entrances or other child stops (having a parent station) must not have a
   # stop_timezone.
   util.ValidateTimezone(self.stop_timezone, 'stop_timezone', problems)
   if (not util.IsEmpty(self.parent_station) and
       not util.IsEmpty(self.stop_timezone)):
     problems.InvalidValue('stop_timezone', self.stop_timezone,
         reason='a stop having a parent stop must not have a stop_timezone',
         type=problems_module.TYPE_WARNING)
Beispiel #4
0
 def ValidateStopDescriptionAndNameAreDifferent(self, problems):
   if (self.stop_desc is not None and self.stop_name is not None and
       self.stop_desc and self.stop_name and
       not util.IsEmpty(self.stop_desc) and
       self.stop_name.strip().lower() == self.stop_desc.strip().lower()):
     problems.InvalidValue('stop_desc', self.stop_desc,
                           'stop_desc should not be the same as stop_name')
 def ValidateTransferType(self, problems):
     if not util.IsEmpty(self.transfer_type):
         if (not isinstance(self.transfer_type, int)) or \
             (self.transfer_type not in range(0, 4)):
             problems.InvalidValue('transfer_type', self.transfer_type)
             return False
     return True
    def ValidateMinimumTransferTime(self, problems):
        if not util.IsEmpty(self.min_transfer_time):
            if self.transfer_type != 2:
                problems.MinimumTransferTimeSetWithInvalidTransferType(
                    self.transfer_type)

            # If min_transfer_time is negative, equal to or bigger than 24h, issue
            # an error. If smaller than 24h but bigger than 3h issue a warning.
            # These errors are not blocking, and should not prevent the transfer
            # from being added to the schedule.
            if (isinstance(self.min_transfer_time, int)):
                if self.min_transfer_time < 0:
                    problems.InvalidValue('min_transfer_time', self.min_transfer_time,
                                          reason="This field cannot contain a negative " \
                                                 "value.")
                elif self.min_transfer_time >= 24 * 3600:
                    problems.InvalidValue('min_transfer_time', self.min_transfer_time,
                                          reason="The value is very large for a " \
                                                 "transfer time and most likely " \
                                                 "indicates an error.")
                elif self.min_transfer_time >= 3 * 3600:
                    problems.InvalidValue('min_transfer_time', self.min_transfer_time,
                                          type=problems_module.TYPE_WARNING,
                                          reason="The value is large for a transfer " \
                                                 "time and most likely indicates " \
                                                 "an error.")
            else:
                # It has a value, but it is not an integer
                problems.InvalidValue('min_transfer_time', self.min_transfer_time,
                                      reason="If present, this field should contain " \
                                        "an integer value.")
                return False
        return True
 def ValidateDate(self, date, field_name, problems, context=None):
     if date is None:
         # No exception is issued because ServicePeriods can be created using only
         # calendar_dates.txt. In that case we have a ServicePeriod consisting
         # entirely of service exceptions, and with no start_date or end_date.
         return False
     if util.IsEmpty(date):
         problems.MissingValue(field_name, date, context)
         return False
     elif not util.ValidateDate(date, field_name, problems):
         return False
     else:
         try:
             date_value = time.strptime(date, "%Y%m%d")
             if not (self._VALID_DATE_RANGE_FROM <= date_value.tm_year <=
                     self._VALID_DATE_RANGE_TO):
                 problems.DateOutsideValidRange(field_name,
                                                date,
                                                self._VALID_DATE_RANGE_FROM,
                                                self._VALID_DATE_RANGE_TO,
                                                context=context)
                 return False
             return True
         except ValueError:
             problems.InvalidValue(field_name,
                                   'Could not parse date value.', date,
                                   context, problems_module.TYPE_ERROR)
             return False
Beispiel #8
0
 def ValidateServicePeriod(self, problems):
   if 'service_period' in self.__dict__:
     # Some tests assign to the service_period attribute. Patch up self before
     # proceeding with validation. See also comment in Trip.__init__.
     self.service_id = self.__dict__['service_period'].service_id
     del self.service_period
   if util.IsEmpty(self.service_id):
     problems.MissingValue('service_id')
 def ValidateEndDate(self, problems):
     if self.end_date is not None:
         if util.IsEmpty(self.end_date):
             problems.MissingValue('end_date')
             self.end_date = None
         elif not self._IsValidDate(self.end_date):
             problems.InvalidValue('end_date', self.end_date)
             self.end_date = None
Beispiel #10
0
 def DeprecatedColumn(self, file_name, column_name, new_name, context=None,
                      type=TYPE_WARNING):
   reason = None
   if not util.IsEmpty(new_name):
     reason = 'Please use the new column "%s" instead.' % (new_name)
   e = DeprecatedColumn(file_name=file_name, column_name=column_name,
                        reason=reason, context=context, context2=self._context,
                        type=type)
   self.AddToAccumulator(e)
 def ValidateDaysOfWeek(self, problems):
     if self.original_day_values:
         index = 0
         for value in self.original_day_values:
             column_name = self._DAYS_OF_WEEK[index]
             if util.IsEmpty(value):
                 problems.MissingValue(column_name)
             elif (value != u'0') and (value != '1'):
                 problems.InvalidValue(column_name, value)
             index += 1
Beispiel #12
0
 def ValidateRouteAgencyId(self, problems):
   # Check that routes' agency IDs are valid, if set
   for route in self.routes.values():
     if (not util.IsEmpty(route.agency_id) and
         not route.agency_id in self._agencies):
       problems.InvalidValue('agency_id',
                             route.agency_id,
                             'The route with ID "%s" specifies agency_id '
                             '"%s", which doesn\'t exist.' %
                             (route.route_id, route.agency_id))
    def ValidateDaysOfWeek(self, problems):
        if self.original_day_values:
            for column_name, value in self.original_day_values.items():

                # check that the day of the week value exists
                if util.IsEmpty(value):
                    problems.MissingValue(column_name)

# and check that it is an expected value
                elif (value != u'0') and (value != '1'):
                    problems.InvalidValue(column_name, value)
Beispiel #14
0
 def ValidateExactTimes(self, problems):
     if util.IsEmpty(self.exact_times):
         self.exact_times = 0
         return
     try:
         self.exact_times = int(self.exact_times)
     except (ValueError, TypeError):
         problems.InvalidValue('exact_times', self.exact_times,
             'Should be 0 (no fixed schedule) or 1 (fixed and ' \
             'regular schedule, shortcut for a repetitive ' \
             'stop_times file).')
         del self.exact_times
         return
     if self.exact_times not in (0, 1):
         problems.InvalidValue('exact_times', self.exact_times,
             'Should be 0 (no fixed schedule) or 1 (fixed and ' \
             'regular schedule, shortcut for a repetitive ' \
             'stop_times file).')
    def ValidateTransferWalkingTime(self, problems):
        if util.IsEmpty(self.min_transfer_time):
            return

        if self.min_transfer_time < 0:
            # Error has already been reported, and it does not make sense
            # to calculate walking speed with negative times.
            return

        distance = self.GetTransferDistance()
        # If min_transfer_time + 120s isn't enough for someone walking very fast
        # (2m/s) then issue a warning.
        #
        # Stops that are close together (less than 240m appart) never trigger this
        # warning, regardless of min_transfer_time.
        FAST_WALKING_SPEED = 2  # 2m/s
        if self.min_transfer_time + 120 < distance / FAST_WALKING_SPEED:
            problems.TransferWalkingSpeedTooFast(
                from_stop_id=self.from_stop_id,
                to_stop_id=self.to_stop_id,
                transfer_time=self.min_transfer_time,
                distance=distance)
Beispiel #16
0
  def AddFareRuleObject(self, rule, problem_reporter=None):
    if not problem_reporter:
      problem_reporter = self.problem_reporter

    if util.IsEmpty(rule.fare_id):
      problem_reporter.MissingValue('fare_id')
      return

    if rule.route_id and rule.route_id not in self.routes:
      problem_reporter.InvalidValue('route_id', rule.route_id)
    if rule.origin_id and rule.origin_id not in self.fare_zones:
      problem_reporter.InvalidValue('origin_id', rule.origin_id)
    if rule.destination_id and rule.destination_id not in self.fare_zones:
      problem_reporter.InvalidValue('destination_id', rule.destination_id)
    if rule.contains_id and rule.contains_id not in self.fare_zones:
      problem_reporter.InvalidValue('contains_id', rule.contains_id)

    if rule.fare_id in self.fares:
      self.GetFareAttribute(rule.fare_id).rules.append(rule)
    else:
      problem_reporter.InvalidValue('fare_id', rule.fare_id,
                                    '(This fare_id doesn\'t correspond to any '
                                    'of the IDs defined in the '
                                    'fare attributes.)')
Beispiel #17
0
 def ValidateRouteId(self, problems):
   if util.IsEmpty(self.route_id):
     problems.MissingValue('route_id')
 def ValidateRequiredFieldNames(self, problems):
     for required in self._REQUIRED_FIELD_NAMES:
         if util.IsEmpty(getattr(self, required, None)):
             problems.MissingValue(required)
             return True
     return False
Beispiel #19
0
 def ValidateRouteTypeIsPresent(self, problems):
     if util.IsEmpty(self.route_type):
         problems.MissingValue('route_type')
 def ValidateAgencyLang(self, problems):
     if (not util.IsEmpty(self.agency_lang)
             and self.agency_lang.lower() not in ISO639.codes_2letter):
         problems.InvalidValue('agency_lang', self.agency_lang)
         return True
     return False
 def ValidateToStopIdIsPresent(self, problems):
     if util.IsEmpty(self.to_stop_id):
         problems.MissingValue('to_stop_id')
         return False
     return True
Beispiel #22
0
 def ValidateStopRequiredFields(self, problems):
   for required in self._REQUIRED_FIELD_NAMES:
     if util.IsEmpty(getattr(self, required, None)):
       # TODO: For now I'm keeping the API stable but it would be cleaner to
       # treat whitespace stop_id as invalid, instead of missing
       problems.MissingValue(required)
 def ValidateCurrencyType(self, problems):
     if util.IsEmpty(self.currency_type):
         problems.MissingValue("currency_type")
     elif self.currency_type not in util.ISO4217.codes:
         problems.InvalidValue("currency_type", self.currency_type)
Beispiel #24
0
 def ValidateDirectionId(self, problems):
   if hasattr(self, 'direction_id') and (not util.IsEmpty(self.direction_id)) \
       and (self.direction_id != '0') and (self.direction_id != '1'):
     problems.InvalidValue('direction_id', self.direction_id,
                           'direction_id must be "0" or "1"')
Beispiel #25
0
  def ParseAttributes(self, problems):
    """Parse all attributes, calling problems as needed.

    Return True if all of the values are valid.
    """
    if util.IsEmpty(self.shape_id):
      problems.MissingValue('shape_id')
      return

    try:
      if not isinstance(self.shape_pt_sequence, int):
        self.shape_pt_sequence = \
                util.NonNegIntStringToInt(self.shape_pt_sequence, problems)
      elif self.shape_pt_sequence < 0:
        problems.InvalidValue('shape_pt_sequence', self.shape_pt_sequence,
                              'Value should be a number (0 or higher)')
    except (TypeError, ValueError):
      problems.InvalidValue('shape_pt_sequence', self.shape_pt_sequence,
                            'Value should be a number (0 or higher)')
      return

    try:
      if not isinstance(self.shape_pt_lat, (int, float)):
        self.shape_pt_lat = util.FloatStringToFloat(self.shape_pt_lat, problems)
      if abs(self.shape_pt_lat) > 90.0:
        problems.InvalidValue('shape_pt_lat', self.shape_pt_lat)
        return
    except (TypeError, ValueError):
      problems.InvalidValue('shape_pt_lat', self.shape_pt_lat)
      return

    try:
      if not isinstance(self.shape_pt_lon, (int, float)):
        self.shape_pt_lon = util.FloatStringToFloat(self.shape_pt_lon, problems)
      if abs(self.shape_pt_lon) > 180.0:
        problems.InvalidValue('shape_pt_lon', self.shape_pt_lon)
        return
    except (TypeError, ValueError):
      problems.InvalidValue('shape_pt_lon', self.shape_pt_lon)
      return

    if abs(self.shape_pt_lat) < 1.0 and abs(self.shape_pt_lon) < 1.0:
      problems.InvalidValue('shape_pt_lat', self.shape_pt_lat,
                            'Point location too close to 0, 0, which means '
                            'that it\'s probably an incorrect location.',
                            type=problems_module.TYPE_WARNING)
      return

    if self.shape_dist_traveled == '':
      self.shape_dist_traveled = None

    if (self.shape_dist_traveled is not None and
        not isinstance(self.shape_dist_traveled, (int, float))):
      try:
        self.shape_dist_traveled = \
                util.FloatStringToFloat(self.shape_dist_traveled, problems)
      except (TypeError, ValueError):
        problems.InvalidValue('shape_dist_traveled', self.shape_dist_traveled,
                              'This value should be a positive number.')
        return

    if self.shape_dist_traveled is not None and self.shape_dist_traveled < 0:
      problems.InvalidValue('shape_dist_traveled', self.shape_dist_traveled,
                            'This value should be a positive number.')
      return

    return True
 def ValidateServiceId(self, problems):
     if util.IsEmpty(self.service_id):
         problems.MissingValue('service_id')
Beispiel #27
0
 def ValidateTripId(self, problems):
   if util.IsEmpty(self.trip_id):
     problems.MissingValue('trip_id')
Beispiel #28
0
 def ValidateStopRequiredFields(self, problems):
     for required in self._REQUIRED_FIELD_NAMES:
         if util.IsEmpty(getattr(self, required, None)):
             self._ReportMissingRequiredField(problems, required)
Beispiel #29
0
 def ValidateShapeId(self, problems):
     if util.IsEmpty(self.shape_id):
         problems.MissingValue('shape_id')
Beispiel #30
0
  def ValidateTrips(self, problems):
    stop_types = {} # a dict mapping stop_id to [route_id, route_type, is_match]
    trips = {} # a dict mapping tuple to (route_id, trip_id)

    # a dict mapping block_id to a list of tuple of
    # (trip_id, first_arrival_secs, last_arrival_secs)
    trip_intervals_by_block_id = defaultdict(lambda: [])

    for trip in sorted(self.trips.values()):
      if trip.route_id not in self.routes:
        continue
      route_type = self.GetRoute(trip.route_id).route_type
      stop_ids = []
      stop_times = trip.GetStopTimes(problems)
      for index, st in enumerate(stop_times):
        stop_id = st.stop.stop_id
        stop_ids.append(stop_id)
        # Check a stop if which belongs to both subway and bus.
        if (route_type == self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Subway'] or
            route_type == self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Bus']):
          if stop_id not in stop_types:
            stop_types[stop_id] = [trip.route_id, route_type, 0]
          elif (stop_types[stop_id][1] != route_type and
                stop_types[stop_id][2] == 0):
            stop_types[stop_id][2] = 1
            if stop_types[stop_id][1] == \
                self._gtfs_factory.Route._ROUTE_TYPE_NAMES['Subway']:
              subway_route_id = stop_types[stop_id][0]
              bus_route_id = trip.route_id
            else:
              subway_route_id = trip.route_id
              bus_route_id = stop_types[stop_id][0]
            problems.StopWithMultipleRouteTypes(st.stop.stop_name, stop_id,
                                                subway_route_id, bus_route_id)

      # We only care about trips with a block id
      if not util.IsEmpty(trip.block_id) and stop_times:

        first_arrival_secs = stop_times[0].arrival_secs
        last_departure_secs = stop_times[-1].departure_secs

        # The arrival and departure time of the first and last stop_time
        # SHOULD be set, but we need to handle the case where we're given
        # an invalid feed anyway
        if first_arrival_secs is not None and last_departure_secs is not None:

          # Create a trip interval tuple of the trip id and arrival time
          # intervals
          key = trip.block_id
          trip_intervals = trip_intervals_by_block_id[key]
          trip_interval = (trip, first_arrival_secs, last_departure_secs)
          trip_intervals.append(trip_interval)

      # Check duplicate trips which go through the same stops with same
      # service and start times.
      if self._check_duplicate_trips:
        if not stop_ids or not stop_times:
          continue
        key = (trip.service_id, stop_times[0].arrival_time, str(stop_ids))
        if key not in trips:
          trips[key] = (trip.route_id, trip.trip_id)
        else:
          problems.DuplicateTrip(trips[key][1], trips[key][0], trip.trip_id,
                                 trip.route_id)

    # Now that we've generated our block trip intervls, we can check for
    # overlaps in the intervals
    self.ValidateBlocks(problems, trip_intervals_by_block_id)