Hello community, here is the log from the commit of package python-cliff for openSUSE:Factory checked in at 2017-11-24 10:53:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cliff (Old) and /work/SRC/openSUSE:Factory/.python-cliff.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cliff" Fri Nov 24 10:53:51 2017 rev:30 rq:544429 version:2.9.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cliff/python-cliff.changes 2017-08-12 20:26:53.510640612 +0200 +++ /work/SRC/openSUSE:Factory/.python-cliff.new/python-cliff.changes 2017-11-24 10:53:53.361558761 +0100 @@ -1,0 +2,23 @@ +Wed Nov 22 09:40:38 UTC 2017 - [email protected] + +- update to version 2.9.1 + - doc: minor cleanup + - trivial: Fix comments in sphinxext module + - add actual column names to error msg + - handle more varied top_level.txt files in distributions + - Allow command hooks to make changes + - Move comments up in [extras] section of setup.cfg + - Update doc on Sphinx integration process + - show the distribution providing the command in help output + - Update and replace http with https for doc links + - Make openstackdocstheme an optional doc dependency + - Docs update for more-hooks + - sphinxext: Correct issues with usage formatting + - Fix regexp for detecting long options + - Updates for stestr + - Updated from global requirements +- Drop 0001-Make-openstackdocstheme-an-optional-doc-dependency.patch . + Applied upstream +- Add _service and switch to openstack/rpm-packging spec template + +------------------------------------------------------------------- Old: ---- 0001-Make-openstackdocstheme-an-optional-doc-dependency.patch cliff-2.8.0.tar.gz New: ---- _service cliff-2.9.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cliff.spec ++++++ --- /var/tmp/diff_new_pack.bAuFXE/_old 2017-11-24 10:53:55.069496375 +0100 +++ /var/tmp/diff_new_pack.bAuFXE/_new 2017-11-24 10:53:55.069496375 +0100 @@ -17,52 +17,62 @@ Name: python-cliff -Version: 2.8.0 +Version: 2.9.1 Release: 0 -Url: https://github.com/dreamhost/cliff Summary: Command Line Interface Formulation Framework License: Apache-2.0 Group: Development/Languages/Python -Source: https://files.pythonhosted.org/packages/source/c/cliff/cliff-%{version}.tar.gz -# PATCH-FEATURE-UPSTREAM 0001-Make-openstackdocstheme-an-optional-doc-dependency.patch -- https://review.openstack.org/491378 -Patch1: 0001-Make-openstackdocstheme-an-optional-doc-dependency.patch -BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: python-argparse +Url: https://launchpad.net/python-cliff +Source0: https://files.pythonhosted.org/packages/source/c/cliff/cliff-2.9.1.tar.gz +BuildRequires: openstack-macros BuildRequires: python-devel -BuildRequires: python-setuptools -# Test requirements: -BuildRequires: python-PrettyTable -BuildRequires: python-Sphinx -BuildRequires: python-cmd2 -BuildRequires: python-coverage >= 3.6 -BuildRequires: python-httplib2 >= 0.7.5 -BuildRequires: python-mock >= 2.0 -BuildRequires: python-nose -BuildRequires: python-oslosphinx -BuildRequires: python-pbr -BuildRequires: python-pyparsing >= 2.1.0 -BuildRequires: python-six -BuildRequires: python-stevedore -Requires: python-PrettyTable >= 0.7 -Requires: python-PyYAML >= 3.10.0 -Requires: python-cmd2 >= 0.6.7 -Requires: python-pyparsing >= 2.1.0 -Requires: python-six >= 1.9.0 -Requires: python-stevedore >= 1.20.0 -Requires: python-unicodecsv >= 0.8.0 +BuildRequires: python2-PrettyTable +BuildRequires: python2-PyYAML +BuildRequires: python2-cmd2 +BuildRequires: python2-mock +BuildRequires: python2-pbr +BuildRequires: python2-python-subunit +BuildRequires: python2-setuptools +BuildRequires: python2-stevedore +BuildRequires: python2-testrepository +BuildRequires: python2-testscenarios +BuildRequires: python2-testtools +BuildRequires: python2-unicodecsv +BuildRequires: python3-PrettyTable +BuildRequires: python3-PyYAML +BuildRequires: python3-cmd2 +BuildRequires: python3-devel +BuildRequires: python3-mock +BuildRequires: python3-pbr +BuildRequires: python3-python-subunit +BuildRequires: python3-setuptools +BuildRequires: python3-stevedore +BuildRequires: python3-testrepository +BuildRequires: python3-testscenarios +BuildRequires: python3-testtools +BuildRequires: python3-unicodecsv +Requires: python-PrettyTable +Requires: python-PyYAML +Requires: python-cmd2 +Requires: python-pyparsing +Requires: python-six +Requires: python-stevedore +Requires: python-unicodecsv BuildArch: noarch +%python_subpackages %description cliff is a framework for building command line programs. It uses setuptools entry points to provide subcommands, output formatters, and other extensions. -%package doc -Summary: Command Line Interface Formulation Framework - Documentation +%package -n python-cliff-doc +Summary: %{summary} - Documentation Group: Documentation/HTML -Requires: %{name} = %{version} +BuildRequires: python2-Sphinx +Provides: %{python_module cliff-doc = %{version}} -%description doc +%description -n python-cliff-doc cliff is a framework for building command line programs. It uses setuptools entry points to provide subcommands, output formatters, and other extensions. @@ -70,28 +80,31 @@ This package contains documentation files for %{name}. %prep -%setup -q -n cliff-%{version} -%patch1 -p1 +%autosetup -p1 -n cliff-2.9.1 +sed -i 's/^warning-is-error.*/warning-is-error = 0/g' setup.cfg +%py_req_cleanup %build -python setup.py build -python setup.py build_sphinx +%python_build +%{__python2} setup.py build_sphinx +rm -rf doc/build/html/.{doctrees,buildinfo} %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install %check -echo > test-requirements.txt -echo > requirements.txt -python setup.py test - -%files -%defattr(-,root,root,-) -%doc LICENSE README.rst -%{python_sitelib}/* - -%files doc -%defattr(-,root,root,-) -%doc doc/build/html demoapp +%{python_expand rm -rf .testrepository +$python setup.py test +} + +%files %{python_files} +%license LICENSE +%doc ChangeLog README.rst +%{python_sitelib}/cliff +%{python_sitelib}/*.egg-info + +%files -n python-cliff-doc +%license LICENSE +%doc doc/build/html %changelog ++++++ _service ++++++ <services> <service mode="disabled" name="renderspec"> <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/master/openstack/cliff/cliff.spec.j2</param> <param name="output-name">python-cliff.spec</param> <param name="requirements">https://raw.githubusercontent.com/openstack/rpm-packaging/master/global-requirements.txt</param> <param name="changelog-email">[email protected]</param> <param name="changelog-provider">gh,openstack,cliff</param> </service> <service mode="disabled" name="download_files"> </service> <service name="format_spec_file" mode="disabled"/> </services> ++++++ cliff-2.8.0.tar.gz -> cliff-2.9.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/.stestr.conf new/cliff-2.9.1/.stestr.conf --- old/cliff-2.8.0/.stestr.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/cliff-2.9.1/.stestr.conf 2017-10-08 23:48:10.000000000 +0200 @@ -0,0 +1,3 @@ +[DEFAULT] +test_path=./cliff +top_dir=./ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/AUTHORS new/cliff-2.9.1/AUTHORS --- old/cliff-2.8.0/AUTHORS 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/AUTHORS 2017-10-08 23:50:16.000000000 +0200 @@ -11,6 +11,7 @@ Christian Berendt <[email protected]> Christophe CHAUVET <[email protected]> Clint Byrum <[email protected]> +Dan Kirkwood <[email protected]> Dean Troyer <[email protected]> Derek Higgins <[email protected]> Dirk Mueller <[email protected]> @@ -63,12 +64,15 @@ Tony Breeds <[email protected]> Tony Xu <[email protected]> Vincent Legoll <[email protected]> +Vitalii Kulanov <[email protected]> Yalei Wang <[email protected]> +Yushiro FURUKAWA <[email protected]> caoyue <[email protected]> dineshbhor <[email protected]> gcmalloc <[email protected]> gengchc2 <[email protected]> heavenshell <[email protected]> +howardlee <[email protected]> kafka <[email protected]> liyingjun <[email protected]> markmcclain <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/CONTRIBUTING.rst new/cliff-2.9.1/CONTRIBUTING.rst --- old/cliff-2.8.0/CONTRIBUTING.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/CONTRIBUTING.rst 2017-10-08 23:48:10.000000000 +0200 @@ -1,7 +1,7 @@ Changes to cliff should be submitted for review via the Gerrit tool, following the workflow documented at: - http://docs.openstack.org/infra/manual/developers.html#development-workflow + https://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/ChangeLog new/cliff-2.9.1/ChangeLog --- old/cliff-2.8.0/ChangeLog 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/ChangeLog 2017-10-08 23:50:16.000000000 +0200 @@ -1,6 +1,33 @@ CHANGES ======= +2.9.1 +----- + +* handle more varied top\_level.txt files in distributions + +2.9.0 +----- + +* show the distribution providing the command in help output +* Docs update for more-hooks +* Updates for stestr +* Allow command hooks to make changes +* Updated from global requirements +* add actual column names to error msg Closes-Bug: 1712876 +* Updated from global requirements +* Update doc on Sphinx integration process +* Fix regexp for detecting long options +* sphinxext: Correct issues with usage formatting +* Move comments up in [extras] section of setup.cfg +* Updated from global requirements +* Make openstackdocstheme an optional doc dependency +* Updated from global requirements +* doc: minor cleanup +* Update and replace http with https for doc links +* trivial: Fix comments in sphinxext module +* Updated from global requirements + 2.8.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/PKG-INFO new/cliff-2.9.1/PKG-INFO --- old/cliff-2.8.0/PKG-INFO 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/PKG-INFO 2017-10-08 23:50:16.000000000 +0200 @@ -1,17 +1,18 @@ Metadata-Version: 1.1 Name: cliff -Version: 2.8.0 +Version: 2.9.1 Summary: Command Line Interface Formulation Framework -Home-page: http://docs.openstack.org/developer/cliff +Home-page: https://docs.openstack.org/cliff/latest/ Author: OpenStack Author-email: [email protected] License: UNKNOWN +Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== - .. image:: http://governance.openstack.org/badges/cliff.svg - :target: http://governance.openstack.org/reference/tags/index.html + .. image:: https://governance.openstack.org/tc/badges/cliff.svg + :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on @@ -26,8 +27,8 @@ .. _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 - * Source: http://git.openstack.org/cgit/openstack/cliff + * Documentation: https://docs.openstack.org/cliff/latest/ + * Source: https://git.openstack.org/cgit/openstack/cliff * Bugs: https://bugs.launchpad.net/python-cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/README.rst new/cliff-2.9.1/README.rst --- old/cliff-2.8.0/README.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/README.rst 2017-10-08 23:48:10.000000000 +0200 @@ -2,8 +2,8 @@ Team and repository tags ======================== -.. image:: http://governance.openstack.org/badges/cliff.svg - :target: http://governance.openstack.org/reference/tags/index.html +.. image:: https://governance.openstack.org/tc/badges/cliff.svg + :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on @@ -18,6 +18,6 @@ .. _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 -* Source: http://git.openstack.org/cgit/openstack/cliff +* Documentation: https://docs.openstack.org/cliff/latest/ +* Source: https://git.openstack.org/cgit/openstack/cliff * Bugs: https://bugs.launchpad.net/python-cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/command.py new/cliff-2.9.1/cliff/command.py --- old/cliff-2.8.0/cliff/command.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/command.py 2017-10-08 23:48:10.000000000 +0200 @@ -13,11 +13,52 @@ import abc import inspect +import pkg_resources import six from stevedore import extension from cliff import _argparse +_dists_by_mods = None + + +def _get_distributions_by_modules(): + """Return dict mapping module name to distribution names. + + The python package name (the name used for importing) and the + distribution name (the name used with pip and PyPI) do not + always match. We want to report which distribution caused the + command to be installed, so we need to look up the values. + + """ + global _dists_by_mods + if _dists_by_mods is None: + results = {} + for dist in pkg_resources.working_set: + try: + mod_names = dist.get_metadata('top_level.txt').strip() + except Exception: + # Could not retrieve metadata. Either the file is not + # present or we cannot read it. Ignore the + # distribution. + pass + else: + # Distributions may include multiple top-level + # packages (see setuptools for an example). + for mod_name in mod_names.splitlines(): + results[mod_name] = dist.project_name + _dists_by_mods = results + return _dists_by_mods + + +def _get_distribution_for_module(module): + "Return the distribution containing the module." + dist_name = None + if module: + pkg_name = module.__name__.partition('.')[0] + dist_name = _get_distributions_by_modules().get(pkg_name) + return dist_name + @six.add_metaclass(abc.ABCMeta) class Command(object): @@ -89,17 +130,23 @@ def get_epilog(self): """Return the command epilog.""" + # replace a None in self._epilog with an empty string + parts = [self._epilog or ''] hook_epilogs = filter( None, (h.obj.get_epilog() for h in self._hooks), ) - if hook_epilogs: - # combine them, replacing a None in self._epilog with an - # empty string - parts = [self._epilog or ''] - parts.extend(hook_epilogs) - return '\n\n'.join(parts) - return self._epilog + parts.extend(hook_epilogs) + app_dist_name = _get_distribution_for_module( + inspect.getmodule(self.app) + ) + dist_name = _get_distribution_for_module(inspect.getmodule(self)) + if dist_name and dist_name != app_dist_name: + parts.append( + 'This command is provided by the %s plugin.' % + (dist_name,) + ) + return '\n\n'.join(parts) def get_parser(self, prog_name): """Return an :class:`argparse.ArgumentParser`. @@ -133,9 +180,9 @@ Return the value returned by :meth:`take_action` or 0. """ - self._run_before_hooks(parsed_args) + parsed_args = self._run_before_hooks(parsed_args) return_code = self.take_action(parsed_args) or 0 - self._run_after_hooks(parsed_args, return_code) + return_code = self._run_after_hooks(parsed_args, return_code) return return_code def _run_before_hooks(self, parsed_args): @@ -149,7 +196,12 @@ hook processing behavior. """ for hook in self._hooks: - hook.obj.before(parsed_args) + ret = hook.obj.before(parsed_args) + # If the return is None do not change parsed_args, otherwise + # set up to pass it to the next hook + if ret is not None: + parsed_args = ret + return parsed_args def _run_after_hooks(self, parsed_args, return_code): """Calls after() method of the hooks. @@ -162,7 +214,12 @@ hook processing behavior. """ for hook in self._hooks: - hook.obj.after(parsed_args, return_code) + ret = hook.obj.after(parsed_args, return_code) + # If the return is None do not change return_code, otherwise + # set up to pass it to the next hook + if ret is not None: + return_code = ret + return return_code class _SmartHelpFormatter(_argparse.HelpFormatter): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/display.py new/cliff-2.9.1/cliff/display.py --- old/cliff-2.8.0/cliff/display.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/display.py 2017-10-08 23:48:10.000000000 +0200 @@ -100,18 +100,21 @@ columns_to_include = [c for c in column_names if c in parsed_args.columns] if not columns_to_include: - raise ValueError('No recognized column names in %s' % - str(parsed_args.columns)) + raise ValueError('No recognized column names in %s. ' + 'Recognized columns are %s.' % + (str(parsed_args.columns), str(column_names))) + # Set up argument to compress() selector = [(c in columns_to_include) for c in column_names] return columns_to_include, selector def run(self, parsed_args): - self._run_before_hooks(parsed_args) + parsed_args = self._run_before_hooks(parsed_args) self.formatter = self._formatter_plugins[parsed_args.formatter].obj column_names, data = self.take_action(parsed_args) - self._run_after_hooks(parsed_args, (column_names, data)) + column_names, data = self._run_after_hooks(parsed_args, + (column_names, data)) self.produce_output(parsed_args, column_names, data) return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/help.py new/cliff-2.9.1/cliff/help.py --- old/cliff-2.8.0/cliff/help.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/help.py 2017-10-08 23:48:10.000000000 +0200 @@ -29,6 +29,13 @@ app = self.default parser.print_help(app.stdout) app.stdout.write('\nCommands:\n') + dists_by_module = command._get_distributions_by_modules() + + def dist_for_obj(obj): + name = inspect.getmodule(obj).__name__.partition('.')[0] + return dists_by_module.get(name) + + app_dist = dist_for_obj(app) command_manager = app.command_manager for name, ep in sorted(command_manager): try: @@ -51,7 +58,12 @@ traceback.print_exc(file=app.stdout) continue one_liner = cmd.get_description().split('\n')[0] - app.stdout.write(' %-13s %s\n' % (name, one_liner)) + dist_name = dist_for_obj(factory) + if dist_name and dist_name != app_dist: + dist_info = ' (' + dist_name + ')' + else: + dist_info = '' + app.stdout.write(' %-13s %s%s\n' % (name, one_liner, dist_info)) sys.exit(0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/hooks.py new/cliff-2.9.1/cliff/hooks.py --- old/cliff-2.8.0/cliff/hooks.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/hooks.py 2017-10-08 23:48:10.000000000 +0200 @@ -46,20 +46,20 @@ def before(self, parsed_args): """Called before the command's take_action() method. - Any return value is ignored. - :param parsed_args: The arguments to the command. :paramtype parsed_args: argparse.Namespace + :returns: argparse.Namespace """ + return parsed_args @abc.abstractmethod def after(self, parsed_args, return_code): """Called after the command's take_action() method. - Any return value is ignored. - :param parsed_args: The arguments to the command. :paramtype parsed_args: argparse.Namespace :param return_code: The value returned from take_action(). :paramtype return_code: int + :returns: int """ + return return_code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/sphinxext.py new/cliff-2.9.1/cliff/sphinxext.py --- old/cliff-2.8.0/cliff/sphinxext.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/sphinxext.py 2017-10-08 23:48:10.000000000 +0200 @@ -56,17 +56,22 @@ # hacked variant of the regex used by the actual argparse module. Unlike # that version, this one attempts to group long and short opts with their - # optional arguments ensuring that, for example, '---format <FORMAT>' + # optional arguments ensuring that, for example, '--format <FORMAT>' # becomes ['--format <FORMAT>'] and not ['--format', '<FORMAT>']. # Yes, they really do use regexes to break apart and rewrap their help # string. Don't ask me why. - part_regexp = r'\(.*?\)+|\[.*?\]+|(?:(?:-\w|--\w+)(?:\s+<\w+>)?)|\S+' + part_regexp = re.compile(r""" + \(.*?\)+ | + \[.*?\]+ | + (?:(?:-\w|--\w+(?:-\w+)*)(?:\s+<?\w[\w-]*>?)?) | + \S+ + """, re.VERBOSE) opt_usage = fmt._format_actions_usage(optionals, groups) pos_usage = fmt._format_actions_usage(positionals, groups) - opt_parts = re.findall(part_regexp, opt_usage) - pos_parts = re.findall(part_regexp, pos_usage) + opt_parts = part_regexp.findall(opt_usage) + pos_parts = part_regexp.findall(pos_usage) parts = opt_parts + pos_parts if len(' '.join([parser.prog] + parts)) < 72: @@ -221,12 +226,10 @@ ignored_opts): """Generate the relevant Sphinx nodes. - This is a little funky. Parts of this use raw docutils nodes while - other parts use reStructuredText and nested parsing. The reason for - this is simple: it avoids us having to reinvent the wheel. While raw - docutils nodes are helpful for the simpler elements of the output, - they don't provide an easy way to use Sphinx's own directives, such as - the 'option' directive. Refer to [1] for more information. + This doesn't bother using raw docutils nodes as they simply don't offer + the power of directives, like Sphinx's 'option' directive. Instead, we + generate reStructuredText and parse this in a nested context (to obtain + correct header levels). Refer to [1] for more information. [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html @@ -241,7 +244,7 @@ parser = command.get_parser(command_name) ignored_opts = ignored_opts or [] - # Drop the automatically-added help action + # Drop any ignored actions for action in list(parser._actions): for option_string in action.option_strings: if option_string in ignored_opts: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/tests/test_command_hooks.py new/cliff-2.9.1/cliff/tests/test_command_hooks.py --- old/cliff-2.8.0/cliff/tests/test_command_hooks.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/tests/test_command_hooks.py 2017-10-08 23:48:10.000000000 +0200 @@ -97,6 +97,75 @@ self._after_called = True +class TestChangeHook(hooks.CommandHook): + + _before_called = False + _after_called = False + + def get_parser(self, parser): + parser.add_argument('--added-by-hook') + return parser + + def get_epilog(self): + return 'hook epilog' + + def before(self, parsed_args): + self._before_called = True + parsed_args.added_by_hook = 'othervalue' + parsed_args.added_by_before = True + return parsed_args + + def after(self, parsed_args, return_code): + self._after_called = True + return 24 + + +class TestDisplayChangeHook(hooks.CommandHook): + + _before_called = False + _after_called = False + + def get_parser(self, parser): + parser.add_argument('--added-by-hook') + return parser + + def get_epilog(self): + return 'hook epilog' + + def before(self, parsed_args): + self._before_called = True + parsed_args.added_by_hook = 'othervalue' + parsed_args.added_by_before = True + return parsed_args + + def after(self, parsed_args, return_code): + self._after_called = True + return (('Name',), ('othervalue',)) + + +class TestListerChangeHook(hooks.CommandHook): + + _before_called = False + _after_called = False + + def get_parser(self, parser): + parser.add_argument('--added-by-hook') + return parser + + def get_epilog(self): + return 'hook epilog' + + def before(self, parsed_args): + self._before_called = True + parsed_args.added_by_hook = 'othervalue' + parsed_args.added_by_before = True + return parsed_args + + def after(self, parsed_args, return_code): + self._after_called = True + return (('Name',), [('othervalue',)]) + + class TestCommandLoadHooks(base.TestBase): def test_no_app_or_name(self): @@ -147,8 +216,54 @@ def test_after(self): self.assertFalse(self.hook._after_called) - self.cmd.run(None) + result = self.cmd.run(None) + self.assertTrue(self.hook._after_called) + self.assertEqual(result, 42) + + +class TestChangeHooks(base.TestBase): + + def setUp(self): + super(TestChangeHooks, self).setUp() + self.app = make_app() + self.cmd = TestCommand(self.app, None, cmd_name='test') + self.hook = TestChangeHook(self.cmd) + self.mgr = extension.ExtensionManager.make_test_instance( + [extension.Extension( + 'parser-hook', + None, + None, + self.hook)], + ) + # Replace the auto-loaded hooks with our explicitly created + # manager. + self.cmd._hooks = self.mgr + + def test_get_parser(self): + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.assertEqual(results.added_by_hook, 'value') + + def test_get_epilog(self): + results = self.cmd.get_epilog() + self.assertIn('hook epilog', results) + + def test_before(self): + self.assertFalse(self.hook._before_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.cmd.run(results) + self.assertTrue(self.hook._before_called) + self.assertEqual(results.added_by_hook, 'othervalue') + self.assertTrue(results.added_by_before) + + def test_after(self): + self.assertFalse(self.hook._after_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + result = self.cmd.run(results) self.assertTrue(self.hook._after_called) + self.assertEqual(result, 24) class TestShowOneHooks(base.TestBase): @@ -193,6 +308,51 @@ self.assertTrue(self.hook._after_called) +class TestShowOneChangeHooks(base.TestBase): + + def setUp(self): + super(TestShowOneChangeHooks, self).setUp() + self.app = make_app() + self.cmd = TestShowCommand(self.app, None, cmd_name='test') + self.hook = TestDisplayChangeHook(self.cmd) + self.mgr = extension.ExtensionManager.make_test_instance( + [extension.Extension( + 'parser-hook', + None, + None, + self.hook)], + ) + # Replace the auto-loaded hooks with our explicitly created + # manager. + self.cmd._hooks = self.mgr + + def test_get_parser(self): + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.assertEqual(results.added_by_hook, 'value') + + def test_get_epilog(self): + results = self.cmd.get_epilog() + self.assertIn('hook epilog', results) + + def test_before(self): + self.assertFalse(self.hook._before_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.cmd.run(results) + self.assertTrue(self.hook._before_called) + self.assertEqual(results.added_by_hook, 'othervalue') + self.assertTrue(results.added_by_before) + + def test_after(self): + self.assertFalse(self.hook._after_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + result = self.cmd.run(results) + self.assertTrue(self.hook._after_called) + self.assertEqual(result, 0) + + class TestListerHooks(base.TestBase): def setUp(self): @@ -233,3 +393,48 @@ results = parser.parse_args(['--added-by-hook', 'value']) self.cmd.run(results) self.assertTrue(self.hook._after_called) + + +class TestListerChangeHooks(base.TestBase): + + def setUp(self): + super(TestListerChangeHooks, self).setUp() + self.app = make_app() + self.cmd = TestListerCommand(self.app, None, cmd_name='test') + self.hook = TestListerChangeHook(self.cmd) + self.mgr = extension.ExtensionManager.make_test_instance( + [extension.Extension( + 'parser-hook', + None, + None, + self.hook)], + ) + # Replace the auto-loaded hooks with our explicitly created + # manager. + self.cmd._hooks = self.mgr + + def test_get_parser(self): + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.assertEqual(results.added_by_hook, 'value') + + def test_get_epilog(self): + results = self.cmd.get_epilog() + self.assertIn('hook epilog', results) + + def test_before(self): + self.assertFalse(self.hook._before_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + self.cmd.run(results) + self.assertTrue(self.hook._before_called) + self.assertEqual(results.added_by_hook, 'othervalue') + self.assertTrue(results.added_by_before) + + def test_after(self): + self.assertFalse(self.hook._after_called) + parser = self.cmd.get_parser('test') + results = parser.parse_args(['--added-by-hook', 'value']) + result = self.cmd.run(results) + self.assertTrue(self.hook._after_called) + self.assertEqual(result, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff/tests/test_sphinxext.py new/cliff-2.9.1/cliff/tests/test_sphinxext.py --- old/cliff-2.8.0/cliff/tests/test_sphinxext.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/cliff/tests/test_sphinxext.py 2017-10-08 23:48:10.000000000 +0200 @@ -157,6 +157,8 @@ parser.add_argument('--write-to-var-log-something-or-other', action='store_true', help='a long opt to force wrapping') + parser.add_argument('--required-arg', dest='stuff', required=True, + help='a required argument') style_group = parser.add_mutually_exclusive_group(required=True) style_group.add_argument('--polite', action='store_true', help='use a polite greeting') @@ -172,6 +174,7 @@ [--language LANG] [--translate] [--write-to-var-log-something-or-other] + --required-arg STUFF (--polite | --profane) name @@ -187,6 +190,10 @@ a long opt to force wrapping + .. option:: --required-arg <STUFF> + + a required argument + .. option:: --polite use a polite greeting @@ -199,3 +206,57 @@ user name """).lstrip(), output) + + def test_various_option_names_with_hyphen(self): + """Handle options whose name and/or metavar contain hyphen(s)""" + parser = argparse.ArgumentParser(prog='hello-world', add_help=False) + parser.add_argument('--foo-bar', metavar='<foo-bar>', + help='foo bar', required=True) + parser.add_argument('--foo-bar-baz', metavar='<foo-bar-baz>', + help='foo bar baz', required=True) + parser.add_argument('--foo', metavar='<foo>', + help='foo', required=True) + parser.add_argument('--alpha', metavar='<A>', + help='alpha') + parser.add_argument('--alpha-beta', metavar='<A-B>', + help='alpha beta') + parser.add_argument('--alpha-beta-gamma', metavar='<A-B-C>', + help='alpha beta gamma') + + output = '\n'.join(sphinxext._format_parser(parser)) + self.assertEqual(textwrap.dedent(""" + .. program:: hello-world + .. code-block:: shell + + hello-world + --foo-bar <foo-bar> + --foo-bar-baz <foo-bar-baz> + --foo <foo> + [--alpha <A>] + [--alpha-beta <A-B>] + [--alpha-beta-gamma <A-B-C>] + + .. option:: --foo-bar <foo-bar> + + foo bar + + .. option:: --foo-bar-baz <foo-bar-baz> + + foo bar baz + + .. option:: --foo <foo> + + foo + + .. option:: --alpha <A> + + alpha + + .. option:: --alpha-beta <A-B> + + alpha beta + + .. option:: --alpha-beta-gamma <A-B-C> + + alpha beta gamma + """).lstrip(), output) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff.egg-info/PKG-INFO new/cliff-2.9.1/cliff.egg-info/PKG-INFO --- old/cliff-2.8.0/cliff.egg-info/PKG-INFO 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/cliff.egg-info/PKG-INFO 2017-10-08 23:50:16.000000000 +0200 @@ -1,17 +1,18 @@ Metadata-Version: 1.1 Name: cliff -Version: 2.8.0 +Version: 2.9.1 Summary: Command Line Interface Formulation Framework -Home-page: http://docs.openstack.org/developer/cliff +Home-page: https://docs.openstack.org/cliff/latest/ Author: OpenStack Author-email: [email protected] License: UNKNOWN +Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== - .. image:: http://governance.openstack.org/badges/cliff.svg - :target: http://governance.openstack.org/reference/tags/index.html + .. image:: https://governance.openstack.org/tc/badges/cliff.svg + :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on @@ -26,8 +27,8 @@ .. _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 - * Source: http://git.openstack.org/cgit/openstack/cliff + * Documentation: https://docs.openstack.org/cliff/latest/ + * Source: https://git.openstack.org/cgit/openstack/cliff * Bugs: https://bugs.launchpad.net/python-cliff diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff.egg-info/SOURCES.txt new/cliff-2.9.1/cliff.egg-info/SOURCES.txt --- old/cliff-2.8.0/cliff.egg-info/SOURCES.txt 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/cliff.egg-info/SOURCES.txt 2017-10-08 23:50:16.000000000 +0200 @@ -1,3 +1,4 @@ +.stestr.conf .testr.conf .travis.yml AUTHORS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff.egg-info/pbr.json new/cliff-2.9.1/cliff.egg-info/pbr.json --- old/cliff-2.8.0/cliff.egg-info/pbr.json 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/cliff.egg-info/pbr.json 2017-10-08 23:50:16.000000000 +0200 @@ -1 +1 @@ -{"git_version": "d025ad9", "is_release": true} \ No newline at end of file +{"git_version": "a9719bc", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/cliff.egg-info/requires.txt new/cliff-2.9.1/cliff.egg-info/requires.txt --- old/cliff-2.8.0/cliff.egg-info/requires.txt 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/cliff.egg-info/requires.txt 2017-10-08 23:50:16.000000000 +0200 @@ -5,4 +5,7 @@ six>=1.9.0 stevedore>=1.20.0 unicodecsv>=0.8.0 -PyYAML>=3.10.0 +PyYAML>=3.10 + +[docs] +openstackdocstheme>=1.17.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/doc/source/conf.py new/cliff-2.9.1/doc/source/conf.py --- old/cliff-2.8.0/doc/source/conf.py 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/doc/source/conf.py 2017-10-08 23:48:10.000000000 +0200 @@ -15,7 +15,15 @@ import datetime import subprocess -import openstackdocstheme +# make openstackdocstheme an optional dependency. cliff is a low level lib +# that is used outside of OpenStack. Not having something OpenStack specific +# as build requirement is a good thing. +try: + import openstackdocstheme +except ImportError: + has_openstackdocstheme = False +else: + has_openstackdocstheme = True # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -32,8 +40,9 @@ # ones. extensions = [ 'sphinx.ext.autodoc', - 'openstackdocstheme', ] +if has_openstackdocstheme: + extensions.append('openstackdocstheme') # openstackdocstheme options repository_name = 'openstack/cliff' @@ -109,7 +118,8 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'default' -html_theme = 'openstackdocs' +if has_openstackdocstheme: + html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -118,7 +128,8 @@ # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] -html_theme_path = [openstackdocstheme.get_html_theme_path()] +if has_openstackdocstheme: + html_theme_path = [openstackdocstheme.get_html_theme_path()] # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/doc/source/contributors/index.rst new/cliff-2.9.1/doc/source/contributors/index.rst --- old/cliff-2.8.0/doc/source/contributors/index.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/doc/source/contributors/index.rst 2017-10-08 23:48:10.000000000 +0200 @@ -10,7 +10,7 @@ Changes to cliff should be submitted for review via the Gerrit tool, following the workflow documented at -http://docs.openstack.org/infra/manual/developers.html#development-workflow +https://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/doc/source/install/index.rst new/cliff-2.9.1/doc/source/install/index.rst --- old/cliff-2.8.0/doc/source/install/index.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/doc/source/install/index.rst 2017-10-08 23:48:10.000000000 +0200 @@ -33,7 +33,7 @@ Source Code =========== -The source is hosted on github: http://git.openstack.org/cgit/openstack/cliff +The source is hosted on github: https://git.openstack.org/cgit/openstack/cliff Reporting Bugs ============== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/doc/source/user/index.rst new/cliff-2.9.1/doc/source/user/index.rst --- old/cliff-2.8.0/doc/source/user/index.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/doc/source/user/index.rst 2017-10-08 23:48:10.000000000 +0200 @@ -12,4 +12,9 @@ complete interactive_mode sphinxext + +.. history contains a lot of sections, toctree with maxdepth 1 is used. +.. toctree:: + :maxdepth: 1 + history diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/doc/source/user/sphinxext.rst new/cliff-2.9.1/doc/source/user/sphinxext.rst --- old/cliff-2.8.0/doc/source/user/sphinxext.rst 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/doc/source/user/sphinxext.rst 2017-10-08 23:48:10.000000000 +0200 @@ -4,6 +4,13 @@ cliff supports integration with Sphinx by way of a `Sphinx directives`__. +Before using the :rst:dir:`autoprogram-cliff` directive you must add +`'cliff.sphinxext'` extension module to a list of `extensions` in `conf.py`: + +.. code-block:: python + + extensions = ['cliff.sphinxext'] + .. rst:directive:: .. autoprogram-cliff:: namespace Automatically document an instance of :py:class:`cliff.command.Command`, @@ -22,7 +29,6 @@ In addition, the following directive options can be supplied: `:command:` - The name of the command, as it would appear if called from the command line without the executable name. This will be defined in `setup.cfg` or `setup.py` albeit with underscores. This is optional and `fnmatch-style`__ @@ -30,7 +36,6 @@ information. `:application:` - The top-level application name, which will be prefixed before all commands. This option overrides the global option `autoprogram_cliff_application` described below. @@ -40,7 +45,6 @@ .. seealso:: The ``autoprogram_cliff_application`` configuration option. `:ignored:` - A comma-separated list of options to exclude from documentation for this option. This is useful for options that are of low value. @@ -50,7 +54,6 @@ placed in `conf.py`: `autoprogram_cliff_application` - The top-level application name, which will be prefixed before all commands. This is generally defined in the `console_scripts` attribute of the `entry_points` section of either `setup.cfg` or `setup.py`. Refer to @@ -68,7 +71,6 @@ .. seealso:: The ``:application:`` directive option. `autoprogram_cliff_ignored` - A global list of options to exclude from documentation. This can be used to prevent duplication of common options, such as those used for pagination, across **all** options. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/requirements.txt new/cliff-2.9.1/requirements.txt --- old/cliff-2.8.0/requirements.txt 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/requirements.txt 2017-10-08 23:48:10.000000000 +0200 @@ -8,4 +8,4 @@ six>=1.9.0 # MIT stevedore>=1.20.0 # Apache-2.0 unicodecsv>=0.8.0;python_version<'3.0' # BSD -PyYAML>=3.10.0 # MIT +PyYAML>=3.10 # MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/setup.cfg new/cliff-2.9.1/setup.cfg --- old/cliff-2.8.0/setup.cfg 2017-07-10 21:30:47.000000000 +0200 +++ new/cliff-2.9.1/setup.cfg 2017-10-08 23:50:16.000000000 +0200 @@ -4,7 +4,7 @@ author = OpenStack author-email = [email protected] summary = Command Line Interface Formulation Framework -home-page = http://docs.openstack.org/developer/cliff +home-page = https://docs.openstack.org/cliff/latest/ classifier = Development Status :: 5 - Production/Stable License :: OSI Approved :: Apache Software License @@ -16,6 +16,10 @@ Intended Audience :: Developers Environment :: Console +[extras] +docs = + openstackdocstheme>=1.17.0 # Apache-2.0 + [global] setup-hooks = pbr.hooks.setup_hook diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/test-requirements.txt new/cliff-2.9.1/test-requirements.txt --- old/cliff-2.8.0/test-requirements.txt 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/test-requirements.txt 2017-10-08 23:48:10.000000000 +0200 @@ -5,11 +5,10 @@ python-subunit>=0.0.18 # Apache-2.0/BSD testrepository>=0.0.18 # Apache-2.0/BSD testtools>=1.4.0 # MIT -mock>=2.0 # BSD +mock>=2.0.0 # BSD testscenarios>=0.4 # Apache-2.0/BSD coverage!=4.4,>=4.0 # Apache-2.0 # this is required for the docs build jobs sphinx>=1.6.2 # BSD -openstackdocstheme>=1.11.0 # Apache-2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cliff-2.8.0/tox.ini new/cliff-2.9.1/tox.ini --- old/cliff-2.8.0/tox.ini 2017-07-10 21:28:10.000000000 +0200 +++ new/cliff-2.9.1/tox.ini 2017-10-08 23:48:10.000000000 +0200 @@ -7,6 +7,9 @@ VIRTUAL_ENV={envdir} BRANCH_NAME=master CLIENT_NAME=cliff + OS_STDOUT_CAPTURE=1 + OS_STDERR_CAPTURE=1 + OS_TEST_TIMEOUT=60 passenv = ZUUL_CACHE_DIR distribute = False @@ -15,6 +18,7 @@ python setup.py test --coverage --coverage-package-name=cliff --slowest --testr-args='{posargs}' coverage report --show-missing deps = -r{toxinidir}/test-requirements.txt + .[docs] [testenv:pep8] deps = flake8
