elem = b.close()
self.assertEqual(elem[0].tail, 'ABCDEFGHIJKL')
- def test_subscr(self):
- # Issue #27863
+ def test_subscr_with_clear(self):
+ # See https://github.com/python/cpython/issues/143200.
+ self.do_test_subscr_with_mutating_slice(use_clear_method=True)
+
+ def test_subscr_with_delete(self):
+ # See https://github.com/python/cpython/issues/72050.
+ self.do_test_subscr_with_mutating_slice(use_clear_method=False)
+
+ def do_test_subscr_with_mutating_slice(self, *, use_clear_method):
class X:
+ def __init__(self, i=0):
+ self.i = i
def __index__(self):
- del e[:]
- return 1
+ if use_clear_method:
+ e.clear()
+ else:
+ del e[:]
+ return self.i
- e = ET.Element('elem')
- e.append(ET.Element('child'))
- e[:X()] # shouldn't crash
+ for s in self.get_mutating_slices(X, 10):
+ with self.subTest(s):
+ e = ET.Element('elem')
+ e.extend([ET.Element(f'c{i}') for i in range(10)])
+ e[s] # shouldn't crash
- e.append(ET.Element('child'))
- e[0:10:X()] # shouldn't crash
+ def test_ass_subscr_with_mutating_slice(self):
+ # See https://github.com/python/cpython/issues/72050
+ # and https://github.com/python/cpython/issues/143200.
- def test_ass_subscr(self):
- # Issue #27863
class X:
+ def __init__(self, i=0):
+ self.i = i
def __index__(self):
e[:] = []
- return 1
+ return self.i
+
+ for s in self.get_mutating_slices(X, 10):
+ with self.subTest(s):
+ e = ET.Element('elem')
+ e.extend([ET.Element(f'c{i}') for i in range(10)])
+ e[s] = [] # shouldn't crash
+
+ def get_mutating_slices(self, index_class, n_children):
+ self.assertGreaterEqual(n_children, 10)
+ return [
+ slice(index_class(), None, None),
+ slice(index_class(2), None, None),
+ slice(None, index_class(), None),
+ slice(None, index_class(2), None),
+ slice(0, 2, index_class(1)),
+ slice(0, 2, index_class(2)),
+ slice(0, n_children, index_class(1)),
+ slice(0, n_children, index_class(2)),
+ slice(0, 2 * n_children, index_class(1)),
+ slice(0, 2 * n_children, index_class(2)),
+ ]
- e = ET.Element('elem')
- for _ in range(10):
- e.insert(0, ET.Element('child'))
+ def test_ass_subscr_with_mutating_iterable_value(self):
+ class V:
+ def __iter__(self):
+ e.clear()
+ return iter([ET.Element('a'), ET.Element('b')])
- e[0:10:X()] = [] # shouldn't crash
+ e = ET.Element('elem')
+ e.extend([ET.Element(f'c{i}') for i in range(10)])
+ e[:] = V()
def test_treebuilder_start(self):
# Issue #27863
return element_getitem(op, i);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, i;
size_t cur;
PyObject* list;
- if (!self->extra)
- return PyList_New(0);
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+
+ if (self->extra == NULL) {
+ return PyList_New(0);
+ }
slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
step);
return element_setitem(op, i, value);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, newlen, i;
size_t cur;
PyObject* recycle = NULL;
PyObject* seq;
- if (!self->extra) {
- if (create_extra(self, NULL) < 0)
- return -1;
- }
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
- slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
- step);
if (value == NULL) {
/* Delete slice */
- size_t cur;
- Py_ssize_t i;
-
+ if (self->extra == NULL) {
+ return 0;
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
if (slicelen <= 0)
return 0;
}
newlen = PySequence_Fast_GET_SIZE(seq);
- if (step != 1 && newlen != slicelen)
- {
+ if (self->extra == NULL) {
+ if (create_extra(self, NULL) < 0) {
+ Py_DECREF(seq);
+ return -1;
+ }
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
+
+ if (step != 1 && newlen != slicelen) {
Py_DECREF(seq);
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of size %zd "