Beispiel #1
0
 def FormatException(self, e, output):
     """Append HTML version of e to list output."""
     d = e.GetDictToFormat()
     for k in ('file_name', 'feedname', 'column_name'):
         if k in d.keys():
             d[k] = '<code>%s</code>' % d[k]
     problem_text = e.FormatProblem(d).replace('\n', '<br>')
     output.append('<li>')
     output.append('<div class="problem">%s</div>' %
                   transitfeed.EncodeUnicode(problem_text))
     try:
         if hasattr(e, 'row_num'):
             line_str = 'line %d of ' % e.row_num
         else:
             line_str = ''
         output.append('in %s<code>%s</code><br>\n' %
                       (line_str, e.file_name))
         row = e.row
         headers = e.headers
         column_name = e.column_name
         table_header = ''  # HTML
         table_data = ''  # HTML
         for header, value in zip(headers, row):
             attributes = ''
             if header == column_name:
                 attributes = ' class="problem"'
             table_header += '<th%s>%s</th>' % (attributes, header)
             table_data += '<td%s>%s</td>' % (attributes, value)
         # Make sure output is encoded into UTF-8
         output.append('<table class="dump"><tr>%s</tr>\n' %
                       transitfeed.EncodeUnicode(table_header))
         output.append('<tr>%s</tr></table>\n' %
                       transitfeed.EncodeUnicode(table_data))
     except AttributeError, e:
         pass  # Hope this was getting an attribute from e ;-)
def WriteOutput(title, locations, limit, f):
    """Write html to f for up to limit trips between locations.

  Args:
    title: String used in html title
    locations: list of (lat, lng) tuples
    limit: maximum number of queries in the html
    f: a file object
  """
    output_prefix = """
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>%(title)s</title>
</head>
<body>
Random queries for %(title)s<p>
This list of random queries should speed up important manual testing. Here are
some things to check when looking at the results of a query.
<ul>
  <li> Check the agency attribution under the trip results:
  <ul>
    <li> has correct name and spelling of the agency
    <li> opens a page with general information about the service
  </ul>
  <li> For each alternate trip check that each of these is reasonable:
  <ul>
    <li> the total time of the trip
    <li> the time for each leg. Bad data frequently results in a leg going a long
    way in a few minutes.
    <li> the icons and mode names (Tram, Bus, etc) are correct for each leg
    <li> the route names and headsigns are correctly formatted and not
    redundant.
    For a good example see <a
    href="http://code.google.com/transit/spec/transit_feed_specification.html#transitScreenshots">the
    screenshots in the Google Transit Feed Specification</a>.
    <li> the shape line on the map looks correct. Make sure the polyline does
    not zig-zag, loop, skip stops or jump far away unless the trip does the
    same thing.
    <li> the route is active on the day the trip planner returns
  </ul>
</ul>
If you find a problem be sure to save the URL. This file is generated randomly.
<ol>
""" % locals()

    output_suffix = """
</ol>
</body>
</html>
""" % locals()

    f.write(transitfeed.EncodeUnicode(output_prefix))
    for source, destination in zip(locations[0:limit], locations[1:limit + 1]):
        f.write(
            transitfeed.EncodeUnicode(
                "<li>%s\n" % LatLngsToGoogleLink(source, destination)))
    f.write(transitfeed.EncodeUnicode(output_suffix))
    def FormatException(self, e, output):
        """Append HTML version of e to list output."""
        d = e.GetDictToFormat()
        for k in ("file_name", "feedname", "column_name"):
            if k in d.keys():
                d[k] = "<code>%s</code>" % d[k]
        if "url" in d.keys():
            d["url"] = '<a href="%(url)s">%(url)s</a>' % d

        problem_text = e.FormatProblem(d).replace("\n", "<br>")
        problem_class = "problem"
        if e.IsNotice():
            problem_class += " notice"
        output.append("<li>")
        output.append(
            '<div class="%s">%s</div>'
            % (problem_class, transitfeed.EncodeUnicode(problem_text))
        )
        try:
            if hasattr(e, "row_num"):
                line_str = "line %d of " % e.row_num
            else:
                line_str = ""
            output.append(
                "in %s<code>%s</code><br>\n"
                % (line_str, transitfeed.EncodeUnicode(e.file_name))
            )
            row = e.row
            headers = e.headers
            column_name = e.column_name
            table_header = ""  # HTML
            table_data = ""  # HTML
            for header, value in zip(headers, row):
                attributes = ""
                if header == column_name:
                    attributes = ' class="problem"'
                table_header += "<th%s>%s</th>" % (attributes, header)
                table_data += "<td%s>%s</td>" % (attributes, value)
            # Make sure output is encoded into UTF-8
            output.append(
                '<table class="dump"><tr>%s</tr>\n'
                % transitfeed.EncodeUnicode(table_header)
            )
            output.append(
                "<tr>%s</tr></table>\n" % transitfeed.EncodeUnicode(table_data)
            )
        except AttributeError as e:
            pass  # Hope this was getting an attribute from e ;-)
        output.append("<br></li>\n")
    def WriteOutput(self, feed_location, f, schedule, extension):
        """Write the html output to f."""
        if self.HasIssues():
            if self.ErrorCount() + self.WarningCount() == 1:
                summary = (
                    '<span class="fail">Found this problem:</span>\n%s'
                    % self.CountTable()
                )
            else:
                summary = (
                    '<span class="fail">Found these problems:</span>\n%s'
                    % self.CountTable()
                )
        else:
            summary = '<span class="pass">feed validated successfully</span>'

        if self.HasNotices():
            summary = (
                '<h3 class="issueHeader">Notices:</h3>'
                + self.FormatType("Notice", self.ProblemListMap(TYPE_NOTICE).items())
                + summary
            )

        basename = os.path.basename(feed_location)
        feed_path = (feed_location[: feed_location.rfind(basename)], basename)

        agencies = ", ".join(
            [
                '<a href="%s">%s</a>' % (a.agency_url, a.agency_name)
                for a in schedule.GetAgencyList()
            ]
        )
        if not agencies:
            agencies = "?"

        dates = "No valid service dates found"
        (start, end) = schedule.GetDateRange()
        if start and end:

            def FormatDate(yyyymmdd):
                src_format = "%Y%m%d"
                dst_format = "%B %d, %Y"
                try:
                    return time.strftime(
                        dst_format, time.strptime(yyyymmdd, src_format)
                    )
                except ValueError:
                    return yyyymmdd

            formatted_start = FormatDate(start)
            formatted_end = FormatDate(end)
            dates = "%s to %s" % (formatted_start, formatted_end)

        calendar_summary = CalendarSummary(schedule)
        if calendar_summary:
            calendar_summary_html = (
                """<br>
During the upcoming service dates %(date_summary_range)s:
<table>
<tr><th class="header">Average trips per date:</th><td class="header">%(mean_trips)s</td></tr>
<tr><th class="header">Most trips on a date:</th><td class="header">%(max_trips)s, on %(max_trips_dates)s</td></tr>
<tr><th class="header">Least trips on a date:</th><td class="header">%(min_trips)s, on %(min_trips_dates)s</td></tr>
</table>"""
                % calendar_summary
            )
        else:
            calendar_summary_html = ""

        output_prefix = """
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FeedValidator: %(feed_file)s</title>
<style>
body {font-family: Georgia, serif; background-color: white}
.path {color: gray}
div.problem {max-width: 500px}
table.dump td,th {background-color: khaki; padding: 2px; font-family:monospace}
table.dump td.problem,th.problem {background-color: dc143c; color: white; padding: 2px; font-family:monospace}
table.count_outside td {vertical-align: top}
table.count_outside {border-spacing: 0px; }
table {border-spacing: 5px 0px; margin-top: 3px}
h3.issueHeader {padding-left: 0.5em}
h4.issueHeader {padding-left: 1em}
.pass {background-color: lightgreen}
.fail {background-color: yellow}
.notice {background-color: yellow}
.pass, .fail {font-size: 16pt}
.header {background-color: white; font-family: Georgia, serif; padding: 0px}
th.header {text-align: right; font-weight: normal; color: gray}
.footer {font-size: 10pt}
</style>
</head>
<body>
GTFS validation results for feed:<br>
<code><span class="path">%(feed_dir)s</span><b>%(feed_file)s</b></code><br>
FeedValidator extension used: %(extension)s
<br><br>
<table>
<tr><th class="header">Agencies:</th><td class="header">%(agencies)s</td></tr>
<tr><th class="header">Routes:</th><td class="header">%(routes)s</td></tr>
<tr><th class="header">Stops:</th><td class="header">%(stops)s</td></tr>
<tr><th class="header">Trips:</th><td class="header">%(trips)s</td></tr>
<tr><th class="header">Shapes:</th><td class="header">%(shapes)s</td></tr>
<tr><th class="header">Effective:</th><td class="header">%(dates)s</td></tr>
</table>
%(calendar_summary)s
<br>
%(problem_summary)s
<br><br>
""" % {
            "feed_file": feed_path[1],
            "feed_dir": feed_path[0],
            "agencies": agencies,
            "routes": len(schedule.GetRouteList()),
            "stops": len(schedule.GetStopList()),
            "trips": len(schedule.GetTripList()),
            "shapes": len(schedule.GetShapeList()),
            "dates": dates,
            "problem_summary": summary,
            "calendar_summary": calendar_summary_html,
            "extension": extension,
        }

        # In output_suffix string
        # time.strftime() returns a regular local time string (not a Unicode one) with
        # default system encoding. And decode() will then convert this time string back
        # into a Unicode string. We use decode() here because we don't want the operating
        # system to do any system encoding (which may cause some problem if the string
        # contains some non-English characters) for the string. Therefore we decode it
        # back to its original Unicode code print.

        time_unicode = time.strftime("%B %d, %Y at %I:%M %p %Z").decode(
            sys.getfilesystemencoding()
        )
        output_suffix = """
<div class="footer">
Generated by <a href="https://github.com/google/transitfeed/wiki/FeedValidator">
FeedValidator</a> version %s on %s.
</div>
</body>
</html>""" % (
            transitfeed.__version__,
            time_unicode,
        )

        f.write(transitfeed.EncodeUnicode(output_prefix))
        if self.ProblemListMap(TYPE_ERROR):
            f.write('<h3 class="issueHeader">Errors:</h3>')
            f.write(self.FormatType("Error", self.ProblemListMap(TYPE_ERROR).items()))
        if self.ProblemListMap(TYPE_WARNING):
            f.write('<h3 class="issueHeader">Warnings:</h3>')
            f.write(
                self.FormatType("Warning", self.ProblemListMap(TYPE_WARNING).items())
            )
        f.write(transitfeed.EncodeUnicode(output_suffix))
Beispiel #5
0
def main():
  usage = \
'''%prog [options] <input GTFS.zip> [<output.kml>]

Reads GTFS file or directory <input GTFS.zip> and creates a KML file
<output.kml> that contains the geographical features of the input. If
<output.kml> is omitted a default filename is picked based on
<input GTFS.zip>. By default the KML contains all stops and shapes.

For more information see
https://github.com/google/transitfeed/wiki/KMLWriter
'''

  parser = util.OptionParserLongError(
      usage=usage, version='%prog '+transitfeed.__version__)
  parser.add_option('-t', '--showtrips', action='store_true',
                    dest='show_trips',
                    help='include the individual trips for each route')
  parser.add_option('-a', '--altitude_per_sec', action='store', type='float',
                    dest='altitude_per_sec',
                    help='if greater than 0 trips are drawn with time axis '
                    'set to this many meters high for each second of time')
  parser.add_option('-s', '--splitroutes', action='store_true',
                    dest='split_routes',
                    help='split the routes by type')
  parser.add_option('-d', '--date_filter', action='store', type='string',
                    dest='date_filter',
                    help='Restrict to trips active on date YYYYMMDD')
  parser.add_option('-p', '--display_shape_points', action='store_true',
                    dest='shape_points',
                    help='shows the actual points along shapes')
  parser.add_option('--show_stop_hierarchy', action='store_true',
                    dest='show_stop_hierarchy',
                    help='include station-stop hierarchy info in output')

  parser.set_defaults(altitude_per_sec=1.0)
  options, args = parser.parse_args()

  if len(args) < 1:
    parser.error('You must provide the path of an input GTFS file.')

  if args[0] == 'IWantMyCrash':
    raise Exception('For testCrashHandler')

  input_path = args[0]
  if len(args) >= 2:
    output_path = args[1]
  else:
    path = os.path.normpath(input_path)
    (feed_dir, feed_name) = os.path.split(path)
    if '.' in feed_name:
      feed_name = feed_name.rsplit('.', 1)[0]  # strip extension
    output_filename = '%s.kml' % feed_name
    output_path = os.path.join(feed_dir, output_filename)

  feed = None
  try:
    loader = transitfeed.Loader(input_path)
    feed = loader.Load()
  except transitfeed.ExceptionWithContext, e:
    print >>sys.stderr, (
        "\n\nGTFS feed must load without any errors.\n"
        "While loading %s the following error was found:\n%s\n%s\n" %
        (input_path,
         e.FormatContext(),
         transitfeed.EncodeUnicode(e.FormatProblem())))
    sys.exit(1)
def main():
    usage = """%prog [options] <input GTFS.zip> [<output.kml>]

Reads GTFS file or directory <input GTFS.zip> and creates a KML file
<output.kml> that contains the geographical features of the input. If
<output.kml> is omitted a default filename is picked based on
<input GTFS.zip>. By default the KML contains all stops and shapes.

For more information see
https://github.com/google/transitfeed/wiki/KMLWriter
"""

    parser = util.OptionParserLongError(
        usage=usage, version="%prog " + transitfeed.__version__
    )
    parser.add_option(
        "-t",
        "--showtrips",
        action="store_true",
        dest="show_trips",
        help="include the individual trips for each route",
    )
    parser.add_option(
        "-a",
        "--altitude_per_sec",
        action="store",
        type="float",
        dest="altitude_per_sec",
        help="if greater than 0 trips are drawn with time axis "
        "set to this many meters high for each second of time",
    )
    parser.add_option(
        "-s",
        "--splitroutes",
        action="store_true",
        dest="split_routes",
        help="split the routes by type",
    )
    parser.add_option(
        "-d",
        "--date_filter",
        action="store",
        type="string",
        dest="date_filter",
        help="Restrict to trips active on date YYYYMMDD",
    )
    parser.add_option(
        "-p",
        "--display_shape_points",
        action="store_true",
        dest="shape_points",
        help="shows the actual points along shapes",
    )
    parser.add_option(
        "--show_stop_hierarchy",
        action="store_true",
        dest="show_stop_hierarchy",
        help="include station-stop hierarchy info in output",
    )

    parser.set_defaults(altitude_per_sec=1.0)
    options, args = parser.parse_args()

    if len(args) < 1:
        parser.error("You must provide the path of an input GTFS file.")

    if args[0] == "IWantMyCrash":
        raise Exception("For testCrashHandler")

    input_path = args[0]
    if len(args) >= 2:
        output_path = args[1]
    else:
        path = os.path.normpath(input_path)
        (feed_dir, feed_name) = os.path.split(path)
        if "." in feed_name:
            feed_name = feed_name.rsplit(".", 1)[0]  # strip extension
        output_filename = "%s.kml" % feed_name
        output_path = os.path.join(feed_dir, output_filename)

    feed = None
    try:
        loader = transitfeed.Loader(input_path)
        feed = loader.Load()
    except transitfeed.ExceptionWithContext as e:
        print(
            (
                "\n\nGTFS feed must load without any errors.\n"
                "While loading %s the following error was found:\n%s\n%s\n"
                % (
                    input_path,
                    e.FormatContext(),
                    transitfeed.EncodeUnicode(e.FormatProblem()),
                )
            ),
            file=sys.stderr,
        )
        sys.exit(1)

    print("Writing %s" % output_path)
    writer = KMLWriter()
    writer.show_trips = options.show_trips
    writer.altitude_per_sec = options.altitude_per_sec
    writer.split_routes = options.split_routes
    writer.date_filter = options.date_filter
    writer.shape_points = options.shape_points
    writer.show_stop_hierarchy = options.show_stop_hierarchy
    writer.Write(feed, output_path)