Skip to content

Commit c5c4077

Browse files
authoredNov 5, 2022
gh-94808: add tests covering PySequence_{Set,Del}Slice (GH-99123)
1 parent 67ade40 commit c5c4077

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
 

‎Lib/test/test_capi.py

+80
Original file line numberDiff line numberDiff line change
@@ -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):

‎Modules/_testcapimodule.c

+33
Original file line numberDiff line numberDiff line change
@@ -4794,6 +4794,37 @@ mapping_has_key(PyObject* self, PyObject *args)
47944794
return PyLong_FromLong(PyMapping_HasKey(context, key));
47954795
}
47964796

4797+
static PyObject *
4798+
sequence_set_slice(PyObject* self, PyObject *args)
4799+
{
4800+
PyObject *sequence, *obj;
4801+
Py_ssize_t i1, i2;
4802+
if (!PyArg_ParseTuple(args, "OnnO", &sequence, &i1, &i2, &obj)) {
4803+
return NULL;
4804+
}
4805+
4806+
int res = PySequence_SetSlice(sequence, i1, i2, obj);
4807+
if (res == -1) {
4808+
return NULL;
4809+
}
4810+
Py_RETURN_NONE;
4811+
}
4812+
4813+
static PyObject *
4814+
sequence_del_slice(PyObject* self, PyObject *args)
4815+
{
4816+
PyObject *sequence;
4817+
Py_ssize_t i1, i2;
4818+
if (!PyArg_ParseTuple(args, "Onn", &sequence, &i1, &i2)) {
4819+
return NULL;
4820+
}
4821+
4822+
int res = PySequence_DelSlice(sequence, i1, i2);
4823+
if (res == -1) {
4824+
return NULL;
4825+
}
4826+
Py_RETURN_NONE;
4827+
}
47974828

47984829
static PyObject *
47994830
test_pythread_tss_key_state(PyObject *self, PyObject *args)
@@ -6196,6 +6227,8 @@ static PyMethodDef TestMethods[] = {
61966227
{"get_mapping_items", get_mapping_items, METH_O},
61976228
{"test_mapping_has_key_string", test_mapping_has_key_string, METH_NOARGS},
61986229
{"mapping_has_key", mapping_has_key, METH_VARARGS},
6230+
{"sequence_set_slice", sequence_set_slice, METH_VARARGS},
6231+
{"sequence_del_slice", sequence_del_slice, METH_VARARGS},
61996232
{"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS},
62006233
{"hamt", new_hamt, METH_NOARGS},
62016234
{"bad_get", _PyCFunction_CAST(bad_get), METH_FASTCALL},

0 commit comments

Comments
 (0)
Please sign in to comment.