llvmbot monitor: Convert table output to a builder class
We could import a library to do this but it doesn't seem
worth it just for tables.
This uses a content manager so you don't have to write the
begin and end of each cell/row/table. Each method returns
self so you can just keep calling methods to build what you
need.
Change-Id: I8eef664f41039a9fbc662a148f292efd61866694
diff --git a/monitor/bot-status.py b/monitor/bot-status.py
index be1801f..9bf60d7 100755
--- a/monitor/bot-status.py
+++ b/monitor/bot-status.py
@@ -21,6 +21,7 @@
# to download multiple files.
import requests
from textwrap import dedent
+from make_table import Table
from buildkite_status import get_buildkite_bots_status
@@ -130,6 +131,7 @@
return bot_cache
+
def write_bot_status(config, output_file, bots_status):
temp = tempfile.NamedTemporaryFile(mode='w+', delete=False)
@@ -157,8 +159,6 @@
"Build In Progress",
]
num_columns = len(column_titles)
- column_titles_html = "<tr>{}</tr>\n".format(
- "".join(["<th>{}</th>".format(t) for t in column_titles]))
# The first table should also say when this was generated.
# If we were to put this in its own header only table, it would
@@ -167,85 +167,83 @@
# Dump all servers / bots
for server in filter(not_ignored, config):
- base_url = server['base_url']
- builder_url = server['builder_url']
- build_url = server['build_url']
+ with Table(temp) as table:
+ table.Border(0).Cellspacing(1).Cellpadding(2)
- temp.write("<table border=0 cellspacing=1 cellpadding=2>\n")
- temp.write("<tr><td colspan={}> </td><tr>\n".format(num_columns))
- if first:
- temp.write("<tr><th colspan={}>Generated {} ({})</td><tr>\n"
- .format(num_columns, datetime.today().ctime(),
- time.tzname[time.daylight]))
- temp.write("<tr><td colspan={}> </td><tr>\n".format(num_columns))
- first = False
+ table.AddRow().AddCell().Colspan(num_columns)
- temp.write("<tr><th colspan={}>{}</td><tr>\n"
- .format(num_columns, server['name']))
+ if first:
+ table.AddRow().AddHeader("Generated {} ({})".format(
+ datetime.today().ctime(), time.tzname[time.daylight])).Colspan(num_columns)
+ table.AddRow().AddCell().Colspan(num_columns)
+ first = False
- for builder in server['builders']:
- temp.write("<tr><td colspan={}> </td><tr>\n".format(num_columns))
- temp.write("<tr><th colspan={}>{}</th><tr>\n".format(num_columns, builder['name']))
- temp.write(column_titles_html)
- temp.write("<tbody>\n")
- for bot in builder['bots']:
- temp.write("<tr>\n")
- logging.debug("Writing out status for {}".format(bot['name']))
- try:
- status = bots_status[(base_url, bot['name'])]
- except KeyError:
- temp.write(" <td colspan={}>{} is offline!</td>\n</tr>\n"
- .format(num_columns, bot['name']))
- continue
- else:
- if not status.get('valid', True):
- temp.write(" <td colspan={}>Could not read status for {}!</td>\n</tr>\n"
- .format(num_columns, bot['name']))
+ table.AddRow().AddHeader(server['name']).Colspan(num_columns)
+
+ for builder in server['builders']:
+ table.AddRow().AddCell().Colspan(num_columns)
+ table.AddRow().AddHeader(builder['name']).Colspan(num_columns)
+ title_row = table.AddRow()
+ for title in column_titles:
+ title_row.AddHeader(title)
+
+ table.BeginBody()
+
+ for bot in builder['bots']:
+ logging.debug("Writing out status for {}".format(bot['name']))
+
+ row = table.AddRow()
+ base_url = server['base_url']
+ try:
+ status = bots_status[(base_url, bot['name'])]
+ except KeyError:
+ row.AddCell("{} is offline!".format(bot['name'])).Colspan(num_columns)
+ continue
+ else:
+ if not status.get('valid', True):
+ row.AddCell("Could not read status for {}!".format(
+ bot['name'])).Colspan(num_columns)
continue
- temp.write(" <td><a href='{}'>{}</a></td>\n".format(
- status['builder_url'], bot['name']))
- temp.write(" <td><font color='{}'>{}</font></td>\n"
- .format('red' if status['fail'] else 'green',
- 'FAIL' if status['fail'] else 'PASS'))
- empty_cell=" <td> </td>\n"
- if 'time_since' in status:
- time_since = status['time_since']
- # No build should be taking more than a day
- if time_since > timedelta(hours=24):
- time_since = "<p style=\"color:red\">{}</p>".format(
- time_since)
- else:
- time_since = str(time_since)
+ row.AddCell("<a href='{}'>{}</a>".format(status['builder_url'], bot['name']))
+ row.AddCell("<font color='{}'>{}</font>"
+ .format('red' if status['fail'] else 'green',
+ 'FAIL' if status['fail'] else 'PASS'))
- temp.write(" <td>{}</td>\n".format(time_since))
- else:
- temp.write(empty_cell)
- if 'duration' in status:
- temp.write(" <td>{}</td>\n".format(status['duration']))
- else:
- temp.write(empty_cell)
- if 'number' in status:
- temp.write(" <td><a href='{}'>{}</a></td>\n".format(
- status['build_url'], status['number']))
- else:
- temp.write(empty_cell)
- if 'steps' in status and status['steps']:
- def render_step(name, result):
- return "<font color='{}'>{}</font>".format(RESULT_COLORS[result], name)
- step_list = ', '.join(render_step(name, result) for name, result in status['steps'])
- temp.write(" <td style=\"text-align:center\">{}</td>\n".format(step_list))
- else:
- temp.write(empty_cell)
- if 'next_in_progress' in status:
- temp.write(" <td>{}</td>\n".format(
- "Yes" if status['next_in_progress'] else "No"))
- else:
- # No value means we don't know either way.
- temp.write(empty_cell)
- temp.write("</tr>\n")
- temp.write("</tbody>\n")
- temp.write("</table>\n")
+ time_since_cell = row.AddCell()
+ if 'time_since' in status:
+ time_since = status['time_since']
+ # No build should be taking more than a day
+ if time_since > timedelta(hours=24):
+ time_since = "<p style=\"color:red\">{}</p>".format(
+ time_since)
+ else:
+ time_since = str(time_since)
+
+ time_since_cell.Content(time_since)
+
+ duration_cell = row.AddCell()
+ if 'duration' in status:
+ duration_cell.Content(status['duration'])
+
+ number_cell = row.AddCell()
+ if 'number' in status:
+ number_cell.Content("<a href='{}'>{}</a>".format(
+ status['build_url'], status['number']))
+
+ steps_cell = row.AddCell()
+ if 'steps' in status and status['steps']:
+ def render_step(name, result):
+ return "<font color='{}'>{}</font>".format(RESULT_COLORS[result], name)
+ step_list = ', '.join(render_step(name, result) for name, result in status['steps'])
+ steps_cell.Style("text-align:center").Content(step_list)
+
+ next_in_progress_cell = row.AddCell()
+ if 'next_in_progress' in status:
+ next_in_progress_cell.Content(
+ "Yes" if status['next_in_progress'] else "No")
+
+ table.EndBody()
# Move temp to main (atomic change)
temp.close()