@@ -416,6 +416,86 @@ class SubDict(dict):
416416 self .assertTrue (_testcapi .mapping_has_key (dct2 , 'a' ))
417417 self .assertFalse (_testcapi .mapping_has_key (dct2 , 'b' ))
418418
419+ def test_sequence_set_slice (self ):
420+ # Correct case:
421+ data = [1 , 2 , 3 , 4 , 5 ]
422+ data_copy = data .copy ()
423+
424+ _testcapi .sequence_set_slice (data , 1 , 3 , [8 , 9 ])
425+ data_copy [1 :3 ] = [8 , 9 ]
426+ self .assertEqual (data , data_copy )
427+ self .assertEqual (data , [1 , 8 , 9 , 4 , 5 ])
428+
429+ # Custom class:
430+ class Custom :
431+ def __setitem__ (self , index , value ):
432+ self .index = index
433+ self .value = value
434+
435+ c = Custom ()
436+ _testcapi .sequence_set_slice (c , 0 , 5 , 'abc' )
437+ self .assertEqual (c .index , slice (0 , 5 ))
438+ self .assertEqual (c .value , 'abc' )
439+
440+ # Immutable sequences must raise:
441+ bad_seq1 = (1 , 2 , 3 , 4 )
442+ with self .assertRaises (TypeError ):
443+ _testcapi .sequence_set_slice (bad_seq1 , 1 , 3 , (8 , 9 ))
444+ self .assertEqual (bad_seq1 , (1 , 2 , 3 , 4 ))
445+
446+ bad_seq2 = 'abcd'
447+ with self .assertRaises (TypeError ):
448+ _testcapi .sequence_set_slice (bad_seq2 , 1 , 3 , 'xy' )
449+ self .assertEqual (bad_seq2 , 'abcd' )
450+
451+ # Not a sequence:
452+ with self .assertRaises (TypeError ):
453+ _testcapi .sequence_set_slice (None , 1 , 3 , 'xy' )
454+
455+ mapping = {1 : 'a' , 2 : 'b' , 3 : 'c' }
456+ with self .assertRaises (TypeError ):
457+ _testcapi .sequence_set_slice (mapping , 1 , 3 , 'xy' )
458+ self .assertEqual (mapping , {1 : 'a' , 2 : 'b' , 3 : 'c' })
459+
460+ def test_sequence_del_slice (self ):
461+ # Correct case:
462+ data = [1 , 2 , 3 , 4 , 5 ]
463+ data_copy = data .copy ()
464+
465+ _testcapi .sequence_del_slice (data , 1 , 3 )
466+ del data_copy [1 :3 ]
467+ self .assertEqual (data , data_copy )
468+ self .assertEqual (data , [1 , 4 , 5 ])
469+
470+ # Custom class:
471+ class Custom :
472+ def __delitem__ (self , index ):
473+ self .index = index
474+
475+ c = Custom ()
476+ _testcapi .sequence_del_slice (c , 0 , 5 )
477+ self .assertEqual (c .index , slice (0 , 5 ))
478+
479+ # Immutable sequences must raise:
480+ bad_seq1 = (1 , 2 , 3 , 4 )
481+ with self .assertRaises (TypeError ):
482+ _testcapi .sequence_del_slice (bad_seq1 , 1 , 3 )
483+ self .assertEqual (bad_seq1 , (1 , 2 , 3 , 4 ))
484+
485+ bad_seq2 = 'abcd'
486+ with self .assertRaises (TypeError ):
487+ _testcapi .sequence_del_slice (bad_seq2 , 1 , 3 )
488+ self .assertEqual (bad_seq2 , 'abcd' )
489+
490+ # Not a sequence:
491+ with self .assertRaises (TypeError ):
492+ _testcapi .sequence_del_slice (None , 1 , 3 )
493+
494+ mapping = {1 : 'a' , 2 : 'b' , 3 : 'c' }
495+ with self .assertRaises (TypeError ):
496+ _testcapi .sequence_del_slice (mapping , 1 , 3 )
497+ self .assertEqual (mapping , {1 : 'a' , 2 : 'b' , 3 : 'c' })
498+
419499 @unittest .skipUnless (hasattr (_testcapi , 'negative_refcount' ),
420500 'need _testcapi.negative_refcount' )
421501 def test_negative_refcount (self ):
@@ -907,6 +987,21 @@ def method_example(self): ...
907987 self .assertEqual (_testcapi .eval_get_func_name (sum ), "sum" ) # c function
908988 self .assertEqual (_testcapi .eval_get_func_name (A ), "type" )
909989
990+ def test_eval_get_func_desc (self ):
991+ def function_example (): ...
992+
993+ class A :
994+ def method_example (self ): ...
995+
996+ self .assertEqual (_testcapi .eval_get_func_desc (function_example ),
997+ "()" )
998+ self .assertEqual (_testcapi .eval_get_func_desc (A .method_example ),
999+ "()" )
1000+ self .assertEqual (_testcapi .eval_get_func_desc (A ().method_example ),
1001+ "()" )
1002+ self .assertEqual (_testcapi .eval_get_func_desc (sum ), "()" ) # c function
1003+ self .assertEqual (_testcapi .eval_get_func_desc (A ), " object" )
1004+
9101005 def test_function_get_code (self ):
9111006 import types
9121007
@@ -943,18 +1038,32 @@ def some():
9431038 _testcapi .function_get_module (None ) # not a function
9441039
9451040 def test_function_get_defaults (self ):
946- def some (pos_only = 'p' , zero = 0 , optional = None ):
1041+ def some (
1042+ pos_only1 , pos_only2 = 'p' ,
1043+ / ,
1044+ zero = 0 , optional = None ,
1045+ * ,
1046+ kw1 ,
1047+ kw2 = True ,
1048+ ):
9471049 pass
9481050
9491051 defaults = _testcapi .function_get_defaults (some )
9501052 self .assertEqual (defaults , ('p' , 0 , None ))
9511053 self .assertEqual (defaults , some .__defaults__ )
9521054
9531055 with self .assertRaises (SystemError ):
954- _testcapi .function_get_module (None ) # not a function
1056+ _testcapi .function_get_defaults (None ) # not a function
9551057
9561058 def test_function_set_defaults (self ):
957- def some (pos_only = 'p' , zero = 0 , optional = None ):
1059+ def some (
1060+ pos_only1 , pos_only2 = 'p' ,
1061+ / ,
1062+ zero = 0 , optional = None ,
1063+ * ,
1064+ kw1 ,
1065+ kw2 = True ,
1066+ ):
9581067 pass
9591068
9601069 old_defaults = ('p' , 0 , None )
@@ -966,11 +1075,22 @@ def some(pos_only='p', zero=0, optional=None):
9661075 self .assertEqual (_testcapi .function_get_defaults (some ), old_defaults )
9671076 self .assertEqual (some .__defaults__ , old_defaults )
9681077
1078+ with self .assertRaises (SystemError ):
1079+ _testcapi .function_set_defaults (1 , ()) # not a function
1080+ self .assertEqual (_testcapi .function_get_defaults (some ), old_defaults )
1081+ self .assertEqual (some .__defaults__ , old_defaults )
1082+
9691083 new_defaults = ('q' , 1 , None )
9701084 _testcapi .function_set_defaults (some , new_defaults )
9711085 self .assertEqual (_testcapi .function_get_defaults (some ), new_defaults )
9721086 self .assertEqual (some .__defaults__ , new_defaults )
9731087
1088+ # Empty tuple is fine:
1089+ new_defaults = ()
1090+ _testcapi .function_set_defaults (some , new_defaults )
1091+ self .assertEqual (_testcapi .function_get_defaults (some ), new_defaults )
1092+ self .assertEqual (some .__defaults__ , new_defaults )
1093+
9741094 class tuplesub (tuple ): ... # tuple subclasses must work
9751095
9761096 new_defaults = tuplesub (((1 , 2 ), ['a' , 'b' ], None ))
@@ -984,6 +1104,73 @@ class tuplesub(tuple): ... # tuple subclasses must work
9841104 self .assertEqual (_testcapi .function_get_defaults (some ), None )
9851105 self .assertEqual (some .__defaults__ , None )
9861106
1107+ def test_function_get_kw_defaults (self ):
1108+ def some (
1109+ pos_only1 , pos_only2 = 'p' ,
1110+ / ,
1111+ zero = 0 , optional = None ,
1112+ * ,
1113+ kw1 ,
1114+ kw2 = True ,
1115+ ):
1116+ pass
1117+
1118+ defaults = _testcapi .function_get_kw_defaults (some )
1119+ self .assertEqual (defaults , {'kw2' : True })
1120+ self .assertEqual (defaults , some .__kwdefaults__ )
1121+
1122+ with self .assertRaises (SystemError ):
1123+ _testcapi .function_get_kw_defaults (None ) # not a function
1124+
1125+ def test_function_set_kw_defaults (self ):
1126+ def some (
1127+ pos_only1 , pos_only2 = 'p' ,
1128+ / ,
1129+ zero = 0 , optional = None ,
1130+ * ,
1131+ kw1 ,
1132+ kw2 = True ,
1133+ ):
1134+ pass
1135+
1136+ old_defaults = {'kw2' : True }
1137+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), old_defaults )
1138+ self .assertEqual (some .__kwdefaults__ , old_defaults )
1139+
1140+ with self .assertRaises (SystemError ):
1141+ _testcapi .function_set_kw_defaults (some , 1 ) # not dict or None
1142+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), old_defaults )
1143+ self .assertEqual (some .__kwdefaults__ , old_defaults )
1144+
1145+ with self .assertRaises (SystemError ):
1146+ _testcapi .function_set_kw_defaults (1 , {}) # not a function
1147+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), old_defaults )
1148+ self .assertEqual (some .__kwdefaults__ , old_defaults )
1149+
1150+ new_defaults = {'kw2' : (1 , 2 , 3 )}
1151+ _testcapi .function_set_kw_defaults (some , new_defaults )
1152+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), new_defaults )
1153+ self .assertEqual (some .__kwdefaults__ , new_defaults )
1154+
1155+ # Empty dict is fine:
1156+ new_defaults = {}
1157+ _testcapi .function_set_kw_defaults (some , new_defaults )
1158+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), new_defaults )
1159+ self .assertEqual (some .__kwdefaults__ , new_defaults )
1160+
1161+ class dictsub (dict ): ... # dict subclasses must work
1162+
1163+ new_defaults = dictsub ({'kw2' : None })
1164+ _testcapi .function_set_kw_defaults (some , new_defaults )
1165+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), new_defaults )
1166+ self .assertEqual (some .__kwdefaults__ , new_defaults )
1167+
1168+ # `None` is special, it sets `kwdefaults` to `NULL`,
1169+ # it needs special handling in `_testcapi`:
1170+ _testcapi .function_set_kw_defaults (some , None )
1171+ self .assertEqual (_testcapi .function_get_kw_defaults (some ), None )
1172+ self .assertEqual (some .__kwdefaults__ , None )
1173+
9871174
9881175class TestPendingCalls (unittest .TestCase ):
9891176
0 commit comments