Hello community, here is the log from the commit of package python-cliff for openSUSE:Factory checked in at 2016-10-04 16:00:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cliff (Old) and /work/SRC/openSUSE:Factory/.python-cliff.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cliff" Changes: -------- --- /work/SRC/openSUSE:Factory/python-cliff/python-cliff.changes 2016-07-14 09:46:16.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-cliff.new/python-cliff.changes 2016-10-04 16:00:34.000000000 +0200 @@ -1,0 +2,15 @@ +Tue Oct 4 10:25:23 UTC 2016 - [email protected] + +update to version 2.2.0 + * Fixed broken link + * pep8: fix F405 error + * add formattable columns concept + * command: make run() return take_action() value + * Fix cliff URLs in doc and demoapp + * Avoid ASCII encoding errors when output is redirected + * Fix Command class doc typo + * Remove announce.rst + * Updated from global requirements + * Add tests, cover more cases + +------------------------------------------------------------------- Old: ---- cliff-2.1.0.tar.gz New: ---- cliff-2.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cliff.spec ++++++ --- /var/tmp/diff_new_pack.6GtgcB/_old 2016-10-04 16:00:35.000000000 +0200 +++ /var/tmp/diff_new_pack.6GtgcB/_new 2016-10-04 16:00:35.000000000 +0200 @@ -17,7 +17,7 @@ Name: python-cliff -Version: 2.1.0 +Version: 2.2.0 Release: 0 Url: https://github.com/dreamhost/cliff Summary: Command Line Interface Formulation Framework ++++++ cliff-2.1.0.tar.gz -> cliff-2.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/AUTHORS new/cliff-2.2.0/AUTHORS --- old/cliff-2.1.0/AUTHORS 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/AUTHORS 2016-08-15 21:21:08.000000000 +0200 @@ -22,6 +22,7 @@ Jamie Lennox <[email protected]> Jeremy Stanley <[email protected]> Joe Server <[email protected]> +John Dennis <[email protected]> Jonathan LaCour <[email protected]> Juan Antonio Osorio Robles <[email protected]> Julien Danjou <[email protected]> @@ -39,6 +40,7 @@ Ricardo Kirkner <[email protected]> Rui Chen <[email protected]> Ryan Petrello <[email protected]> +Ryan Selden <[email protected]> Sascha Peilicke <[email protected]> Sean Perry <[email protected]> Steve Baker <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/ChangeLog new/cliff-2.2.0/ChangeLog --- old/cliff-2.1.0/ChangeLog 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/ChangeLog 2016-08-15 21:21:08.000000000 +0200 @@ -1,6 +1,21 @@ CHANGES ======= +2.2.0 +----- + +* Avoid ASCII encoding errors when output is redirected +* Fix cliff URLs in doc and demoapp +* Remove announce.rst +* Fix Command class doc typo +* Updated from global requirements +* Fixed broken link +* add formattable columns concept +* Add tests, cover more cases +* Updated from global requirements +* pep8: fix F405 error +* command: make run() return take_action() value + 2.1.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/PKG-INFO new/cliff-2.2.0/PKG-INFO --- old/cliff-2.1.0/PKG-INFO 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/PKG-INFO 2016-08-15 21:21:09.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cliff -Version: 2.1.0 +Version: 2.2.0 Summary: Command Line Interface Formulation Framework Home-page: https://launchpad.net/python-cliff Author: OpenStack @@ -14,7 +14,7 @@ `setuptools entry points`_ to provide subcommands, output formatters, and other extensions. - .. _setuptools entry points: http://pythonhosted.org/setuptools/pkg_resources.html#convenience-api + .. _setuptools entry points: http://setuptools.readthedocs.io/en/latest/pkg_resources.html#convenience-api * Free software: Apache license * Documentation: http://docs.openstack.org/developer/cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/README.rst new/cliff-2.2.0/README.rst --- old/cliff-2.1.0/README.rst 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/README.rst 2016-08-15 21:19:43.000000000 +0200 @@ -6,7 +6,7 @@ `setuptools entry points`_ to provide subcommands, output formatters, and other extensions. -.. _setuptools entry points: http://pythonhosted.org/setuptools/pkg_resources.html#convenience-api +.. _setuptools entry points: http://setuptools.readthedocs.io/en/latest/pkg_resources.html#convenience-api * Free software: Apache license * Documentation: http://docs.openstack.org/developer/cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/announce.rst new/cliff-2.2.0/announce.rst --- old/cliff-2.1.0/announce.rst 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/announce.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,40 +0,0 @@ -======================================================================== - cliff -- Command Line Interface Formulation Framework -- version 1.5.0 -======================================================================== - -.. tags:: python cliff release DreamHost - -cliff is a framework for building command line programs. It uses -setuptools entry points to provide subcommands, output formatters, and -other extensions. - -What's New In This Release? -=========================== - -- Fix the arguments passed to commands when they are instantiated to - pull out help. See https://github.com/dreamhost/cliff/issues/52 for - details. -- Add bash command completion. (Contributed by Terry Howe) -- Use stevedore to load formatter plugins. -- Use pbr for packaging. - -Documentation -============= - -`Documentation for cliff`_ is hosted on `readthedocs.org`_ - -.. _Documentation for cliff: http://readthedocs.org/docs/cliff/en/latest/ - -.. _readthedocs.org: http://readthedocs.org - -Installation -============ - -Use pip:: - - $ pip install cliff - -See `the installation guide`_ for more details. - -.. _the installation guide: http://cliff.readthedocs.org/en/latest/install.html - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/app.py new/cliff-2.2.0/cliff/app.py --- old/cliff-2.1.0/cliff/app.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/app.py 2016-08-15 21:19:43.000000000 +0200 @@ -1,11 +1,13 @@ """Application base class. """ +import codecs import inspect import locale import logging import logging.handlers import os +import six import sys from cliff import argparse @@ -70,6 +72,45 @@ locale.setlocale(locale.LC_ALL, '') except locale.Error: pass + + # Unicode must be encoded/decoded for text I/O streams, the + # correct encoding for the stream must be selected and it must + # be capable of handling the set of characters in the stream + # or Python will raise a codec error. The correct codec is + # selected based on the locale. Python2 uses the locales + # encoding but only when the I/O stream is attached to a + # terminal (TTY) otherwise it uses the default ASCII + # encoding. The effect is internationalized text written to + # the terminal works as expected but if command line output is + # redirected (file or pipe) the ASCII codec is used and the + # program aborts with a codec error. + # + # The default I/O streams stdin, stdout and stderr can be + # wrapped in a codec based on the locale thus assuring the + # users desired encoding is always used no matter the I/O + # destination. Python3 does this by default. + # + # If the caller supplies an I/O stream we use it unmodified on + # the assumption the caller has taken all responsibility for + # the stream. But with Python2 if the caller allows us to + # default the I/O streams to sys.stdin, sys.stdout and + # sys.stderr we apply the locales encoding just as Python3 + # would do. We also check to make sure the main Python program + # has not already already wrapped sys.stdin, sys.stdout and + # sys.stderr as this is a common recommendation. + + if six.PY2: + encoding = locale.getpreferredencoding() + if encoding: + if not (stdin or isinstance(sys.stdin, codecs.StreamReader)): + stdin = codecs.getreader(encoding)(sys.stdin) + + if not (stdout or isinstance(sys.stdout, codecs.StreamWriter)): + stdout = codecs.getwriter(encoding)(sys.stdout) + + if not (stderr or isinstance(sys.stderr, codecs.StreamWriter)): + stderr = codecs.getwriter(encoding)(sys.stderr) + self.stdin = stdin or sys.stdin self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/argparse.py new/cliff-2.2.0/cliff/argparse.py --- old/cliff-2.1.0/cliff/argparse.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/argparse.py 2016-08-15 21:19:43.000000000 +0200 @@ -6,7 +6,7 @@ if sys.version_info < (3, 5): - class ArgumentParser(ArgumentParser): + class ArgumentParser(ArgumentParser): # noqa def __init__(self, *args, **kwargs): self.allow_abbrev = kwargs.pop("allow_abbrev", True) super(ArgumentParser, self).__init__(*args, **kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/columns.py new/cliff-2.2.0/cliff/columns.py --- old/cliff-2.1.0/cliff/columns.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cliff-2.2.0/cliff/columns.py 2016-08-15 21:19:43.000000000 +0200 @@ -0,0 +1,28 @@ +"""Formattable column tools. +""" + +import abc + +import six + + [email protected]_metaclass(abc.ABCMeta) +class FormattableColumn(object): + + def __init__(self, value): + self._value = value + + @abc.abstractmethod + def human_readable(self): + """Return a basic human readable version of the data. + """ + + def machine_readable(self): + """Return a raw data structure using only Python built-in types. + + It must be possible to serialize the return value directly + using a formatter like JSON, and it will be up to the + formatter plugin to decide how to make that transformation. + + """ + return self._value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/command.py new/cliff-2.2.0/cliff/command.py --- old/cliff-2.1.0/cliff/command.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/command.py 2016-08-15 21:19:43.000000000 +0200 @@ -40,6 +40,8 @@ @abc.abstractmethod def take_action(self, parsed_args): """Override to do something useful. + + The returned value will be returned by the program. """ def run(self, parsed_args): @@ -51,6 +53,7 @@ Developers creating new command base classes (such as :class:`Lister` and :class:`ShowOne`) should override this method to wrap :meth:`take_action`. + + Return the value returned by :meth:`take_action` or 0. """ - self.take_action(parsed_args) - return 0 + return self.take_action(parsed_args) or 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/base.py new/cliff-2.2.0/cliff/formatters/base.py --- old/cliff-2.1.0/cliff/formatters/base.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/base.py 2016-08-15 21:19:43.000000000 +0200 @@ -26,11 +26,18 @@ def emit_list(self, column_names, data, stdout, parsed_args): """Format and print the list from the iterable data source. + Data values can be primitive types like ints and strings, or + can be an instance of a :class:`FormattableColumn` for + situations where the value is complex, and may need to be + handled differently for human readable output vs. machine + readable output. + :param column_names: names of the columns :param data: iterable data source, one tuple per object with values in order of column names :param stdout: output stream where data should be written :param parsed_args: argparse namespace from our local options + """ @@ -43,6 +50,12 @@ def emit_one(self, column_names, data, stdout, parsed_args): """Format and print the values associated with the single object. + Data values can be primitive types like ints and strings, or + can be an instance of a :class:`FormattableColumn` for + situations where the value is complex, and may need to be + handled differently for human readable output vs. machine + readable output. + :param column_names: names of the columns :param data: iterable data source with values in order of column names :param stdout: output stream where data should be written diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/commaseparated.py new/cliff-2.2.0/cliff/formatters/commaseparated.py --- old/cliff-2.1.0/cliff/formatters/commaseparated.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/commaseparated.py 2016-08-15 21:19:43.000000000 +0200 @@ -5,6 +5,9 @@ import sys from .base import ListFormatter +from cliff import columns + +import six if sys.version_info[0] == 3: import csv @@ -35,8 +38,14 @@ writer = csv.writer(stdout, quoting=self.QUOTE_MODES[parsed_args.quote_mode], lineterminator=os.linesep, + escapechar='\\', ) writer.writerow(column_names) for row in data: - writer.writerow(row) + writer.writerow( + [(six.text_type(c.machine_readable()) + if isinstance(c, columns.FormattableColumn) + else c) + for c in row] + ) return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/json_format.py new/cliff-2.2.0/cliff/formatters/json_format.py --- old/cliff-2.1.0/cliff/formatters/json_format.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/json_format.py 2016-08-15 21:19:43.000000000 +0200 @@ -4,6 +4,7 @@ import json from .base import ListFormatter, SingleFormatter +from cliff import columns class JSONFormatter(ListFormatter, SingleFormatter): @@ -20,11 +21,21 @@ def emit_list(self, column_names, data, stdout, parsed_args): items = [] for item in data: - items.append(dict(zip(column_names, item))) + items.append( + {n: (i.machine_readable() + if isinstance(i, columns.FormattableColumn) + else i) + for n, i in zip(column_names, item)} + ) indent = None if parsed_args.noindent else 2 json.dump(items, stdout, indent=indent) def emit_one(self, column_names, data, stdout, parsed_args): - one = dict(zip(column_names, data)) + one = { + n: (i.machine_readable() + if isinstance(i, columns.FormattableColumn) + else i) + for n, i in zip(column_names, data) + } indent = None if parsed_args.noindent else 2 json.dump(one, stdout, indent=indent) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/shell.py new/cliff-2.2.0/cliff/formatters/shell.py --- old/cliff-2.1.0/cliff/formatters/shell.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/shell.py 2016-08-15 21:19:43.000000000 +0200 @@ -2,6 +2,7 @@ """ from .base import SingleFormatter +from cliff import columns import argparse import six @@ -37,6 +38,9 @@ desired_columns = parsed_args.variables for name, value in zip(variable_names, data): if name in desired_columns or not desired_columns: + value = (six.text_type(value.machine_readable()) + if isinstance(value, columns.FormattableColumn) + else value) if isinstance(value, six.string_types): value = value.replace('"', '\\"') stdout.write('%s%s="%s"\n' % (parsed_args.prefix, name, value)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/table.py new/cliff-2.2.0/cliff/formatters/table.py --- old/cliff-2.1.0/cliff/formatters/table.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/table.py 2016-08-15 21:19:43.000000000 +0200 @@ -7,6 +7,18 @@ from cliff import utils from .base import ListFormatter, SingleFormatter +from cliff import columns + + +def _format_row(row): + new_row = [] + for r in row: + if isinstance(r, columns.FormattableColumn): + r = r.human_readable() + if isinstance(r, six.string_types): + r = r.replace('\r\n', '\n').replace('\r', ' ') + new_row.append(r) + return new_row class TableFormatter(ListFormatter, SingleFormatter): @@ -52,12 +64,9 @@ alignment = self.ALIGNMENTS.get(type(value), 'l') x.align[name] = alignment # Now iterate over the data and add the rows. - x.add_row(first_row) + x.add_row(_format_row(first_row)) for row in data_iter: - row = [r.replace('\r\n', '\n').replace('\r', ' ') - if isinstance(r, six.string_types) else r - for r in row] - x.add_row(row) + x.add_row(_format_row(row)) # Choose a reasonable min_width to better handle many columns on a # narrow console. The table will overflow the console width in @@ -80,9 +89,7 @@ x.align['Field'] = 'l' x.align['Value'] = 'l' for name, value in zip(column_names, data): - value = (value.replace('\r\n', '\n').replace('\r', ' ') if - isinstance(value, six.string_types) else value) - x.add_row((name, value)) + x.add_row(_format_row((name, value))) # Choose a reasonable min_width to better handle a narrow # console. The table will overflow the console width in preference diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/value.py new/cliff-2.2.0/cliff/formatters/value.py --- old/cliff-2.1.0/cliff/formatters/value.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/value.py 2016-08-15 21:19:43.000000000 +0200 @@ -5,6 +5,7 @@ from .base import ListFormatter from .base import SingleFormatter +from cliff import columns class ValueFormatter(ListFormatter, SingleFormatter): @@ -14,10 +15,19 @@ def emit_list(self, column_names, data, stdout, parsed_args): for row in data: - stdout.write(' '.join(map(six.text_type, row)) + u'\n') + stdout.write( + ' '.join( + six.text_type(c.machine_readable() + if isinstance(c, columns.FormattableColumn) + else c) + for c in row) + u'\n') return def emit_one(self, column_names, data, stdout, parsed_args): for value in data: - stdout.write('%s\n' % str(value)) + stdout.write('%s\n' % six.text_type( + value.machine_readable() + if isinstance(value, columns.FormattableColumn) + else value) + ) return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/formatters/yaml_format.py new/cliff-2.2.0/cliff/formatters/yaml_format.py --- old/cliff-2.1.0/cliff/formatters/yaml_format.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/formatters/yaml_format.py 2016-08-15 21:19:43.000000000 +0200 @@ -4,6 +4,7 @@ import yaml from .base import ListFormatter, SingleFormatter +from cliff import columns class YAMLFormatter(ListFormatter, SingleFormatter): @@ -14,10 +15,19 @@ def emit_list(self, column_names, data, stdout, parsed_args): items = [] for item in data: - items.append(dict(zip(column_names, item))) + items.append( + {n: (i.machine_readable() + if isinstance(i, columns.FormattableColumn) + else i) + for n, i in zip(column_names, item)} + ) yaml.safe_dump(items, stream=stdout, default_flow_style=False) def emit_one(self, column_names, data, stdout, parsed_args): for key, value in zip(column_names, data): - dict_data = {key: value} + dict_data = { + key: (value.machine_readable() + if isinstance(value, columns.FormattableColumn) + else value) + } yaml.safe_dump(dict_data, stream=stdout, default_flow_style=False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_app.py new/cliff-2.2.0/cliff/tests/test_app.py --- old/cliff-2.1.0/cliff/tests/test_app.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_app.py 2016-08-15 21:19:43.000000000 +0200 @@ -5,7 +5,11 @@ except ImportError: from io import StringIO +import codecs +import locale import mock +import six +import sys from cliff.app import App from cliff.command import Command @@ -398,3 +402,82 @@ pass else: raise Exception('Exception was not thrown') + + +def test_io_streams(): + cmd_mgr = CommandManager('cliff.tests') + io = mock.Mock() + + if six.PY2: + stdin_save = sys.stdin + stdout_save = sys.stdout + stderr_save = sys.stderr + encoding = locale.getpreferredencoding() or 'utf-8' + + app = App('no io streams', 1, cmd_mgr) + assert isinstance(app.stdin, codecs.StreamReader) + assert isinstance(app.stdout, codecs.StreamWriter) + assert isinstance(app.stderr, codecs.StreamWriter) + + app = App('with stdin io stream', 1, cmd_mgr, stdin=io) + assert app.stdin is io + assert isinstance(app.stdout, codecs.StreamWriter) + assert isinstance(app.stderr, codecs.StreamWriter) + + app = App('with stdout io stream', 1, cmd_mgr, stdout=io) + assert isinstance(app.stdin, codecs.StreamReader) + assert app.stdout is io + assert isinstance(app.stderr, codecs.StreamWriter) + + app = App('with stderr io stream', 1, cmd_mgr, stderr=io) + assert isinstance(app.stdin, codecs.StreamReader) + assert isinstance(app.stdout, codecs.StreamWriter) + assert app.stderr is io + + try: + sys.stdin = codecs.getreader(encoding)(sys.stdin) + app = App('with wrapped sys.stdin io stream', 1, cmd_mgr) + assert app.stdin is sys.stdin + assert isinstance(app.stdout, codecs.StreamWriter) + assert isinstance(app.stderr, codecs.StreamWriter) + finally: + sys.stdin = stdin_save + + try: + sys.stdout = codecs.getwriter(encoding)(sys.stdout) + app = App('with wrapped stdout io stream', 1, cmd_mgr) + assert isinstance(app.stdin, codecs.StreamReader) + assert app.stdout is sys.stdout + assert isinstance(app.stderr, codecs.StreamWriter) + finally: + sys.stdout = stdout_save + + try: + sys.stderr = codecs.getwriter(encoding)(sys.stderr) + app = App('with wrapped stderr io stream', 1, cmd_mgr) + assert isinstance(app.stdin, codecs.StreamReader) + assert isinstance(app.stdout, codecs.StreamWriter) + assert app.stderr is sys.stderr + finally: + sys.stderr = stderr_save + + else: + app = App('no io streams', 1, cmd_mgr) + assert app.stdin is sys.stdin + assert app.stdout is sys.stdout + assert app.stderr is sys.stderr + + app = App('with stdin io stream', 1, cmd_mgr, stdin=io) + assert app.stdin is io + assert app.stdout is sys.stdout + assert app.stderr is sys.stderr + + app = App('with stdout io stream', 1, cmd_mgr, stdout=io) + assert app.stdin is sys.stdin + assert app.stdout is io + assert app.stderr is sys.stderr + + app = App('with stderr io stream', 1, cmd_mgr, stderr=io) + assert app.stdin is sys.stdin + assert app.stdout is sys.stdout + assert app.stderr is io diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_columns.py new/cliff-2.2.0/cliff/tests/test_columns.py --- old/cliff-2.1.0/cliff/tests/test_columns.py 1970-01-01 01:00:00.000000000 +0100 +++ new/cliff-2.2.0/cliff/tests/test_columns.py 2016-08-15 21:19:43.000000000 +0200 @@ -0,0 +1,18 @@ +from cliff import columns + + +class FauxColumn(columns.FormattableColumn): + + def human_readable(self): + return u'I made this string myself: {}'.format(self._value) + + +def test_faux_column_machine(): + c = FauxColumn(['list', 'of', 'values']) + assert c.machine_readable() == ['list', 'of', 'values'] + + +def test_faux_column_human(): + c = FauxColumn(['list', 'of', 'values']) + assert c.human_readable() == \ + u"I made this string myself: ['list', 'of', 'values']" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_command.py new/cliff-2.2.0/cliff/tests/test_command.py --- old/cliff-2.1.0/cliff/tests/test_command.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_command.py 2016-08-15 21:19:43.000000000 +0200 @@ -7,7 +7,7 @@ """ def take_action(self, parsed_args): - return + return 42 def test_get_description(): @@ -25,3 +25,8 @@ def test_get_name(): cmd = TestCommand(None, None, cmd_name='object action') assert cmd.cmd_name == 'object action' + + +def test_run_return(): + cmd = TestCommand(None, None, cmd_name='object action') + assert cmd.run(None) == 42 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_csv.py new/cliff-2.2.0/cliff/tests/test_formatters_csv.py --- old/cliff-2.1.0/cliff/tests/test_formatters_csv.py 2016-06-16 15:19:53.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_csv.py 2016-08-15 21:19:43.000000000 +0200 @@ -6,6 +6,7 @@ import six from cliff.formatters import commaseparated +from cliff.tests import test_columns def test_commaseparated_list_formatter(): @@ -38,6 +39,20 @@ sf.emit_list(c, data, output, parsed_args) actual = output.getvalue() assert expected == actual + + +def test_commaseparated_list_formatter_formattable_column(): + sf = commaseparated.CSVLister() + c = ('a', 'b', 'c') + d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) + data = [d1] + expected = 'a,b,c\nA,B,[\'the\'\\, \'value\']\n' + output = six.StringIO() + parsed_args = mock.Mock() + parsed_args.quote_mode = 'none' + sf.emit_list(c, data, output, parsed_args) + actual = output.getvalue() + assert expected == actual def test_commaseparated_list_formatter_unicode(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_json.py new/cliff-2.2.0/cliff/tests/test_formatters_json.py --- old/cliff-2.1.0/cliff/tests/test_formatters_json.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_json.py 2016-08-15 21:19:43.000000000 +0200 @@ -3,6 +3,7 @@ import json from cliff.formatters import json_format +from cliff.tests import test_columns import mock @@ -38,6 +39,29 @@ assert expected == actual +def test_json_format_formattablecolumn_one(): + sf = json_format.JSONFormatter() + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) + expected = { + 'a': 'A', + 'b': 'B', + 'c': 'C', + 'd': ['the', 'value'], + } + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_one(c, d, output, args) + value = output.getvalue() + print(len(value.splitlines())) + assert 1 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual + + def test_json_format_list(): sf = json_format.JSONFormatter() c = ('a', 'b', 'c') @@ -69,3 +93,24 @@ assert 17 == len(value.splitlines()) actual = json.loads(value) assert expected == actual + + +def test_json_format_formattablecolumn_list(): + sf = json_format.JSONFormatter() + c = ('a', 'b', 'c') + d = ( + ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])), + ) + expected = [ + {'a': 'A1', 'b': 'B1', 'c': ['the', 'value']}, + ] + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_list(c, d, output, args) + value = output.getvalue() + assert 1 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_shell.py new/cliff-2.2.0/cliff/tests/test_formatters_shell.py --- old/cliff-2.1.0/cliff/tests/test_formatters_shell.py 2016-06-16 15:19:53.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_shell.py 2016-08-15 21:19:43.000000000 +0200 @@ -5,6 +5,7 @@ from six import StringIO, text_type from cliff.formatters import shell +from cliff.tests import test_columns import mock @@ -37,6 +38,24 @@ actual = output.getvalue() assert expected == actual + +def test_shell_formatter_formattable_column(): + sf = shell.ShellFormatter() + c = ('a', 'b', 'c') + d = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) + expected = '\n'.join([ + 'a="A"', + 'b="B"', + 'c="[\'the\', \'value\']"\n', + ]) + output = StringIO() + args = mock.Mock() + args.variables = ['a', 'b', 'c'] + args.prefix = '' + sf.emit_one(c, d, output, args) + actual = output.getvalue() + assert expected == actual + def test_shell_formatter_with_non_string_values(): sf = shell.ShellFormatter() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_table.py new/cliff-2.2.0/cliff/tests/test_formatters_table.py --- old/cliff-2.1.0/cliff/tests/test_formatters_table.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_table.py 2016-08-15 21:19:43.000000000 +0200 @@ -6,6 +6,7 @@ import argparse from cliff.formatters import table +from cliff.tests import test_columns class args(object): @@ -65,7 +66,7 @@ ''' assert expected == _table_tester_helper(c, d) - +# Multi-line output when width is restricted to 42 columns expected_ml_val = '''\ +-------+--------------------------------+ | Field | Value | @@ -79,6 +80,39 @@ +-------+--------------------------------+ ''' +# Multi-line output when width is restricted to 80 columns +expected_ml_80_val = '''\ ++-------+----------------------------------------------------------------------+ +| Field | Value | ++-------+----------------------------------------------------------------------+ +| a | A | +| b | B | +| c | C | +| d | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd | +| | ddddddddd | ++-------+----------------------------------------------------------------------+ +''' # noqa + +# Single-line output, for when no line length restriction apply +expected_sl_val = '''\ ++-------+-------------------------------------------------------------------------------+ +| Field | Value | ++-------+-------------------------------------------------------------------------------+ +| a | A | +| b | B | +| c | C | +| d | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd | ++-------+-------------------------------------------------------------------------------+ +''' # noqa + + [email protected]('cliff.utils.terminal_width') +def test_table_formatter_no_cli_param(tw): + tw.return_value = 80 + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', 'd' * 77) + assert expected_ml_80_val == _table_tester_helper(c, d, extra_args=args()) + @mock.patch('cliff.utils.terminal_width') def test_table_formatter_cli_param(tw): @@ -90,6 +124,24 @@ @mock.patch('cliff.utils.terminal_width') +def test_table_formatter_no_cli_param_unlimited_tw(tw): + tw.return_value = 0 + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', 'd' * 77) + # output should not be wrapped to multiple lines + assert expected_sl_val == _table_tester_helper(c, d, extra_args=args()) + + [email protected]('cliff.utils.terminal_width') +def test_table_formatter_cli_param_unlimited_tw(tw): + tw.return_value = 0 + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', 'd' * 77) + assert (expected_ml_val == + _table_tester_helper(c, d, extra_args=['--max-width', '42'])) + + [email protected]('cliff.utils.terminal_width') @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '666'}) def test_table_formatter_cli_param_envvar_big(tw): tw.return_value = 80 @@ -185,6 +237,24 @@ assert expected == _table_tester_helper(c, data) [email protected]('cliff.utils.terminal_width') +def test_table_formatter_formattable_column(tw): + tw.return_value = 0 + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) + expected = '''\ ++-------+---------------------------------------------+ +| Field | Value | ++-------+---------------------------------------------+ +| a | A | +| b | B | +| c | C | +| d | I made this string myself: ['the', 'value'] | ++-------+---------------------------------------------+ +''' + assert expected == _table_tester_helper(c, d) + + _col_names = ('one', 'two', 'three') _col_data = [( 'one one one one one', @@ -250,6 +320,22 @@ @mock.patch('cliff.utils.terminal_width') +def test_table_list_formatter_formattable_column(tw): + tw.return_value = 80 + c = ('a', 'b', 'c') + d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) + data = [d1] + expected = '''\ ++---+---+---------------------------------------------+ +| a | b | c | ++---+---+---------------------------------------------+ +| A | B | I made this string myself: ['the', 'value'] | ++---+---+---------------------------------------------+ +''' + assert expected == _table_tester_helper(c, data) + + [email protected]('cliff.utils.terminal_width') def test_table_list_formatter_max_width(tw): # no resize l = tw.return_value = 80 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_value.py new/cliff-2.2.0/cliff/tests/test_formatters_value.py --- old/cliff-2.1.0/cliff/tests/test_formatters_value.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_value.py 2016-08-15 21:19:43.000000000 +0200 @@ -2,6 +2,7 @@ from six import StringIO from cliff.formatters import value +from cliff.tests import test_columns def test_value_formatter(): @@ -15,6 +16,17 @@ assert expected == actual +def test_value_formatter_formattable_column(): + sf = value.ValueFormatter() + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) + expected = "A\nB\nC\n['the', 'value']\n" + output = StringIO() + sf.emit_one(c, d, output, None) + actual = output.getvalue() + assert expected == actual + + def test_value_list_formatter(): sf = value.ValueFormatter() c = ('a', 'b', 'c') @@ -25,4 +37,16 @@ output = StringIO() sf.emit_list(c, data, output, None) actual = output.getvalue() + assert expected == actual + + +def test_value_list_formatter_formattable_column(): + sf = value.ValueFormatter() + c = ('a', 'b', 'c') + d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) + data = [d1] + expected = "A B ['the', 'value']\n" + output = StringIO() + sf.emit_list(c, data, output, None) + actual = output.getvalue() assert expected == actual diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff/tests/test_formatters_yaml.py new/cliff-2.2.0/cliff/tests/test_formatters_yaml.py --- old/cliff-2.1.0/cliff/tests/test_formatters_yaml.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/cliff/tests/test_formatters_yaml.py 2016-08-15 21:19:43.000000000 +0200 @@ -3,6 +3,7 @@ import yaml from cliff.formatters import yaml_format +from cliff.tests import test_columns import mock @@ -24,6 +25,28 @@ assert expected == actual +def test_yaml_format_formattablecolumn_one(): + sf = yaml_format.YAMLFormatter() + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) + expected = { + 'a': 'A', + 'b': 'B', + 'c': 'C', + 'd': ['the', 'value'], + } + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_one(c, d, output, args) + value = output.getvalue() + print(len(value.splitlines())) + actual = yaml.safe_load(output.getvalue()) + assert expected == actual + + def test_yaml_format_list(): sf = yaml_format.YAMLFormatter() c = ('a', 'b', 'c') @@ -43,3 +66,22 @@ sf.emit_list(c, d, output, args) actual = yaml.safe_load(output.getvalue()) assert expected == actual + + +def test_yaml_format_formattablecolumn_list(): + sf = yaml_format.YAMLFormatter() + c = ('a', 'b', 'c') + d = ( + ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])), + ) + expected = [ + {'a': 'A1', 'b': 'B1', 'c': ['the', 'value']}, + ] + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_list(c, d, output, args) + actual = yaml.safe_load(output.getvalue()) + assert expected == actual diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff.egg-info/PKG-INFO new/cliff-2.2.0/cliff.egg-info/PKG-INFO --- old/cliff-2.1.0/cliff.egg-info/PKG-INFO 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/cliff.egg-info/PKG-INFO 2016-08-15 21:21:08.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cliff -Version: 2.1.0 +Version: 2.2.0 Summary: Command Line Interface Formulation Framework Home-page: https://launchpad.net/python-cliff Author: OpenStack @@ -14,7 +14,7 @@ `setuptools entry points`_ to provide subcommands, output formatters, and other extensions. - .. _setuptools entry points: http://pythonhosted.org/setuptools/pkg_resources.html#convenience-api + .. _setuptools entry points: http://setuptools.readthedocs.io/en/latest/pkg_resources.html#convenience-api * Free software: Apache license * Documentation: http://docs.openstack.org/developer/cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff.egg-info/SOURCES.txt new/cliff-2.2.0/cliff.egg-info/SOURCES.txt --- old/cliff-2.1.0/cliff.egg-info/SOURCES.txt 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/cliff.egg-info/SOURCES.txt 2016-08-15 21:21:09.000000000 +0200 @@ -6,7 +6,6 @@ MANIFEST.in Makefile README.rst -announce.rst openstack-common.conf requirements.txt setup.cfg @@ -16,6 +15,7 @@ cliff/__init__.py cliff/app.py cliff/argparse.py +cliff/columns.py cliff/command.py cliff/commandmanager.py cliff/complete.py @@ -43,6 +43,7 @@ cliff/formatters/yaml_format.py cliff/tests/__init__.py cliff/tests/test_app.py +cliff/tests/test_columns.py cliff/tests/test_command.py cliff/tests/test_commandmanager.py cliff/tests/test_complete.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff.egg-info/pbr.json new/cliff-2.2.0/cliff.egg-info/pbr.json --- old/cliff-2.1.0/cliff.egg-info/pbr.json 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/cliff.egg-info/pbr.json 2016-08-15 21:21:08.000000000 +0200 @@ -1 +1 @@ -{"is_release": true, "git_version": "21f133f"} \ No newline at end of file +{"is_release": true, "git_version": "50d6708"} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/cliff.egg-info/requires.txt new/cliff-2.2.0/cliff.egg-info/requires.txt --- old/cliff-2.1.0/cliff.egg-info/requires.txt 2016-06-16 15:21:48.000000000 +0200 +++ new/cliff-2.2.0/cliff.egg-info/requires.txt 2016-08-15 21:21:08.000000000 +0200 @@ -3,6 +3,6 @@ PrettyTable<0.8,>=0.7 pyparsing>=2.0.1 six>=1.9.0 -stevedore>=1.10.0 +stevedore>=1.16.0 unicodecsv>=0.8.0 PyYAML>=3.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/demoapp/setup.py new/cliff-2.2.0/demoapp/setup.py --- old/cliff-2.1.0/demoapp/setup.py 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/demoapp/setup.py 2016-08-15 21:19:43.000000000 +0200 @@ -22,8 +22,8 @@ author='Doug Hellmann', author_email='[email protected]', - url='https://github.com/dreamhost/cliff', - download_url='https://github.com/dreamhost/cliff/tarball/master', + url='https://github.com/openstack/cliff', + download_url='https://github.com/openstack/cliff/tarball/master', classifiers=['Development Status :: 3 - Alpha', 'License :: OSI Approved :: Apache Software License', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/doc/source/install.rst new/cliff-2.2.0/doc/source/install.rst --- old/cliff-2.1.0/doc/source/install.rst 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/doc/source/install.rst 2016-08-15 21:19:43.000000000 +0200 @@ -42,10 +42,10 @@ Source Code =========== -The source is hosted on github: https://github.com/dreamhost/cliff +The source is hosted on github: http://git.openstack.org/cgit/openstack/cliff Reporting Bugs ============== Please report bugs through the github project: -https://github.com/dreamhost/cliff/issues +https://bugs.launchpad.net/python-cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/requirements.txt new/cliff-2.2.0/requirements.txt --- old/cliff-2.1.0/requirements.txt 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/requirements.txt 2016-08-15 21:19:43.000000000 +0200 @@ -6,6 +6,6 @@ PrettyTable<0.8,>=0.7 # BSD pyparsing>=2.0.1 # MIT six>=1.9.0 # MIT -stevedore>=1.10.0 # Apache-2.0 +stevedore>=1.16.0 # Apache-2.0 unicodecsv>=0.8.0;python_version<'3.0' # BSD PyYAML>=3.1.0 # MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.1.0/test-requirements.txt new/cliff-2.2.0/test-requirements.txt --- old/cliff-2.1.0/test-requirements.txt 2016-06-16 15:19:52.000000000 +0200 +++ new/cliff-2.2.0/test-requirements.txt 2016-08-15 21:19:43.000000000 +0200 @@ -5,5 +5,5 @@ mock>=2.0 # BSD coverage>=3.6 # Apache-2.0 # this is required for the docs build jobs -sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD +sphinx!=1.3b1,<1.3,>=1.2.1 # BSD oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 ++++++ relax-sphinx-requirement.patch ++++++ --- /var/tmp/diff_new_pack.6GtgcB/_old 2016-10-04 16:00:36.000000000 +0200 +++ /var/tmp/diff_new_pack.6GtgcB/_new 2016-10-04 16:00:36.000000000 +0200 @@ -6,6 +6,6 @@ mock>=2.0 # BSD coverage>=3.6 # Apache-2.0 # this is required for the docs build jobs --sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD +-sphinx!=1.3b1,<1.3,>=1.2.1 # BSD +sphinx oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
