33import io
44import json
55import logging
6+ from collections .abc import Callable
67from dataclasses import dataclass
7- from functools import cache , cached_property
8+ from functools import cached_property , lru_cache , wraps
9+ from inspect import signature
810from itertools import combinations as combi
911from typing import TYPE_CHECKING , Any , NamedTuple
1012from 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+
6187class 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 :
0 commit comments