]> granicus.if.org Git - vim/commitdiff
updated for version 7.4.151 v7.4.151
authorBram Moolenaar <Bram@vim.org>
Tue, 14 Jan 2014 15:36:51 +0000 (16:36 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 14 Jan 2014 15:36:51 +0000 (16:36 +0100)
Problem:    Python: slices with steps are not supported.
Solution:   Support slices in Python vim.List. (ZyX)

src/eval.c
src/if_py_both.h
src/if_python.c
src/if_python3.c
src/proto/eval.pro
src/testdir/test86.in
src/testdir/test86.ok
src/testdir/test87.in
src/testdir/test87.ok
src/version.c

index 693896cffff90c233805704ab7931e6fda340023..65f4b1138c5553dd2a8dc1a49578e72782170c0b 100644 (file)
@@ -6425,6 +6425,16 @@ list_insert_tv(l, tv, item)
     if (ni == NULL)
        return FAIL;
     copy_tv(tv, &ni->li_tv);
+    list_insert(l, ni, item);
+    return OK;
+}
+
+    void
+list_insert(l, ni, item)
+    list_T     *l;
+    listitem_T *ni;
+    listitem_T *item;
+{
     if (item == NULL)
        /* Append new item at end of list. */
        list_append(l, ni);
@@ -6446,7 +6456,6 @@ list_insert_tv(l, tv, item)
        item->li_prev = ni;
        ++l->lv_len;
     }
-    return OK;
 }
 
 /*
index 17c02a9ec2e31ea8796fd31f72bd96a2f1ba20ea..6e3939abe569f4b634d990a7d1e6a1df5939fa73 100644 (file)
@@ -36,8 +36,9 @@ static const char *vim_special_path = "_vim_path_";
 #define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
 #define PyErr_SetVim(str) PyErr_SetString(VimError, str)
 #define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
-#define PyErr_FORMAT(exc, str, tail) PyErr_Format(exc, _(str), tail)
-#define PyErr_VIM_FORMAT(str, tail) PyErr_FORMAT(VimError, str, tail)
+#define PyErr_FORMAT(exc, str, arg) PyErr_Format(exc, _(str), arg)
+#define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2)
+#define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg)
 
 #define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \
        ? "(NULL)" \
@@ -2108,8 +2109,6 @@ static struct PyMethodDef DictionaryMethods[] = {
 };
 
 static PyTypeObject ListType;
-static PySequenceMethods ListAsSeq;
-static PyMappingMethods ListAsMapping;
 
 typedef struct
 {
@@ -2253,7 +2252,7 @@ ListLength(ListObject *self)
 }
 
     static PyObject *
-ListItem(ListObject *self, Py_ssize_t index)
+ListIndex(ListObject *self, Py_ssize_t index)
 {
     listitem_T *li;
 
@@ -2273,164 +2272,110 @@ ListItem(ListObject *self, Py_ssize_t index)
     return ConvertToPyObject(&li->li_tv);
 }
 
-#define PROC_RANGE \
-    if (last < 0) {\
-       if (last < -size) \
-           last = 0; \
-       else \
-           last += size; \
-    } \
-    if (first < 0) \
-       first = 0; \
-    if (first > size) \
-       first = size; \
-    if (last > size) \
-       last = size;
-
     static PyObject *
-ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
+ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step,
+         Py_ssize_t slicelen)
 {
     PyInt      i;
-    PyInt      size = ListLength(self);
-    PyInt      n;
     PyObject   *list;
-    int                reversed = 0;
 
-    PROC_RANGE
-    if (first >= last)
-       first = last;
+    if (step == 0)
+    {
+       PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
+       return NULL;
+    }
 
-    n = last-first;
-    list = PyList_New(n);
+    list = PyList_New(slicelen);
     if (list == NULL)
        return NULL;
 
-    for (i = 0; i < n; ++i)
+    for (i = 0; i < slicelen; ++i)
     {
-       PyObject        *item = ListItem(self, first + i);
+       PyObject        *item;
+
+       item = ListIndex(self, first + i*step);
        if (item == NULL)
        {
            Py_DECREF(list);
            return NULL;
        }
 
-       PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
+       PyList_SET_ITEM(list, i, item);
     }
 
     return list;
 }
 
-typedef struct
-{
-    listwatch_T        lw;
-    list_T     *list;
-} listiterinfo_T;
-
-    static void
-ListIterDestruct(listiterinfo_T *lii)
-{
-    list_rem_watch(lii->list, &lii->lw);
-    PyMem_Free(lii);
-}
-
     static PyObject *
-ListIterNext(listiterinfo_T **lii)
+ListItem(ListObject *self, PyObject* idx)
 {
-    PyObject   *ret;
-
-    if (!((*lii)->lw.lw_item))
-       return NULL;
-
-    if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
-       return NULL;
-
-    (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
-
-    return ret;
-}
-
-    static PyObject *
-ListIter(ListObject *self)
-{
-    listiterinfo_T     *lii;
-    list_T     *l = self->list;
-
-    if (!(lii = PyMem_New(listiterinfo_T, 1)))
+#if PY_MAJOR_VERSION < 3
+    if (PyInt_Check(idx))
     {
-       PyErr_NoMemory();
-       return NULL;
+       long _idx = PyInt_AsLong(idx);
+       return ListIndex(self, _idx);
     }
-
-    list_add_watch(l, &lii->lw);
-    lii->lw.lw_item = l->lv_first;
-    lii->list = l;
-
-    return IterNew(lii,
-           (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
-           NULL, NULL);
-}
-
-    static int
-ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
-{
-    typval_T   tv;
-    list_T     *l = self->list;
-    listitem_T *li;
-    Py_ssize_t length = ListLength(self);
-
-    if (l->lv_lock)
+    else
+#endif
+    if (PyLong_Check(idx))
     {
-       RAISE_LOCKED_LIST;
-       return -1;
+       long _idx = PyLong_AsLong(idx);
+       return ListIndex(self, _idx);
     }
-    if (index > length || (index == length && obj == NULL))
+    else if (PySlice_Check(idx))
     {
-       PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
-       return -1;
-    }
+       Py_ssize_t start, stop, step, slicelen;
 
-    if (obj == NULL)
+       if (PySlice_GetIndicesEx(idx, ListLength(self),
+                                &start, &stop, &step, &slicelen) < 0)
+           return NULL;
+       return ListSlice(self, start, step, slicelen);
+    }
+    else
     {
-       li = list_find(l, (long) index);
-       list_remove(l, li, li);
-       clear_tv(&li->li_tv);
-       vim_free(li);
-       return 0;
+       RAISE_INVALID_INDEX_TYPE(idx);
+       return NULL;
     }
+}
 
-    if (ConvertFromPyObject(obj, &tv) == -1)
-       return -1;
-
-    if (index == length)
+    static void
+list_restore(Py_ssize_t numadded, Py_ssize_t numreplaced, Py_ssize_t slicelen,
+       list_T *l, listitem_T **lis, listitem_T *lastaddedli)
+{
+    while (numreplaced--)
     {
-       if (list_append_tv(l, &tv) == FAIL)
-       {
-           clear_tv(&tv);
-           PyErr_SET_VIM(N_("failed to add item to list"));
-           return -1;
-       }
+       list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]);
+       listitem_remove(l, lis[slicelen + numreplaced]);
     }
-    else
+    while (numadded--)
     {
-       li = list_find(l, (long) index);
-       clear_tv(&li->li_tv);
-       copy_tv(&tv, &li->li_tv);
-       clear_tv(&tv);
+       listitem_T      *next;
+
+       next = lastaddedli->li_prev;
+       listitem_remove(l, lastaddedli);
+       lastaddedli = next;
     }
-    return 0;
 }
 
     static int
-ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
+ListAssSlice(ListObject *self, Py_ssize_t first,
+            Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj)
 {
-    PyInt      size = ListLength(self);
     PyObject   *iterator;
     PyObject   *item;
     listitem_T *li;
+    listitem_T *lastaddedli = NULL;
     listitem_T *next;
     typval_T   v;
     list_T     *l = self->list;
     PyInt      i;
+    PyInt      j;
+    PyInt      numreplaced = 0;
+    PyInt      numadded = 0;
+    PyInt      size;
+    listitem_T **lis;
+
+    size = ListLength(self);
 
     if (l->lv_lock)
     {
@@ -2438,7 +2383,42 @@ ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
        return -1;
     }
 
-    PROC_RANGE
+    if (step == 0)
+    {
+       PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
+       return -1;
+    }
+
+    if (step != 1 && slicelen == 0)
+    {
+       /* Nothing to do. Only error out if obj has some items. */
+       int             ret = 0;
+
+       if (obj == NULL)
+           return 0;
+
+       if (!(iterator = PyObject_GetIter(obj)))
+           return -1;
+
+       if ((item = PyIter_Next(iterator)))
+       {
+           PyErr_FORMAT(PyExc_ValueError,
+                   N_("attempt to assign sequence of size greater then %d "
+                       "to extended slice"), 0);
+           Py_DECREF(item);
+           ret = -1;
+       }
+       Py_DECREF(iterator);
+       return ret;
+    }
+
+    if (obj != NULL)
+       /* XXX May allocate zero bytes. */
+       if (!(lis = PyMem_New(listitem_T *, slicelen * 2)))
+       {
+           PyErr_NoMemory();
+           return -1;
+       }
 
     if (first == size)
        li = NULL;
@@ -2449,17 +2429,33 @@ ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
        {
            PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"),
                    (int)first);
+           if (obj != NULL)
+               PyMem_Free(lis);
            return -1;
        }
-       if (last > first)
+       i = slicelen;
+       while (i-- && li != NULL)
        {
-           i = last - first;
-           while (i-- && li != NULL)
-           {
-               next = li->li_next;
+           j = step;
+           next = li;
+           if (step > 0)
+               while (next != NULL && ((next = next->li_next) != NULL) && --j);
+           else
+               while (next != NULL && ((next = next->li_prev) != NULL) && ++j);
+
+           if (obj == NULL)
                listitem_remove(l, li);
-               li = next;
-           }
+           else
+               lis[slicelen - i - 1] = li;
+
+           li = next;
+       }
+       if (li == NULL && i != -1)
+       {
+           PyErr_SET_VIM(N_("internal error: not enough list items"));
+           if (obj != NULL)
+               PyMem_Free(lis);
+           return -1;
        }
     }
 
@@ -2467,33 +2463,172 @@ ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
        return 0;
 
     if (!(iterator = PyObject_GetIter(obj)))
+    {
+       PyMem_Free(lis);
        return -1;
+    }
 
+    i = 0;
     while ((item = PyIter_Next(iterator)))
     {
        if (ConvertFromPyObject(item, &v) == -1)
        {
            Py_DECREF(iterator);
            Py_DECREF(item);
+           PyMem_Free(lis);
            return -1;
        }
        Py_DECREF(item);
-       if (list_insert_tv(l, &v, li) == FAIL)
+       if (list_insert_tv(l, &v, numreplaced < slicelen
+                                   ? lis[numreplaced]
+                                   : li) == FAIL)
        {
            clear_tv(&v);
            PyErr_SET_VIM(N_("internal error: failed to add item to list"));
+           list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
+           PyMem_Free(lis);
            return -1;
        }
+       if (numreplaced < slicelen)
+       {
+           lis[slicelen + numreplaced] = lis[numreplaced]->li_prev;
+           list_remove(l, lis[numreplaced], lis[numreplaced]);
+           numreplaced++;
+       }
+       else
+       {
+           if (li)
+               lastaddedli = li->li_prev;
+           else
+               lastaddedli = l->lv_last;
+           numadded++;
+       }
        clear_tv(&v);
+       if (step != 1 && i >= slicelen)
+       {
+           Py_DECREF(iterator);
+           PyErr_FORMAT(PyExc_ValueError,
+                   N_("attempt to assign sequence of size greater then %d "
+                       "to extended slice"), slicelen);
+           list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
+           PyMem_Free(lis);
+           return -1;
+       }
+       ++i;
     }
     Py_DECREF(iterator);
 
+    if (step != 1 && i != slicelen)
+    {
+       PyErr_FORMAT2(PyExc_ValueError,
+               N_("attempt to assign sequence of size %d to extended slice "
+                   "of size %d"), i, slicelen);
+       list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
+       PyMem_Free(lis);
+       return -1;
+    }
+
     if (PyErr_Occurred())
+    {
+       list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
+       PyMem_Free(lis);
+       return -1;
+    }
+
+    for (i = 0; i < numreplaced; i++)
+       listitem_free(lis[i]);
+    if (step == 1)
+       for (i = numreplaced; i < slicelen; i++)
+           listitem_remove(l, lis[i]);
+
+    PyMem_Free(lis);
+
+    return 0;
+}
+
+    static int
+ListAssIndex(ListObject *self, Py_ssize_t index, PyObject *obj)
+{
+    typval_T   tv;
+    list_T     *l = self->list;
+    listitem_T *li;
+    Py_ssize_t length = ListLength(self);
+
+    if (l->lv_lock)
+    {
+       RAISE_LOCKED_LIST;
+       return -1;
+    }
+    if (index > length || (index == length && obj == NULL))
+    {
+       PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
        return -1;
+    }
 
+    if (obj == NULL)
+    {
+       li = list_find(l, (long) index);
+       list_remove(l, li, li);
+       clear_tv(&li->li_tv);
+       vim_free(li);
+       return 0;
+    }
+
+    if (ConvertFromPyObject(obj, &tv) == -1)
+       return -1;
+
+    if (index == length)
+    {
+       if (list_append_tv(l, &tv) == FAIL)
+       {
+           clear_tv(&tv);
+           PyErr_SET_VIM(N_("failed to add item to list"));
+           return -1;
+       }
+    }
+    else
+    {
+       li = list_find(l, (long) index);
+       clear_tv(&li->li_tv);
+       copy_tv(&tv, &li->li_tv);
+       clear_tv(&tv);
+    }
     return 0;
 }
 
+    static Py_ssize_t
+ListAssItem(ListObject *self, PyObject *idx, PyObject *obj)
+{
+#if PY_MAJOR_VERSION < 3
+    if (PyInt_Check(idx))
+    {
+       long _idx = PyInt_AsLong(idx);
+       return ListAssIndex(self, _idx, obj);
+    }
+    else
+#endif
+    if (PyLong_Check(idx))
+    {
+       long _idx = PyLong_AsLong(idx);
+       return ListAssIndex(self, _idx, obj);
+    }
+    else if (PySlice_Check(idx))
+    {
+       Py_ssize_t start, stop, step, slicelen;
+
+       if (PySlice_GetIndicesEx(idx, ListLength(self),
+                                &start, &stop, &step, &slicelen) < 0)
+           return -1;
+       return ListAssSlice(self, start, step, slicelen,
+               obj);
+    }
+    else
+    {
+       RAISE_INVALID_INDEX_TYPE(idx);
+       return -1;
+    }
+}
+
     static PyObject *
 ListConcatInPlace(ListObject *self, PyObject *obj)
 {
@@ -2520,6 +2655,56 @@ ListConcatInPlace(ListObject *self, PyObject *obj)
     return (PyObject *)(self);
 }
 
+typedef struct
+{
+    listwatch_T        lw;
+    list_T     *list;
+} listiterinfo_T;
+
+    static void
+ListIterDestruct(listiterinfo_T *lii)
+{
+    list_rem_watch(lii->list, &lii->lw);
+    PyMem_Free(lii);
+}
+
+    static PyObject *
+ListIterNext(listiterinfo_T **lii)
+{
+    PyObject   *ret;
+
+    if (!((*lii)->lw.lw_item))
+       return NULL;
+
+    if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
+       return NULL;
+
+    (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
+
+    return ret;
+}
+
+    static PyObject *
+ListIter(ListObject *self)
+{
+    listiterinfo_T     *lii;
+    list_T     *l = self->list;
+
+    if (!(lii = PyMem_New(listiterinfo_T, 1)))
+    {
+       PyErr_NoMemory();
+       return NULL;
+    }
+
+    list_add_watch(l, &lii->lw);
+    lii->lw.lw_item = l->lv_first;
+    lii->list = l;
+
+    return IterNew(lii,
+           (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
+           NULL, NULL);
+}
+
 static char *ListAttrs[] = {
     "locked",
     NULL
@@ -2567,6 +2752,25 @@ ListSetattr(ListObject *self, char *name, PyObject *valObject)
     }
 }
 
+static PySequenceMethods ListAsSeq = {
+    (lenfunc)          ListLength,      /* sq_length,    len(x)   */
+    (binaryfunc)       0,               /* RangeConcat, sq_concat,  x+y   */
+    0,                                  /* RangeRepeat, sq_repeat,  x*n   */
+    (PyIntArgFunc)     ListIndex,       /* sq_item,      x[i]     */
+    0,                                  /* was_sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)  ListAssIndex,    /* sq_as_item,  x[i]=v   */
+    0,                                  /* was_sq_ass_slice, x[i:j]=v */
+    0,                                  /* sq_contains */
+    (binaryfunc)       ListConcatInPlace,/* sq_inplace_concat */
+    0,                                  /* sq_inplace_repeat */
+};
+
+static PyMappingMethods ListAsMapping = {
+    /* mp_length       */ (lenfunc) ListLength,
+    /* mp_subscript     */ (binaryfunc) ListItem,
+    /* mp_ass_subscript */ (objobjargproc) ListAssItem,
+};
+
 static struct PyMethodDef ListMethods[] = {
     {"extend", (PyCFunction)ListConcatInPlace, METH_O,         ""},
     {"__dir__",        (PyCFunction)ListDir,           METH_NOARGS,    ""},
index e34bd280f148bfc95682f492f3f32543fffe7587..92510b367684c0a334f0a0b83b27ec87b07f2129 100644 (file)
@@ -196,6 +196,7 @@ struct PyMethodDef { Py_ssize_t a; };
 # define PyTuple_Size dll_PyTuple_Size
 # define PyTuple_GetItem dll_PyTuple_GetItem
 # define PyTuple_Type (*dll_PyTuple_Type)
+# define PySlice_GetIndicesEx dll_PySlice_GetIndicesEx
 # define PyImport_ImportModule dll_PyImport_ImportModule
 # define PyDict_New dll_PyDict_New
 # define PyDict_GetItemString dll_PyDict_GetItemString
@@ -241,6 +242,7 @@ struct PyMethodDef { Py_ssize_t a; };
 # define PySys_GetObject dll_PySys_GetObject
 # define PySys_SetArgv dll_PySys_SetArgv
 # define PyType_Type (*dll_PyType_Type)
+# define PySlice_Type (*dll_PySlice_Type)
 # define PyType_Ready (*dll_PyType_Ready)
 # define PyType_GenericAlloc dll_PyType_GenericAlloc
 # define Py_BuildValue dll_Py_BuildValue
@@ -341,6 +343,9 @@ static PyObject*(*dll_PySequence_Fast)(PyObject *, const char *);
 static PyInt(*dll_PyTuple_Size)(PyObject *);
 static PyObject*(*dll_PyTuple_GetItem)(PyObject *, PyInt);
 static PyTypeObject* dll_PyTuple_Type;
+static int (*dll_PySlice_GetIndicesEx)(PyObject *r, PyInt length,
+                    PyInt *start, PyInt *stop, PyInt *step,
+                    PyInt *slicelen);
 static PyObject*(*dll_PyImport_ImportModule)(const char *);
 static PyObject*(*dll_PyDict_New)(void);
 static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
@@ -382,6 +387,7 @@ static int(*dll_PySys_SetObject)(char *, PyObject *);
 static PyObject *(*dll_PySys_GetObject)(char *);
 static int(*dll_PySys_SetArgv)(int, char **);
 static PyTypeObject* dll_PyType_Type;
+static PyTypeObject* dll_PySlice_Type;
 static int (*dll_PyType_Ready)(PyTypeObject *type);
 static PyObject* (*dll_PyType_GenericAlloc)(PyTypeObject *type, PyInt nitems);
 static PyObject*(*dll_Py_BuildValue)(char *, ...);
@@ -521,6 +527,7 @@ static struct
     {"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem},
     {"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size},
     {"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type},
+    {"PySlice_GetIndicesEx", (PYTHON_PROC*)&dll_PySlice_GetIndicesEx},
     {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
     {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
     {"PyDict_Next", (PYTHON_PROC*)&dll_PyDict_Next},
@@ -562,6 +569,7 @@ static struct
     {"PySys_GetObject", (PYTHON_PROC*)&dll_PySys_GetObject},
     {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
     {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
+    {"PySlice_Type", (PYTHON_PROC*)&dll_PySlice_Type},
     {"PyType_Ready", (PYTHON_PROC*)&dll_PyType_Ready},
     {"PyType_GenericAlloc", (PYTHON_PROC*)&dll_PyType_GenericAlloc},
     {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod},
@@ -1472,21 +1480,6 @@ DictionaryGetattr(PyObject *self, char *name)
     return Py_FindMethod(DictionaryMethods, self, name);
 }
 
-static PySequenceMethods ListAsSeq = {
-    (PyInquiry)                        ListLength,
-    (binaryfunc)               0,
-    (PyIntArgFunc)             0,
-    (PyIntArgFunc)             ListItem,
-    (PyIntIntArgFunc)          ListSlice,
-    (PyIntObjArgProc)          ListAssItem,
-    (PyIntIntObjArgProc)       ListAssSlice,
-    (objobjproc)               0,
-#if PY_MAJOR_VERSION >= 2
-    (binaryfunc)               ListConcatInPlace,
-    0,
-#endif
-};
-
     static PyObject *
 ListGetattr(PyObject *self, char *name)
 {
index 40bc97bc8c931bed6e6a8acc3b71c4a49ffae128..55779e79b35405ea56ed93d98e46efe28792fe76 100644 (file)
@@ -97,6 +97,9 @@
 #define Py_ssize_t_fmt "n"
 #define Py_bytes_fmt "y"
 
+#define PyIntArgFunc   ssizeargfunc
+#define PyIntObjArgProc        ssizeobjargproc
+
 #if defined(DYNAMIC_PYTHON3) || defined(PROTO)
 
 # ifndef WIN3264
@@ -292,7 +295,8 @@ static PyObject* (*py3_PyTuple_GetItem)(PyObject *, Py_ssize_t);
 static int (*py3_PyMapping_Check)(PyObject *);
 static PyObject* (*py3_PyMapping_Keys)(PyObject *);
 static int (*py3_PySlice_GetIndicesEx)(PyObject *r, Py_ssize_t length,
-                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength);
+                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
+                    Py_ssize_t *slicelen);
 static PyObject* (*py3_PyErr_NoMemory)(void);
 static void (*py3_Py_Finalize)(void);
 static void (*py3_PyErr_SetString)(PyObject *, const char *);
@@ -1478,76 +1482,6 @@ DictionarySetattro(PyObject *self, PyObject *nameobj, PyObject *val)
 /* List object - Definitions
  */
 
-static PySequenceMethods ListAsSeq = {
-    (lenfunc)          ListLength,      /* sq_length,    len(x)   */
-    (binaryfunc)       0,               /* RangeConcat, sq_concat,  x+y   */
-    (ssizeargfunc)     0,               /* RangeRepeat, sq_repeat,  x*n   */
-    (ssizeargfunc)     ListItem,        /* sq_item,      x[i]     */
-    (void *)           0,               /* was_sq_slice,     x[i:j]   */
-    (ssizeobjargproc)  ListAssItem,     /* sq_as_item,  x[i]=v   */
-    (void *)           0,               /* was_sq_ass_slice, x[i:j]=v */
-    0,                                  /* sq_contains */
-    (binaryfunc)       ListConcatInPlace,/* sq_inplace_concat */
-    0,                                  /* sq_inplace_repeat */
-};
-
-static PyObject *ListSubscript(PyObject *, PyObject *);
-static Py_ssize_t ListAsSubscript(PyObject *, PyObject *, PyObject *);
-
-static PyMappingMethods ListAsMapping = {
-    /* mp_length       */ (lenfunc) ListLength,
-    /* mp_subscript     */ (binaryfunc) ListSubscript,
-    /* mp_ass_subscript */ (objobjargproc) ListAsSubscript,
-};
-
-    static PyObject *
-ListSubscript(PyObject *self, PyObject* idx)
-{
-    if (PyLong_Check(idx))
-    {
-       long _idx = PyLong_AsLong(idx);
-       return ListItem((ListObject *)(self), _idx);
-    }
-    else if (PySlice_Check(idx))
-    {
-       Py_ssize_t start, stop, step, slicelen;
-
-       if (PySlice_GetIndicesEx(idx, ListLength((ListObject *)(self)),
-                                &start, &stop, &step, &slicelen) < 0)
-           return NULL;
-       return ListSlice((ListObject *)(self), start, stop);
-    }
-    else
-    {
-       RAISE_INVALID_INDEX_TYPE(idx);
-       return NULL;
-    }
-}
-
-    static Py_ssize_t
-ListAsSubscript(PyObject *self, PyObject *idx, PyObject *obj)
-{
-    if (PyLong_Check(idx))
-    {
-       long _idx = PyLong_AsLong(idx);
-       return ListAssItem((ListObject *)(self), _idx, obj);
-    }
-    else if (PySlice_Check(idx))
-    {
-       Py_ssize_t start, stop, step, slicelen;
-
-       if (PySlice_GetIndicesEx(idx, ListLength((ListObject *)(self)),
-                                &start, &stop, &step, &slicelen) < 0)
-           return -1;
-       return ListAssSlice((ListObject *)(self), start, stop, obj);
-    }
-    else
-    {
-       RAISE_INVALID_INDEX_TYPE(idx);
-       return -1;
-    }
-}
-
     static PyObject *
 ListGetattro(PyObject *self, PyObject *nameobj)
 {
index ee2da1b0266f81a9b0a37b26642b240e6d05d48f..3fa265ef7480ee3083e1815e3c640167d2992543 100644 (file)
@@ -60,6 +60,7 @@ int list_append_dict __ARGS((list_T *list, dict_T *dict));
 int list_append_string __ARGS((list_T *l, char_u *str, int len));
 int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
 void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
+void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
 int garbage_collect __ARGS((void));
 void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
 void set_ref_in_list __ARGS((list_T *l, int copyID));
index 128055b32e23503b85875ad29752693ff1225606..1ccf7bd3ded3151f3572a552147ced6652cea95e 100644 (file)
@@ -135,6 +135,18 @@ EOF
 :py l=vim.bindeval('l')
 :py del l[-6:2]
 :$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[::2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[3:0:-2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[2:4:-2]
+:$put =string(l)
 :"
 :" Slice assignment to a list
 :let l = [0, 1, 2, 3]
@@ -169,6 +181,26 @@ EOF
 :py l=vim.bindeval('l')
 :py l[0:0]=['h']
 :$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:py l[2:6:2] = [10, 20]
+:$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:py l[6:2:-2] = [10, 20]
+:$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:py l[6:2] = ()
+:$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:py l[6:2:1] = ()
+:$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:py l[2:2:1] = ()
+:$put =string(l)
 :"
 :" Locked variables
 :let l = [0, 1, 2, 3]
@@ -390,6 +422,13 @@ EOF
 :$put =string(pyeval('l'))
 :py l = ll[-10:10]
 :$put =string(pyeval('l'))
+:py l = ll[4:2:-1]
+:$put =string(pyeval('l'))
+:py l = ll[::2]
+:$put =string(pyeval('l'))
+:py l = ll[4:2:1]
+:$put =string(pyeval('l'))
+:py del l
 :"
 :" Vars
 :let g:foo = 'bac'
@@ -907,6 +946,7 @@ dl.locked = True
 l = vim.List()
 ll = vim.List('abcE')
 ll.locked = True
+nel = vim.List('abcO')
 f = vim.Function('string')
 fd = vim.Function('F')
 fdel = vim.Function('D')
@@ -994,6 +1034,20 @@ class FailingIterNext(object):
     def next(self):
         raise NotImplementedError('next')
 
+class FailingIterNextN(object):
+    def __init__(self, n):
+        self.n = n
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if self.n:
+            self.n -= 1
+            return 1
+        else:
+            raise NotImplementedError('next N')
+
 class FailingMappingKey(object):
     def __getitem__(self, item):
         raise NotImplementedError('getitem:mappingkey')
@@ -1098,6 +1152,7 @@ cb.append(">>> kwargs")
 cb.append(">>> iter")
 ee('d.update(FailingMapping())')
 ee('d.update([FailingIterNext()])')
+ee('d.update([FailingIterNextN(1)])')
 iter_test('d.update(%s)')
 convertfrompyobject_test('d.update(%s)')
 stringtochars_test('d.update(((%s, 0),))')
@@ -1120,6 +1175,14 @@ ee('l[1000] = 3')
 cb.append(">> ListAssSlice")
 ee('ll[1:100] = "abcJ"')
 iter_test('l[:] = %s')
+ee('nel[1:10:2]  = "abcK"')
+cb.append(repr(tuple(nel)))
+ee('nel[1:10:2]  = "a"')
+cb.append(repr(tuple(nel)))
+ee('nel[1:1:-1]  = "a"')
+cb.append(repr(tuple(nel)))
+ee('nel[:] = FailingIterNextN(2)')
+cb.append(repr(tuple(nel)))
 convertfrompyobject_test('l[:] = [%s]')
 cb.append(">> ListConcatInPlace")
 iter_test('l.extend(%s)')
@@ -1201,6 +1264,7 @@ del ned
 del dl
 del l
 del ll
+del nel
 del f
 del fd
 del fdel
@@ -1214,6 +1278,7 @@ del number_test
 del FailingTrue
 del FailingIter
 del FailingIterNext
+del FailingIterNextN
 del FailingMapping
 del FailingMappingKey
 del FailingList
index 9ef21db0cba69840f0e09de86fed4f2a27ead2e5..42cb0259c8b047bc7c5c0ed464dba1ecdb3bc064 100644 (file)
@@ -41,6 +41,9 @@ None
 [2, 3]
 [2, 3]
 [2, 3]
+[1, 3]
+[0, 2]
+[0, 1, 2, 3]
 ['a', 0, 1, 2, 3]
 [0, 'b', 2, 3]
 [0, 1, 'c']
@@ -49,6 +52,11 @@ None
 ['f', 2, 3]
 [0, 1, 'g', 2, 3]
 ['h']
+[0, 1, 10, 3, 20, 5, 6, 7]
+[0, 1, 2, 3, 20, 5, 10, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
 [0, 1, 2, 3]
 [function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
 [function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
@@ -96,6 +104,9 @@ vim: Vim(let):E859:
 [0, 1, 2, 3, 4, 5]
 [0, 1, 2, 3, 4, 5]
 [0, 1, 2, 3, 4, 5]
+[4, 3]
+[0, 2, 4]
+[]
 Abc
 bac
 def
@@ -599,6 +610,7 @@ d["a"] = FailingNumber():TypeError:('long() argument must be a string or a numbe
 >>> iter
 d.update(FailingMapping()):NotImplementedError:('keys',)
 d.update([FailingIterNext()]):NotImplementedError:('next',)
+d.update([FailingIterNextN(1)]):NotImplementedError:('next N',)
 >>> Testing *Iter* using d.update(%s)
 d.update(FailingIter()):NotImplementedError:('iter',)
 d.update(FailingIterNext()):NotImplementedError:('next',)
@@ -829,6 +841,14 @@ ll[1:100] = "abcJ":error:('list is locked',)
 l[:] = FailingIter():NotImplementedError:('iter',)
 l[:] = FailingIterNext():NotImplementedError:('next',)
 <<< Finished
+nel[1:10:2]  = "abcK":ValueError:('attempt to assign sequence of size greater then 2 to extended slice',)
+('a', 'b', 'c', 'O')
+nel[1:10:2]  = "a":ValueError:('attempt to assign sequence of size 1 to extended slice of size 2',)
+('a', 'b', 'c', 'O')
+nel[1:1:-1]  = "a":ValueError:('attempt to assign sequence of size greater then 0 to extended slice',)
+('a', 'b', 'c', 'O')
+nel[:] = FailingIterNextN(2):NotImplementedError:('next N',)
+('a', 'b', 'c', 'O')
 >>> Testing StringToChars using l[:] = [{%s : 1}]
 l[:] = [{1 : 1}]:TypeError:('expected str() or unicode() instance, but got int',)
 l[:] = [{u"\0" : 1}]:TypeError:('expected string without null bytes',)
index 9abc17b1e38d6ddeafb76df650d9740e25f1eb72..79b24b00dedaae056362bc4bd391aae7b6f10364 100644 (file)
@@ -128,6 +128,18 @@ EOF
 :py3 l=vim.bindeval('l')
 :py3 del l[-6:2]
 :$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[::2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[3:0:-2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[2:4:-2]
+:$put =string(l)
 :"
 :" Slice assignment to a list
 :let l = [0, 1, 2, 3]
@@ -162,6 +174,26 @@ EOF
 :py3 l=vim.bindeval('l')
 :py3 l[0:0]=['h']
 :$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:py3 l[2:6:2] = [10, 20]
+:$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:py3 l[6:2:-2] = [10, 20]
+:$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:py3 l[6:2] = ()
+:$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:py3 l[6:2:1] = ()
+:$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:py3 l[2:2:1] = ()
+:$put =string(l)
 :"
 :" Locked variables
 :let l = [0, 1, 2, 3]
@@ -363,6 +395,38 @@ EOF
 :py3 del trace_main
 :$put =string(l)
 :"
+:" Slice
+:py3 ll = vim.bindeval('[0, 1, 2, 3, 4, 5]')
+:py3 l = ll[:4]
+:$put =string(py3eval('l'))
+:py3 l = ll[2:]
+:$put =string(py3eval('l'))
+:py3 l = ll[:-4]
+:$put =string(py3eval('l'))
+:py3 l = ll[-2:]
+:$put =string(py3eval('l'))
+:py3 l = ll[2:4]
+:$put =string(py3eval('l'))
+:py3 l = ll[4:2]
+:$put =string(py3eval('l'))
+:py3 l = ll[-4:-2]
+:$put =string(py3eval('l'))
+:py3 l = ll[-2:-4]
+:$put =string(py3eval('l'))
+:py3 l = ll[:]
+:$put =string(py3eval('l'))
+:py3 l = ll[0:6]
+:$put =string(py3eval('l'))
+:py3 l = ll[-10:10]
+:$put =string(py3eval('l'))
+:py3 l = ll[4:2:-1]
+:$put =string(py3eval('l'))
+:py3 l = ll[::2]
+:$put =string(py3eval('l'))
+:py3 l = ll[4:2:1]
+:$put =string(py3eval('l'))
+:py3 del l
+:"
 :" Vars
 :let g:foo = 'bac'
 :let w:abc3 = 'def'
@@ -859,6 +923,7 @@ dl.locked = True
 l = vim.List()
 ll = vim.List('abcE')
 ll.locked = True
+nel = vim.List('abcO')
 f = vim.Function('string')
 fd = vim.Function('F')
 fdel = vim.Function('D')
@@ -946,6 +1011,20 @@ class FailingIterNext(object):
     def __next__(self):
         raise NotImplementedError('next')
 
+class FailingIterNextN(object):
+    def __init__(self, n):
+        self.n = n
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if self.n:
+            self.n -= 1
+            return 1
+        else:
+            raise NotImplementedError('next N')
+
 class FailingMappingKey(object):
     def __getitem__(self, item):
         raise NotImplementedError('getitem:mappingkey')
@@ -1050,6 +1129,7 @@ cb.append(">>> kwargs")
 cb.append(">>> iter")
 ee('d.update(FailingMapping())')
 ee('d.update([FailingIterNext()])')
+ee('d.update([FailingIterNextN(1)])')
 iter_test('d.update(%s)')
 convertfrompyobject_test('d.update(%s)')
 stringtochars_test('d.update(((%s, 0),))')
@@ -1072,6 +1152,14 @@ ee('l[1000] = 3')
 cb.append(">> ListAssSlice")
 ee('ll[1:100] = "abcJ"')
 iter_test('l[:] = %s')
+ee('nel[1:10:2]  = "abcK"')
+cb.append(repr(tuple(nel)))
+ee('nel[1:10:2]  = "a"')
+cb.append(repr(tuple(nel)))
+ee('nel[1:1:-1]  = "a"')
+cb.append(repr(tuple(nel)))
+ee('nel[:] = FailingIterNextN(2)')
+cb.append(repr(tuple(nel)))
 convertfrompyobject_test('l[:] = [%s]')
 cb.append(">> ListConcatInPlace")
 iter_test('l.extend(%s)')
@@ -1153,6 +1241,7 @@ del ned
 del dl
 del l
 del ll
+del nel
 del f
 del fd
 del fdel
@@ -1166,6 +1255,7 @@ del number_test
 del FailingTrue
 del FailingIter
 del FailingIterNext
+del FailingIterNextN
 del FailingMapping
 del FailingMappingKey
 del FailingList
index d970d5f3aa90c9a727943a17985727c013908414..57ac1a63a9341d7e2af181fe51a951092bdbc7ba 100644 (file)
@@ -41,6 +41,9 @@ None
 [2, 3]
 [2, 3]
 [2, 3]
+[1, 3]
+[0, 2]
+[0, 1, 2, 3]
 ['a', 0, 1, 2, 3]
 [0, 'b', 2, 3]
 [0, 1, 'c']
@@ -49,6 +52,11 @@ None
 ['f', 2, 3]
 [0, 1, 'g', 2, 3]
 ['h']
+[0, 1, 10, 3, 20, 5, 6, 7]
+[0, 1, 2, 3, 20, 5, 10, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
+[0, 1, 2, 3, 4, 5, 6, 7]
 [0, 1, 2, 3]
 [function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
 [function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
@@ -85,6 +93,20 @@ undefined_name:      Vim(let):Trace
 vim:   Vim(let):E859:
 [1]
 [1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1]
+[0, 1, 2, 3]
+[2, 3, 4, 5]
+[0, 1]
+[4, 5]
+[2, 3]
+[]
+[2, 3]
+[]
+[0, 1, 2, 3, 4, 5]
+[0, 1, 2, 3, 4, 5]
+[0, 1, 2, 3, 4, 5]
+[4, 3]
+[0, 2, 4]
+[]
 Abc
 bac
 def
@@ -588,6 +610,7 @@ d["a"] = FailingNumber():(<class 'NotImplementedError'>, NotImplementedError('in
 >>> iter
 d.update(FailingMapping()):(<class 'NotImplementedError'>, NotImplementedError('keys',))
 d.update([FailingIterNext()]):(<class 'NotImplementedError'>, NotImplementedError('next',))
+d.update([FailingIterNextN(1)]):(<class 'NotImplementedError'>, NotImplementedError('next N',))
 >>> Testing *Iter* using d.update(%s)
 d.update(FailingIter()):(<class 'NotImplementedError'>, NotImplementedError('iter',))
 d.update(FailingIterNext()):(<class 'NotImplementedError'>, NotImplementedError('next',))
@@ -818,6 +841,14 @@ ll[1:100] = "abcJ":(<class 'vim.error'>, error('list is locked',))
 l[:] = FailingIter():(<class 'NotImplementedError'>, NotImplementedError('iter',))
 l[:] = FailingIterNext():(<class 'NotImplementedError'>, NotImplementedError('next',))
 <<< Finished
+nel[1:10:2]  = "abcK":(<class 'ValueError'>, ValueError('attempt to assign sequence of size greater then 2 to extended slice',))
+(b'a', b'b', b'c', b'O')
+nel[1:10:2]  = "a":(<class 'ValueError'>, ValueError('attempt to assign sequence of size 1 to extended slice of size 2',))
+(b'a', b'b', b'c', b'O')
+nel[1:1:-1]  = "a":(<class 'ValueError'>, ValueError('attempt to assign sequence of size greater then 0 to extended slice',))
+(b'a', b'b', b'c', b'O')
+nel[:] = FailingIterNextN(2):(<class 'NotImplementedError'>, NotImplementedError('next N',))
+(b'a', b'b', b'c', b'O')
 >>> Testing StringToChars using l[:] = [{%s : 1}]
 l[:] = [{1 : 1}]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
 l[:] = [{b"\0" : 1}]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
index 6c2c60fb095d16a4f5fc47f1b8dde1152c12fcb1..c0fe21f3f978b1bd9db9a254c5f16860a0c8d792 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    151,
 /**/
     150,
 /**/