@@ -174,18 +174,14 @@ def test_newempty(self):
174174 @cpython_only
175175 def test_closure_injection (self ):
176176 # From https://bugs.python.org/issue32176
177- from types import FunctionType , CodeType
177+ from types import FunctionType
178178
179179 def create_closure (__class__ ):
180180 return (lambda : __class__ ).__closure__
181181
182182 def new_code (c ):
183183 '''A new code object with a __class__ cell added to freevars'''
184- return CodeType (
185- c .co_argcount , c .co_posonlyargcount , c .co_kwonlyargcount , c .co_nlocals ,
186- c .co_stacksize , c .co_flags , c .co_code , c .co_consts , c .co_names ,
187- c .co_varnames , c .co_filename , c .co_name , c .co_firstlineno ,
188- c .co_lnotab , c .co_freevars + ('__class__' ,), c .co_cellvars )
184+ return c .replace (co_freevars = c .co_freevars + ('__class__' ,))
189185
190186 def add_foreign_method (cls , name , f ):
191187 code = new_code (f .__code__ )
@@ -212,6 +208,64 @@ class List(list):
212208 obj = List ([1 , 2 , 3 ])
213209 self .assertEqual (obj [0 ], "Foreign getitem: 1" )
214210
211+ def test_constructor (self ):
212+ def func (): pass
213+ co = func .__code__
214+ CodeType = type (co )
215+
216+ # test code constructor
217+ return CodeType (co .co_argcount ,
218+ co .co_posonlyargcount ,
219+ co .co_kwonlyargcount ,
220+ co .co_nlocals ,
221+ co .co_stacksize ,
222+ co .co_flags ,
223+ co .co_code ,
224+ co .co_consts ,
225+ co .co_names ,
226+ co .co_varnames ,
227+ co .co_filename ,
228+ co .co_name ,
229+ co .co_firstlineno ,
230+ co .co_lnotab ,
231+ co .co_freevars ,
232+ co .co_cellvars )
233+
234+ def test_replace (self ):
235+ def func ():
236+ x = 1
237+ return x
238+ code = func .__code__
239+
240+ # different co_name, co_varnames, co_consts
241+ def func2 ():
242+ y = 2
243+ return y
244+ code2 = func .__code__
245+
246+ for attr , value in (
247+ ("co_argcount" , 0 ),
248+ ("co_posonlyargcount" , 0 ),
249+ ("co_kwonlyargcount" , 0 ),
250+ ("co_nlocals" , 0 ),
251+ ("co_stacksize" , 0 ),
252+ ("co_flags" , code .co_flags | inspect .CO_COROUTINE ),
253+ ("co_firstlineno" , 100 ),
254+ ("co_code" , code2 .co_code ),
255+ ("co_consts" , code2 .co_consts ),
256+ ("co_names" , ("myname" ,)),
257+ ("co_varnames" , code2 .co_varnames ),
258+ ("co_freevars" , ("freevar" ,)),
259+ ("co_cellvars" , ("cellvar" ,)),
260+ ("co_filename" , "newfilename" ),
261+ ("co_name" , "newname" ),
262+ ("co_lnotab" , code2 .co_lnotab ),
263+ ):
264+ with self .subTest (attr = attr , value = value ):
265+ new_code = code .replace (** {attr : value })
266+ self .assertEqual (getattr (new_code , attr ), value )
267+
268+
215269def isinterned (s ):
216270 return s is sys .intern (('_' + s + '_' )[1 :- 1 ])
217271
0 commit comments