Fix --help with required options
This works by adding an argparse Action that will raise an exception in order to skip the rest of the argument parsing. This prevents argparse from quitting due to missing required arguments, similar to the way that the builtin argparse --help option is implemented by raising SystemExit. Fixes: #1999
This commit is contained in:
parent
bcbad5b1af
commit
f74f14f038
1
AUTHORS
1
AUTHORS
|
@ -144,6 +144,7 @@ Ross Lawley
|
|||
Russel Winder
|
||||
Ryan Wooden
|
||||
Samuele Pedroni
|
||||
Segev Finer
|
||||
Simon Gomizelj
|
||||
Skylar Downes
|
||||
Stefan Farmbauer
|
||||
|
|
|
@ -71,6 +71,12 @@ class UsageError(Exception):
|
|||
""" error in pytest usage or invocation"""
|
||||
|
||||
|
||||
class PrintHelp(Exception):
|
||||
"""Raised when pytest should print it's help to skip the rest of the
|
||||
argument parsing and validation."""
|
||||
pass
|
||||
|
||||
|
||||
def filename_arg(path, optname):
|
||||
""" Argparse type validator for filename arguments.
|
||||
|
||||
|
@ -1100,6 +1106,8 @@ class Config(object):
|
|||
self._preparse(args, addopts=addopts)
|
||||
# XXX deprecated hook:
|
||||
self.hook.pytest_cmdline_preparse(config=self, args=args)
|
||||
self._parser.after_preparse = True
|
||||
try:
|
||||
args = self._parser.parse_setoption(args, self.option, namespace=self.option)
|
||||
if not args:
|
||||
cwd = os.getcwd()
|
||||
|
@ -1108,6 +1116,8 @@ class Config(object):
|
|||
if not args:
|
||||
args = [cwd]
|
||||
self.args = args
|
||||
except PrintHelp:
|
||||
pass
|
||||
|
||||
def addinivalue_line(self, name, line):
|
||||
""" add a line to an ini-file option. The option must have been
|
||||
|
|
|
@ -3,13 +3,38 @@ from __future__ import absolute_import, division, print_function
|
|||
|
||||
import py
|
||||
import pytest
|
||||
from _pytest.config import PrintHelp
|
||||
import os, sys
|
||||
from argparse import Action
|
||||
|
||||
|
||||
class HelpAction(Action):
|
||||
def __init__(self,
|
||||
option_strings,
|
||||
dest=None,
|
||||
default=False,
|
||||
help=None):
|
||||
super(HelpAction, self).__init__(
|
||||
option_strings=option_strings,
|
||||
dest=dest,
|
||||
const=True,
|
||||
default=default,
|
||||
nargs=0,
|
||||
help=help)
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
setattr(namespace, self.dest, self.const)
|
||||
|
||||
# We should only skip the rest of the parsing after preparse is done
|
||||
if getattr(parser._parser, 'after_preparse', False):
|
||||
raise PrintHelp
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup('debugconfig')
|
||||
group.addoption('--version', action="store_true",
|
||||
help="display pytest lib version and import information.")
|
||||
group._addoption("-h", "--help", action="store_true", dest="help",
|
||||
group._addoption("-h", "--help", action=HelpAction, dest="help",
|
||||
help="show help message and configuration info")
|
||||
group._addoption('-p', action="append", dest="plugins", default = [],
|
||||
metavar="name",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Required options added via ``pytest_addoption`` will no longer prevent
|
||||
using --help without passing them.
|
|
@ -449,3 +449,15 @@ def test_hook_proxy(testdir):
|
|||
'*test_foo4.py*',
|
||||
'*3 passed*',
|
||||
])
|
||||
|
||||
|
||||
def test_required_option_help(testdir):
|
||||
testdir.makeconftest("assert 0")
|
||||
x = testdir.mkdir("x")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--xyz", action="store_true", required=True)
|
||||
"""))
|
||||
result = testdir.runpytest("-h", x)
|
||||
assert 'argument --xyz is required' not in result.stdout.str()
|
||||
assert 'general:' in result.stdout.str()
|
||||
|
|
Loading…
Reference in New Issue