44
55# %% auto #0
66__all__ = ['test_sig' , 'FixSigMeta' , 'PrePostInitMeta' , 'AutoInit' , 'NewChkMeta' , 'BypassNewMeta' , 'empty2none' , 'anno_dict' ,
7- 'use_kwargs_dict' , 'use_kwargs' , 'delegates' , 'method' , 'funcs_kwargs' , 'splice_sig' ]
7+ 'use_kwargs_dict' , 'use_kwargs' , 'delegates' , 'method' , 'delegated' , ' funcs_kwargs' , 'splice_sig' ]
88
99# %% ../nbs/05_meta.ipynb #d26e95dd
1010from .imports import *
@@ -111,24 +111,44 @@ def _f(f):
111111 return f
112112 return _f
113113
114- # %% ../nbs/05_meta.ipynb #11583391
115- def delegates (to :FunctionType = None , # Delegatee
116- keep = False , # Keep `kwargs` in decorated function?
117- but :list = None , # Exclude these parameters from signature
118- sort_args = False ): # Sort arguments alphabetically, doesn't work with call_parse
114+ # %% ../nbs/05_meta.ipynb #90afe67f
115+ def _del_funcs (
116+ to , # Delegatee function/class/None
117+ f # Decorated function/class
118+ )-> tuple : # (to_f, from_f) resolved underlying functions
119+ "Resolve delegate source and target functions, unwrapping bound methods"
120+ if to is None : to_f ,from_f = f .__base__ .__init__ ,f .__init__
121+ else : to_f ,from_f = to .__init__ if isinstance (to ,type ) else to ,f
122+ return getattr (to_f ,'__func__' ,to_f ), getattr (from_f ,'__func__' ,from_f )
123+
124+ # %% ../nbs/05_meta.ipynb #7341bbbc
125+ def _del_params (
126+ to_f , # Delegatee function
127+ sig , # Signature of decorated function
128+ but :list = None , # Params to exclude
129+ sort_args = False # Sort params alphabetically?
130+ ):
131+ "Get keyword-only params from `to_f` not already in `sig`, excluding `but`"
132+ s2 = {k :v .replace (kind = Parameter .KEYWORD_ONLY ) for k ,v in inspect .signature (to_f ).parameters .items ()
133+ if v .default != Parameter .empty and k not in sig .parameters and k not in listify (but )}
134+ if sort_args : s2 = dict (sorted (s2 .items ()))
135+ return s2
136+
137+ # %% ../nbs/05_meta.ipynb #a621d150
138+ def delegates (
139+ to :FunctionType = None , # Delegatee
140+ keep = False , # Keep `kwargs` in decorated function?
141+ but :list = None , # Exclude these parameters from signature
142+ sort_args = False # Sort arguments alphabetically, doesn't work with call_parse
143+ ):
119144 "Decorator: replace `**kwargs` in signature with params from `to`"
120- if but is None : but = []
121145 def _f (f ):
122- if to is None : to_f ,from_f = f .__base__ .__init__ ,f .__init__
123- else : to_f ,from_f = to .__init__ if isinstance (to ,type ) else to ,f
124- from_f = getattr (from_f ,'__func__' ,from_f )
125- to_f = getattr (to_f ,'__func__' ,to_f )
146+ to_f ,from_f = _del_funcs (to , f )
126147 if hasattr (from_f ,'__delwrap__' ): return f
127148 sig = inspect .signature (from_f )
128- s2 = {k :v .replace (kind = inspect .Parameter .KEYWORD_ONLY ) for k ,v in inspect .signature (to_f ).parameters .items ()
129- if v .default != inspect .Parameter .empty and k not in sig .parameters and k not in but }
130- if sort_args : s2 = dict (sorted (s2 .items ()))
131- anno = {k :v for k ,v in getattr (to_f , "__annotations__" , {}).items () if k not in sig .parameters and k not in but }
149+ s2 = _del_params (to_f , sig , but , sort_args )
150+ anno = {k :v for k ,v in getattr (to_f , "__annotations__" , {}).items ()
151+ if k not in sig .parameters and k not in listify (but )}
132152 from_f .__signature__ = sig_with_params (sig , remove = None if keep else 'kwargs' , keep = 'kwargs' if keep else None , ** s2 )
133153 if not keep : from_f .__delwrap__ = to_f
134154 if hasattr (from_f , '__annotations__' ): from_f .__annotations__ .update (anno )
@@ -141,6 +161,27 @@ def method(f):
141161 # `1` is a dummy instance since Py3 doesn't allow `None` any more
142162 return MethodType (f , 1 )
143163
164+ # %% ../nbs/05_meta.ipynb #3aad059d
165+ def delegated (
166+ to :FunctionType = None , # Delegatee
167+ keep = False , # Keep `kwargs` in decorated function?
168+ but :list = None , # Exclude these parameters from signature
169+ sort_args = False # Sort arguments alphabetically, doesn't work with call_parse
170+ ):
171+ "Like `delegates` but also populates delegated default kwargs at call time"
172+ def _f (f ):
173+ to_f ,from_f = _del_funcs (to , f )
174+ dp = _del_params (to_f , inspect .signature (from_f ), but , sort_args )
175+ f = delegates (to , keep = keep , but = but , sort_args = sort_args )(f )
176+ dflts = {k :v .default for k ,v in dp .items ()}
177+ @wraps (f )
178+ def _inner (* args , ** kwargs ):
179+ for k ,v in dflts .items ():
180+ if k not in kwargs : kwargs [k ] = v
181+ return f (* args , ** kwargs )
182+ return _inner
183+ return _f
184+
144185# %% ../nbs/05_meta.ipynb #0d934a51
145186def _funcs_kwargs (cls , as_method ):
146187 old_init = cls .__init__
0 commit comments