Merge remote-tracking branch 'upstream/features' into merge-features-into-master
This commit is contained in:
commit
019455298b
|
@ -0,0 +1,7 @@
|
||||||
|
Pytest no longer accepts prefixes of command-line arguments, for example
|
||||||
|
typing ``pytest --doctest-mod`` inplace of ``--doctest-modules``.
|
||||||
|
This was previously allowed where the ``ArgumentParser`` thought it was unambiguous,
|
||||||
|
but this could be incorrect due to delayed parsing of options for plugins.
|
||||||
|
See for example issues `#1149 <https://github.com/pytest-dev/pytest/issues/1149>`__,
|
||||||
|
`#3413 <https://github.com/pytest-dev/pytest/issues/3413>`__, and
|
||||||
|
`#4009 <https://github.com/pytest-dev/pytest/issues/4009>`__.
|
|
@ -74,7 +74,7 @@ def report(issues):
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser("process bitbucket issues")
|
parser = argparse.ArgumentParser("process bitbucket issues", allow_abbrev=False)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--refresh", action="store_true", help="invalidate cache, refresh issues"
|
"--refresh", action="store_true", help="invalidate cache, refresh issues"
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,7 +105,7 @@ def changelog(version, write_out=False):
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
init(autoreset=True)
|
init(autoreset=True)
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||||
parser.add_argument("version", help="Release version")
|
parser.add_argument("version", help="Release version")
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
pre_release(options.version)
|
pre_release(options.version)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
from gettext import gettext
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
@ -328,6 +330,7 @@ class MyOptionParser(argparse.ArgumentParser):
|
||||||
usage=parser._usage,
|
usage=parser._usage,
|
||||||
add_help=False,
|
add_help=False,
|
||||||
formatter_class=DropShorterLongHelpFormatter,
|
formatter_class=DropShorterLongHelpFormatter,
|
||||||
|
allow_abbrev=False,
|
||||||
)
|
)
|
||||||
# extra_info is a dict of (param -> value) to display if there's
|
# extra_info is a dict of (param -> value) to display if there's
|
||||||
# an usage error to provide more contextual information to the user
|
# an usage error to provide more contextual information to the user
|
||||||
|
@ -355,6 +358,42 @@ class MyOptionParser(argparse.ArgumentParser):
|
||||||
getattr(args, FILE_OR_DIR).extend(argv)
|
getattr(args, FILE_OR_DIR).extend(argv)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
if sys.version_info[:2] < (3, 8): # pragma: no cover
|
||||||
|
# Backport of https://github.com/python/cpython/pull/14316 so we can
|
||||||
|
# disable long --argument abbreviations without breaking short flags.
|
||||||
|
def _parse_optional(self, arg_string):
|
||||||
|
if not arg_string:
|
||||||
|
return None
|
||||||
|
if not arg_string[0] in self.prefix_chars:
|
||||||
|
return None
|
||||||
|
if arg_string in self._option_string_actions:
|
||||||
|
action = self._option_string_actions[arg_string]
|
||||||
|
return action, arg_string, None
|
||||||
|
if len(arg_string) == 1:
|
||||||
|
return None
|
||||||
|
if "=" in arg_string:
|
||||||
|
option_string, explicit_arg = arg_string.split("=", 1)
|
||||||
|
if option_string in self._option_string_actions:
|
||||||
|
action = self._option_string_actions[option_string]
|
||||||
|
return action, option_string, explicit_arg
|
||||||
|
if self.allow_abbrev or not arg_string.startswith("--"):
|
||||||
|
option_tuples = self._get_option_tuples(arg_string)
|
||||||
|
if len(option_tuples) > 1:
|
||||||
|
msg = gettext(
|
||||||
|
"ambiguous option: %(option)s could match %(matches)s"
|
||||||
|
)
|
||||||
|
options = ", ".join(option for _, option, _ in option_tuples)
|
||||||
|
self.error(msg % {"option": arg_string, "matches": options})
|
||||||
|
elif len(option_tuples) == 1:
|
||||||
|
option_tuple, = option_tuples
|
||||||
|
return option_tuple
|
||||||
|
if self._negative_number_matcher.match(arg_string):
|
||||||
|
if not self._has_negative_number_optionals:
|
||||||
|
return None
|
||||||
|
if " " in arg_string:
|
||||||
|
return None
|
||||||
|
return None, arg_string, None
|
||||||
|
|
||||||
|
|
||||||
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
||||||
"""shorten help for long options that differ only in extra hyphens
|
"""shorten help for long options that differ only in extra hyphens
|
||||||
|
|
|
@ -996,7 +996,7 @@ def test_zipimport_hook(testdir, tmpdir):
|
||||||
"app/foo.py": """
|
"app/foo.py": """
|
||||||
import pytest
|
import pytest
|
||||||
def main():
|
def main():
|
||||||
pytest.main(['--pyarg', 'foo'])
|
pytest.main(['--pyargs', 'foo'])
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import pathlib
|
||||||
HERE = pathlib.Path(__file__).parent
|
HERE = pathlib.Path(__file__).parent
|
||||||
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
|
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||||
parser.add_argument("numbers", nargs="*", type=int)
|
parser.add_argument("numbers", nargs="*", type=int)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -735,7 +735,7 @@ def test_capture_badoutput_issue412(testdir):
|
||||||
assert 0
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result = testdir.runpytest("--cap=fd")
|
result = testdir.runpytest("--capture=fd")
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
"""
|
"""
|
||||||
*def test_func*
|
*def test_func*
|
||||||
|
|
|
@ -200,7 +200,7 @@ class TestParser:
|
||||||
|
|
||||||
def test_drop_short_helper(self):
|
def test_drop_short_helper(self):
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
formatter_class=parseopt.DropShorterLongHelpFormatter
|
formatter_class=parseopt.DropShorterLongHelpFormatter, allow_abbrev=False
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
||||||
|
@ -239,10 +239,8 @@ class TestParser:
|
||||||
parser.addoption("--funcarg", "--func-arg", action="store_true")
|
parser.addoption("--funcarg", "--func-arg", action="store_true")
|
||||||
parser.addoption("--abc-def", "--abc-def", action="store_true")
|
parser.addoption("--abc-def", "--abc-def", action="store_true")
|
||||||
parser.addoption("--klm-hij", action="store_true")
|
parser.addoption("--klm-hij", action="store_true")
|
||||||
args = parser.parse(["--funcarg", "--k"])
|
with pytest.raises(UsageError):
|
||||||
assert args.funcarg is True
|
parser.parse(["--funcarg", "--k"])
|
||||||
assert args.abc_def is False
|
|
||||||
assert args.klm_hij is True
|
|
||||||
|
|
||||||
def test_drop_short_2(self, parser):
|
def test_drop_short_2(self, parser):
|
||||||
parser.addoption("--func-arg", "--doit", action="store_true")
|
parser.addoption("--func-arg", "--doit", action="store_true")
|
||||||
|
|
|
@ -21,7 +21,7 @@ class TestPasteCapture:
|
||||||
pytest.skip("")
|
pytest.skip("")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
reprec = testdir.inline_run(testpath, "--paste=failed")
|
reprec = testdir.inline_run(testpath, "--pastebin=failed")
|
||||||
assert len(pastebinlist) == 1
|
assert len(pastebinlist) == 1
|
||||||
s = pastebinlist[0]
|
s = pastebinlist[0]
|
||||||
assert s.find("def test_fail") != -1
|
assert s.find("def test_fail") != -1
|
||||||
|
|
Loading…
Reference in New Issue