Skip to content

Commit 2aad8c0

Browse files
authored
Merge pull request #3147 from nicoddemus/issue-3103
'-o' option no longer swallows all other non-options after it
2 parents 3b3d237 + 3f5e9ea commit 2aad8c0

File tree

6 files changed

+67
-17
lines changed

6 files changed

+67
-17
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Anthon van der Neut
1818
Anthony Sottile
1919
Antony Lee
2020
Armin Rigo
21+
Aron Coyle
2122
Aron Curzon
2223
Aviv Palivoda
2324
Barney Gale

_pytest/config.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,16 +1188,15 @@ def _getconftest_pathlist(self, name, path):
11881188

11891189
def _get_override_ini_value(self, name):
11901190
value = None
1191-
# override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
1192-
# and -o foo1=bar1 -o foo2=bar2 options
1193-
# always use the last item if multiple value set for same ini-name,
1191+
# override_ini is a list of "ini=value" options
1192+
# always use the last item if multiple values are set for same ini-name,
11941193
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
1195-
for ini_config_list in self._override_ini:
1196-
for ini_config in ini_config_list:
1197-
try:
1198-
(key, user_ini_value) = ini_config.split("=", 1)
1199-
except ValueError:
1200-
raise UsageError("-o/--override-ini expects option=value style.")
1194+
for ini_config in self._override_ini:
1195+
try:
1196+
key, user_ini_value = ini_config.split("=", 1)
1197+
except ValueError:
1198+
raise UsageError("-o/--override-ini expects option=value style.")
1199+
else:
12011200
if key == name:
12021201
value = user_ini_value
12031202
return value

_pytest/helpconfig.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ def pytest_addoption(parser):
5757
action="store_true", dest="debug", default=False,
5858
help="store internal tracing debug information in 'pytestdebug.log'.")
5959
group._addoption(
60-
'-o', '--override-ini', nargs='*', dest="override_ini",
60+
'-o', '--override-ini', dest="override_ini",
6161
action="append",
62-
help="override config option with option=value style, e.g. `-o xfail_strict=True`.")
62+
help='override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`.')
6363

6464

6565
@pytest.hookimpl(hookwrapper=True)

changelog/3103.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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``.

doc/en/customize.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,25 @@ above will show verbose output because ``-v`` overwrites ``-q``.
152152
Builtin configuration file options
153153
----------------------------------------------
154154

155+
Here is a list of builtin configuration options that may be written in a ``pytest.ini``, ``tox.ini`` or ``setup.cfg``
156+
file, usually located at the root of your repository. All options must be under a ``[pytest]`` section
157+
(``[tool:pytest]`` for ``setup.cfg`` files).
158+
159+
Configuration file options may be overwritten in the command-line by using ``-o/--override``, which can also be
160+
passed multiple times. The expected format is ``name=value``. For example::
161+
162+
pytest -o console_output_style=classic -o cache_dir=/tmp/mycache
163+
164+
155165
.. confval:: minversion
156166

157167
Specifies a minimal pytest version required for running tests.
158168

159-
minversion = 2.1 # will fail if we run with pytest-2.0
169+
.. code-block:: ini
170+
171+
# content of pytest.ini
172+
[pytest]
173+
minversion = 3.0 # will fail if we run with pytest-2.8
160174
161175
.. confval:: addopts
162176

@@ -165,6 +179,7 @@ Builtin configuration file options
165179

166180
.. code-block:: ini
167181
182+
# content of pytest.ini
168183
[pytest]
169184
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
170185

testing/test_config.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -781,16 +781,18 @@ def pytest_addoption(parser):
781781
testdir.makeini("""
782782
[pytest]
783783
custom_option_1=custom_option_1
784-
custom_option_2=custom_option_2""")
784+
custom_option_2=custom_option_2
785+
""")
785786
testdir.makepyfile("""
786787
def test_multiple_options(pytestconfig):
787788
prefix = "custom_option"
788789
for x in range(1, 5):
789790
ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
790-
print('\\nini%d:%s' % (x, ini_value))""")
791+
print('\\nini%d:%s' % (x, ini_value))
792+
""")
791793
result = testdir.runpytest(
792794
"--override-ini", 'custom_option_1=fulldir=/tmp/user1',
793-
'custom_option_2=url=/tmp/user2?a=b&d=e',
795+
'-o', 'custom_option_2=url=/tmp/user2?a=b&d=e',
794796
"-o", 'custom_option_3=True',
795797
"-o", 'custom_option_4=no', "-s")
796798
result.stdout.fnmatch_lines(["ini1:fulldir=/tmp/user1",
@@ -853,10 +855,42 @@ def test_with_existing_file_in_subdir(self, tmpdir):
853855
assert rootdir == tmpdir
854856
assert inifile is None
855857

856-
def test_addopts_before_initini(self, testdir, tmpdir, monkeypatch):
858+
def test_addopts_before_initini(self, monkeypatch):
857859
cache_dir = '.custom_cache'
858860
monkeypatch.setenv('PYTEST_ADDOPTS', '-o cache_dir=%s' % cache_dir)
859861
from _pytest.config import get_config
860862
config = get_config()
861863
config._preparse([], addopts=True)
862-
assert config._override_ini == [['cache_dir=%s' % cache_dir]]
864+
assert config._override_ini == ['cache_dir=%s' % cache_dir]
865+
866+
def test_override_ini_does_not_contain_paths(self):
867+
"""Check that -o no longer swallows all options after it (#3103)"""
868+
from _pytest.config import get_config
869+
config = get_config()
870+
config._preparse(['-o', 'cache_dir=/cache', '/some/test/path'])
871+
assert config._override_ini == ['cache_dir=/cache']
872+
873+
def test_multiple_override_ini_options(self, testdir, request):
874+
"""Ensure a file path following a '-o' option does not generate an error (#3103)"""
875+
testdir.makepyfile(**{
876+
"conftest.py": """
877+
def pytest_addoption(parser):
878+
parser.addini('foo', default=None, help='some option')
879+
parser.addini('bar', default=None, help='some option')
880+
""",
881+
"test_foo.py": """
882+
def test(pytestconfig):
883+
assert pytestconfig.getini('foo') == '1'
884+
assert pytestconfig.getini('bar') == '0'
885+
""",
886+
"test_bar.py": """
887+
def test():
888+
assert False
889+
""",
890+
})
891+
result = testdir.runpytest('-o', 'foo=1', '-o', 'bar=0', 'test_foo.py')
892+
assert 'ERROR:' not in result.stderr.str()
893+
result.stdout.fnmatch_lines([
894+
'collected 1 item',
895+
'*= 1 passed in *=',
896+
])

0 commit comments

Comments
 (0)