From 89da8d808e45b96c590480e9569a5cb8fa050ac8 Mon Sep 17 00:00:00 2001 From: Marcel Wilson Date: Tue, 19 Mar 2024 17:31:11 -0500 Subject: [PATCH] allowing Matches to accept `re.compile` --- screenpy/resolutions/matches.py | 22 ++++++++++++++++++---- tests/test_resolutions.py | 27 ++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/screenpy/resolutions/matches.py b/screenpy/resolutions/matches.py index fccf917..74c8e5f 100644 --- a/screenpy/resolutions/matches.py +++ b/screenpy/resolutions/matches.py @@ -1,10 +1,17 @@ """Matches a string using a regex pattern.""" +from __future__ import annotations + +from re import Pattern +from typing import TYPE_CHECKING + from hamcrest import matches_regexp -from hamcrest.core.matcher import Matcher from screenpy.pacing import beat +if TYPE_CHECKING: # pragma: no cover + from hamcrest.core.matcher import Matcher + class Matches: """Match a string using a regular expression. @@ -17,14 +24,21 @@ class Matches: ) """ + @property + def item_to_log(self) -> str: + """Represent the item in a log-friendly way.""" + if isinstance(self.pattern, Pattern): + return f"r'{self.pattern.pattern}'" + return f"r'{self.pattern}'" + def describe(self) -> str: """Describe the Resolution's expectation.""" - return f'Text matching the pattern r"{self.pattern}".' + return f"Text matching the pattern {self.item_to_log}." - @beat('... hoping it\'s text matching the pattern r"{pattern}".') + @beat("... hoping it's text matching the pattern {item_to_log}.") def resolve(self) -> Matcher[str]: """Produce the Matcher to make the assertion.""" return matches_regexp(self.pattern) - def __init__(self, pattern: str) -> None: + def __init__(self, pattern: str | Pattern[str]) -> None: self.pattern = pattern diff --git a/tests/test_resolutions.py b/tests/test_resolutions.py index e0c88b4..4e861da 100644 --- a/tests/test_resolutions.py +++ b/tests/test_resolutions.py @@ -1,5 +1,7 @@ from __future__ import annotations +import logging +import re from itertools import chain from unittest import mock @@ -570,12 +572,35 @@ def test_the_test(self) -> None: assert m.matches("Spam spam spam spam baked beans and spam") assert not m.matches("What do you mean Eugh?!") + def test_the_test_with_compile(self) -> None: + m = Matches(re.compile(r"([Ss]pam ?)+")).resolve() + + assert m.matches("Spam spam spam spam baked beans and spam") + assert not m.matches("What do you mean Eugh?!") + def test_description(self) -> None: test_match = r"(spam)+" m = Matches(test_match) - expected_description = 'Text matching the pattern r"(spam)+".' + expected_description = "Text matching the pattern r'(spam)+'." + assert m.describe() == expected_description + + def test_beat_logging(self, caplog: pytest.LogCaptureFixture) -> None: + caplog.set_level(logging.INFO) + Matches(r"pattern").resolve() + + assert [r.msg for r in caplog.records] == [ + "... hoping it's text matching the pattern r'pattern'.", + " => a string matching 'pattern'", + ] + + def test_description_with_compile(self) -> None: + test_match = re.compile(r"(spam)+") + + m = Matches(test_match) + + expected_description = "Text matching the pattern r'(spam)+'." assert m.describe() == expected_description