Skip to content

Commit 53f5e08

Browse files
committed
Add bounds to cache and clean key before caching
1 parent c13015b commit 53f5e08

2 files changed

Lines changed: 33 additions & 8 deletions

File tree

src/ert/gui/plotting/plot_api.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import io
44
import json
55
import logging
6+
from collections.abc import Callable
67
from dataclasses import dataclass
7-
from functools import cache, cached_property
8+
from functools import cached_property, lru_cache, wraps
9+
from inspect import signature
810
from itertools import combinations as combi
911
from typing import TYPE_CHECKING, Any, NamedTuple
1012
from urllib.parse import quote
@@ -58,6 +60,30 @@ class PlotApiKeyDefinition(NamedTuple):
5860
response: ResponseConfig | None = None
5961

6062

63+
def clear_suffix[**P, R](
64+
key: str,
65+
split: str
66+
) -> Callable[[Callable[P, R]], Callable[P, R]]:
67+
"""Return a decorator that strips a trailing ``@<suffix>`` from the
68+
argument named ``key`` before calling the wrapped function.
69+
"""
70+
71+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
72+
sig = signature(func)
73+
74+
@wraps(func)
75+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
76+
bound = sig.bind(*args, **kwargs)
77+
value = bound.arguments.get(key)
78+
if isinstance(value, str) and "@" in value:
79+
bound.arguments[key] = value.split(split, maxsplit=1)[0]
80+
return func(*bound.args, **bound.kwargs)
81+
82+
return wrapper
83+
84+
return decorator
85+
86+
6187
class PlotApi:
6288
def __init__(self, ens_path: Path) -> None:
6389
self.ens_path: Path = ens_path
@@ -344,10 +370,9 @@ def data_for_response(
344370
return df
345371

346372
@staticmethod
347-
@cache
373+
@lru_cache(maxsize=64)
374+
@clear_suffix(key="key", split="@")
348375
def data_for_gradient(ensemble_id: str, key: str, ens_path: Path) -> pd.DataFrame:
349-
if "@" in key:
350-
key = key.split("@", maxsplit=1)[0]
351376
with create_ertserver_client(ens_path) as client:
352377
http_response = client.get(
353378
f"/ensembles/{ensemble_id}/gradients/{PlotApi.escape(key)}",
@@ -371,7 +396,7 @@ def data_for_gradient(ensemble_id: str, key: str, ens_path: Path) -> pd.DataFram
371396
)
372397

373398
@staticmethod
374-
@cache
399+
@lru_cache(maxsize=32)
375400
def data_for_controls(
376401
ensemble_id: str, parameter_keys: tuple[str, ...], ens_path: Path
377402
) -> pd.DataFrame:
@@ -395,7 +420,7 @@ def data_for_controls(
395420
return pd.concat(frames, ignore_index=True)
396421

397422
@staticmethod
398-
@cache
423+
@lru_cache(maxsize=64)
399424
def data_for_parameter(
400425
ensemble_id: str, parameter_key: str, ens_path: Path
401426
) -> pd.DataFrame:

tests/ert/unit_tests/gui/tools/plot/test_plot_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,9 +694,9 @@ def test_that_data_for_gradient_is_fetched_once_for_repeated_calls(api_and_stora
694694
PlotApi.data_for_gradient.cache_clear()
695695

696696
for _ in range(5):
697-
_ = PlotApi.data_for_gradient(str(ensemble.id), objective_key, ens_path)
697+
_ = PlotApi.data_for_gradient(str(ensemble.id), objective_key + "@filler", ens_path)
698698

699699
# hits, misses, maxsize, currsize
700-
expected_cache_info = (4, 1, None, 1)
700+
expected_cache_info = (4, 1, 64, 1)
701701

702702
assert PlotApi.data_for_gradient.cache_info() == expected_cache_info

0 commit comments

Comments
 (0)