From 7fbcc6d7c7f8ed28770e20a01d63aa98af9bdc00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Gir=C3=A3o=20Serr=C3=A3o?= <5621605+rodrigogiraoserrao@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:26:57 +0100 Subject: [PATCH] Conditionally bypass cache when adding styles. Working on https://github.com/Textualize/textual/issues/1587 surfaced a caching issue that is best shown by running the code below: ```py from rich.style import Style meta = {"click": "something"} s1 = Style.from_meta(meta) s2 = Style.from_meta(meta) print(s1.link_id, s2.link_id) # Different link_id. base = Style(color="red") print((base + s1).link_id) # This is the link_id of s1. print((base + s2).link_id) # This is the link_id of s1! ``` The change presented here will bypass cache when adding styles that have a link id but don't have a link attribute (if they did, so would the combined style and the call to .copy would refresh the link id either way). Simply refreshing the link id will break Textual link highlighting. --- rich/style.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/rich/style.py b/rich/style.py index 313c88949..27924907d 100644 --- a/rich/style.py +++ b/rich/style.py @@ -729,8 +729,7 @@ def test(self, text: Optional[str] = None) -> None: text = text or str(self) sys.stdout.write(f"{self.render(text)}\n") - @lru_cache(maxsize=1024) - def _add(self, style: Optional["Style"]) -> "Style": + def _add_no_cache(self, style: Optional["Style"]) -> "Style": if style is None or style._null: return self if self._null: @@ -754,8 +753,20 @@ def _add(self, style: Optional["Style"]) -> "Style": new_style._hash = None return new_style + @lru_cache(maxsize=1024) + def _add(self, style: Optional["Style"]) -> "Style": + return self._add_no_cache(style) + def __add__(self, style: Optional["Style"]) -> "Style": - combined_style = self._add(style) + if ( + style is not None + and not style._link + and not self._link + and (self._link_id or style._link_id) + ): + combined_style = self._add_no_cache(style) + else: + combined_style = self._add(style) return combined_style.copy() if combined_style.link else combined_style