elif self.type is py_object_type:
code.globalstate.use_utility_code(
UtilityCode.load_cached("GetObjectSlice", "ObjectHandling.c"))
- has_c_start, c_start, py_start = False, '0', 'NULL'
- if self.start:
- has_c_start = not self.start.type.is_pyobject
- if has_c_start:
- c_start = self.start.result()
- else:
- py_start = '&%s' % self.start.py_result()
- has_c_stop, c_stop, py_stop = False, '0', 'NULL'
- if self.stop:
- has_c_stop = not self.stop.type.is_pyobject
- if has_c_stop:
- c_stop = self.stop.result()
- else:
- py_stop = '&%s' % self.stop.py_result()
- py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL'
+ (has_c_start, has_c_stop, c_start, c_stop,
+ py_start, py_stop, py_slice) = self.get_slice_config()
code.putln(
"%s = __Pyx_PySequence_GetObjectSlice(%s, %s, %s, %s, %s, %s, %d, %d); %s" % (
result,
def generate_assignment_code(self, rhs, code):
self.generate_subexpr_evaluation_code(code)
if self.type.is_pyobject:
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("SetObjectSlice", "ObjectHandling.c"))
+ (has_c_start, has_c_stop, c_start, c_stop,
+ py_start, py_stop, py_slice) = self.get_slice_config()
code.put_error_if_neg(self.pos,
- "__Pyx_PySequence_SetSlice(%s, %s, %s, %s)" % (
+ "__Pyx_PySequence_SetObjectSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d)" % (
self.base.py_result(),
- self.start_code(),
- self.stop_code(),
- rhs.py_result()))
+ rhs.py_result(),
+ c_start, c_stop,
+ py_start, py_stop, py_slice,
+ has_c_start, has_c_stop))
else:
start_offset = ''
if self.start:
"Deleting slices is only supported for Python types, not '%s'." % self.type)
return
self.generate_subexpr_evaluation_code(code)
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("SetObjectSlice", "ObjectHandling.c"))
+ (has_c_start, has_c_stop, c_start, c_stop,
+ py_start, py_stop, py_slice) = self.get_slice_config()
code.put_error_if_neg(self.pos,
- "__Pyx_PySequence_DelSlice(%s, %s, %s)" % (
+ "__Pyx_PySequence_DelObjectSlice(%s, %s, %s, %s, %s, %s, %d, %d)" % (
self.base.py_result(),
- self.start_code(),
- self.stop_code()))
+ c_start, c_stop,
+ py_start, py_stop, py_slice,
+ has_c_start, has_c_stop))
self.generate_subexpr_disposal_code(code)
self.free_subexpr_temps(code)
+ def get_slice_config(self):
+ has_c_start, c_start, py_start = False, '0', 'NULL'
+ if self.start:
+ has_c_start = not self.start.type.is_pyobject
+ if has_c_start:
+ c_start = self.start.result()
+ else:
+ py_start = '&%s' % self.start.py_result()
+ has_c_stop, c_stop, py_stop = False, '0', 'NULL'
+ if self.stop:
+ has_c_stop = not self.stop.type.is_pyobject
+ if has_c_stop:
+ c_stop = self.stop.result()
+ else:
+ py_stop = '&%s' % self.stop.py_result()
+ py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL'
+ return (has_c_start, has_c_stop, c_start, c_stop,
+ py_start, py_stop, py_slice)
+
def generate_slice_guard_code(self, code, target_size):
if not self.base.type.is_array:
return
return NULL;
}
+/////////////// SetObjectSlice.proto ///////////////
+
+#define __Pyx_PySequence_DelObjectSlice(obj, cstart, cstop, py_start, py_stop, py_slice, has_cstart, has_cstop) \
+ __Pyx_PySequence_SetObjectSlice(obj, (PyObject*)NULL, cstart, cstop, py_start, py_stop, py_slice, has_cstart, has_cstop)
+
+// we pass pointer addresses to show the C compiler what is NULL and what isn't
+static CYTHON_INLINE int __Pyx_PySequence_SetObjectSlice(
+ PyObject* obj, PyObject* value, Py_ssize_t cstart, Py_ssize_t cstop,
+ PyObject** py_start, PyObject** py_stop, PyObject** py_slice,
+ int has_cstart, int has_cstop);
+
+/////////////// SetObjectSlice ///////////////
+
+static CYTHON_INLINE int __Pyx_PySequence_SetObjectSlice(
+ PyObject* obj, PyObject* value, Py_ssize_t cstart, Py_ssize_t cstop,
+ PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice,
+ int has_cstart, int has_cstop) {
+ PyMappingMethods* mp;
+#if PY_MAJOR_VERSION < 3
+ PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence;
+ if (likely(ms && ms->sq_ass_slice)) {
+ if (!has_cstart) {
+ if (_py_start) {
+ cstart = __Pyx_PyIndex_AsSsize_t(*_py_start);
+ if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) return -1;
+ } else
+ cstart = 0;
+ }
+ if (!has_cstop) {
+ if (_py_stop) {
+ cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop);
+ if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) return -1;
+ } else
+ cstop = PY_SSIZE_T_MAX;
+ }
+ if (unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) {
+ Py_ssize_t l = ms->sq_length(obj);
+ if (likely(l >= 0)) {
+ if (cstop < 0) {
+ cstop += l;
+ if (cstop < 0) cstop = 0;
+ }
+ if (cstart < 0) {
+ cstart += l;
+ if (cstart < 0) cstart = 0;
+ }
+ } else {
+ // if length > max(Py_ssize_t), maybe the object can wrap around itself?
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))
+ PyErr_Clear();
+ else
+ return -1;
+ }
+ }
+ return ms->sq_ass_slice(obj, cstart, cstop, value);
+ }
+#endif
+ mp = Py_TYPE(obj)->tp_as_mapping;
+ if (likely(mp && mp->mp_ass_subscript)) {
+ PyObject *py_slice, *py_start, *py_stop;
+ int result;
+ if (_py_slice) {
+ py_slice = *_py_slice;
+ } else {
+ PyObject* owned_start = NULL;
+ PyObject* owned_stop = NULL;
+ if (_py_start) {
+ py_start = *_py_start;
+ } else {
+ if (has_cstart) {
+ owned_start = py_start = PyInt_FromSsize_t(cstart);
+ if (unlikely(!py_start)) return -1;
+ } else
+ py_start = Py_None;
+ }
+ if (_py_stop) {
+ py_stop = *_py_stop;
+ } else {
+ if (has_cstop) {
+ owned_stop = py_stop = PyInt_FromSsize_t(cstop);
+ if (unlikely(!py_stop)) {
+ Py_XDECREF(owned_start);
+ return -1;
+ }
+ } else
+ py_stop = Py_None;
+ }
+ py_slice = PySlice_New(py_start, py_stop, Py_None);
+ Py_XDECREF(owned_start);
+ Py_XDECREF(owned_stop);
+ if (unlikely(!py_slice)) return -1;
+ }
+ result = mp->mp_ass_subscript(obj, py_slice, value);
+ if (!_py_slice) {
+ Py_DECREF(py_slice);
+ }
+ return result;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name);
+ return -1;
+}
+
/////////////// SliceTupleAndList.proto ///////////////
#if CYTHON_COMPILING_IN_CPYTHON
+++ /dev/null
-# mode: compile
-
-cdef void spam():
- cdef object x
- del x[17:42]
-
-spam()
--- /dev/null
+# mode: run
+# tag: del, slice
+
+def del_constant_start_stop(x):
+ """
+ >>> l = [1,2,3,4]
+ >>> del_constant_start_stop(l)
+ [1, 2]
+
+ >>> l = [1,2,3,4,5,6,7]
+ >>> del_constant_start_stop(l)
+ [1, 2, 7]
+ """
+ del x[2:6]
+ return x
+
+
+def del_start(x, start):
+ """
+ >>> l = [1,2,3,4]
+ >>> del_start(l, 2)
+ [1, 2]
+
+ >>> l = [1,2,3,4,5,6,7]
+ >>> del_start(l, 20)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_start(l, 8)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_start(l, 4)
+ [1, 2, 3, 4]
+
+ >>> del_start(l, -2)
+ [1, 2]
+ >>> l
+ [1, 2]
+ >>> del_start(l, -2)
+ []
+ >>> del_start(l, 2)
+ []
+ >>> del_start(l, -2)
+ []
+ >>> del_start(l, 20)
+ []
+
+ >>> del_start([1,2,3,4], -20)
+ []
+ >>> del_start([1,2,3,4], 0)
+ []
+ """
+ del x[start:]
+ return x
+
+
+def del_stop(x, stop):
+ """
+ >>> l = [1,2,3,4]
+ >>> del_stop(l, 2)
+ [3, 4]
+
+ >>> l = [1,2,3,4,5,6,7]
+ >>> del_stop(l, -20)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_stop(l, -8)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_stop(l, -4)
+ [4, 5, 6, 7]
+
+ >>> del_stop(l, -2)
+ [6, 7]
+ >>> l
+ [6, 7]
+ >>> del_stop(l, -2)
+ [6, 7]
+ >>> del_stop(l, 2)
+ []
+ >>> del_stop(l, -2)
+ []
+ >>> del_stop(l, 20)
+ []
+
+ >>> del_stop([1,2,3,4], -20)
+ [1, 2, 3, 4]
+ >>> del_stop([1,2,3,4], 0)
+ [1, 2, 3, 4]
+ """
+ del x[:stop]
+ return x
+
+
+def del_start_stop(x, start, stop):
+ """
+ >>> l = [1,2,3,4]
+ >>> del_start_stop(l, 0, 2)
+ [3, 4]
+ >>> l
+ [3, 4]
+
+ >>> l = [1,2,3,4,5,6,7]
+ >>> del_start_stop(l, -1, -20)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_start_stop(l, -20, -8)
+ [1, 2, 3, 4, 5, 6, 7]
+ >>> del_start_stop(l, -6, -4)
+ [1, 4, 5, 6, 7]
+
+ >>> del_start_stop(l, -20, -2)
+ [6, 7]
+ >>> l
+ [6, 7]
+ >>> del_start_stop(l, -2, 1)
+ [7]
+ >>> del_start_stop(l, -2, 3)
+ []
+ >>> del_start_stop(l, 2, 4)
+ []
+
+ >>> del_start_stop([1,2,3,4], 20, -20)
+ [1, 2, 3, 4]
+ >>> del_start_stop([1,2,3,4], 0, 0)
+ [1, 2, 3, 4]
+ """
+ del x[start:stop]
+ return x