From d42911948c6eb08e4dd23f112ec9ac2e7002697a Mon Sep 17 00:00:00 2001 From: "Samuel J. Woodward" Date: Sat, 27 Apr 2024 13:51:52 -0400 Subject: [PATCH 1/7] highlight_regex in rich.text.Text now assumes the passed 're_highlight' is a compiled regular expression. If a str is passed, as was the previous assumption, the str will be compiled as a regular expression. --- rich/text.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rich/text.py b/rich/text.py index 7b32967f7..b64205c07 100644 --- a/rich/text.py +++ b/rich/text.py @@ -591,7 +591,7 @@ def extend_style(self, spaces: int) -> None: def highlight_regex( self, - re_highlight: str, + re_highlight: Union[re.Pattern, str], style: Optional[Union[GetStyleCallable, StyleType]] = None, *, style_prefix: str = "", @@ -600,7 +600,7 @@ def highlight_regex( translated to styles. Args: - re_highlight (str): A regular expression. + re_highlight (Union[re.Pattern, str]): A regular expression. style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable which accepts the matched text and returns a style. Defaults to None. style_prefix (str, optional): Optional prefix to add to style group names. @@ -612,7 +612,9 @@ def highlight_regex( append_span = self._spans.append _Span = Span plain = self.plain - for match in re.finditer(re_highlight, plain): + if isinstance(re_highlight, str): + re_highlight = re.compile(re_highlight) + for match in re_highlight.finditer(plain): get_span = match.span if style: start, end = get_span() From c1d3fca7e290436ad25b8ce0f4507fd101c5efb2 Mon Sep 17 00:00:00 2001 From: "Samuel J. Woodward" Date: Sat, 27 Apr 2024 14:03:30 -0400 Subject: [PATCH 2/7] Adding named to CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 22b1be0db..72825f899 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -76,3 +76,4 @@ The following people have contributed to the development of Rich: - [Pierro](https://github.com/xpierroz) - [Bernhard Wagner](https://github.com/bwagner) - [Aaron Beaudoin](https://github.com/AaronBeaudoin) +- [Sam Woodward](https://github.com/PyWoody) From 794b6c4241d10465eb852bef232396e9abe5ab64 Mon Sep 17 00:00:00 2001 From: "Samuel J. Woodward" Date: Mon, 26 Aug 2024 10:02:37 -0400 Subject: [PATCH 3/7] Use of Text.highlight_regex now tests against receiving a str or a compiled regular expression --- tests/test_text.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/test_text.py b/tests/test_text.py index 18c91cffa..c06ba482b 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -1,3 +1,5 @@ +import re + from io import StringIO from typing import List @@ -159,6 +161,7 @@ def test_stylize_negative_index(): def test_highlight_regex(): + # As a string text = Text("peek-a-boo") count = text.highlight_regex(r"NEVER_MATCH", "red") @@ -176,6 +179,7 @@ def test_highlight_regex(): ] text = Text("Ada Lovelace, Alan Turing") + count = text.highlight_regex( r"(?P[A-Za-z]+)[ ]+(?P[A-Za-z]+)(?PNEVER_MATCH)*" ) @@ -189,16 +193,51 @@ def test_highlight_regex(): Span(19, 25, "red"), # Turing ] + # As a regular expression object + text = Text("peek-a-boo") + + count = text.highlight_regex(re.compile(r"NEVER_MATCH"), "red") + assert count == 0 + assert len(text._spans) == 0 + + # text: peek-a-boo + # indx: 0123456789 + count = text.highlight_regex(re.compile(r"[a|e|o]+"), "red") + assert count == 3 + assert sorted(text._spans) == [ + Span(1, 3, "red"), + Span(5, 6, "red"), + Span(8, 10, "red"), + ] + + text = Text("Ada Lovelace, Alan Turing") + + count = text.highlight_regex( + re.compile(r"(?P[A-Za-z]+)[ ]+(?P[A-Za-z]+)(?PNEVER_MATCH)*") + ) + + # The number of matched name should be 2 + assert count == 2 + assert sorted(text._spans) == [ + Span(0, 3, "yellow"), # Ada + Span(4, 12, "red"), # Lovelace + Span(14, 18, "yellow"), # Alan + Span(19, 25, "red"), # Turing + ] + + def test_highlight_regex_callable(): text = Text("Vulnerability CVE-2018-6543 detected") re_cve = r"CVE-\d{4}-\d+" + compiled_re_cve = re.compile(r"CVE-\d{4}-\d+") def get_style(text: str) -> Style: return Style.parse( f"bold yellow link https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword={text}" ) + # string count = text.highlight_regex(re_cve, get_style) assert count == 1 assert len(text._spans) == 1 @@ -209,6 +248,20 @@ def get_style(text: str) -> Style: == "https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=CVE-2018-6543" ) + # Clear the tracked _spans for the regular expression object's use + text._spans.clear() + + # regular expression object + count = text.highlight_regex(compiled_re_cve, get_style) + assert count == 1 + assert len(text._spans) == 1 + assert text._spans[0].start == 14 + assert text._spans[0].end == 27 + assert ( + text._spans[0].style.link + == "https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=CVE-2018-6543" + ) + def test_highlight_words(): text = Text("Do NOT! touch anything!") From 4929ee49c331b3d3694ccaeb279a1e5daa78cb7d Mon Sep 17 00:00:00 2001 From: "Samuel J. Woodward" Date: Mon, 26 Aug 2024 10:18:15 -0400 Subject: [PATCH 4/7] highlight_regex change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f9a8329d..332423136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Running tests in environment with `FORCE_COLOR` or `NO_COLOR` environment variables - ansi decoder will now strip problematic private escape sequences (like `\x1b7`) https://github.com/Textualize/rich/pull/3278/ - Tree's ASCII_GUIDES and TREE_GUIDES constants promoted to class attributes +- `rich.Text.highlight_regex` now expects a regular expression object https://github.com/Textualize/rich/pull/3347 ### Added From 65fcf281283244b8ee4ded75a4b60c7eb316da6e Mon Sep 17 00:00:00 2001 From: "Samuel J. Woodward" Date: Mon, 26 Aug 2024 16:40:22 -0400 Subject: [PATCH 5/7] Tweaks required by black --- tests/test_text.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_text.py b/tests/test_text.py index c06ba482b..e1bd438b7 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -1,5 +1,4 @@ import re - from io import StringIO from typing import List @@ -213,7 +212,9 @@ def test_highlight_regex(): text = Text("Ada Lovelace, Alan Turing") count = text.highlight_regex( - re.compile(r"(?P[A-Za-z]+)[ ]+(?P[A-Za-z]+)(?PNEVER_MATCH)*") + re.compile( + r"(?P[A-Za-z]+)[ ]+(?P[A-Za-z]+)(?PNEVER_MATCH)*" + ) ) # The number of matched name should be 2 @@ -226,7 +227,6 @@ def test_highlight_regex(): ] - def test_highlight_regex_callable(): text = Text("Vulnerability CVE-2018-6543 detected") re_cve = r"CVE-\d{4}-\d+" From e933d3cb79a97cb9bc17f611cdbcc8cc5a5bcf68 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 30 Sep 2024 15:38:07 +0100 Subject: [PATCH 6/7] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 332423136..e716dc611 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Running tests in environment with `FORCE_COLOR` or `NO_COLOR` environment variables - ansi decoder will now strip problematic private escape sequences (like `\x1b7`) https://github.com/Textualize/rich/pull/3278/ - Tree's ASCII_GUIDES and TREE_GUIDES constants promoted to class attributes -- `rich.Text.highlight_regex` now expects a regular expression object https://github.com/Textualize/rich/pull/3347 +- `rich.Text.highlight_regex` now accepts a regular expression object https://github.com/Textualize/rich/pull/3347 ### Added From 03e574bedcd4fd142076fd4d064914fb0309bab0 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 30 Sep 2024 15:38:58 +0100 Subject: [PATCH 7/7] Update rich/text.py --- rich/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rich/text.py b/rich/text.py index b64205c07..1643a0921 100644 --- a/rich/text.py +++ b/rich/text.py @@ -600,7 +600,7 @@ def highlight_regex( translated to styles. Args: - re_highlight (Union[re.Pattern, str]): A regular expression. + re_highlight (Union[re.Pattern, str]): A regular expression object or string. style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable which accepts the matched text and returns a style. Defaults to None. style_prefix (str, optional): Optional prefix to add to style group names.