|
4 | 4 | """ |
5 | 5 |
|
6 | 6 | # Import statements |
| 7 | +import functools |
7 | 8 | import inspect |
8 | 9 | from importlib import import_module |
9 | 10 | from numbers import Integral, Real |
@@ -155,6 +156,40 @@ def _get_rc_matplotlib(): |
155 | 156 | }, |
156 | 157 | } |
157 | 158 |
|
| 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 | + |
158 | 193 | _LAZY_ATTRS = { |
159 | 194 | "benchmarks": ("benchmarks", None), |
160 | 195 | "context": ("context", None), |
@@ -224,28 +259,19 @@ def _pop_params(kwargs, *funcs, ignore_internal=False): |
224 | 259 | """ |
225 | 260 | Pop parameters of the input functions or methods. |
226 | 261 | """ |
227 | | - internal_params = { |
228 | | - "default_cmap", |
229 | | - "default_discrete", |
230 | | - "inbounds", |
231 | | - "plot_contours", |
232 | | - "plot_lines", |
233 | | - "skip_autolev", |
234 | | - "to_centers", |
235 | | - } |
236 | 262 | output = {} |
237 | 263 | for func in funcs: |
238 | 264 | if isinstance(func, inspect.Signature): |
239 | 265 | sig = func |
240 | 266 | elif callable(func): |
241 | | - sig = inspect.signature(func) |
| 267 | + sig = _get_signature(func) |
242 | 268 | elif func is None: |
243 | 269 | continue |
244 | 270 | else: |
245 | 271 | raise RuntimeError(f"Internal error. Invalid function {func!r}.") |
246 | 272 | for key in sig.parameters: |
247 | 273 | value = kwargs.pop(key, None) |
248 | | - if ignore_internal and key in internal_params: |
| 274 | + if ignore_internal and key in _INTERNAL_POP_PARAMS: |
249 | 275 | continue |
250 | 276 | if value is not None: |
251 | 277 | output[key] = value |
|
0 commit comments