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

This commit is contained in:
symonk 2020-04-13 13:25:06 +01:00
parent f214a4be97
commit 87edc09dea
4 changed files with 53 additions and 5 deletions

View File

@ -246,6 +246,7 @@ Segev Finer
Serhii Mozghovyi Serhii Mozghovyi
Seth Junot Seth Junot
Simon Gomizelj Simon Gomizelj
Simon Kerr
Skylar Downes Skylar Downes
Srinivas Reddy Thatiparthy Srinivas Reddy Thatiparthy
Stefan Farmbauer Stefan Farmbauer

View File

@ -0,0 +1 @@
Prevent crashing and provide user friendly error(s) when marker expressions (-m) invoking of eval() raises a SyntaxError or TypeError

View File

@ -84,8 +84,13 @@ def matchmark(colitem, markexpr):
"""Tries to match on any marker names, attached to the given colitem.""" """Tries to match on any marker names, attached to the given colitem."""
try: try:
return eval(markexpr, {}, MarkMapping.from_item(colitem)) return eval(markexpr, {}, MarkMapping.from_item(colitem))
except SyntaxError as e: except (SyntaxError, TypeError):
raise SyntaxError(str(e) + "\nMarker expression must be valid Python!") raise UsageError(
"Marker expression provided to -m:{} was not valid python syntax."
" Please check the syntax provided and ensure it is correct".format(
markexpr
)
)
def matchkeyword(colitem, keywordexpr): def matchkeyword(colitem, keywordexpr):

View File

@ -608,10 +608,13 @@ class TestFunctional:
pass pass
""" """
) )
result = testdir.runpytest("-m bogus/") expected = (
result.stdout.fnmatch_lines( "ERROR: Marker expression provided to -m: bogus/ was not valid python syntax. Please "
["INTERNALERROR> Marker expression must be valid Python!"] "check the syntax provided and ensure it is correct"
) )
result = testdir.runpytest("-m bogus/")
result.stderr.fnmatch_lines([expected])
assert result.ret == ExitCode.USAGE_ERROR
def test_keywords_at_node_level(self, testdir): def test_keywords_at_node_level(self, testdir):
testdir.makepyfile( testdir.makepyfile(
@ -1022,3 +1025,41 @@ def test_pytest_param_id_requires_string():
@pytest.mark.parametrize("s", (None, "hello world")) @pytest.mark.parametrize("s", (None, "hello world"))
def test_pytest_param_id_allows_none_or_string(s): def test_pytest_param_id_allows_none_or_string(s):
assert pytest.param(id=s) assert pytest.param(id=s)
def test_ux_eval_syntax_error(testdir):
foo = testdir.makepyfile(
"""
import pytest
@pytest.mark.internal_err
def test_foo():
pass
"""
)
expected = (
"ERROR: Marker expression provided to -m: NOT internal_err was not valid python syntax. Please "
"check the syntax provided and ensure it is correct"
)
result = testdir.runpytest(foo, "-m NOT internal_err")
result.stderr.fnmatch_lines([expected])
assert result.ret == ExitCode.USAGE_ERROR
def test_ux_eval_type_error(testdir):
foo = testdir.makepyfile(
"""
import pytest
@pytest.mark.internal_err
def test_foo():
pass
"""
)
expected = (
"ERROR: Marker expression provided to -m: NOT (internal_err) was not valid python syntax. Please "
"check the syntax provided and ensure it is correct"
)
result = testdir.runpytest(foo, "-m NOT (internal_err)")
result.stderr.fnmatch_lines([expected])
assert result.ret == ExitCode.USAGE_ERROR