diff --git a/cliff/formatters/__init__.py b/cliff/formatters/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cliff/formatters/base.py b/cliff/formatters/base.py new file mode 100644 index 00000000..8634f414 --- /dev/null +++ b/cliff/formatters/base.py @@ -0,0 +1,26 @@ +"""Base classes for formatters. +""" + +import abc + + +class Formatter(object): + + def __init__(self): + return + + def add_argument_group(self, parser): + """Add any options to the argument parser. + + Should use our own argument group. + """ + return + + +class ListFormatter(Formatter): + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def emit_list(self, column_names, data, stdout): + """Format and print the list from the iterable data source. + """ diff --git a/cliff/formatters/table.py b/cliff/formatters/table.py new file mode 100644 index 00000000..1813e3e7 --- /dev/null +++ b/cliff/formatters/table.py @@ -0,0 +1,46 @@ +"""Output formatters using prettytable. +""" + +import prettytable + +from .base import ListFormatter + + +class TableLister(ListFormatter): + + ALIGNMENTS = { + int: 'r', + str: 'l', + unicode: 'l', + float: 'r', + } + + def add_argument_group(self, parser): + group = parser.add_argument_group('Table Formatter') + group.add_argument( + '-c', '--column', + action='append', + default=[], + dest='columns', + help='specify the column(s) to include, can be repeated', + ) + + def emit_list(self, column_names, data, stdout, parsed_args): + x = prettytable.PrettyTable(column_names) + x.set_padding_width(1) + # Figure out the types of the columns in the + # first row and set the alignment of the + # output accordingly. + data_iter = iter(data) + first_row = next(data_iter) + for value, name in zip(first_row, column_names): + alignment = self.ALIGNMENTS.get(type(value), 'l') + x.set_field_align(name, alignment) + # Now iterate over the data and add the rows. + x.add_row(first_row) + for row in data_iter: + x.add_row(row) + formatted = x.get_string(fields=(parsed_args.columns or column_names)) + stdout.write(formatted) + stdout.write('\n') + return diff --git a/cliff/lister.py b/cliff/lister.py new file mode 100644 index 00000000..01f25ef8 --- /dev/null +++ b/cliff/lister.py @@ -0,0 +1,47 @@ +"""Application base class for providing a list of data as output. +""" + +import pkg_resources + +from .command import Command + + +class Lister(Command): + """Command base class for providing a list of data as output. + """ + + def __init__(self, app, app_args): + super(Lister, self).__init__(app, app_args) + self.load_formatter_plugins() + + def load_formatter_plugins(self): + self.formatters = dict( + (ep.name, ep.load()()) + for ep in pkg_resources.iter_entry_points('cliff.formatter.list') + ) + + def get_parser(self, prog_name): + parser = super(Lister, self).get_parser(prog_name) + formatter_group = parser.add_argument_group( + title='Output Formatters', + description='List output formatter options', + ) + formatter_choices = sorted(self.formatters.keys()) + formatter_default = formatter_choices[0] + formatter_group.add_argument( + '-f', '--format', + dest='formatter', + action='store', + choices=formatter_choices, + default=formatter_default, + help='the output format to use, defaults to %s' % formatter_default, + ) + for name, formatter in sorted(self.formatters.items()): + formatter.add_argument_group(parser) + return parser + + def run(self, parsed_args): + column_names, data = self.get_data(parsed_args) + formatter = self.formatters[parsed_args.formatter] + formatter.emit_list(column_names, data, self.app.stdout, parsed_args) + return 0 diff --git a/demoapp/cliffdemo/list.py b/demoapp/cliffdemo/list.py new file mode 100644 index 00000000..e1a04a48 --- /dev/null +++ b/demoapp/cliffdemo/list.py @@ -0,0 +1,16 @@ +import logging +import os +import stat + +from cliff.lister import Lister + + +class Files(Lister): + "Show a list of files in the current directory." + + log = logging.getLogger(__name__) + + def get_data(self, parsed_args): + return (('Name', 'Size'), + ((n, os.stat(n).st_size) for n in os.listdir('.')) + ) diff --git a/demoapp/setup.py b/demoapp/setup.py index fea934c4..1d2b6b2c 100644 --- a/demoapp/setup.py +++ b/demoapp/setup.py @@ -164,6 +164,7 @@ setup( 'simple = cliffdemo.simple:Simple', 'two_part = cliffdemo.simple:Simple', 'error = cliffdemo.simple:Error', + 'files = cliffdemo.list:Files', ], # 'virtualenvwrapper.initialize': [ # 'user_scripts = virtualenvwrapper.user_scripts:initialize', diff --git a/setup.py b/setup.py index deeec443..bb14f6dd 100644 --- a/setup.py +++ b/setup.py @@ -158,13 +158,9 @@ setup( ), entry_points={ - # 'console_scripts': [ - # 'venvw_hook = virtualenvwrapper.hook_loader:main' - # ], - # 'virtualenvwrapper.initialize': [ - # 'user_scripts = virtualenvwrapper.user_scripts:initialize', - # 'project = virtualenvwrapper.project:initialize', - # ], + 'cliff.formatter.list': [ + 'table = cliff.formatters.table:TableLister', + ], }, zip_safe=False,