Skip to content

Commit 6ab0bef

Browse files
authored
Internal: cache inspect.signature used by pop_params (#596)
cache inspect signature on a hot function
1 parent 153df0d commit 6ab0bef

1 file changed

Lines changed: 37 additions & 11 deletions

File tree

ultraplot/internals/__init__.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"""
55

66
# Import statements
7+
import functools
78
import inspect
89
from importlib import import_module
910
from numbers import Integral, Real
@@ -155,6 +156,40 @@ def _get_rc_matplotlib():
155156
},
156157
}
157158

159+
160+
_INTERNAL_POP_PARAMS = frozenset(
161+
{
162+
"default_cmap",
163+
"default_discrete",
164+
"inbounds",
165+
"plot_contours",
166+
"plot_lines",
167+
"skip_autolev",
168+
"to_centers",
169+
}
170+
)
171+
172+
173+
@functools.lru_cache(maxsize=256)
174+
def _signature_cached(func):
175+
"""
176+
Cache inspect.signature lookups for hot utility paths.
177+
"""
178+
return inspect.signature(func)
179+
180+
181+
def _get_signature(func):
182+
"""
183+
Return a signature, normalizing bound methods to their underlying function.
184+
"""
185+
key = getattr(func, "__func__", func)
186+
try:
187+
return _signature_cached(key)
188+
except TypeError:
189+
# Some callable objects may be unhashable for lru_cache keys.
190+
return inspect.signature(func)
191+
192+
158193
_LAZY_ATTRS = {
159194
"benchmarks": ("benchmarks", None),
160195
"context": ("context", None),
@@ -224,28 +259,19 @@ def _pop_params(kwargs, *funcs, ignore_internal=False):
224259
"""
225260
Pop parameters of the input functions or methods.
226261
"""
227-
internal_params = {
228-
"default_cmap",
229-
"default_discrete",
230-
"inbounds",
231-
"plot_contours",
232-
"plot_lines",
233-
"skip_autolev",
234-
"to_centers",
235-
}
236262
output = {}
237263
for func in funcs:
238264
if isinstance(func, inspect.Signature):
239265
sig = func
240266
elif callable(func):
241-
sig = inspect.signature(func)
267+
sig = _get_signature(func)
242268
elif func is None:
243269
continue
244270
else:
245271
raise RuntimeError(f"Internal error. Invalid function {func!r}.")
246272
for key in sig.parameters:
247273
value = kwargs.pop(key, None)
248-
if ignore_internal and key in internal_params:
274+
if ignore_internal and key in _INTERNAL_POP_PARAMS:
249275
continue
250276
if value is not None:
251277
output[key] = value

0 commit comments

Comments
 (0)