To: vim_dev@googlegroups.com Subject: Patch 7.4.151 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.151 Problem: Python: slices with steps are not supported. Solution: Support slices in Python vim.List. (ZyX) Files: src/eval.c, src/if_py_both.h, src/if_python3.c, src/if_python.c, src/proto/eval.pro, src/testdir/test86.in, src/testdir/test86.ok, src/testdir/test87.in, src/testdir/test87.ok *** ../vim-7.4.150/src/eval.c 2014-01-14 15:24:24.000000000 +0100 --- src/eval.c 2014-01-14 16:24:49.000000000 +0100 *************** *** 6425,6430 **** --- 6425,6440 ---- 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,6452 **** item->li_prev = ni; ++l->lv_len; } - return OK; } /* --- 6456,6461 ---- *** ../vim-7.4.150/src/if_py_both.h 2014-01-10 18:16:00.000000000 +0100 --- src/if_py_both.h 2014-01-14 16:31:49.000000000 +0100 *************** *** 36,43 **** #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 Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \ ? "(NULL)" \ --- 36,44 ---- #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, 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,2115 **** }; static PyTypeObject ListType; - static PySequenceMethods ListAsSeq; - static PyMappingMethods ListAsMapping; typedef struct { --- 2109,2114 ---- *************** *** 2253,2259 **** } static PyObject * ! ListItem(ListObject *self, Py_ssize_t index) { listitem_T *li; --- 2252,2258 ---- } static PyObject * ! ListIndex(ListObject *self, Py_ssize_t index) { listitem_T *li; *************** *** 2273,2436 **** 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) { PyInt i; - PyInt size = ListLength(self); - PyInt n; PyObject *list; - int reversed = 0; ! PROC_RANGE ! if (first >= last) ! first = last; ! n = last-first; ! list = PyList_New(n); if (list == NULL) return NULL; ! for (i = 0; i < n; ++i) { ! PyObject *item = ListItem(self, first + i); if (item == NULL) { Py_DECREF(list); return NULL; } ! PyList_SET_ITEM(list, ((reversed)?(n-i-1):(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) { ! 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 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) { ! 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 int ! ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj) { - PyInt size = ListLength(self); PyObject *iterator; PyObject *item; listitem_T *li; listitem_T *next; typval_T v; list_T *l = self->list; PyInt i; if (l->lv_lock) { --- 2272,2381 ---- return ConvertToPyObject(&li->li_tv); } static PyObject * ! ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step, ! Py_ssize_t slicelen) { PyInt i; PyObject *list; ! if (step == 0) ! { ! PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero")); ! return NULL; ! } ! list = PyList_New(slicelen); if (list == NULL) return NULL; ! for (i = 0; i < slicelen; ++i) { ! PyObject *item; ! ! item = ListIndex(self, first + i*step); if (item == NULL) { Py_DECREF(list); return NULL; } ! PyList_SET_ITEM(list, i, item); } return list; } static PyObject * ! ListItem(ListObject *self, PyObject* idx) { ! #if PY_MAJOR_VERSION < 3 ! if (PyInt_Check(idx)) { ! long _idx = PyInt_AsLong(idx); ! return ListIndex(self, _idx); } ! else ! #endif ! if (PyLong_Check(idx)) { ! long _idx = PyLong_AsLong(idx); ! return ListIndex(self, _idx); } ! else if (PySlice_Check(idx)) { ! Py_ssize_t start, stop, step, slicelen; ! if (PySlice_GetIndicesEx(idx, ListLength(self), ! &start, &stop, &step, &slicelen) < 0) ! return NULL; ! return ListSlice(self, start, step, slicelen); ! } ! else { ! RAISE_INVALID_INDEX_TYPE(idx); ! return NULL; } + } ! 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--) { ! list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]); ! listitem_remove(l, lis[slicelen + numreplaced]); } ! while (numadded--) { ! listitem_T *next; ! ! next = lastaddedli->li_prev; ! listitem_remove(l, lastaddedli); ! lastaddedli = next; } } static int ! ListAssSlice(ListObject *self, Py_ssize_t first, ! Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj) { 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,2444 **** return -1; } ! PROC_RANGE if (first == size) li = NULL; --- 2383,2424 ---- return -1; } ! 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,2465 **** { PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"), (int)first); return -1; } ! if (last > first) { ! i = last - first; ! while (i-- && li != NULL) ! { ! next = li->li_next; listitem_remove(l, li); ! li = next; ! } } } --- 2429,2461 ---- { PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"), (int)first); + if (obj != NULL) + PyMem_Free(lis); return -1; } ! i = slicelen; ! while (i-- && li != NULL) { ! 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); ! 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,2499 **** return 0; if (!(iterator = PyObject_GetIter(obj))) return -1; while ((item = PyIter_Next(iterator))) { if (ConvertFromPyObject(item, &v) == -1) { Py_DECREF(iterator); Py_DECREF(item); return -1; } Py_DECREF(item); ! if (list_insert_tv(l, &v, li) == FAIL) { clear_tv(&v); PyErr_SET_VIM(N_("internal error: failed to add item to list")); return -1; } clear_tv(&v); } Py_DECREF(iterator); if (PyErr_Occurred()) return -1; return 0; } static PyObject * ListConcatInPlace(ListObject *self, PyObject *obj) { --- 2463,2634 ---- 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, 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,2525 **** --- 2655,2710 ---- 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,2572 **** --- 2752,2776 ---- } } + 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, ""}, *** ../vim-7.4.150/src/if_python3.c 2013-11-03 00:28:20.000000000 +0100 --- src/if_python3.c 2014-01-14 16:32:40.000000000 +0100 *************** *** 97,102 **** --- 97,105 ---- #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,298 **** 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); static PyObject* (*py3_PyErr_NoMemory)(void); static void (*py3_Py_Finalize)(void); static void (*py3_PyErr_SetString)(PyObject *, const char *); --- 295,302 ---- 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 *slicelen); static PyObject* (*py3_PyErr_NoMemory)(void); static void (*py3_Py_Finalize)(void); static void (*py3_PyErr_SetString)(PyObject *, const char *); *************** *** 1478,1553 **** /* 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) { --- 1482,1487 ---- *** ../vim-7.4.150/src/if_python.c 2013-11-03 00:28:20.000000000 +0100 --- src/if_python.c 2014-01-14 16:24:49.000000000 +0100 *************** *** 196,201 **** --- 196,202 ---- # 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,246 **** --- 242,248 ---- # 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,346 **** --- 343,351 ---- 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,387 **** --- 387,393 ---- 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,526 **** --- 527,533 ---- {"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,567 **** --- 569,575 ---- {"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,1492 **** 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) { --- 1480,1485 ---- *** ../vim-7.4.150/src/proto/eval.pro 2013-08-10 13:37:09.000000000 +0200 --- src/proto/eval.pro 2014-01-14 16:24:49.000000000 +0100 *************** *** 60,65 **** --- 60,66 ---- 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)); *** ../vim-7.4.150/src/testdir/test86.in 2013-11-28 17:04:38.000000000 +0100 --- src/testdir/test86.in 2014-01-14 16:24:49.000000000 +0100 *************** *** 135,140 **** --- 135,152 ---- :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,174 **** --- 181,206 ---- :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,395 **** --- 422,434 ---- :$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,912 **** --- 946,952 ---- 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,999 **** --- 1034,1053 ---- 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,1103 **** --- 1152,1158 ---- 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,1125 **** --- 1175,1188 ---- 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,1206 **** --- 1264,1270 ---- del dl del l del ll + del nel del f del fd del fdel *************** *** 1214,1219 **** --- 1278,1284 ---- del FailingTrue del FailingIter del FailingIterNext + del FailingIterNextN del FailingMapping del FailingMappingKey del FailingList *** ../vim-7.4.150/src/testdir/test86.ok 2013-11-28 17:04:38.000000000 +0100 --- src/testdir/test86.ok 2014-01-14 16:24:49.000000000 +0100 *************** *** 41,46 **** --- 41,49 ---- [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,54 **** --- 52,62 ---- ['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,101 **** --- 104,112 ---- [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,604 **** --- 610,616 ---- >>> 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,834 **** --- 841,854 ---- 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',) *** ../vim-7.4.150/src/testdir/test87.in 2013-11-28 17:04:38.000000000 +0100 --- src/testdir/test87.in 2014-01-14 16:24:49.000000000 +0100 *************** *** 128,133 **** --- 128,145 ---- :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,167 **** --- 174,199 ---- :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,368 **** --- 395,432 ---- :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,864 **** --- 923,929 ---- 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,951 **** --- 1011,1030 ---- 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,1055 **** --- 1129,1135 ---- 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,1077 **** --- 1152,1165 ---- 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,1158 **** --- 1241,1247 ---- del dl del l del ll + del nel del f del fd del fdel *************** *** 1166,1171 **** --- 1255,1261 ---- del FailingTrue del FailingIter del FailingIterNext + del FailingIterNextN del FailingMapping del FailingMappingKey del FailingList *** ../vim-7.4.150/src/testdir/test87.ok 2013-11-28 17:04:38.000000000 +0100 --- src/testdir/test87.ok 2014-01-14 16:24:49.000000000 +0100 *************** *** 41,46 **** --- 41,49 ---- [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,54 **** --- 52,62 ---- ['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,90 **** --- 93,112 ---- 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,593 **** --- 610,616 ---- >>> 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',)) *************** *** 818,823 **** --- 841,854 ---- 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',)) + (b'a', b'b', b'c', b'O') + nel[1:10:2] = "a":(, 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":(, ValueError('attempt to assign sequence of size greater then 0 to extended slice',)) + (b'a', b'b', b'c', b'O') + nel[:] = FailingIterNextN(2):(, NotImplementedError('next N',)) + (b'a', b'b', b'c', b'O') >>> Testing StringToChars using l[:] = [{%s : 1}] l[:] = [{1 : 1}]:(, TypeError('expected bytes() or str() instance, but got int',)) l[:] = [{b"\0" : 1}]:(, TypeError('expected bytes with no null',)) *** ../vim-7.4.150/src/version.c 2014-01-14 15:53:47.000000000 +0100 --- src/version.c 2014-01-14 16:27:01.000000000 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 151, /**/ -- hundred-and-one symptoms of being an internet addict: 159. You get excited whenever discussing your hard drive. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///