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 - tbechtold@suse.com
+
+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
Jeremy Stanley
Joe Server
+John Dennis
Jonathan LaCour
Juan Antonio Osorio Robles
Julien Danjou
@@ -39,6 +40,7 @@
Ricardo Kirkner
Rui Chen
Ryan Petrello
+Ryan Selden
Sascha Peilicke
Sean Perry
Steve Baker
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-ap...
* 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-ap...
* 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
+
+
+@six.add_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
+
+
+@mock.patch('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())
+
+
+@mock.patch('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']))
+
+
+@mock.patch('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)
+@mock.patch('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)
+
+
+@mock.patch('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-ap...
* 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='doug.hellmann@gmail.com',
- 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