|
22 | 22 | ## ---------------------------------------------------------------------
|
23 | 23 | import warnings
|
24 | 24 | import numpy as np
|
| 25 | +import inspect |
25 | 26 | from functools import wraps
|
26 | 27 | from pkg_resources import parse_version
|
27 | 28 |
|
@@ -58,8 +59,26 @@ def cached_member_function(function):
|
58 | 59 | """
|
59 | 60 | fname = function.__name__
|
60 | 61 |
|
| 62 | + # get the function signature and ensure that we don't have any |
| 63 | + # keyword only arguments: |
| 64 | + # func(..., *, kwarg=None, ...) or func(..., **kwargs). |
| 65 | + # If we want to support them we need to add them in a well defined |
| 66 | + # order to the cache key (sort them by name) |
| 67 | + func_signature = inspect.signature(function) |
| 68 | + bad_arg_types = (inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.VAR_KEYWORD) |
| 69 | + if any(arg.kind in bad_arg_types for arg in func_signature.parameters.values()): |
| 70 | + raise ValueError("Member functions with keyword only arguments can not be " |
| 71 | + "wrapped with the cached_member_function.") |
| 72 | + |
61 | 73 | @wraps(function)
|
62 |
| - def wrapper(self, *args): |
| 74 | + def wrapper(self, *args, **kwargs): |
| 75 | + # convert all arguments to poisitonal arguments and add default arguments |
| 76 | + # for not provided arguments |
| 77 | + bound_args = func_signature.bind(self, *args, **kwargs) |
| 78 | + bound_args.apply_defaults() |
| 79 | + assert not bound_args.kwargs |
| 80 | + args = bound_args.args[1:] # remove self from args |
| 81 | + |
63 | 82 | try:
|
64 | 83 | fun_cache = self._function_cache[fname]
|
65 | 84 | except AttributeError:
|
|
0 commit comments