CLI: Added a Table abstraction. This utility class helps print information in left-aligned columns. This will be used by future plugins.
NOTE: The original review was posted by Kevin Klues on behalf of Haris Choudhary ( https://reviews.apache.org/r/52948/ ). Review: https://reviews.apache.org/r/58381/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/12e4812e Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/12e4812e Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/12e4812e Branch: refs/heads/master Commit: 12e4812e360d553539a810512d08bef6434d48af Parents: 703d001 Author: Haris Choudhary <[email protected]> Authored: Thu Apr 13 18:22:01 2017 -0700 Committer: Joseph Wu <[email protected]> Committed: Thu Apr 13 18:22:40 2017 -0700 ---------------------------------------------------------------------- src/cli_new/lib/cli/util.py | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/12e4812e/src/cli_new/lib/cli/util.py ---------------------------------------------------------------------- diff --git a/src/cli_new/lib/cli/util.py b/src/cli_new/lib/cli/util.py index ace07fb..27c4f17 100644 --- a/src/cli_new/lib/cli/util.py +++ b/src/cli_new/lib/cli/util.py @@ -21,6 +21,7 @@ A collection of helper functions used by the CLI and its Plugins. import imp import importlib import os +import re import textwrap from cli.exceptions import CLIException @@ -149,3 +150,95 @@ def format_subcommands_help(cmd): flag_string += " %s%s%s\n" % (flag, " " * num_spaces, flags[flag]) return (arguments, short_help, long_help, flag_string) + + +class Table(object): + """ + Defines a custom table structure for printing to the terminal. + """ + def __init__(self, columns): + """ + Initialize a table with a list of column names + to act as headers for each column in the table. + """ + if not isinstance(columns, list): + raise CLIException("Column headers must be supplied as a list") + + for column in columns: + if re.search(r"(\s)\1{2,}", column): + raise CLIException("Column headers cannot have more" + " than one space between words") + + self.table = [columns] + self.padding = [len(column) for column in columns] + + def __getitem__(self, index): + return list(self.table[index]) + + def dimensions(self): + """ + Returns the dimensions of the table as (<num-rows>, <num-columns>). + """ + return (len(self.table), len(self.table[0])) + + def add_row(self, row): + """ + Add a row to the table. Input must be a list where each entry + corresponds to its respective column in order. + """ + if len(row) != len(self.table[0]): + raise CLIException("Number of entries and columns do not match!") + + # Adjust padding for each column. + for index, elem in enumerate(row): + if len(elem) > self.padding[index]: + self.padding[index] = len(elem) + + self.table.append(row) + + def __str__(self): + """ + Convert a table to string for printing. + """ + table_string = "" + for r_index, row in enumerate(self.table): + for index, entry in enumerate(row): + table_string += "%s%s" % \ + (entry, " " * (self.padding[index] - len(entry) + 2)) + + if r_index != len(self.table) - 1: + table_string += "\n" + + return table_string + + @staticmethod + def parse(string): + """ + Parse a string previously printed as a `Table` back into a `Table`. + """ + lines = string.split("\n") + + # Find the location and contents of column headers in the string. + # Assume only single spaces between words in column headers. + matches = re.finditer(r"([\w\d]+\s?[\w\d]+)+", lines[0]) + columns = [(m.start(), m.group()) for m in matches] + + # Build a table from the column header contents. + table = Table([c[1] for c in columns]) + + # Fill in the subsequent rows. + for line in lines[1:]: + row = [] + start_indices = [c[0] for c in columns] + + for i, start_index in enumerate(start_indices): + if i + 1 < len(start_indices): + column = line[start_index:start_indices[i + 1]] + else: + column = line[start_index:] + + row.append(str(column.strip())) + + table.add_row(row) + + return table
