@@ -416,6 +416,86 @@ class SubDict(dict):
416
416
self .assertTrue (_testcapi .mapping_has_key (dct2 , 'a' ))
417
417
self .assertFalse (_testcapi .mapping_has_key (dct2 , 'b' ))
418
418
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
+
419
499
@unittest .skipUnless (hasattr (_testcapi , 'negative_refcount' ),
420
500
'need _testcapi.negative_refcount' )
421
501
def test_negative_refcount (self ):
@@ -907,6 +987,21 @@ def method_example(self): ...
907
987
self .assertEqual (_testcapi .eval_get_func_name (sum ), "sum" ) # c function
908
988
self .assertEqual (_testcapi .eval_get_func_name (A ), "type" )
909
989
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
+
910
1005
def test_function_get_code (self ):
911
1006
import types
912
1007
@@ -943,18 +1038,32 @@ def some():
943
1038
_testcapi .function_get_module (None ) # not a function
944
1039
945
1040
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
+ ):
947
1049
pass
948
1050
949
1051
defaults = _testcapi .function_get_defaults (some )
950
1052
self .assertEqual (defaults , ('p' , 0 , None ))
951
1053
self .assertEqual (defaults , some .__defaults__ )
952
1054
953
1055
with self .assertRaises (SystemError ):
954
- _testcapi .function_get_module (None ) # not a function
1056
+ _testcapi .function_get_defaults (None ) # not a function
955
1057
956
1058
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
+ ):
958
1067
pass
959
1068
960
1069
old_defaults = ('p' , 0 , None )
@@ -966,11 +1075,22 @@ def some(pos_only='p', zero=0, optional=None):
966
1075
self .assertEqual (_testcapi .function_get_defaults (some ), old_defaults )
967
1076
self .assertEqual (some .__defaults__ , old_defaults )
968
1077
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
+
969
1083
new_defaults = ('q' , 1 , None )
970
1084
_testcapi .function_set_defaults (some , new_defaults )
971
1085
self .assertEqual (_testcapi .function_get_defaults (some ), new_defaults )
972
1086
self .assertEqual (some .__defaults__ , new_defaults )
973
1087
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
+
974
1094
class tuplesub (tuple ): ... # tuple subclasses must work
975
1095
976
1096
new_defaults = tuplesub (((1 , 2 ), ['a' , 'b' ], None ))
@@ -984,6 +1104,73 @@ class tuplesub(tuple): ... # tuple subclasses must work
984
1104
self .assertEqual (_testcapi .function_get_defaults (some ), None )
985
1105
self .assertEqual (some .__defaults__ , None )
986
1106
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
+
987
1174
988
1175
class TestPendingCalls (unittest .TestCase ):
989
1176
0 commit comments