150
150
gc_collect )
151
151
from test .support .script_helper import assert_python_ok
152
152
from test .support import threading_helper
153
- from opcode import opmap
153
+ from opcode import opmap , opname
154
154
COPY_FREE_VARS = opmap ['COPY_FREE_VARS' ]
155
155
156
156
@@ -357,6 +357,28 @@ def func():
357
357
new_code = code = func .__code__ .replace (co_linetable = b'' )
358
358
self .assertEqual (list (new_code .co_lines ()), [])
359
359
360
+ def test_co_lnotab_is_deprecated (self ): # TODO: remove in 3.14
361
+ def func ():
362
+ pass
363
+
364
+ with self .assertWarns (DeprecationWarning ):
365
+ func .__code__ .co_lnotab
366
+
367
+ def test_invalid_bytecode (self ):
368
+ def foo ():
369
+ pass
370
+
371
+ # assert that opcode 229 is invalid
372
+ self .assertEqual (opname [229 ], '<229>' )
373
+
374
+ # change first opcode to 0xeb (=229)
375
+ foo .__code__ = foo .__code__ .replace (
376
+ co_code = b'\xe5 ' + foo .__code__ .co_code [1 :])
377
+
378
+ msg = "unknown opcode 229"
379
+ with self .assertRaisesRegex (SystemError , msg ):
380
+ foo ()
381
+
360
382
# TODO: RUSTPYTHON
361
383
@unittest .expectedFailure
362
384
# @requires_debug_ranges()
@@ -479,6 +501,32 @@ def f():
479
501
self .assertNotEqual (code_b , code_d )
480
502
self .assertNotEqual (code_c , code_d )
481
503
504
+ def test_code_hash_uses_firstlineno (self ):
505
+ c1 = (lambda : 1 ).__code__
506
+ c2 = (lambda : 1 ).__code__
507
+ self .assertNotEqual (c1 , c2 )
508
+ self .assertNotEqual (hash (c1 ), hash (c2 ))
509
+ c3 = c1 .replace (co_firstlineno = 17 )
510
+ self .assertNotEqual (c1 , c3 )
511
+ self .assertNotEqual (hash (c1 ), hash (c3 ))
512
+
513
+ def test_code_hash_uses_order (self ):
514
+ # Swapping posonlyargcount and kwonlyargcount should change the hash.
515
+ c = (lambda x , y , * , z = 1 , w = 1 : 1 ).__code__
516
+ self .assertEqual (c .co_argcount , 2 )
517
+ self .assertEqual (c .co_posonlyargcount , 0 )
518
+ self .assertEqual (c .co_kwonlyargcount , 2 )
519
+ swapped = c .replace (co_posonlyargcount = 2 , co_kwonlyargcount = 0 )
520
+ self .assertNotEqual (c , swapped )
521
+ self .assertNotEqual (hash (c ), hash (swapped ))
522
+
523
+ def test_code_hash_uses_bytecode (self ):
524
+ c = (lambda x , y : x + y ).__code__
525
+ d = (lambda x , y : x * y ).__code__
526
+ c1 = c .replace (co_code = d .co_code )
527
+ self .assertNotEqual (c , c1 )
528
+ self .assertNotEqual (hash (c ), hash (c1 ))
529
+
482
530
483
531
def isinterned (s ):
484
532
return s is sys .intern (('_' + s + '_' )[1 :- 1 ])
@@ -692,7 +740,8 @@ def test_positions(self):
692
740
693
741
def check_lines (self , func ):
694
742
co = func .__code__
695
- lines1 = list (dedup (l for (_ , _ , l ) in co .co_lines ()))
743
+ lines1 = [line for _ , _ , line in co .co_lines ()]
744
+ self .assertEqual (lines1 , list (dedup (lines1 )))
696
745
lines2 = list (lines_from_postions (positions_from_location_table (co )))
697
746
for l1 , l2 in zip (lines1 , lines2 ):
698
747
self .assertEqual (l1 , l2 )
@@ -714,6 +763,7 @@ def f():
714
763
pass
715
764
PY_CODE_LOCATION_INFO_NO_COLUMNS = 13
716
765
f .__code__ = f .__code__ .replace (
766
+ co_stacksize = 1 ,
717
767
co_firstlineno = 42 ,
718
768
co_code = bytes (
719
769
[
@@ -742,15 +792,15 @@ def f():
742
792
py = ctypes .pythonapi
743
793
freefunc = ctypes .CFUNCTYPE (None ,ctypes .c_voidp )
744
794
745
- RequestCodeExtraIndex = py ._PyEval_RequestCodeExtraIndex
795
+ RequestCodeExtraIndex = py .PyUnstable_Eval_RequestCodeExtraIndex
746
796
RequestCodeExtraIndex .argtypes = (freefunc ,)
747
797
RequestCodeExtraIndex .restype = ctypes .c_ssize_t
748
798
749
- SetExtra = py ._PyCode_SetExtra
799
+ SetExtra = py .PyUnstable_Code_SetExtra
750
800
SetExtra .argtypes = (ctypes .py_object , ctypes .c_ssize_t , ctypes .c_voidp )
751
801
SetExtra .restype = ctypes .c_int
752
802
753
- GetExtra = py ._PyCode_GetExtra
803
+ GetExtra = py .PyUnstable_Code_GetExtra
754
804
GetExtra .argtypes = (ctypes .py_object , ctypes .c_ssize_t ,
755
805
ctypes .POINTER (ctypes .c_voidp ))
756
806
GetExtra .restype = ctypes .c_int
0 commit comments