1from inspect import signature, Parameter 2from functools import wraps 3import warnings 4 5 6# This function was adapted from scikit-learn 7# github.com/scikit-learn/scikit-learn/blob/master/sklearn/utils/validation.py 8def _deprecate_positional_args(f): 9 """Decorator for methods that issues warnings for positional arguments. 10 11 Using the keyword-only argument syntax in pep 3102, arguments after the 12 * will issue a warning when passed as a positional argument. 13 14 Parameters 15 ---------- 16 f : function 17 function to check arguments on 18 19 """ 20 sig = signature(f) 21 kwonly_args = [] 22 all_args = [] 23 24 for name, param in sig.parameters.items(): 25 if param.kind == Parameter.POSITIONAL_OR_KEYWORD: 26 all_args.append(name) 27 elif param.kind == Parameter.KEYWORD_ONLY: 28 kwonly_args.append(name) 29 30 @wraps(f) 31 def inner_f(*args, **kwargs): 32 extra_args = len(args) - len(all_args) 33 if extra_args > 0: 34 plural = "s" if extra_args > 1 else "" 35 article = "" if plural else "a " 36 warnings.warn( 37 "Pass the following variable{} as {}keyword arg{}: {}. " 38 "From version 0.12, the only valid positional argument " 39 "will be `data`, and passing other arguments without an " 40 "explicit keyword will result in an error or misinterpretation." 41 .format(plural, article, plural, 42 ", ".join(kwonly_args[:extra_args])), 43 FutureWarning 44 ) 45 kwargs.update({k: arg for k, arg in zip(sig.parameters, args)}) 46 return f(**kwargs) 47 return inner_f 48 49 50def share_init_params_with_map(cls): 51 """Make cls.map a classmethod with same signature as cls.__init__.""" 52 map_sig = signature(cls.map) 53 init_sig = signature(cls.__init__) 54 55 new = [v for k, v in init_sig.parameters.items() if k != "self"] 56 new.insert(0, map_sig.parameters["cls"]) 57 cls.map.__signature__ = map_sig.replace(parameters=new) 58 cls.map.__doc__ = cls.__init__.__doc__ 59 60 cls.map = classmethod(cls.map) 61 62 return cls 63