From 9196f8d545d1118f1233c1b45e7b740cb95c370c Mon Sep 17 00:00:00 2001 From: Marco Edward Gorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Sat, 19 Nov 2022 09:36:58 +0000 Subject: [PATCH] Backport PR STYLE enable pylint: method-cache-max-size-none (#49784) Co-authored-by: Natalia Mokeeva <91160475+natmokval@users.noreply.github.com> --- doc/source/whatsnew/v1.5.2.rst | 2 +- pandas/io/formats/excel.py | 10 +++++++++- pandas/tests/io/formats/test_to_excel.py | 10 +++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v1.5.2.rst b/doc/source/whatsnew/v1.5.2.rst index c1fde3d13ef74..64f57986cc3e4 100644 --- a/doc/source/whatsnew/v1.5.2.rst +++ b/doc/source/whatsnew/v1.5.2.rst @@ -28,7 +28,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ - Bug in the Copy-on-Write implementation losing track of views in certain chained indexing cases (:issue:`48996`) -- +- Fixed memory leak in :meth:`.Styler.to_excel` (:issue:`49751`) .. --------------------------------------------------------------------------- .. _whatsnew_152.other: diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index ce7f663dd5703..19b766fd70675 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -170,10 +170,13 @@ def __init__(self, inherited: str | None = None) -> None: self.inherited = self.compute_css(inherited) else: self.inherited = None + # We should avoid lru_cache on the __call__ method. + # Otherwise once the method __call__ has been called + # garbage collection no longer deletes the instance. + self._call_cached = lru_cache(maxsize=None)(self._call_uncached) compute_css = CSSResolver() - @lru_cache(maxsize=None) def __call__( self, declarations: str | frozenset[tuple[str, str]] ) -> dict[str, dict[str, str]]: @@ -193,6 +196,11 @@ def __call__( A style as interpreted by ExcelWriter when found in ExcelCell.style. """ + return self._call_cached(declarations) + + def _call_uncached( + self, declarations: str | frozenset[tuple[str, str]] + ) -> dict[str, dict[str, str]]: properties = self.compute_css(declarations, self.inherited) return self.build_xlstyle(properties) diff --git a/pandas/tests/io/formats/test_to_excel.py b/pandas/tests/io/formats/test_to_excel.py index 7481baaee94f6..2a0f9f59972ef 100644 --- a/pandas/tests/io/formats/test_to_excel.py +++ b/pandas/tests/io/formats/test_to_excel.py @@ -357,7 +357,7 @@ def test_css_excel_cell_precedence(styles, expected): """It applies favors latter declarations over former declarations""" # See GH 47371 converter = CSSToExcelConverter() - converter.__call__.cache_clear() + converter._call_cached.cache_clear() css_styles = {(0, 0): styles} cell = CssExcelCell( row=0, @@ -369,7 +369,7 @@ def test_css_excel_cell_precedence(styles, expected): css_col=0, css_converter=converter, ) - converter.__call__.cache_clear() + converter._call_cached.cache_clear() assert cell.style == converter(expected) @@ -410,7 +410,7 @@ def test_css_excel_cell_cache(styles, cache_hits, cache_misses): """It caches unique cell styles""" # See GH 47371 converter = CSSToExcelConverter() - converter.__call__.cache_clear() + converter._call_cached.cache_clear() css_styles = {(0, i): _style for i, _style in enumerate(styles)} for css_row, css_col in css_styles: @@ -424,8 +424,8 @@ def test_css_excel_cell_cache(styles, cache_hits, cache_misses): css_col=css_col, css_converter=converter, ) - cache_info = converter.__call__.cache_info() - converter.__call__.cache_clear() + cache_info = converter._call_cached.cache_info() + converter._call_cached.cache_clear() assert cache_info.hits == cache_hits assert cache_info.misses == cache_misses