From 75735396a3acd642c04272a01284836baac2e562 Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 11 Apr 2024 12:31:07 -0400 Subject: [PATCH 01/11] truncate test for output checking --- testing/test_assertion.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index ef4e36644..2e099ec19 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -678,6 +678,13 @@ class TestAssert_reprcompare: assert expl is not None assert len(expl) > 1 + def test_dict_truncate(self) -> None: + dict1 = {"asdf": [1, 1, 1, 1, 1, 1, 1, 1]} + dict2 = {"asdf": [1, 1, 1, 1, 1, 1, 1, 2]} + expl = callequal(dict1, dict2) + print(expl) + assert False + def test_dict_omitting(self) -> None: lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}) assert lines is not None From 9f7770efe3b18450e9500b4c508e32e203c06d9a Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 25 Apr 2024 23:14:28 -0400 Subject: [PATCH 02/11] Emit warning when unregistered mark is used with -m --- src/_pytest/mark/expression.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 78b7fda69..b81361478 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -26,6 +26,7 @@ from typing import Mapping from typing import NoReturn from typing import Optional from typing import Sequence +from .structures import MARK_GEN __all__ = [ @@ -96,6 +97,7 @@ class Scanner: elif value == "not": yield Token(TokenType.NOT, value, pos) else: + MARK_GEN.verify_mark(value) yield Token(TokenType.IDENT, value, pos) pos += len(value) else: From 048abb60bfa112810e4a566639177d2666017e2e Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 25 Apr 2024 23:15:38 -0400 Subject: [PATCH 03/11] Add helper function to MarkGenerator to verify a mark is registered --- src/_pytest/mark/structures.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index a6503bf1d..c60cf6da3 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -520,11 +520,7 @@ class MarkGenerator: self._config: Optional[Config] = None self._markers: Set[str] = set() - def __getattr__(self, name: str) -> MarkDecorator: - """Generate a new :class:`MarkDecorator` with the given name.""" - if name[0] == "_": - raise AttributeError("Marker name must NOT start with underscore") - + def verify_mark(self, name: str) -> None: if self._config is not None: # We store a set of markers as a performance optimisation - if a mark # name is in the set we definitely know it, but a mark may be known and @@ -556,9 +552,16 @@ class MarkGenerator: "custom marks to avoid this warning - for details, see " "https://docs.pytest.org/en/stable/how-to/mark.html" % name, PytestUnknownMarkWarning, - 2, + 3, ) + def __getattr__(self, name: str) -> MarkDecorator: + """Generate a new :class:`MarkDecorator` with the given name.""" + if name[0] == "_": + raise AttributeError("Marker name must NOT start with underscore") + + self.verify_mark(name) + return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True) From 4c76999494c5114375928ed37c7376fb0625ce39 Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 25 Apr 2024 23:20:36 -0400 Subject: [PATCH 04/11] Adding self to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index d7148acfc..41982db59 100644 --- a/AUTHORS +++ b/AUTHORS @@ -267,6 +267,7 @@ Matt Bachmann Matt Duck Matt Williams Matthias Hafner +Max Berkowitz Maxim Filipenko Maximilian Cosmo Sitter mbyt From e42727d756197b63c0b726dc66a26672da1228d6 Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 25 Apr 2024 23:25:15 -0400 Subject: [PATCH 05/11] Add to changelog --- changelog/10514.improvement.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/10514.improvement.rst diff --git a/changelog/10514.improvement.rst b/changelog/10514.improvement.rst new file mode 100644 index 000000000..12430ba26 --- /dev/null +++ b/changelog/10514.improvement.rst @@ -0,0 +1 @@ +Emit a warning when unregistered marks are used with the command line option -m. From 8bf20497d05cfb633a8fc68ce2c8b5bb8ff7913a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:26:59 +0000 Subject: [PATCH 06/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/mark/expression.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index b81361478..93e784911 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -26,6 +26,7 @@ from typing import Mapping from typing import NoReturn from typing import Optional from typing import Sequence + from .structures import MARK_GEN From 917af40c60c5891cf9a31e6ad1de08249a3e726a Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Thu, 25 Apr 2024 23:55:37 -0400 Subject: [PATCH 07/11] Reverting changes accidentally included from other branch --- testing/test_assertion.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 2e099ec19..ef4e36644 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -678,13 +678,6 @@ class TestAssert_reprcompare: assert expl is not None assert len(expl) > 1 - def test_dict_truncate(self) -> None: - dict1 = {"asdf": [1, 1, 1, 1, 1, 1, 1, 1]} - dict2 = {"asdf": [1, 1, 1, 1, 1, 1, 1, 2]} - expl = callequal(dict1, dict2) - print(expl) - assert False - def test_dict_omitting(self) -> None: lines = callequal({"a": 0, "b": 1}, {"a": 1, "b": 1}) assert lines is not None From fbfb4ebf58f2203b06dba0d67207d8508fa20efa Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Fri, 26 Apr 2024 00:34:48 -0400 Subject: [PATCH 08/11] Make mark verification occur in expression compilation --- src/_pytest/mark/expression.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 93e784911..d9a241834 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -200,12 +200,19 @@ class Expression: self.code = code @classmethod - def compile(self, input: str) -> "Expression": + def compile(self, input: str, mark: bool = False) -> "Expression": """Compile a match expression. :param input: The input expression - one line. """ astexpr = expression(Scanner(input)) + + if mark: + for node in ast.walk(astexpr): + #if the node is an identifier, i.e. a mark name + if isinstance(node, ast.Name): + MARK_GEN.verify_mark(node.id[len(IDENT_PREFIX):]) + code: types.CodeType = compile( astexpr, filename="", From 58521efcaa30fc46f6c981c835688d36100928ce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 04:35:07 +0000 Subject: [PATCH 09/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/mark/expression.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index d9a241834..75056a483 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -206,13 +206,13 @@ class Expression: :param input: The input expression - one line. """ astexpr = expression(Scanner(input)) - + if mark: for node in ast.walk(astexpr): - #if the node is an identifier, i.e. a mark name - if isinstance(node, ast.Name): - MARK_GEN.verify_mark(node.id[len(IDENT_PREFIX):]) - + # if the node is an identifier, i.e. a mark name + if isinstance(node, ast.Name): + MARK_GEN.verify_mark(node.id[len(IDENT_PREFIX) :]) + code: types.CodeType = compile( astexpr, filename="", From 6c4c3036e5613b22482daba26512605207ec7228 Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Fri, 26 Apr 2024 00:36:30 -0400 Subject: [PATCH 10/11] Trigger command line expr to run compile with mark checks --- src/_pytest/mark/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 77dabd95d..6c4fd560d 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -236,7 +236,7 @@ def deselect_by_mark(items: "List[Item]", config: Config) -> None: if not matchexpr: return - expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'") + expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'", True) remaining: List[Item] = [] deselected: List[Item] = [] for item in items: @@ -249,9 +249,9 @@ def deselect_by_mark(items: "List[Item]", config: Config) -> None: items[:] = remaining -def _parse_expression(expr: str, exc_message: str) -> Expression: +def _parse_expression(expr: str, exc_message: str, mark: bool = False) -> Expression: try: - return Expression.compile(expr) + return Expression.compile(expr, mark) except ParseError as e: raise UsageError(f"{exc_message}: {expr}: {e}") from None From 54beed5df7b01a143949c475464d3b865fc80d71 Mon Sep 17 00:00:00 2001 From: Max Berkowitz Date: Fri, 26 Apr 2024 00:37:37 -0400 Subject: [PATCH 11/11] Remove errant check --- src/_pytest/mark/expression.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 75056a483..52ec2bca1 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -98,7 +98,6 @@ class Scanner: elif value == "not": yield Token(TokenType.NOT, value, pos) else: - MARK_GEN.verify_mark(value) yield Token(TokenType.IDENT, value, pos) pos += len(value) else: