summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml4
-rw-r--r--MANIFEST.in6
-rw-r--r--Makefile21
-rw-r--r--README.rst2
-rw-r--r--cliff/_argparse.py80
-rw-r--r--cliff/command.py1
-rw-r--r--cliff/formatters/json_format.py1
-rw-r--r--cliff/tests/test_command.py30
-rw-r--r--doc/Makefile153
-rw-r--r--doc/source/install/index.rst2
-rw-r--r--setup.cfg5
-rw-r--r--tox.ini4
12 files changed, 115 insertions, 194 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index e825123..af9f46b 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -26,9 +26,7 @@
- lib-forward-testing-python3
- openstack-lower-constraints-jobs
- openstack-python-jobs
- - openstack-python35-jobs
- - openstack-python36-jobs
- - openstack-python37-jobs
+ - openstack-python3-train-jobs
- publish-openstack-docs-pti
check:
jobs:
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index bb56f02..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,6 +0,0 @@
-include setup.py
-recursive-include docs *.rst *.py *.html *.css *.js *.png *.txt
-recursive-include demoapp *.py
-recursive-include tests *.py
-include tox.ini
-
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 73adad1..0000000
--- a/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-help:
- @echo "release - package and upload a release"
- @echo "sdist - package"
- @echo "docs - generate HTML documentation"
- @echo "clean - remove build artifacts"
-
-release: docs
- rm -rf dist build
- python setup.py sdist upload
-
-sdist: docs
- python setup.py sdist
- ls -l dist
-
-clean:
- rm -rf dist build *.egg-info
- (cd doc && make clean)
-
-.PHONY: docs
-docs:
- (cd doc && make clean html)
diff --git a/README.rst b/README.rst
index e72ba11..b3a0f18 100644
--- a/README.rst
+++ b/README.rst
@@ -19,5 +19,5 @@ other extensions.
* Free software: Apache license
* Documentation: https://docs.openstack.org/cliff/latest/
-* Source: https://git.openstack.org/cgit/openstack/cliff
+* Source: https://opendev.org/openstack/cliff
* Bugs: https://bugs.launchpad.net/python-cliff
diff --git a/cliff/_argparse.py b/cliff/_argparse.py
index e48dc79..5358e72 100644
--- a/cliff/_argparse.py
+++ b/cliff/_argparse.py
@@ -14,11 +14,14 @@
from __future__ import absolute_import
from argparse import * # noqa
+import argparse
import sys
+import warnings
-if sys.version_info < (3, 5):
- class ArgumentParser(ArgumentParser): # noqa
+class ArgumentParser(argparse.ArgumentParser):
+
+ if sys.version_info < (3, 5):
def __init__(self, *args, **kwargs):
self.allow_abbrev = kwargs.pop("allow_abbrev", True)
super(ArgumentParser, self).__init__(*args, **kwargs)
@@ -28,3 +31,76 @@ if sys.version_info < (3, 5):
return super(ArgumentParser, self)._get_option_tuples(
option_string)
return ()
+
+ # NOTE(dhellmann): We have to override the methods for creating
+ # groups to return our objects that know how to deal with the
+ # special conflict handler.
+
+ def add_argument_group(self, *args, **kwargs):
+ group = _ArgumentGroup(self, *args, **kwargs)
+ self._action_groups.append(group)
+ return group
+
+ def add_mutually_exclusive_group(self, **kwargs):
+ group = _MutuallyExclusiveGroup(self, **kwargs)
+ self._mutually_exclusive_groups.append(group)
+ return group
+
+ def _handle_conflict_ignore(self, action, conflicting_actions):
+ _handle_conflict_ignore(
+ self,
+ self._option_string_actions,
+ action,
+ conflicting_actions,
+ )
+
+
+def _handle_conflict_ignore(container, option_string_actions,
+ new_action, conflicting_actions):
+
+ # Remember the option strings the new action starts with so we can
+ # restore them as part of error reporting if we need to.
+ original_option_strings = new_action.option_strings
+
+ # Remove all of the conflicting option strings from the new action
+ # and report an error if none are left at the end.
+ for option_string, action in conflicting_actions:
+
+ # remove the conflicting option from the new action
+ new_action.option_strings.remove(option_string)
+ warnings.warn(
+ ('Ignoring option string {} for new action '
+ 'because it conflicts with an existing option.').format(
+ option_string))
+
+ # if the option now has no option string, remove it from the
+ # container holding it
+ if not new_action.option_strings:
+ new_action.option_strings = original_option_strings
+ raise argparse.ArgumentError(
+ new_action,
+ ('Cannot resolve conflicting option string, '
+ 'all names conflict.'),
+ )
+
+
+class _ArgumentGroup(argparse._ArgumentGroup):
+
+ def _handle_conflict_ignore(self, action, conflicting_actions):
+ _handle_conflict_ignore(
+ self,
+ self._option_string_actions,
+ action,
+ conflicting_actions,
+ )
+
+
+class _MutuallyExclusiveGroup(argparse._MutuallyExclusiveGroup):
+
+ def _handle_conflict_ignore(self, action, conflicting_actions):
+ _handle_conflict_ignore(
+ self,
+ self._option_string_actions,
+ action,
+ conflicting_actions,
+ )
diff --git a/cliff/command.py b/cliff/command.py
index 13b872d..760832b 100644
--- a/cliff/command.py
+++ b/cliff/command.py
@@ -156,6 +156,7 @@ class Command(object):
epilog=self.get_epilog(),
prog=prog_name,
formatter_class=_SmartHelpFormatter,
+ conflict_handler='ignore',
)
for hook in self._hooks:
hook.obj.get_parser(parser)
diff --git a/cliff/formatters/json_format.py b/cliff/formatters/json_format.py
index 4483e91..0480432 100644
--- a/cliff/formatters/json_format.py
+++ b/cliff/formatters/json_format.py
@@ -52,3 +52,4 @@ class JSONFormatter(base.ListFormatter, base.SingleFormatter):
}
indent = None if parsed_args.noindent else 2
json.dump(one, stdout, indent=indent)
+ stdout.write('\n')
diff --git a/cliff/tests/test_command.py b/cliff/tests/test_command.py
index 6aecff3..29c8c33 100644
--- a/cliff/tests/test_command.py
+++ b/cliff/tests/test_command.py
@@ -45,7 +45,9 @@ class TestCommand(command.Command):
)
parser.add_argument(
'-z',
- help='used in TestArgumentParser',
+ dest='zippy',
+ default='zippy-default',
+ help='defined in TestCommand and used in TestArgumentParser',
)
return parser
@@ -141,10 +143,32 @@ class TestArgumentParser(base.TestBase):
cmd = TestCommand(None, None)
parser = cmd.get_parser('NAME')
# We should have an exception registering an option with a
- # name that already exists because we do not want commands to
- # override global options.
+ # name that already exists because we configure the argument
+ # parser to ignore conflicts but this option has no other name
+ # to be used.
self.assertRaises(
argparse.ArgumentError,
parser.add_argument,
'-z',
)
+
+ def test_option_name_collision_with_alias(self):
+ cmd = TestCommand(None, None)
+ parser = cmd.get_parser('NAME')
+ # We not should have an exception registering an option with a
+ # name that already exists because we configure the argument
+ # parser to ignore conflicts and this option can be added as
+ # --zero even if the -z is ignored.
+ parser.add_argument('-z', '--zero')
+
+ def test_resolve_option_with_name_collision(self):
+ cmd = TestCommand(None, None)
+ parser = cmd.get_parser('NAME')
+ parser.add_argument(
+ '-z', '--zero',
+ dest='zero',
+ default='zero-default',
+ )
+ args = parser.parse_args(['-z', 'foo', 'a', 'b'])
+ self.assertEqual(args.zippy, 'foo')
+ self.assertEqual(args.zero, 'zero-default')
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index 0127250..0000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,153 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cliff.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cliff.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/cliff"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/cliff"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst
index 51e0250..406bea0 100644
--- a/doc/source/install/index.rst
+++ b/doc/source/install/index.rst
@@ -33,7 +33,7 @@ or::
Source Code
===========
-The source is hosted on github: https://git.openstack.org/cgit/openstack/cliff
+The source is hosted on OpenDev: https://opendev.org/openstack/cliff
Reporting Bugs
==============
diff --git a/setup.cfg b/setup.cfg
index eb03f01..02b9fba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,7 +2,7 @@
name = cliff
description-file = README.rst
author = OpenStack
-author-email = openstack-dev@lists.openstack.org
+author-email = openstack-discuss@lists.openstack.org
summary = Command Line Interface Formulation Framework
home-page = https://docs.openstack.org/cliff/latest/
classifier =
@@ -12,7 +12,8 @@ classifier =
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
+ Programming Language :: Python :: 3.6
+ Programming Language :: Python :: 3.7
Intended Audience :: Developers
Environment :: Console
diff --git a/tox.ini b/tox.ini
index 4680a6e..64d19d2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
[tox]
minversion = 2.0
-envlist = py35,py27,pep8
+envlist = py27,py37,pep8
[testenv]
setenv =
@@ -16,7 +16,7 @@ commands =
python setup.py test --coverage --coverage-package-name=cliff --slowest --testr-args='{posargs}'
coverage report --show-missing
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/upper-constraints.txt}
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt