Files
pytest2/testing/test_mark_expression.py
Pierre Sassoulas 4588653b24 Migrate from autoflake, black, isort, pyupgrade, flake8 and pydocstyle, to ruff
ruff is faster and handle everything we had prior.

isort configuration done based on the indication from
https://github.com/astral-sh/ruff/issues/4670, previousely based on
reorder-python-import (#11896)

flake8-docstrings was a wrapper around pydocstyle (now archived) that
explicitly asks to use ruff in https://github.com/PyCQA/pydocstyle/pull/658.

flake8-typing-import is useful mainly for project that support python 3.7
and the one useful check will be implemented in https://github.com/astral-sh/ruff/issues/2302

We need to keep blacken-doc because ruff does not handle detection
of python code inside .md and .rst. The direct link to the repo is
now used to avoid a redirection.

Manual fixes:
- Lines that became too long
- % formatting that was not done automatically
- type: ignore that were moved around
- noqa of hard to fix issues (UP031 generally)
- fmt: off and fmt: on that is not really identical
  between black and ruff
- autofix re-order in pre-commit from faster to slower

Co-authored-by: Ran Benita <ran@unusedvar.com>
2024-02-02 09:27:00 +01:00

196 lines
5.3 KiB
Python

from typing import Callable
from _pytest.mark.expression import Expression
from _pytest.mark.expression import ParseError
import pytest
def evaluate(input: str, matcher: Callable[[str], bool]) -> bool:
return Expression.compile(input).evaluate(matcher)
def test_empty_is_false() -> None:
assert not evaluate("", lambda ident: False)
assert not evaluate("", lambda ident: True)
assert not evaluate(" ", lambda ident: False)
assert not evaluate("\t", lambda ident: False)
@pytest.mark.parametrize(
("expr", "expected"),
(
("true", True),
("true", True),
("false", False),
("not true", False),
("not false", True),
("not not true", True),
("not not false", False),
("true and true", True),
("true and false", False),
("false and true", False),
("true and true and true", True),
("true and true and false", False),
("true and true and not true", False),
("false or false", False),
("false or true", True),
("true or true", True),
("true or true or false", True),
("true and true or false", True),
("not true or true", True),
("(not true) or true", True),
("not (true or true)", False),
("true and true or false and false", True),
("true and (true or false) and false", False),
("true and (true or (not (not false))) and false", False),
),
)
def test_basic(expr: str, expected: bool) -> None:
matcher = {"true": True, "false": False}.__getitem__
assert evaluate(expr, matcher) is expected
@pytest.mark.parametrize(
("expr", "expected"),
(
(" true ", True),
(" ((((((true)))))) ", True),
(" ( ((\t (((true))))) \t \t)", True),
("( true and (((false))))", False),
("not not not not true", True),
("not not not not not true", False),
),
)
def test_syntax_oddeties(expr: str, expected: bool) -> None:
matcher = {"true": True, "false": False}.__getitem__
assert evaluate(expr, matcher) is expected
def test_backslash_not_treated_specially() -> None:
r"""When generating nodeids, if the source name contains special characters
like a newline, they are escaped into two characters like \n. Therefore, a
user will never need to insert a literal newline, only \n (two chars). So
mark expressions themselves do not support escaping, instead they treat
backslashes as regular identifier characters."""
matcher = {r"\nfoo\n"}.__contains__
assert evaluate(r"\nfoo\n", matcher)
assert not evaluate(r"foo", matcher)
with pytest.raises(ParseError):
evaluate("\nfoo\n", matcher)
@pytest.mark.parametrize(
("expr", "column", "message"),
(
("(", 2, "expected not OR left parenthesis OR identifier; got end of input"),
(
" (",
3,
"expected not OR left parenthesis OR identifier; got end of input",
),
(
")",
1,
"expected not OR left parenthesis OR identifier; got right parenthesis",
),
(
") ",
1,
"expected not OR left parenthesis OR identifier; got right parenthesis",
),
(
"not",
4,
"expected not OR left parenthesis OR identifier; got end of input",
),
(
"not not",
8,
"expected not OR left parenthesis OR identifier; got end of input",
),
(
"(not)",
5,
"expected not OR left parenthesis OR identifier; got right parenthesis",
),
("and", 1, "expected not OR left parenthesis OR identifier; got and"),
(
"ident and",
10,
"expected not OR left parenthesis OR identifier; got end of input",
),
(
"ident and or",
11,
"expected not OR left parenthesis OR identifier; got or",
),
("ident ident", 7, "expected end of input; got identifier"),
),
)
def test_syntax_errors(expr: str, column: int, message: str) -> None:
with pytest.raises(ParseError) as excinfo:
evaluate(expr, lambda ident: True)
assert excinfo.value.column == column
assert excinfo.value.message == message
@pytest.mark.parametrize(
"ident",
(
".",
"...",
":::",
"a:::c",
"a+-b",
r"\nhe\\l\lo\n\t\rbye",
"a/b",
"אבגד",
"aaאבגדcc",
"a[bcd]",
"1234",
"1234abcd",
"1234and",
"notandor",
"not_and_or",
"not[and]or",
"1234+5678",
"123.232",
"True",
"False",
"None",
"if",
"else",
"while",
),
)
def test_valid_idents(ident: str) -> None:
assert evaluate(ident, {ident: True}.__getitem__)
@pytest.mark.parametrize(
"ident",
(
"^",
"*",
"=",
"&",
"%",
"$",
"#",
"@",
"!",
"~",
"{",
"}",
'"',
"'",
"|",
";",
"",
),
)
def test_invalid_idents(ident: str) -> None:
with pytest.raises(ParseError):
evaluate(ident, lambda ident: True)