@@ -151,14 +151,18 @@ def change_function( function, **kwds ):
151
151
152
152
153
153
"""
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" ,
162
166
"co_stacksize" ,
163
167
"co_flags" ,
164
168
"co_code" ,
@@ -167,16 +171,24 @@ def change_function( function, **kwds ):
167
171
"co_varnames" ,
168
172
"co_filename" ,
169
173
"co_name" ,
174
+ "co_qualname" ,
170
175
"co_firstlineno" ,
171
176
"co_lnotab" ,
177
+ "co_exceptiontable" ,
172
178
"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
+ ]
180
192
modi_code = types .CodeType ( * modi_args )
181
193
modi_func = types .FunctionType ( modi_code , function .__globals__ )
182
194
function .__code__ = modi_func .__code__
0 commit comments