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

Gracefully handle eval() failure(s) for marker expressions #7082

Merged
merged 3 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ Segev Finer
Serhii Mozghovyi
Seth Junot
Simon Gomizelj
Simon Kerr
Skylar Downes
Srinivas Reddy Thatiparthy
Stefan Farmbauer
Expand Down
1 change: 1 addition & 0 deletions changelog/4583.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent crashing and provide user friendly error(s) when marker expressions (-m) invoking of eval() raises a SyntaxError or TypeError
symonk marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions src/_pytest/mark/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ def matchmark(colitem, markexpr):
"""Tries to match on any marker names, attached to the given colitem."""
try:
return eval(markexpr, {}, MarkMapping.from_item(colitem))
except SyntaxError as e:
raise SyntaxError(str(e) + "\nMarker expression must be valid Python!")
except Exception:
raise UsageError("Wrong expression passed to '-m': {}".format(markexpr))


def matchkeyword(colitem, keywordexpr):
Expand Down
29 changes: 17 additions & 12 deletions testing/test_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,18 +601,6 @@ def test_unmarked():
deselected_tests = dlist[0].items
assert len(deselected_tests) == 2

def test_invalid_m_option(self, testdir):
testdir.makepyfile(
"""
def test_a():
pass
"""
)
result = testdir.runpytest("-m bogus/")
result.stdout.fnmatch_lines(
["INTERNALERROR> Marker expression must be valid Python!"]
)

def test_keywords_at_node_level(self, testdir):
testdir.makepyfile(
"""
Expand Down Expand Up @@ -1022,3 +1010,20 @@ def test_pytest_param_id_requires_string():
@pytest.mark.parametrize("s", (None, "hello world"))
def test_pytest_param_id_allows_none_or_string(s):
assert pytest.param(id=s)


@pytest.mark.parametrize("expr", ("NOT internal_err", "NOT (internal_err)", "bogus/"))
def test_marker_expr_eval_failure_handling(testdir, expr):
foo = testdir.makepyfile(
"""
import pytest
@pytest.mark.internal_err
def test_foo():
pass
"""
)
expected = "ERROR: Wrong expression passed to '-m': {}".format(expr)
result = testdir.runpytest(foo, "-m", expr)
result.stderr.fnmatch_lines([expected])
assert result.ret == ExitCode.USAGE_ERROR