Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2953 show a simple and easy error when keyword expressions trigger a syntax error #3121

Merged
merged 8 commits into from
Jan 17, 2018
3 changes: 2 additions & 1 deletion _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ def main(args=None, plugins=None):
finally:
config._ensure_unconfigure()
except UsageError as e:
tw = py.io.TerminalWriter(sys.stderr)
for msg in e.args:
sys.stderr.write("ERROR: %s\n" % (msg,))
tw.line("ERROR: {}\n".format(msg), red=True)
return 4


Expand Down
14 changes: 13 additions & 1 deletion _pytest/mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
from __future__ import absolute_import, division, print_function

import inspect
import keyword
import warnings
import attr
from collections import namedtuple
from operator import attrgetter
from six.moves import map

from _pytest.config import UsageError
from .deprecated import MARK_PARAMETERSET_UNPACKING
from .compat import NOTSET, getfslineno

Expand Down Expand Up @@ -222,6 +225,9 @@ def __getitem__(self, subname):
return False


python_keywords_allowed_list = ["or", "and", "not"]


def matchmark(colitem, markexpr):
"""Tries to match on any marker names, attached to the given colitem."""
return eval(markexpr, {}, MarkMapping.from_keywords(colitem.keywords))
Expand Down Expand Up @@ -259,7 +265,13 @@ def matchkeyword(colitem, keywordexpr):
return mapping[keywordexpr]
elif keywordexpr.startswith("not ") and " " not in keywordexpr[4:]:
return not mapping[keywordexpr[4:]]
return eval(keywordexpr, {}, mapping)
for kwd in keywordexpr.split():
if keyword.iskeyword(kwd) and kwd not in python_keywords_allowed_list:
raise UsageError("Python keyword '{}' not accepted in expressions passed to '-k'".format(kwd))
try:
return eval(keywordexpr, {}, mapping)
except SyntaxError:
raise UsageError("Wrong expression passed to '-k': {}".format(keywordexpr))


def pytest_configure(config):
Expand Down
1 change: 1 addition & 0 deletions changelog/2953.trivial
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Show a simple and easy error when keyword expressions trigger a syntax error (for example, ``"-k foo and import"`` will show an error that you can not use the ``import`` keyword in expressions).
15 changes: 15 additions & 0 deletions testing/test_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,21 @@ def test_func(arg):
assert list(passed) == list(passed_result)


@pytest.mark.parametrize("spec", [
("foo or import", "ERROR: Python keyword 'import' not accepted in expressions passed to '-k'"),
("foo or", "ERROR: Wrong expression passed to '-k': foo or")
])
def test_keyword_option_wrong_arguments(spec, testdir, capsys):
testdir.makepyfile("""
def test_func(arg):
pass
""")
opt, expected_result = spec
testdir.inline_run("-k", opt)
out = capsys.readouterr().err
assert expected_result in out


def test_parametrized_collected_from_command_line(testdir):
"""Parametrized test not collected if test named specified
in command line issue#649.
Expand Down