Merge pull request #3147 from nicoddemus/issue-3103
'-o' option no longer swallows all other non-options after it
This commit is contained in:
commit
2aad8c0fce
1
AUTHORS
1
AUTHORS
|
@ -18,6 +18,7 @@ Anthon van der Neut
|
||||||
Anthony Sottile
|
Anthony Sottile
|
||||||
Antony Lee
|
Antony Lee
|
||||||
Armin Rigo
|
Armin Rigo
|
||||||
|
Aron Coyle
|
||||||
Aron Curzon
|
Aron Curzon
|
||||||
Aviv Palivoda
|
Aviv Palivoda
|
||||||
Barney Gale
|
Barney Gale
|
||||||
|
|
|
@ -1188,16 +1188,15 @@ class Config(object):
|
||||||
|
|
||||||
def _get_override_ini_value(self, name):
|
def _get_override_ini_value(self, name):
|
||||||
value = None
|
value = None
|
||||||
# override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
|
# override_ini is a list of "ini=value" options
|
||||||
# and -o foo1=bar1 -o foo2=bar2 options
|
# always use the last item if multiple values are set for same ini-name,
|
||||||
# always use the last item if multiple value set for same ini-name,
|
|
||||||
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
|
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
|
||||||
for ini_config_list in self._override_ini:
|
for ini_config in self._override_ini:
|
||||||
for ini_config in ini_config_list:
|
try:
|
||||||
try:
|
key, user_ini_value = ini_config.split("=", 1)
|
||||||
(key, user_ini_value) = ini_config.split("=", 1)
|
except ValueError:
|
||||||
except ValueError:
|
raise UsageError("-o/--override-ini expects option=value style.")
|
||||||
raise UsageError("-o/--override-ini expects option=value style.")
|
else:
|
||||||
if key == name:
|
if key == name:
|
||||||
value = user_ini_value
|
value = user_ini_value
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -57,9 +57,9 @@ def pytest_addoption(parser):
|
||||||
action="store_true", dest="debug", default=False,
|
action="store_true", dest="debug", default=False,
|
||||||
help="store internal tracing debug information in 'pytestdebug.log'.")
|
help="store internal tracing debug information in 'pytestdebug.log'.")
|
||||||
group._addoption(
|
group._addoption(
|
||||||
'-o', '--override-ini', nargs='*', dest="override_ini",
|
'-o', '--override-ini', dest="override_ini",
|
||||||
action="append",
|
action="append",
|
||||||
help="override config option with option=value style, e.g. `-o xfail_strict=True`.")
|
help='override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`.')
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
**Incompatible change**: ``-o/--override`` option no longer eats all the remaining options, which can lead to surprising behavior: for example, ``pytest -o foo=1 /path/to/test.py`` would fail because ``/path/to/test.py`` would be considered as part of the ``-o`` command-line argument. One consequence of this is that now multiple configuration overrides need multiple ``-o`` flags: ``pytest -o foo=1 -o bar=2``.
|
|
@ -152,11 +152,25 @@ above will show verbose output because ``-v`` overwrites ``-q``.
|
||||||
Builtin configuration file options
|
Builtin configuration file options
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
Here is a list of builtin configuration options that may be written in a ``pytest.ini``, ``tox.ini`` or ``setup.cfg``
|
||||||
|
file, usually located at the root of your repository. All options must be under a ``[pytest]`` section
|
||||||
|
(``[tool:pytest]`` for ``setup.cfg`` files).
|
||||||
|
|
||||||
|
Configuration file options may be overwritten in the command-line by using ``-o/--override``, which can also be
|
||||||
|
passed multiple times. The expected format is ``name=value``. For example::
|
||||||
|
|
||||||
|
pytest -o console_output_style=classic -o cache_dir=/tmp/mycache
|
||||||
|
|
||||||
|
|
||||||
.. confval:: minversion
|
.. confval:: minversion
|
||||||
|
|
||||||
Specifies a minimal pytest version required for running tests.
|
Specifies a minimal pytest version required for running tests.
|
||||||
|
|
||||||
minversion = 2.1 # will fail if we run with pytest-2.0
|
.. code-block:: ini
|
||||||
|
|
||||||
|
# content of pytest.ini
|
||||||
|
[pytest]
|
||||||
|
minversion = 3.0 # will fail if we run with pytest-2.8
|
||||||
|
|
||||||
.. confval:: addopts
|
.. confval:: addopts
|
||||||
|
|
||||||
|
@ -165,6 +179,7 @@ Builtin configuration file options
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
|
# content of pytest.ini
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
||||||
|
|
||||||
|
|
|
@ -781,16 +781,18 @@ class TestOverrideIniArgs(object):
|
||||||
testdir.makeini("""
|
testdir.makeini("""
|
||||||
[pytest]
|
[pytest]
|
||||||
custom_option_1=custom_option_1
|
custom_option_1=custom_option_1
|
||||||
custom_option_2=custom_option_2""")
|
custom_option_2=custom_option_2
|
||||||
|
""")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_multiple_options(pytestconfig):
|
def test_multiple_options(pytestconfig):
|
||||||
prefix = "custom_option"
|
prefix = "custom_option"
|
||||||
for x in range(1, 5):
|
for x in range(1, 5):
|
||||||
ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
|
ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
|
||||||
print('\\nini%d:%s' % (x, ini_value))""")
|
print('\\nini%d:%s' % (x, ini_value))
|
||||||
|
""")
|
||||||
result = testdir.runpytest(
|
result = testdir.runpytest(
|
||||||
"--override-ini", 'custom_option_1=fulldir=/tmp/user1',
|
"--override-ini", 'custom_option_1=fulldir=/tmp/user1',
|
||||||
'custom_option_2=url=/tmp/user2?a=b&d=e',
|
'-o', 'custom_option_2=url=/tmp/user2?a=b&d=e',
|
||||||
"-o", 'custom_option_3=True',
|
"-o", 'custom_option_3=True',
|
||||||
"-o", 'custom_option_4=no', "-s")
|
"-o", 'custom_option_4=no', "-s")
|
||||||
result.stdout.fnmatch_lines(["ini1:fulldir=/tmp/user1",
|
result.stdout.fnmatch_lines(["ini1:fulldir=/tmp/user1",
|
||||||
|
@ -853,10 +855,42 @@ class TestOverrideIniArgs(object):
|
||||||
assert rootdir == tmpdir
|
assert rootdir == tmpdir
|
||||||
assert inifile is None
|
assert inifile is None
|
||||||
|
|
||||||
def test_addopts_before_initini(self, testdir, tmpdir, monkeypatch):
|
def test_addopts_before_initini(self, monkeypatch):
|
||||||
cache_dir = '.custom_cache'
|
cache_dir = '.custom_cache'
|
||||||
monkeypatch.setenv('PYTEST_ADDOPTS', '-o cache_dir=%s' % cache_dir)
|
monkeypatch.setenv('PYTEST_ADDOPTS', '-o cache_dir=%s' % cache_dir)
|
||||||
from _pytest.config import get_config
|
from _pytest.config import get_config
|
||||||
config = get_config()
|
config = get_config()
|
||||||
config._preparse([], addopts=True)
|
config._preparse([], addopts=True)
|
||||||
assert config._override_ini == [['cache_dir=%s' % cache_dir]]
|
assert config._override_ini == ['cache_dir=%s' % cache_dir]
|
||||||
|
|
||||||
|
def test_override_ini_does_not_contain_paths(self):
|
||||||
|
"""Check that -o no longer swallows all options after it (#3103)"""
|
||||||
|
from _pytest.config import get_config
|
||||||
|
config = get_config()
|
||||||
|
config._preparse(['-o', 'cache_dir=/cache', '/some/test/path'])
|
||||||
|
assert config._override_ini == ['cache_dir=/cache']
|
||||||
|
|
||||||
|
def test_multiple_override_ini_options(self, testdir, request):
|
||||||
|
"""Ensure a file path following a '-o' option does not generate an error (#3103)"""
|
||||||
|
testdir.makepyfile(**{
|
||||||
|
"conftest.py": """
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addini('foo', default=None, help='some option')
|
||||||
|
parser.addini('bar', default=None, help='some option')
|
||||||
|
""",
|
||||||
|
"test_foo.py": """
|
||||||
|
def test(pytestconfig):
|
||||||
|
assert pytestconfig.getini('foo') == '1'
|
||||||
|
assert pytestconfig.getini('bar') == '0'
|
||||||
|
""",
|
||||||
|
"test_bar.py": """
|
||||||
|
def test():
|
||||||
|
assert False
|
||||||
|
""",
|
||||||
|
})
|
||||||
|
result = testdir.runpytest('-o', 'foo=1', '-o', 'bar=0', 'test_foo.py')
|
||||||
|
assert 'ERROR:' not in result.stderr.str()
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
'collected 1 item',
|
||||||
|
'*= 1 passed in *=',
|
||||||
|
])
|
||||||
|
|
Loading…
Reference in New Issue