(Translated by https://www.hiragana.jp/)
highlight_regex in rich.text.Text Now Expects a Compiled Regular Expression (re.compile) Has Been Passed by PyWoody · Pull Request #3347 · Textualize/rich · GitHub
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

highlight_regex in rich.text.Text Now Expects a Compiled Regular Expression (re.compile) Has Been Passed #3347

Merged
merged 9 commits into from
Sep 30, 2024

Conversation

PyWoody
Copy link
Contributor

@PyWoody PyWoody commented Apr 27, 2024

Type of changes

  • Bug fix
  • New feature
  • Documentation / docstrings
  • Tests
  • Other

Checklist

  • I've run the latest black with default args on new code.
  • I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate.
  • I've added tests for new code.
  • I accept that @willmcgugan may be pedantic in the code review.

Description

highlight_regex in rich.text.Text now expects the passed re_highlight to be a compiled regular expression. If a str is passed, as was the previous expectation, the str will be compiled as a regular expression and the method will continue on as before.

The proposed change is for a minor performance bump in the rich.highlighter.RegexHighlighter class. A user can now pass compiled regular expressions in the the list of highlights, which will be guaranteed to not re-compiled by Text. Previously, highlight_regex expected it was receiving a str so it compiled the regular expression every time.

There will be no breaking changes to the user as the user can continue to pass str in their respective RegexHighlighter.highlights. The only performance degradation will be caused by the isinstance(re_highlight, str) check, which will be minimal.

Below is a silly speed test (hopefully) showing the new highlight_regex as performing faster. I used 600 "words" for the regular expressions because Python's current re. actions use a shared internal cache of a maximum of 512[0] regular expressions and I wanted demonstrate how relying on that can cause slowdowns.

[0] https://github.com/python/cpython/blob/3.12/Lib/re/__init__.py#L277

import itertools
import re
import time

from rich.console import Console
from rich.highlighter import RegexHighlighter
from rich.theme import Theme


PHRASE = ' '.join(f'word{i}' for i in range(600))


class SillyCompiledHighlighter(RegexHighlighter):

    base_style = 'example.'
    highlights = [re.compile(rf'(?P<{i}>{i})') for i in PHRASE.split()]


class SillyStringHighlighter(RegexHighlighter):

    base_style = 'example.'
    highlights = [rf'(?P<{i}>{i})' for i in PHRASE.split()]


def run():
    colors = itertools.cycle(range(256))
    theme = Theme(
        {f'example.{v}': f'color({i})' for i, v in zip(colors, PHRASE.split())}
    )
    console = Console(
        highlighter=SillyCompiledHighlighter(), theme=theme, quiet=True
    )
    start = time.time()
    for _ in range(1_000):
        console.print(PHRASE)
    print('Compiled:', time.time() - start)
    console = Console(
        highlighter=SillyStringHighlighter(), theme=theme, quiet=True
    )
    start = time.time()
    for _ in range(1_000):
        console.print(PHRASE)
    print('String:', time.time() - start)


if __name__ == '__main__':
    run()

…t' is a compiled regular expression. If a str is passed, as was the previous assumption, the str will be compiled as a regular expression.
@willmcgugan
Copy link
Collaborator

Changelog and tests please.

@willmcgugan
Copy link
Collaborator

@PyWoody Are you still working on this?

@PyWoody
Copy link
Contributor Author

PyWoody commented Aug 26, 2024

Hi @willmcgugan , Sorry! This slipped through the cracks. Please find the updated CHANGELOG and requisite tests in the branch now. Please let me know if there is anything else you need done or modified and I'd be glad to do it.

@PyWoody
Copy link
Contributor Author

PyWoody commented Aug 26, 2024

Sorry, in haste I pushed from a location that didn't have the pre-commit hooks installed. I've installed the hooks, updated the test file according to black, and have pushed a new commit. The pre-commit hooks passed on my local. Sorry about that.

rich/text.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@willmcgugan willmcgugan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@willmcgugan willmcgugan merged commit 7008364 into Textualize:master Sep 30, 2024
2 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants