@@ -151,14 +151,18 @@ def change_function( function, **kwds ):
151151
152152
153153 """
154- # Enumerate all the __code__ attributes in the same order; types.CodeTypes
155- # doesn't accept keyword args, only position.
156- attrs = [ "co_argcount" ]
157- if sys .version_info [0 ] >= 3 :
158- attrs += [ "co_kwonlyargcount" ]
159- if sys .version_info [1 ] >= 8 :
160- attrs += [ "co_posonlyargcount" ]
161- attrs += [ "co_nlocals" ,
154+ if hasattr ( function .__code__ , 'replace' ):
155+ function .__code__ = function .__code__ .replace ( ** kwds )
156+ return
157+
158+ # Enumerate all the __code__ attributes in the same order; types.CodeTypes doesn't accept
159+ # keyword args, only positional. This must be updated if new releases of Python have additional
160+ # parameters, but should be backward-compatible (the positional ordering should be consistent
161+ # for any parameters in use by a version)
162+ attrs = [ "co_argcount" ,
163+ "co_posonlyargcount" ,
164+ "co_kwonlyargcount" ,
165+ "co_nlocals" ,
162166 "co_stacksize" ,
163167 "co_flags" ,
164168 "co_code" ,
@@ -167,16 +171,24 @@ def change_function( function, **kwds ):
167171 "co_varnames" ,
168172 "co_filename" ,
169173 "co_name" ,
174+ "co_qualname" ,
170175 "co_firstlineno" ,
171176 "co_lnotab" ,
177+ "co_exceptiontable" ,
172178 "co_freevars" ,
173- "co_cellvars" ]
174-
175- assert all ( k in attrs for k in kwds ), \
176- "Invalid function keyword(s) supplied: %s" % ( ", " .join ( kwds .keys () ))
177-
178- # Alter the desired function attributes, and update the function's __code__
179- modi_args = [ kwds .get ( a , getattr ( function .__code__ , a )) for a in attrs ]
179+ "co_cellvars" , ]
180+
181+ assert all ( k in attrs and hasattr ( function .__code__ , k ) for k in kwds ), \
182+ "Invalid function keyword(s) supplied: %s" % ( ", " .join ( kwds ))
183+
184+ # Alter the desired function attributes w/ any supplied keywaords, and update the function's
185+ # __code__. Deduces what positional args are required by which attrs exist in this function's
186+ # code object
187+ modi_args = [
188+ kwds .get ( a , getattr ( function .__code__ , a ))
189+ for a in attrs
190+ if hasattr ( function .__code__ , a )
191+ ]
180192 modi_code = types .CodeType ( * modi_args )
181193 modi_func = types .FunctionType ( modi_code , function .__globals__ )
182194 function .__code__ = modi_func .__code__
0 commit comments