diff -pruN 2.11.0-1/cliff/app.py 2.13.0-1/cliff/app.py
--- 2.11.0-1/cliff/app.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/app.py	2018-06-29 19:40:28.000000000 +0000
@@ -14,7 +14,6 @@
 """
 
 import codecs
-import inspect
 import locale
 import logging
 import logging.handlers
@@ -55,6 +54,8 @@ class App(object):
     """
 
     NAME = os.path.splitext(os.path.basename(sys.argv[0]))[0]
+    if NAME == '__main__':
+        NAME = os.path.split(os.path.dirname(sys.argv[0]))[-1]
     LOG = logging.getLogger(NAME)
 
     CONSOLE_MESSAGE_FORMAT = '%(message)s'
@@ -151,7 +152,7 @@ class App(object):
         parser.add_argument(
             '--version',
             action='version',
-            version='%(prog)s {0}'.format(version),
+            version='{0} {1}'.format(App.NAME, version),
         )
         verbose_group = parser.add_mutually_exclusive_group()
         verbose_group.add_argument(
@@ -243,6 +244,7 @@ class App(object):
         :param argv: input arguments and options
         :paramtype argv: list of str
         """
+
         try:
             self.options, remainder = self.parser.parse_known_args(argv)
             self.configure_logging()
@@ -384,7 +386,7 @@ class App(object):
             return 2
         cmd_factory, cmd_name, sub_argv = subcommand
         kwargs = {}
-        if 'cmd_name' in inspect.getargspec(cmd_factory.__init__).args:
+        if 'cmd_name' in utils.getargspec(cmd_factory.__init__).args:
             kwargs['cmd_name'] = cmd_name
         cmd = cmd_factory(self, self.options, **kwargs)
         err = None
diff -pruN 2.11.0-1/cliff/commandmanager.py 2.13.0-1/cliff/commandmanager.py
--- 2.11.0-1/cliff/commandmanager.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/commandmanager.py	2018-06-29 19:40:28.000000000 +0000
@@ -13,11 +13,12 @@
 """Discover and lookup command plugins.
 """
 
-import inspect
 import logging
 
 import pkg_resources
 
+from . import utils
+
 
 LOG = logging.getLogger(__name__)
 
@@ -103,7 +104,7 @@ class CommandManager(object):
                 else:
                     # NOTE(dhellmann): Some fake classes don't take
                     # require as an argument. Yay?
-                    arg_spec = inspect.getargspec(cmd_ep.load)
+                    arg_spec = utils.getargspec(cmd_ep.load)
                     if 'require' in arg_spec[0]:
                         cmd_factory = cmd_ep.load(require=False)
                     else:
diff -pruN 2.11.0-1/cliff/command.py 2.13.0-1/cliff/command.py
--- 2.11.0-1/cliff/command.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/command.py	2018-06-29 19:40:28.000000000 +0000
@@ -191,7 +191,7 @@ class Command(object):
         This method is intended to be called from the run() method before
         take_action() is called.
 
-        This method should only be overriden by developers creating new
+        This method should only be overridden by developers creating new
         command base classes and only if it is necessary to have different
         hook processing behavior.
         """
@@ -209,7 +209,7 @@ class Command(object):
         This method is intended to be called from the run() method after
         take_action() is called.
 
-        This method should only be overriden by developers creating new
+        This method should only be overridden by developers creating new
         command base classes and only if it is necessary to have different
         hook processing behavior.
         """
diff -pruN 2.11.0-1/cliff/help.py 2.13.0-1/cliff/help.py
--- 2.11.0-1/cliff/help.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/help.py	2018-06-29 19:40:28.000000000 +0000
@@ -16,6 +16,7 @@ import sys
 import traceback
 
 from . import command
+from . import utils
 
 
 class HelpAction(argparse.Action):
@@ -47,7 +48,7 @@ class HelpAction(argparse.Action):
                 continue
             try:
                 kwargs = {}
-                if 'cmd_name' in inspect.getargspec(factory.__init__).args:
+                if 'cmd_name' in utils.getargspec(factory.__init__).args:
                     kwargs['cmd_name'] = name
                 cmd = factory(app, None, **kwargs)
                 if cmd.deprecated:
@@ -100,7 +101,7 @@ class HelpCommand(command.Command):
                 return
             self.app_args.cmd = search_args
             kwargs = {}
-            if 'cmd_name' in inspect.getargspec(cmd_factory.__init__).args:
+            if 'cmd_name' in utils.getargspec(cmd_factory.__init__).args:
                 kwargs['cmd_name'] = cmd_name
             cmd = cmd_factory(self.app, self.app_args, **kwargs)
             full_name = (cmd_name
diff -pruN 2.11.0-1/cliff/interactive.py 2.13.0-1/cliff/interactive.py
--- 2.11.0-1/cliff/interactive.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/interactive.py	2018-06-29 19:40:28.000000000 +0000
@@ -26,7 +26,7 @@ class InteractiveApp(cmd2.Cmd):
     Refer to the cmd2_ and cmd_ documentation for details
     about subclassing and configuring this class.
 
-    .. _cmd2: http://packages.python.org/cmd2/index.html
+    .. _cmd2: https://cmd2.readthedocs.io/en/latest/
     .. _cmd: http://docs.python.org/library/cmd.html
 
     :param parent_app: The calling application (expected to be derived
@@ -51,13 +51,24 @@ class InteractiveApp(cmd2.Cmd):
         self.command_manager = command_manager
         cmd2.Cmd.__init__(self, 'tab', stdin=stdin, stdout=stdout)
 
+    def _split_line(self, line):
+        try:
+            return shlex.split(line.parsed.raw)
+        except AttributeError:
+            # cmd2 >= 0.9.1 gives us a Statement not a PyParsing parse
+            # result.
+            parts = shlex.split(line)
+            if getattr(line, 'command', None):
+                parts.insert(0, line.command)
+            return parts
+
     def default(self, line):
         # Tie in the default command processor to
         # dispatch commands known to the command manager.
         # We send the message through our parent app,
         # since it already has the logic for executing
         # the subcommand.
-        line_parts = shlex.split(line.parsed.raw)
+        line_parts = self._split_line(line)
         self.parent_app.run_subcommand(line_parts)
 
     def completenames(self, text, line, begidx, endidx):
@@ -111,7 +122,17 @@ class InteractiveApp(cmd2.Cmd):
             # Dispatch to the underlying help command,
             # which knows how to provide help for extension
             # commands.
-            self.default(self.parsed('help ' + arg))
+            try:
+                # NOTE(coreycb): This try path can be removed once
+                # requirements.txt has cmd2 >= 0.7.3.
+                parsed = self.parsed
+            except AttributeError:
+                try:
+                    parsed = self.parser_manager.parsed
+                except AttributeError:
+                    # cmd2 >= 0.9.1 does not have a parser manager
+                    parsed = lambda x: x  # noqa
+            self.default(parsed('help ' + arg))
         else:
             cmd2.Cmd.do_help(self, arg)
             cmd_names = sorted([n for n, v in self.command_manager])
@@ -134,7 +155,7 @@ class InteractiveApp(cmd2.Cmd):
         # Pre-process the parsed command in case it looks like one of
         # our subcommands, since cmd2 does not handle multi-part
         # command names by default.
-        line_parts = shlex.split(statement.parsed.raw)
+        line_parts = self._split_line(statement)
         try:
             the_cmd = self.command_manager.find_command(line_parts)
             cmd_factory, cmd_name, sub_argv = the_cmd
@@ -142,8 +163,15 @@ class InteractiveApp(cmd2.Cmd):
             # Not a plugin command
             pass
         else:
-            statement.parsed.command = cmd_name
-            statement.parsed.args = ' '.join(sub_argv)
+            if hasattr(statement, 'parsed'):
+                # Older cmd2 uses PyParsing
+                statement.parsed.command = cmd_name
+                statement.parsed.args = ' '.join(sub_argv)
+            else:
+                # cmd2 >= 0.9.1 uses shlex and gives us a Statement.
+                statement.command = cmd_name
+                statement.argv = [cmd_name] + sub_argv
+                statement.args = ' '.join(statement.argv)
         return statement
 
     def cmdloop(self):
diff -pruN 2.11.0-1/cliff/sphinxext.py 2.13.0-1/cliff/sphinxext.py
--- 2.11.0-1/cliff/sphinxext.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/sphinxext.py	2018-06-29 19:40:28.000000000 +0000
@@ -268,6 +268,15 @@ class AutoprogramCliffDirective(rst.Dire
                         if fnmatch.fnmatch(x, command_pattern)]
         else:
             commands = manager.commands.keys()
+
+        if not commands:
+            msg = 'No commands found in the "{}" namespace'
+            if command_pattern:
+                msg += ' using the "{}" command name/pattern'
+            msg += ('. Are you sure this is correct and the application being '
+                    'documented is installed?')
+            raise self.warning(msg.format(self.arguments[0], command_pattern))
+
         return dict((name, self._load_command(manager, name))
                     for name in commands)
 
diff -pruN 2.11.0-1/cliff/utils.py 2.13.0-1/cliff/utils.py
--- 2.11.0-1/cliff/utils.py	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/cliff/utils.py	2018-06-29 19:40:28.000000000 +0000
@@ -13,6 +13,7 @@
 
 import codecs
 import ctypes
+import inspect
 import os
 import struct
 import sys
@@ -28,6 +29,12 @@ import six
 COST = {'w': 0, 's': 2, 'a': 1, 'd': 3}
 
 
+if hasattr(inspect, 'getfullargspec'):
+    getargspec = inspect.getfullargspec
+else:
+    getargspec = inspect.getargspec
+
+
 def damerau_levenshtein(s1, s2, cost):
     """Calculates the Damerau-Levenshtein distance between two strings.
 
diff -pruN 2.11.0-1/debian/changelog 2.13.0-1/debian/changelog
--- 2.11.0-1/debian/changelog	2018-03-03 16:52:29.000000000 +0000
+++ 2.13.0-1/debian/changelog	2018-09-11 13:13:50.000000000 +0000
@@ -1,3 +1,19 @@
+python-cliff (2.13.0-1) unstable; urgency=medium
+
+  [ Ondřej Nový ]
+  * d/control: Use team+openstack@tracker.debian.org as maintainer
+
+  [ Thomas Goirand ]
+  * New upstream release.
+  * Fixed (build-)depends for this release.
+  * Apply Ubuntu patch (Closes: #898732):
+    - d/control, d/compat: Set debhelper>=10.
+    - d/control: Enable autopkgtest-pkg-python tests.
+    - d/control: Drop (Build-)Depends on python3-unicodecsv as its only
+    needed for Python 2 (LP: #1736717).
+
+ -- Thomas Goirand <zigo@debian.org>  Tue, 11 Sep 2018 15:13:50 +0200
+
 python-cliff (2.11.0-1) unstable; urgency=medium
 
   [ Ondřej Nový ]
diff -pruN 2.11.0-1/debian/compat 2.13.0-1/debian/compat
--- 2.11.0-1/debian/compat	2018-03-03 16:52:29.000000000 +0000
+++ 2.13.0-1/debian/compat	2018-09-11 13:13:50.000000000 +0000
@@ -1 +1 @@
-9
+10
diff -pruN 2.11.0-1/debian/control 2.13.0-1/debian/control
--- 2.11.0-1/debian/control	2018-03-03 16:52:29.000000000 +0000
+++ 2.13.0-1/debian/control	2018-09-11 13:13:50.000000000 +0000
@@ -1,12 +1,12 @@
 Source: python-cliff
 Section: python
 Priority: optional
-Maintainer: Debian OpenStack <openstack-devel@lists.alioth.debian.org>
+Maintainer: Debian OpenStack <team+openstack@tracker.debian.org>
 Uploaders:
  Jan Dittberner <jandd@debian.org>,
  Thomas Goirand <zigo@debian.org>,
 Build-Depends:
- debhelper (>= 9),
+ debhelper (>= 10),
  dh-python,
  openstack-pkg-tools,
  python-all,
@@ -17,7 +17,7 @@ Build-Depends:
  python3-pbr (>= 2.0.0),
  python3-setuptools,
 Build-Depends-Indep:
- python-cmd2,
+ python-cmd2 (>= 0.8.5),
  python-coverage,
  python-docutils,
  python-mock,
@@ -31,7 +31,7 @@ Build-Depends-Indep:
  python-testtools (>= 2.2.0),
  python-unicodecsv,
  python-yaml,
- python3-cmd2,
+ python3-cmd2 (>= 0.8.5),
  python3-coverage,
  python3-docutils,
  python3-mock,
@@ -42,17 +42,17 @@ Build-Depends-Indep:
  python3-stevedore (>= 1.20.0),
  python3-testscenarios,
  python3-testtools (>= 2.2.0),
- python3-unicodecsv,
  python3-yaml,
 Standards-Version: 4.1.3
 Vcs-Browser: https://salsa.debian.org/openstack-team/python/python-cliff
 Vcs-Git: https://salsa.debian.org/openstack-team/python/python-cliff.git
 Homepage: https://github.com/dreamhost/cliff
+Testsuite: autopkgtest-pkg-python
 
 Package: python-cliff
 Architecture: all
 Depends:
- python-cmd2,
+ python-cmd2 (>= 0.8.5),
  python-docutils,
  python-pbr (>= 2.0.0),
  python-prettytable,
@@ -96,7 +96,7 @@ Description: command line interface form
 Package: python3-cliff
 Architecture: all
 Depends:
- python3-cmd2,
+ python3-cmd2 (>= 0.8.5),
  python3-docutils,
  python3-pbr (>= 2.0.0),
  python3-prettytable,
diff -pruN 2.11.0-1/demoapp/cliffdemo/__main__.py 2.13.0-1/demoapp/cliffdemo/__main__.py
--- 2.11.0-1/demoapp/cliffdemo/__main__.py	1970-01-01 00:00:00.000000000 +0000
+++ 2.13.0-1/demoapp/cliffdemo/__main__.py	2018-06-29 19:40:28.000000000 +0000
@@ -0,0 +1,6 @@
+import sys
+from cliffdemo.main import main
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
diff -pruN 2.11.0-1/doc/requirements.txt 2.13.0-1/doc/requirements.txt
--- 2.11.0-1/doc/requirements.txt	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/doc/requirements.txt	2018-06-29 19:40:28.000000000 +0000
@@ -1,5 +1,5 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-sphinx>=1.6.2 # BSD
-openstackdocstheme>=1.17.0 # Apache-2.0
+sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
+openstackdocstheme>=1.18.1 # Apache-2.0
diff -pruN 2.11.0-1/lower-constraints.txt 2.13.0-1/lower-constraints.txt
--- 2.11.0-1/lower-constraints.txt	1970-01-01 00:00:00.000000000 +0000
+++ 2.13.0-1/lower-constraints.txt	2018-06-29 19:40:28.000000000 +0000
@@ -0,0 +1,37 @@
+alabaster==0.7.10
+Babel==2.3.4
+bandit==1.1.0
+cmd2==0.8.0
+coverage==4.0
+docutils==0.11
+extras==1.0.0
+fixtures==3.0.0
+gitdb==0.6.4
+GitPython==1.0.1
+imagesize==0.7.1
+Jinja2==2.10
+linecache2==1.0.0
+MarkupSafe==1.0
+mock==2.0.0
+pbr==2.0.0
+prettytable==0.7.2
+Pygments==2.2.0
+pyparsing==2.1.0
+pyperclip==1.5.27
+python-mimeparse==1.6.0
+python-subunit==1.0.0
+pytz==2013.6
+PyYAML==3.12
+requests==2.14.2
+six==1.10.0
+smmap==0.9.0
+snowballstemmer==1.2.1
+Sphinx==1.6.2
+sphinxcontrib-websupport==1.0.1
+stevedore==1.20.0
+testrepository==0.0.18
+testscenarios==0.4
+testtools==2.2.0
+traceback2==1.4.0
+unicodecsv==0.8.0;python_version<'3.0'
+unittest2==1.1.0
diff -pruN 2.11.0-1/requirements.txt 2.13.0-1/requirements.txt
--- 2.11.0-1/requirements.txt	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/requirements.txt	2018-06-29 19:40:28.000000000 +0000
@@ -2,10 +2,11 @@
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
 pbr!=2.1.0,>=2.0.0 # Apache-2.0
-cmd2>=0.6.7 # MIT
-PrettyTable<0.8,>=0.7.1 # BSD
+cmd2!=0.8.3,<0.9.0;python_version<'3.0' # MIT
+cmd2!=0.8.3;python_version>='3.0' # MIT
+PrettyTable<0.8,>=0.7.2 # BSD
 pyparsing>=2.1.0 # MIT
 six>=1.10.0 # MIT
 stevedore>=1.20.0 # Apache-2.0
 unicodecsv>=0.8.0;python_version<'3.0' # BSD
-PyYAML>=3.10 # MIT
+PyYAML>=3.12 # MIT
diff -pruN 2.11.0-1/setup.cfg 2.13.0-1/setup.cfg
--- 2.11.0-1/setup.cfg	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/setup.cfg	2018-06-29 19:40:28.000000000 +0000
@@ -54,6 +54,8 @@ cliff.demo =
 cliff.demo.hooked =
     sample-hook = cliffdemo.hook:Hook
 
+[bdist_wheel]
+universal = 1
 
 [build_sphinx]
 all-files = 1
diff -pruN 2.11.0-1/test-requirements.txt 2.13.0-1/test-requirements.txt
--- 2.11.0-1/test-requirements.txt	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/test-requirements.txt	2018-06-29 19:40:28.000000000 +0000
@@ -12,7 +12,7 @@ coverage!=4.4,>=4.0 # Apache-2.0
 
 # sphinx is required in test-requirements in addition to doc/requirements
 # because there is a sphinx extension that has tests
-sphinx>=1.6.2 # BSD
+sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
 
 # Bandit security code scanner
 bandit>=1.1.0 # Apache-2.0
diff -pruN 2.11.0-1/tox.ini 2.13.0-1/tox.ini
--- 2.11.0-1/tox.ini	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/tox.ini	2018-06-29 19:40:28.000000000 +0000
@@ -21,6 +21,7 @@ deps =
   -r{toxinidir}/requirements.txt
 
 [testenv:pep8]
+basepython = python3
 deps =
   -r{toxinidir}/test-requirements.txt
   flake8
@@ -30,6 +31,7 @@ commands =
   bandit -c bandit.yaml -r cliff -x tests -n5
 
 [testenv:venv]
+basepython = python3
 # TODO(modred) remove doc/requirements.txt once the openstack-build-sphinx-docs
 # job is updated.
 deps =
@@ -48,5 +50,13 @@ deps = os:openstack/python-openstackclie
 commands = {toxinidir}/integration-tests/openstackclient-tip.sh {envdir}
 
 [testenv:docs]
+basepython = python3
 deps = -r{toxinidir}/doc/requirements.txt
 commands = sphinx-build -b html doc/source doc/build/html
+
+[testenv:lower-constraints]
+basepython = python3
+deps =
+  -c{toxinidir}/lower-constraints.txt
+  -r{toxinidir}/test-requirements.txt
+  -r{toxinidir}/requirements.txt
diff -pruN 2.11.0-1/.travis.yml 2.13.0-1/.travis.yml
--- 2.11.0-1/.travis.yml	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/.travis.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-language: python
-python:
-  - 2.7
-  - 3.2
-  - 3.3
-  - pypy
-install: pip install -r test-requirements.txt
-script: nosetests -d
\ No newline at end of file
diff -pruN 2.11.0-1/.zuul.yaml 2.13.0-1/.zuul.yaml
--- 2.11.0-1/.zuul.yaml	2018-01-18 14:53:52.000000000 +0000
+++ 2.13.0-1/.zuul.yaml	2018-06-29 19:40:28.000000000 +0000
@@ -20,14 +20,15 @@
       zuul_work_dir: src/git.openstack.org/openstack/python-neutronclient
 
 - project:
-    name: openstack/cliff
     check:
       jobs:
         - cliff-tox-py27-neutronclient-tip
         - osc-tox-unit-tips:
             branches: ^master$
+        - openstack-tox-lower-constraints
     gate:
       jobs:
         - cliff-tox-py27-neutronclient-tip
         - osc-tox-unit-tips:
             branches: ^master$
+        - openstack-tox-lower-constraints
