Skip to content

Commit

Permalink
cli - documentation strings for printer
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomas Strachota committed Apr 13, 2012
1 parent d74c722 commit 7d02351
Showing 1 changed file with 132 additions and 16 deletions.
148 changes: 132 additions & 16 deletions cli/src/katello/client/utils/printer.py
Expand Up @@ -23,14 +23,45 @@


class PrinterStrategy:
"""
Strategy of formatting the data and printing them on the output.
"""

def print_item(self, heading, columns, item):
"""
Print one item
@type heading: string
@param heading: Title for the list of items
@type columns: list of dicts
@param columns: definition of columns
@type item: dict
@param item: data to be printed, one item
"""
self.print_items(heading, columns, [item])

def print_items(self, heading, columns, items):
"""
Print list of items
@type heading: string
@param heading: Title for the list of items
@type columns: list of dicts
@param columns: definition of columns
@type items: list of dicts
@param items: data to be printed, list of items
"""
pass

def _get_column_value(self, column, item):
"""
Returns string that should be displayed in the column.
It's either a given value or attribute of the item. Formatters
are applied if they are available.
@type column: dict
@param column: column definition
@type item: dict
@param item: data to get the value from
@rtype: string
"""
value = item.get(column['attr_name'], column.get('value', None))
value_format_func = column.get('formatter', column.get('value_formatter', None))
item_format_func = column.get('item_formatter', None)
Expand All @@ -41,10 +72,18 @@ def _get_column_value(self, column, item):
value = item_format_func(item)
return value


class VerboseStrategy(PrinterStrategy):

def print_items(self, heading, columns, items):
"""
Print list of items
@type heading: string
@param heading: Title for the list of items
@type columns: list of dicts
@param columns: definition of columns
@type items: list of dicts
@param items: data to be printed, list of items
"""
self._print_header(heading)
for item in items:
Expand All @@ -63,6 +102,11 @@ def _print_header(self, heading):

def _print_item(self, item, columns):
"""
Print one record.
@type item: hash
@param item: data to print
@type columns: list of dicts
@param columns: columns definition
"""
print
for column in columns:
Expand All @@ -72,15 +116,19 @@ def _print_item(self, item, columns):
continue

if not column.get('multiline', False):
col_width = self._column_width(columns)
col_width = self._max_label_width(columns)
print ("{0:<" + u_str(col_width + 1) + "} {1}").format(u_str(column['name'])+":", u_str(value))
# +1 to account for the : after the column name
else:
print column['name']+":"
print indent_text(value, " ")

def _column_width(self, columns):
def _max_label_width(self, columns):
"""
Returns maximum width of the column labels.
@type columns: list of dicts
@param columns: columns definition
@rtype: int
"""
width = 0
for column in columns:
Expand All @@ -90,14 +138,27 @@ def _column_width(self, columns):


class GrepStrategy(PrinterStrategy):
"""
Prints data into a grid that can be grepped easily.
String to divide the columns can be set optionally.
"""

def __init__(self, delimiter=None):
"""
@type delimiter: string
@param delimiter: delimiter for dividing the grid columns
"""
self.__delim = delimiter if delimiter else ""

def print_items(self, heading, columns, items):
"""
Print list of items
@type heading: string
@param heading: Title for the list of items
@type columns: list of dicts
@param columns: definition of columns
@type items: list of dicts
@param items: data to be printed, list of items
"""
column_widths = self._calc_column_widths(items, columns)
self._print_header(heading, columns, column_widths)
Expand All @@ -107,9 +168,13 @@ def print_items(self, heading, columns, items):

def _print_header(self, heading, columns, column_widths):
"""
Print a fancy header to stdout.
Print a fancy header with column labels to stdout.
@type heading: string or list of strings
@param heading: headers to be displayed
@type columns: list of dicts
@param columns: columns definition
@type column_widths: dict
@param column_widths: dictionary that holds maximal widths of columns {attr_name -> width}
"""
print_line()
print center_text(heading)
Expand All @@ -129,6 +194,10 @@ def _print_item(self, item, columns, column_widths):
Print item of a list on single line
@type item: hash
@param item: data to print
@type columns: list of dicts
@param columns: columns definition
@type column_widths:
@param column_widths:
"""
print self.__delim,
for column in columns:
Expand All @@ -150,6 +219,13 @@ def _print_item(self, item, columns, column_widths):

def _column_width(self, items, column):
"""
Returns maximum width for the column to ensure that all the data
and the label fits in.
@type columns: list of dicts
@param columns: columns definition
@type column: dict
@param column: column definition
@rtype: int
"""
key = column['attr_name']
width = len(column['name'])+1
Expand All @@ -160,6 +236,12 @@ def _column_width(self, items, column):

def _calc_column_widths(self, items, columns):
"""
Counts and retunrs dictionary that holds maximal widths of all columns {attr_name -> width}
@type items: list of dicts
@param items: data to be printed
@type columns: list of dicts
@param columns: columns definition
@rtype: dict
"""
widths = {}
for column in columns:
Expand All @@ -169,38 +251,42 @@ def _calc_column_widths(self, items, columns):

class Printer:
"""
Class for unified printing of the CLI output.
Unified interface for printing data in CLI.
"""

def __init__(self, strategy=None):
"""
@type strategy: PrinterStrategy
@param strategy: strategy that is used for formatting the output.
"""
self.__printer_strategy = strategy
self.__columns = []
self.__heading = ""

def set_header(self, heading):
"""
Sets label for a fancy header that is printed above the data.
@type heading: string
"""
self.__heading = heading

def set_strategy(self, strategy):
"""
Sets formatting strategy
@type strategy: PrinterStrategy
@param strategy: strategy that is used for formatting the output.
"""
self.__printer_strategy = strategy

def add_column(self, attr_name, name = None, **kwargs):
"""
Add column to display
Add column of data thet will be displayed
@type attr_name: string
@param attr_name: key to data hash
@type name: string
@param name: display name of the column. It is automatically transformed from display name
if not set.
@type multiline: bool
@param multiline: flag to mark multiline values
@type show_in_grep: bool
@param show_in_grep: flag to set whether the column should be displayed also in grep mode or not
@type value: string
@param value: value that should be used rather than accessing the data hash
@param name: label for the column. It is generated automatically attr_name if it's not set.
@type kwargs: dict
@param kwargs: other parameters that are passed to the printer strategy
"""
col = kwargs
col['attr_name'] = attr_name
Expand All @@ -209,13 +295,19 @@ def add_column(self, attr_name, name = None, **kwargs):

def print_item(self, item):
"""
Print one record
@type item: dict
@param item: data to be printed
"""
if not self.__printer_strategy:
self.set_strategy(VerboseStrategy())
self.__printer_strategy.print_item(self.__heading, self.__filtered_columns(), item)

def print_items(self, items):
"""
Print list of records
@type items: list of dicts
@param items: data to be printed
"""
if not self.__printer_strategy:
self.set_strategy(GrepStrategy())
Expand All @@ -227,11 +319,14 @@ def __attr_to_name(self, attr_name):
oraganization_id -> Organization Id
@type attr_name: string
@param attr_name: attribute name
@rtype: string
"""
return " ".join([part[0].upper() + part[1:] for part in attr_name.split("_")])

def __filtered_columns(self):
"""
@return: list of columns that can be printed with current strategy
@rtype: list of column definition dicts
"""
filtered = []
for column in self.__columns:
Expand All @@ -241,10 +336,14 @@ def __filtered_columns(self):
return filtered



# indent block of text --------------------------------------------------------
def indent_text(text, indent="\t"):
"""
Indents given text.
@type text: string or list of strings
@param text: text to be indented
@type indent: string
@param indent: value that is added at the beggining of each line of the text
@rtype: string
"""
if not text:
text = u_str(None)
Expand All @@ -256,9 +355,14 @@ def indent_text(text, indent="\t"):
return indent_text(text.split("\n"), indent)


# converts block of text to one line ------------------------------------------
def text_to_line(text, glue=" "):
"""
Squeezes a block of text to one line.
@type text: string
@param text: text to be processed
@type glue: string
@param glue: string used for joining lines of the text
@rtype: string
"""
if not text:
text = u_str(None)
Expand All @@ -271,6 +375,13 @@ def text_to_line(text, glue=" "):

def center_text(text, width = None):
"""
Centers block of text in given width.
@type text: string
@param text: text to be processed
@type width: int
@param width: width of space the text should be centered to. If no width is given,
full terminal size is used.
@rtype: string
"""
if not width:
width = get_term_width()
Expand All @@ -286,6 +397,10 @@ def center_text(text, width = None):

def print_line(width = None):
"""
Prints line of characters '-' to stdout
@type width: int
@param width: width of the line in characters. If no width is given,
full terminal size is used.
"""
if not width:
width = get_term_width()
Expand All @@ -295,6 +410,7 @@ def print_line(width = None):
def get_term_width():
"""
returns terminal width (tested only with Linux)
@rtype: int
"""
try:
import fcntl
Expand Down

0 comments on commit 7d02351

Please sign in to comment.