Loading ...
Sorry, an error occurred while loading the content.
 

Patch 7.3.947

Expand Messages
  • Bram Moolenaar
    Patch 7.3.947 Problem: Python: No iterator for vim.list and vim.bufferlist. Solution: Add the iterators. Also fix name of FunctionType. Add tests for
    Message 1 of 1 , May 15, 2013
      Patch 7.3.947
      Problem: Python: No iterator for vim.list and vim.bufferlist.
      Solution: Add the iterators. Also fix name of FunctionType. Add tests for
      vim.buffers. (ZyX)
      Files: runtime/doc/if_pyth.txt, 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.3.946/runtime/doc/if_pyth.txt 2013-05-15 13:38:41.000000000 +0200
      --- runtime/doc/if_pyth.txt 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 214,219 ****
      --- 214,220 ----
      :py b = vim.buffers[i] # Indexing (read-only)
      :py b in vim.buffers # Membership test
      :py n = len(vim.buffers) # Number of elements
      + :py for b in vim.buffers: # Iterating over buffer list
      <
      vim.windows *python-windows*
      A sequence object providing access to the list of vim windows. The
      *** ../vim-7.3.946/src/eval.c 2013-05-06 04:50:26.000000000 +0200
      --- src/eval.c 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 390,397 ****
      static void clear_lval __ARGS((lval_T *lp));
      static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
      static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
      - static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
      - static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
      static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
      static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
      static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
      --- 390,395 ----
      ***************
      *** 3106,3112 ****
      /*
      * Add a watcher to a list.
      */
      ! static void
      list_add_watch(l, lw)
      list_T *l;
      listwatch_T *lw;
      --- 3104,3110 ----
      /*
      * Add a watcher to a list.
      */
      ! void
      list_add_watch(l, lw)
      list_T *l;
      listwatch_T *lw;
      ***************
      *** 3119,3125 ****
      * Remove a watcher from a list.
      * No warning when it isn't found...
      */
      ! static void
      list_rem_watch(l, lwrem)
      list_T *l;
      listwatch_T *lwrem;
      --- 3117,3123 ----
      * Remove a watcher from a list.
      * No warning when it isn't found...
      */
      ! void
      list_rem_watch(l, lwrem)
      list_T *l;
      listwatch_T *lwrem;
      *** ../vim-7.3.946/src/if_py_both.h 2013-05-15 13:38:41.000000000 +0200
      --- src/if_py_both.h 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 531,596 ****
      };

      /*
      ! * Buffer list object - Implementation
      */

      ! static PyTypeObject BufMapType;

      typedef struct
      {
      PyObject_HEAD
      ! } BufMapObject;

      ! static PyInt
      ! BufMapLength(PyObject *self UNUSED)
      {
      ! buf_T *b = firstbuf;
      ! PyInt n = 0;

      ! while (b)
      ! {
      ! ++n;
      ! b = b->b_next;
      ! }

      ! return n;
      }

      ! static PyObject *
      ! BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
      {
      ! buf_T *b;
      ! int bnr;

      ! #if PY_MAJOR_VERSION < 3
      ! if (PyInt_Check(keyObject))
      ! bnr = PyInt_AsLong(keyObject);
      ! else
      ! #endif
      ! if (PyLong_Check(keyObject))
      ! bnr = PyLong_AsLong(keyObject);
      ! else
      ! {
      ! PyErr_SetString(PyExc_ValueError, _("key must be integer"));
      ! return NULL;
      ! }

      ! b = buflist_findnr(bnr);

      ! if (b)
      ! return BufferNew(b);
      ! else
      ! {
      ! PyErr_SetString(PyExc_KeyError, _("no such buffer"));
      ! return NULL;
      ! }
      }

      ! static PyMappingMethods BufMapAsMapping = {
      ! (lenfunc) BufMapLength,
      ! (binaryfunc) BufMapItem,
      ! (objobjargproc) 0,
      ! };

      typedef struct pylinkedlist_S {
      struct pylinkedlist_S *pll_next;
      --- 531,592 ----
      };

      /*
      ! * Generic iterator object
      */

      ! static PyTypeObject IterType;
      !
      ! typedef PyObject *(*nextfun)(void **);
      ! typedef void (*destructorfun)(void *);
      !
      ! /* Main purpose of this object is removing the need for do python initialization
      ! * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
      ! */

      typedef struct
      {
      PyObject_HEAD
      ! void *cur;
      ! nextfun next;
      ! destructorfun destruct;
      ! } IterObject;

      ! static PyObject *
      ! IterNew(void *start, destructorfun destruct, nextfun next)
      {
      ! IterObject *self;

      ! self = PyObject_NEW(IterObject, &IterType);
      ! self->cur = start;
      ! self->next = next;
      ! self->destruct = destruct;

      ! return (PyObject *)(self);
      }

      ! static void
      ! IterDestructor(PyObject *self)
      {
      ! IterObject *this = (IterObject *)(self);

      ! this->destruct(this->cur);

      ! DESTRUCTOR_FINISH(self);
      ! }

      ! static PyObject *
      ! IterNext(PyObject *self)
      ! {
      ! IterObject *this = (IterObject *)(self);
      !
      ! return this->next(&this->cur);
      }

      ! static PyObject *
      ! IterIter(PyObject *self)
      ! {
      ! return self;
      ! }

      typedef struct pylinkedlist_S {
      struct pylinkedlist_S *pll_next;
      ***************
      *** 990,995 ****
      --- 986,1040 ----
      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 *r;
      +
      + if (!((*lii)->lw.lw_item))
      + return NULL;
      +
      + if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
      + return NULL;
      +
      + (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
      +
      + return r;
      + }
      +
      + static PyObject *
      + ListIter(PyObject *self)
      + {
      + listiterinfo_T *lii;
      + list_T *l = ((ListObject *) (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);
      + }
      +
      static int
      ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
      {
      ***************
      *** 2869,2874 ****
      --- 2914,3029 ----
      { NULL, NULL, 0, NULL }
      };

      + /*
      + * Buffer list object - Implementation
      + */
      +
      + static PyTypeObject BufMapType;
      +
      + typedef struct
      + {
      + PyObject_HEAD
      + } BufMapObject;
      +
      + static PyInt
      + BufMapLength(PyObject *self UNUSED)
      + {
      + buf_T *b = firstbuf;
      + PyInt n = 0;
      +
      + while (b)
      + {
      + ++n;
      + b = b->b_next;
      + }
      +
      + return n;
      + }
      +
      + static PyObject *
      + BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
      + {
      + buf_T *b;
      + int bnr;
      +
      + #if PY_MAJOR_VERSION < 3
      + if (PyInt_Check(keyObject))
      + bnr = PyInt_AsLong(keyObject);
      + else
      + #endif
      + if (PyLong_Check(keyObject))
      + bnr = PyLong_AsLong(keyObject);
      + else
      + {
      + PyErr_SetString(PyExc_ValueError, _("key must be integer"));
      + return NULL;
      + }
      +
      + b = buflist_findnr(bnr);
      +
      + if (b)
      + return BufferNew(b);
      + else
      + {
      + PyErr_SetString(PyExc_KeyError, _("no such buffer"));
      + return NULL;
      + }
      + }
      +
      + static void
      + BufMapIterDestruct(PyObject *buffer)
      + {
      + /* Iteration was stopped before all buffers were processed */
      + if (buffer)
      + {
      + Py_DECREF(buffer);
      + }
      + }
      +
      + static PyObject *
      + BufMapIterNext(PyObject **buffer)
      + {
      + PyObject *next;
      + PyObject *r;
      +
      + if (!*buffer)
      + return NULL;
      +
      + r = *buffer;
      +
      + if (CheckBuffer((BufferObject *)(r)))
      + {
      + *buffer = NULL;
      + return NULL;
      + }
      +
      + if (!((BufferObject *)(r))->buf->b_next)
      + next = NULL;
      + else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
      + return NULL;
      + *buffer = next;
      + /* Do not increment reference: we no longer hold it (decref), but whoever on
      + * other side will hold (incref). Decref+incref = nothing.
      + */
      + return r;
      + }
      +
      + static PyObject *
      + BufMapIter(PyObject *self UNUSED)
      + {
      + PyObject *buffer;
      +
      + buffer = BufferNew(firstbuf);
      + return IterNew(buffer,
      + (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext);
      + }
      +
      + static PyMappingMethods BufMapAsMapping = {
      + (lenfunc) BufMapLength,
      + (binaryfunc) BufMapItem,
      + (objobjargproc) 0,
      + };
      +
      /* Current items object
      */

      ***************
      *** 3383,3388 ****
      --- 3538,3551 ----
      OutputType.tp_setattr = OutputSetattr;
      #endif

      + vim_memset(&IterType, 0, sizeof(IterType));
      + IterType.tp_name = "vim.iter";
      + IterType.tp_basicsize = sizeof(IterObject);
      + IterType.tp_flags = Py_TPFLAGS_DEFAULT;
      + IterType.tp_doc = "generic iterator object";
      + IterType.tp_iter = IterIter;
      + IterType.tp_iternext = IterNext;
      +
      vim_memset(&BufferType, 0, sizeof(BufferType));
      BufferType.tp_name = "vim.buffer";
      BufferType.tp_basicsize = sizeof(BufferType);
      ***************
      *** 3426,3431 ****
      --- 3589,3595 ----
      BufMapType.tp_basicsize = sizeof(BufMapObject);
      BufMapType.tp_as_mapping = &BufMapAsMapping;
      BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
      + BufMapType.tp_iter = BufMapIter;
      BufferType.tp_doc = "vim buffer list";

      vim_memset(&WinListType, 0, sizeof(WinListType));
      ***************
      *** 3492,3497 ****
      --- 3656,3662 ----
      ListType.tp_flags = Py_TPFLAGS_DEFAULT;
      ListType.tp_doc = "list pushing modifications to vim structure";
      ListType.tp_methods = ListMethods;
      + ListType.tp_iter = ListIter;
      #if PY_MAJOR_VERSION >= 3
      ListType.tp_getattro = ListGetattro;
      ListType.tp_setattro = ListSetattro;
      ***************
      *** 3501,3507 ****
      #endif

      vim_memset(&FunctionType, 0, sizeof(FunctionType));
      ! FunctionType.tp_name = "vim.list";
      FunctionType.tp_basicsize = sizeof(FunctionObject);
      FunctionType.tp_dealloc = FunctionDestructor;
      FunctionType.tp_call = FunctionCall;
      --- 3666,3672 ----
      #endif

      vim_memset(&FunctionType, 0, sizeof(FunctionType));
      ! FunctionType.tp_name = "vim.function";
      FunctionType.tp_basicsize = sizeof(FunctionObject);
      FunctionType.tp_dealloc = FunctionDestructor;
      FunctionType.tp_call = FunctionCall;
      *** ../vim-7.3.946/src/if_python3.c 2013-05-15 13:38:41.000000000 +0200
      --- src/if_python3.c 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 1519,1524 ****
      --- 1519,1525 ----
      /* The special value is removed from sys.path in Python3_Init(). */
      static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};

      + PyType_Ready(&IterType);
      PyType_Ready(&BufferType);
      PyType_Ready(&RangeType);
      PyType_Ready(&WindowType);
      *** ../vim-7.3.946/src/if_python.c 2013-05-15 13:38:41.000000000 +0200
      --- src/if_python.c 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 1219,1224 ****
      --- 1219,1225 ----
      static char *(argv[2]) = {"/must>not&exist/foo", NULL};

      /* Fixups... */
      + PyType_Ready(&IterType);
      PyType_Ready(&BufferType);
      PyType_Ready(&RangeType);
      PyType_Ready(&WindowType);
      *** ../vim-7.3.946/src/proto/eval.pro 2013-05-06 03:52:44.000000000 +0200
      --- src/proto/eval.pro 2013-05-15 14:24:11.000000000 +0200
      ***************
      *** 127,130 ****
      --- 127,132 ----
      char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
      int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
      void restore_win __ARGS((win_T *, tabpage_T *));
      + void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
      + void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
      /* vim: set ft=c : */
      *** ../vim-7.3.946/src/testdir/test86.in 2013-05-12 21:16:17.000000000 +0200
      --- src/testdir/test86.in 2013-05-15 14:27:21.000000000 +0200
      ***************
      *** 477,482 ****
      --- 477,485 ----
      : call RecVars(oname)
      :endfor
      :only
      + :for buf in g:bufs[1:]
      + : execute 'bwipeout!' buf
      + :endfor
      :"
      :" Test buffer object
      :vnew
      ***************
      *** 519,524 ****
      --- 522,583 ----
      # Should not happen in any case
      cb.append('No exception for ' + expr)
      EOF
      + :"
      + :" Test vim.buffers object
      + :set hidden
      + :edit a
      + :buffer #
      + :edit b
      + :buffer #
      + :edit c
      + :buffer #
      + py << EOF
      + # Check GCing iterator that was not fully exhausted
      + i = iter(vim.buffers)
      + cb.append('i:' + str(next(i)))
      + # and also check creating more then one iterator at a time
      + i2 = iter(vim.buffers)
      + cb.append('i2:' + str(next(i2)))
      + cb.append('i:' + str(next(i)))
      + # The following should trigger GC and not cause any problems
      + del i
      + del i2
      + i3 = iter(vim.buffers)
      + cb.append('i3:' + str(next(i3)))
      + del i3
      +
      + prevnum = 0
      + for b in vim.buffers:
      + # Check buffer order
      + if prevnum >= b.number:
      + cb.append('!!! Buffer numbers not in strictly ascending order')
      + # Check indexing: vim.buffers[number].number == number
      + cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
      + prevnum = b.number
      +
      + cb.append(str(len(vim.buffers)))
      +
      + bnums = list(map(lambda b: b.number, vim.buffers))[1:]
      +
      + # Test wiping out buffer with existing iterator
      + i4 = iter(vim.buffers)
      + cb.append('i4:' + str(next(i4)))
      + vim.command('bwipeout! ' + str(bnums.pop(0)))
      + try:
      + next(i4)
      + except vim.error:
      + pass
      + else:
      + cb.append('!!!! No vim.error')
      + i4 = iter(vim.buffers)
      + vim.command('bwipeout! ' + str(bnums.pop(-1)))
      + vim.command('bwipeout! ' + str(bnums.pop(-1)))
      + cb.append('i4:' + str(next(i4)))
      + try:
      + next(i4)
      + except StopIteration:
      + cb.append('StopIteration')
      + EOF
      :endfun
      :"
      :call Test()
      *** ../vim-7.3.946/src/testdir/test86.ok 2013-05-15 13:38:41.000000000 +0200
      --- src/testdir/test86.ok 2013-05-15 14:27:21.000000000 +0200
      ***************
      *** 319,321 ****
      --- 319,333 ----
      Second line
      Third line
      foo
      + i:<buffer test86.in>
      + i2:<buffer test86.in>
      + i:<buffer a>
      + i3:<buffer test86.in>
      + 1:<buffer test86.in>=<buffer test86.in>
      + 6:<buffer a>=<buffer a>
      + 7:<buffer b>=<buffer b>
      + 8:<buffer c>=<buffer c>
      + 4
      + i4:<buffer test86.in>
      + i4:<buffer test86.in>
      + StopIteration
      *** ../vim-7.3.946/src/testdir/test87.in 2013-05-12 21:16:17.000000000 +0200
      --- src/testdir/test87.in 2013-05-15 14:27:21.000000000 +0200
      ***************
      *** 446,451 ****
      --- 446,454 ----
      : call RecVars(oname)
      :endfor
      :only
      + :for buf in g:bufs[1:]
      + : execute 'bwipeout!' buf
      + :endfor
      :"
      :" Test buffer object
      :vnew
      ***************
      *** 488,493 ****
      --- 491,552 ----
      # Should not happen in any case
      cb.append('No exception for ' + expr)
      EOF
      + :"
      + :" Test vim.buffers object
      + :set hidden
      + :edit a
      + :buffer #
      + :edit b
      + :buffer #
      + :edit c
      + :buffer #
      + py3 << EOF
      + # Check GCing iterator that was not fully exhausted
      + i = iter(vim.buffers)
      + cb.append('i:' + str(next(i)))
      + # and also check creating more then one iterator at a time
      + i2 = iter(vim.buffers)
      + cb.append('i2:' + str(next(i2)))
      + cb.append('i:' + str(next(i)))
      + # The following should trigger GC and not cause any problems
      + del i
      + del i2
      + i3 = iter(vim.buffers)
      + cb.append('i3:' + str(next(i3)))
      + del i3
      +
      + prevnum = 0
      + for b in vim.buffers:
      + # Check buffer order
      + if prevnum >= b.number:
      + cb.append('!!! Buffer numbers not in strictly ascending order')
      + # Check indexing: vim.buffers[number].number == number
      + cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
      + prevnum = b.number
      +
      + cb.append(str(len(vim.buffers)))
      +
      + bnums = list(map(lambda b: b.number, vim.buffers))[1:]
      +
      + # Test wiping out buffer with existing iterator
      + i4 = iter(vim.buffers)
      + cb.append('i4:' + str(next(i4)))
      + vim.command('bwipeout! ' + str(bnums.pop(0)))
      + try:
      + next(i4)
      + except vim.error:
      + pass
      + else:
      + cb.append('!!!! No vim.error')
      + i4 = iter(vim.buffers)
      + vim.command('bwipeout! ' + str(bnums.pop(-1)))
      + vim.command('bwipeout! ' + str(bnums.pop(-1)))
      + cb.append('i4:' + str(next(i4)))
      + try:
      + next(i4)
      + except StopIteration:
      + cb.append('StopIteration')
      + EOF
      :endfun
      :"
      :call Test()
      ***************
      *** 496,501 ****
      --- 555,561 ----
      :call garbagecollect(1)
      :"
      :/^start:/,$wq! test.out
      + :call getchar()
      ENDTEST

      start:
      *** ../vim-7.3.946/src/testdir/test87.ok 2013-05-15 13:38:41.000000000 +0200
      --- src/testdir/test87.ok 2013-05-15 14:27:21.000000000 +0200
      ***************
      *** 308,310 ****
      --- 308,322 ----
      Second line
      Third line
      foo
      + i:<buffer test87.in>
      + i2:<buffer test87.in>
      + i:<buffer a>
      + i3:<buffer test87.in>
      + 1:<buffer test87.in>=<buffer test87.in>
      + 6:<buffer a>=<buffer a>
      + 7:<buffer b>=<buffer b>
      + 8:<buffer c>=<buffer c>
      + 4
      + i4:<buffer test87.in>
      + i4:<buffer test87.in>
      + StopIteration
      *** ../vim-7.3.946/src/version.c 2013-05-15 14:22:36.000000000 +0200
      --- src/version.c 2013-05-15 14:25:26.000000000 +0200
      ***************
      *** 730,731 ****
      --- 730,733 ----
      { /* Add new patch number below this line */
      + /**/
      + 947,
      /**/

      --
      "It's so simple to be wise. Just think of something stupid to say
      and then don't say it." -- Sam Levenson

      /// Bram Moolenaar -- Bram@... -- 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 ///

      --
      --
      You received this message from the "vim_dev" maillist.
      Do not top-post! Type your reply below the text you are replying to.
      For more information, visit http://www.vim.org/maillist.php

      ---
      You received this message because you are subscribed to the Google Groups "vim_dev" group.
      To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscribe@....
      For more options, visit https://groups.google.com/groups/opt_out.
    Your message has been successfully submitted and would be delivered to recipients shortly.