There is still a bunch of not supported methods present in python list().

# HG changeset patch
# User ZyX <[email protected]>
# Date 1369570433 -14400
# Node ID f7c3343a64a716b37dd0f8a3165d16ab93483c24
# Parent  570cdbf800e8790e250e4e5beadac7b489960c8e
Make vim.List more like built-in list:

- Make it subclassable
- Add constructor
- Use iterator in ListAssSlice
- Remove separate pyiter_to_tv as we are in any case using iterator
- Fix some messages (lowercase their first letter)

diff -r 570cdbf800e8 -r f7c3343a64a7 src/if_py_both.h
--- a/src/if_py_both.h  Sun May 26 16:13:34 2013 +0400
+++ b/src/if_py_both.h  Sun May 26 16:13:53 2013 +0400
@@ -1531,12 +1531,14 @@
     pylinkedlist_T     ref;
 } ListObject;
 
+#define NEW_LIST(list) ListNew(&ListType, list)
+
     static PyObject *
-ListNew(list_T *list)
+ListNew(PyTypeObject *subtype, list_T *list)
 {
     ListObject *self;
 
-    self = PyObject_NEW(ListObject, &ListType);
+    self = (ListObject *) subtype->tp_alloc(subtype, 0);
     if (self == NULL)
        return NULL;
     self->list = list;
@@ -1547,44 +1549,116 @@
     return (PyObject *)(self);
 }
 
-    static void
-ListDestructor(ListObject *self)
-{
-    pyll_remove(&self->ref, &lastlist);
-    list_unref(self->list);
-
-    DESTRUCTOR_FINISH(self);
+    static list_T *
+py_list_alloc()
+{
+    list_T     *r;
+
+    if (!(r = list_alloc()))
+    {
+       PyErr_NoMemory();
+       return NULL;
+    }
+    ++r->lv_refcount;
+
+    return r;
 }
 
     static int
 list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
 {
-    Py_ssize_t i;
-    Py_ssize_t lsize = PySequence_Size(obj);
-    PyObject   *litem;
+    PyObject   *iterator;
+    PyObject   *item;
     listitem_T *li;
 
-    for(i=0; i<lsize; i++)
+    if (!(iterator = PyObject_GetIter(obj)))
+       return -1;
+
+    while ((item = PyIter_Next(iterator)))
     {
-       li = listitem_alloc();
-       if (li == NULL)
+       if (!(li = listitem_alloc()))
        {
            PyErr_NoMemory();
+           Py_DECREF(item);
+           Py_DECREF(iterator);
            return -1;
        }
        li->li_tv.v_lock = 0;
-
-       litem = PySequence_GetItem(obj, i);
-       if (litem == NULL)
+       li->li_tv.v_type = VAR_UNKNOWN;
+
+       if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
+       {
+           Py_DECREF(item);
+           Py_DECREF(iterator);
+           listitem_free(li);
            return -1;
-       if (_ConvertFromPyObject(litem, &li->li_tv, lookup_dict) == -1)
-           return -1;
+       }
+
+       Py_DECREF(item);
 
        list_append(l, li);
     }
+
+    Py_DECREF(iterator);
+
+    /* Iterator may have finished due to an exception */
+    if (PyErr_Occurred())
+       return -1;
+
     return 0;
 }
 
+    static PyObject *
+ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+{
+    list_T     *list;
+    PyObject   *obj = NULL;
+
+    if (kwargs)
+    {
+       PyErr_SetString(PyExc_TypeError,
+               _("list constructor does not accept keyword arguments"));
+       return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, "|O", &obj))
+       return NULL;
+
+    if (!(list = py_list_alloc()))
+       return NULL;
+
+    if (obj)
+    {
+       PyObject        *lookup_dict;
+
+       if (!(lookup_dict = PyDict_New()))
+       {
+           list_unref(list);
+           return NULL;
+       }
+
+       if (list_py_concat(list, obj, lookup_dict) == -1)
+       {
+           Py_DECREF(lookup_dict);
+           list_unref(list);
+           return NULL;
+       }
+
+       Py_DECREF(lookup_dict);
+    }
+
+    return ListNew(subtype, list);
+}
+
+    static void
+ListDestructor(ListObject *self)
+{
+    pyll_remove(&self->ref, &lastlist);
+    list_unref(self->list);
+
+    DESTRUCTOR_FINISH(self);
+}
+
     static PyInt
 ListLength(ListObject *self)
 {
@@ -1748,7 +1822,7 @@
        if (list_append_tv(l, &tv) == FAIL)
        {
            clear_tv(&tv);
-           PyErr_SetVim(_("Failed to add item to list"));
+           PyErr_SetVim(_("failed to add item to list"));
            return -1;
        }
     }
@@ -1766,13 +1840,13 @@
 ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject 
*obj)
 {
     PyInt      size = ListLength(self);
-    Py_ssize_t i;
-    Py_ssize_t lsize;
-    PyObject   *litem;
+    PyObject   *iterator;
+    PyObject   *item;
     listitem_T *li;
     listitem_T *next;
     typval_T   v;
     list_T     *l = self->list;
+    PyInt      i;
 
     if (l->lv_lock)
     {
@@ -1807,21 +1881,18 @@
     if (obj == NULL)
        return 0;
 
-    if (!PyList_Check(obj))
+    if (!(iterator = PyObject_GetIter(obj)))
+       return -1;
+
+    while ((item = PyIter_Next(iterator)))
     {
-       PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
-       return -1;
-    }
-
-    lsize = PyList_Size(obj);
-
-    for(i=0; i<lsize; i++)
-    {
-       litem = PyList_GetItem(obj, i);
-       if (litem == NULL)
+       if (ConvertFromPyObject(item, &v) == -1)
+       {
+           Py_DECREF(iterator);
+           Py_DECREF(item);
            return -1;
-       if (ConvertFromPyObject(litem, &v) == -1)
-           return -1;
+       }
+       Py_DECREF(item);
        if (list_insert_tv(l, &v, li) == FAIL)
        {
            clear_tv(&v);
@@ -1830,6 +1901,7 @@
        }
        clear_tv(&v);
     }
+    Py_DECREF(iterator);
     return 0;
 }
 
@@ -1845,12 +1917,6 @@
        return NULL;
     }
 
-    if (!PySequence_Check(obj))
-    {
-       PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
-       return NULL;
-    }
-
     if (!(lookup_dict = PyDict_New()))
        return NULL;
 
@@ -1882,7 +1948,7 @@
     if (val == NULL)
     {
        PyErr_SetString(PyExc_AttributeError,
-               _("cannot delete vim.dictionary attributes"));
+               _("cannot delete vim.List attributes"));
        return -1;
     }
 
@@ -4592,21 +4658,6 @@
     return 0;
 }
 
-    static list_T *
-py_list_alloc()
-{
-    list_T     *r;
-
-    if (!(r = list_alloc()))
-    {
-       PyErr_NoMemory();
-       return NULL;
-    }
-    ++r->lv_refcount;
-
-    return r;
-}
-
     static int
 pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
 {
@@ -4628,65 +4679,6 @@
     return 0;
 }
 
-    static int
-pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
-{
-    PyObject   *iterator;
-    PyObject   *item;
-    list_T     *l;
-    listitem_T *li;
-
-    if (!(l = py_list_alloc()))
-       return -1;
-
-    tv->vval.v_list = l;
-    tv->v_type = VAR_LIST;
-
-    if (!(iterator = PyObject_GetIter(obj)))
-    {
-       list_unref(l);
-       return -1;
-    }
-
-    while ((item = PyIter_Next(iterator)))
-    {
-       li = listitem_alloc();
-       if (li == NULL)
-       {
-           list_unref(l);
-           Py_DECREF(iterator);
-           PyErr_NoMemory();
-           return -1;
-       }
-       li->li_tv.v_lock = 0;
-
-       if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
-       {
-           list_unref(l);
-           listitem_free(li);
-           Py_DECREF(item);
-           Py_DECREF(iterator);
-           return -1;
-       }
-
-       list_append(l, li);
-
-       Py_DECREF(item);
-    }
-
-    Py_DECREF(iterator);
-
-    /* Iterator may have finished due to an exception */
-    if (PyErr_Occurred())
-    {
-       list_unref(l);
-       return -1;
-    }
-
-    --l->lv_refcount;
-    return 0;
-}
-
 typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
 
     static int
@@ -4867,9 +4859,7 @@
        tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
     }
 #endif
-    else if (PyIter_Check(obj))
-       return convert_dl(obj, tv, pyiter_to_tv, lookup_dict);
-    else if (PySequence_Check(obj))
+    else if (PyIter_Check(obj) || PySequence_Check(obj))
        return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
     else if (PyMapping_Check(obj))
        return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
@@ -4902,7 +4892,7 @@
            return PyFloat_FromDouble((double) tv->vval.v_float);
 #endif
        case VAR_LIST:
-           return ListNew(tv->vval.v_list);
+           return NEW_LIST(tv->vval.v_list);
        case VAR_DICT:
            return NEW_DICTIONARY(tv->vval.v_dict);
        case VAR_FUNC:
@@ -5097,10 +5087,12 @@
     ListType.tp_basicsize = sizeof(ListObject);
     ListType.tp_as_sequence = &ListAsSeq;
     ListType.tp_as_mapping = &ListAsMapping;
-    ListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
     ListType.tp_doc = "list pushing modifications to vim structure";
     ListType.tp_methods = ListMethods;
     ListType.tp_iter = (getiterfunc)ListIter;
+    ListType.tp_new = (newfunc)ListConstructor;
+    ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
 #if PY_MAJOR_VERSION >= 3
     ListType.tp_getattro = (getattrofunc)ListGetattro;
     ListType.tp_setattro = (setattrofunc)ListSetattro;
diff -r 570cdbf800e8 -r f7c3343a64a7 src/testdir/test86.in
--- a/src/testdir/test86.in     Sun May 26 16:13:34 2013 +0400
+++ b/src/testdir/test86.in     Sun May 26 16:13:53 2013 +0400
@@ -735,6 +735,8 @@
 :$put =string(pyeval('vim.Dictionary({})'))
 :$put =string(pyeval('vim.Dictionary(a=1)'))
 :$put =string(pyeval('vim.Dictionary(((''a'', 1),))'))
+:$put =string(pyeval('vim.List()'))
+:$put =string(pyeval('vim.List(iter(''abc''))'))
 :"
 :" Test stdout/stderr
 :redir => messages
@@ -752,8 +754,18 @@
         super(DupDict, self).__setitem__('dup_' + key, value)
 dd = DupDict()
 dd['a'] = 'b'
+
+class DupList(vim.List):
+    def __getitem__(self, idx):
+        return [super(DupList, self).__getitem__(idx)] * 2
+
+dl = DupList()
+dl2 = DupList(iter('abc'))
+dl.extend(dl2[0])
 EOF
 :$put =string(sort(keys(pyeval('dd'))))
+:$put =string(pyeval('dl'))
+:$put =string(pyeval('dl2'))
 :"
 :" Test exceptions
 :fun Exe(e)
diff -r 570cdbf800e8 -r f7c3343a64a7 src/testdir/test86.ok
--- a/src/testdir/test86.ok     Sun May 26 16:13:34 2013 +0400
+++ b/src/testdir/test86.ok     Sun May 26 16:13:53 2013 +0400
@@ -412,6 +412,8 @@
 {}
 {'a': 1}
 {'a': 1}
+[]
+['a', 'b', 'c']
 '
 abcdef
 line  :
@@ -420,6 +422,8 @@
 line  :
 abc'
 ['a', 'dup_a']
+['a', 'a']
+['a', 'b', 'c']
 (<class 'vim.error'>, error('abc',))
 (<class 'vim.error'>, error('def',))
 (<class 'vim.error'>, error('ghi',))
diff -r 570cdbf800e8 -r f7c3343a64a7 src/testdir/test87.in
--- a/src/testdir/test87.in     Sun May 26 16:13:34 2013 +0400
+++ b/src/testdir/test87.in     Sun May 26 16:13:53 2013 +0400
@@ -692,10 +692,12 @@
 del o
 EOF
 :"
-:" Test vim.Dictionary.__new__
+:" Test vim.*.__new__
 :$put =string(py3eval('vim.Dictionary({})'))
 :$put =string(py3eval('vim.Dictionary(a=1)'))
 :$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
+:$put =string(py3eval('vim.List()'))
+:$put =string(py3eval('vim.List(iter(''abc''))'))
 :"
 :" Test stdout/stderr
 :redir => messages
@@ -713,8 +715,18 @@
         super(DupDict, self).__setitem__('dup_' + key, value)
 dd = DupDict()
 dd['a'] = 'b'
+
+class DupList(vim.List):
+    def __getitem__(self, idx):
+        return [super(DupList, self).__getitem__(idx)] * 2
+
+dl = DupList()
+dl2 = DupList(iter('abc'))
+dl.extend(dl2[0])
 EOF
 :$put =string(sort(keys(py3eval('dd'))))
+:$put =string(py3eval('dl'))
+:$put =string(py3eval('dl2'))
 :"
 :" Test exceptions
 :fun Exe(e)
diff -r 570cdbf800e8 -r f7c3343a64a7 src/testdir/test87.ok
--- a/src/testdir/test87.ok     Sun May 26 16:13:34 2013 +0400
+++ b/src/testdir/test87.ok     Sun May 26 16:13:53 2013 +0400
@@ -401,6 +401,8 @@
 {}
 {'a': 1}
 {'a': 1}
+[]
+['a', 'b', 'c']
 '
 abcdef
 line  :
@@ -409,6 +411,8 @@
 line  :
 abc'
 ['a', 'dup_a']
+['a', 'a']
+['a', 'b', 'c']
 (<class 'vim.error'>, error('abc',))
 (<class 'vim.error'>, error('def',))
 (<class 'vim.error'>, error('ghi',))

-- 
-- 
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


diff -cr vim.570cdbf800e8/src/if_py_both.h vim.f7c3343a64a7/src/if_py_both.h
*** vim.570cdbf800e8/src/if_py_both.h	2013-05-26 16:21:42.516997781 +0400
--- vim.f7c3343a64a7/src/if_py_both.h	2013-05-26 16:21:42.526997650 +0400
***************
*** 1531,1542 ****
      pylinkedlist_T	ref;
  } ListObject;
  
      static PyObject *
! ListNew(list_T *list)
  {
      ListObject	*self;
  
!     self = PyObject_NEW(ListObject, &ListType);
      if (self == NULL)
  	return NULL;
      self->list = list;
--- 1531,1544 ----
      pylinkedlist_T	ref;
  } ListObject;
  
+ #define NEW_LIST(list) ListNew(&ListType, list)
+ 
      static PyObject *
! ListNew(PyTypeObject *subtype, list_T *list)
  {
      ListObject	*self;
  
!     self = (ListObject *) subtype->tp_alloc(subtype, 0);
      if (self == NULL)
  	return NULL;
      self->list = list;
***************
*** 1547,1590 ****
      return (PyObject *)(self);
  }
  
!     static void
! ListDestructor(ListObject *self)
  {
!     pyll_remove(&self->ref, &lastlist);
!     list_unref(self->list);
  
!     DESTRUCTOR_FINISH(self);
  }
  
      static int
  list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
  {
!     Py_ssize_t	i;
!     Py_ssize_t	lsize = PySequence_Size(obj);
!     PyObject	*litem;
      listitem_T	*li;
  
!     for(i=0; i<lsize; i++)
      {
! 	li = listitem_alloc();
! 	if (li == NULL)
  	{
  	    PyErr_NoMemory();
  	    return -1;
  	}
  	li->li_tv.v_lock = 0;
  
! 	litem = PySequence_GetItem(obj, i);
! 	if (litem == NULL)
! 	    return -1;
! 	if (_ConvertFromPyObject(litem, &li->li_tv, lookup_dict) == -1)
  	    return -1;
  
  	list_append(l, li);
      }
      return 0;
  }
  
      static PyInt
  ListLength(ListObject *self)
  {
--- 1549,1664 ----
      return (PyObject *)(self);
  }
  
!     static list_T *
! py_list_alloc()
  {
!     list_T	*r;
  
!     if (!(r = list_alloc()))
!     {
! 	PyErr_NoMemory();
! 	return NULL;
!     }
!     ++r->lv_refcount;
! 
!     return r;
  }
  
      static int
  list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
  {
!     PyObject	*iterator;
!     PyObject	*item;
      listitem_T	*li;
  
!     if (!(iterator = PyObject_GetIter(obj)))
! 	return -1;
! 
!     while ((item = PyIter_Next(iterator)))
      {
! 	if (!(li = listitem_alloc()))
  	{
  	    PyErr_NoMemory();
+ 	    Py_DECREF(item);
+ 	    Py_DECREF(iterator);
  	    return -1;
  	}
  	li->li_tv.v_lock = 0;
+ 	li->li_tv.v_type = VAR_UNKNOWN;
  
! 	if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
! 	{
! 	    Py_DECREF(item);
! 	    Py_DECREF(iterator);
! 	    listitem_free(li);
  	    return -1;
+ 	}
+ 
+ 	Py_DECREF(item);
  
  	list_append(l, li);
      }
+ 
+     Py_DECREF(iterator);
+ 
+     /* Iterator may have finished due to an exception */
+     if (PyErr_Occurred())
+ 	return -1;
+ 
      return 0;
  }
  
+     static PyObject *
+ ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+ {
+     list_T	*list;
+     PyObject	*obj = NULL;
+ 
+     if (kwargs)
+     {
+ 	PyErr_SetString(PyExc_TypeError,
+ 		_("list constructor does not accept keyword arguments"));
+ 	return NULL;
+     }
+ 
+     if (!PyArg_ParseTuple(args, "|O", &obj))
+ 	return NULL;
+ 
+     if (!(list = py_list_alloc()))
+ 	return NULL;
+ 
+     if (obj)
+     {
+ 	PyObject	*lookup_dict;
+ 
+ 	if (!(lookup_dict = PyDict_New()))
+ 	{
+ 	    list_unref(list);
+ 	    return NULL;
+ 	}
+ 
+ 	if (list_py_concat(list, obj, lookup_dict) == -1)
+ 	{
+ 	    Py_DECREF(lookup_dict);
+ 	    list_unref(list);
+ 	    return NULL;
+ 	}
+ 
+ 	Py_DECREF(lookup_dict);
+     }
+ 
+     return ListNew(subtype, list);
+ }
+ 
+     static void
+ ListDestructor(ListObject *self)
+ {
+     pyll_remove(&self->ref, &lastlist);
+     list_unref(self->list);
+ 
+     DESTRUCTOR_FINISH(self);
+ }
+ 
      static PyInt
  ListLength(ListObject *self)
  {
***************
*** 1748,1754 ****
  	if (list_append_tv(l, &tv) == FAIL)
  	{
  	    clear_tv(&tv);
! 	    PyErr_SetVim(_("Failed to add item to list"));
  	    return -1;
  	}
      }
--- 1822,1828 ----
  	if (list_append_tv(l, &tv) == FAIL)
  	{
  	    clear_tv(&tv);
! 	    PyErr_SetVim(_("failed to add item to list"));
  	    return -1;
  	}
      }
***************
*** 1766,1778 ****
  ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
  {
      PyInt	size = ListLength(self);
!     Py_ssize_t	i;
!     Py_ssize_t	lsize;
!     PyObject	*litem;
      listitem_T	*li;
      listitem_T	*next;
      typval_T	v;
      list_T	*l = self->list;
  
      if (l->lv_lock)
      {
--- 1840,1852 ----
  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)
      {
***************
*** 1807,1827 ****
      if (obj == NULL)
  	return 0;
  
!     if (!PyList_Check(obj))
!     {
! 	PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
  	return -1;
-     }
- 
-     lsize = PyList_Size(obj);
  
!     for(i=0; i<lsize; i++)
      {
! 	litem = PyList_GetItem(obj, i);
! 	if (litem == NULL)
! 	    return -1;
! 	if (ConvertFromPyObject(litem, &v) == -1)
  	    return -1;
  	if (list_insert_tv(l, &v, li) == FAIL)
  	{
  	    clear_tv(&v);
--- 1881,1898 ----
      if (obj == NULL)
  	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);
***************
*** 1830,1835 ****
--- 1901,1907 ----
  	}
  	clear_tv(&v);
      }
+     Py_DECREF(iterator);
      return 0;
  }
  
***************
*** 1845,1856 ****
  	return NULL;
      }
  
-     if (!PySequence_Check(obj))
-     {
- 	PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
- 	return NULL;
-     }
- 
      if (!(lookup_dict = PyDict_New()))
  	return NULL;
  
--- 1917,1922 ----
***************
*** 1882,1888 ****
      if (val == NULL)
      {
  	PyErr_SetString(PyExc_AttributeError,
! 		_("cannot delete vim.dictionary attributes"));
  	return -1;
      }
  
--- 1948,1954 ----
      if (val == NULL)
      {
  	PyErr_SetString(PyExc_AttributeError,
! 		_("cannot delete vim.List attributes"));
  	return -1;
      }
  
***************
*** 4592,4612 ****
      return 0;
  }
  
-     static list_T *
- py_list_alloc()
- {
-     list_T	*r;
- 
-     if (!(r = list_alloc()))
-     {
- 	PyErr_NoMemory();
- 	return NULL;
-     }
-     ++r->lv_refcount;
- 
-     return r;
- }
- 
      static int
  pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
  {
--- 4658,4663 ----
***************
*** 4628,4692 ****
      return 0;
  }
  
-     static int
- pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
- {
-     PyObject	*iterator;
-     PyObject	*item;
-     list_T	*l;
-     listitem_T	*li;
- 
-     if (!(l = py_list_alloc()))
- 	return -1;
- 
-     tv->vval.v_list = l;
-     tv->v_type = VAR_LIST;
- 
-     if (!(iterator = PyObject_GetIter(obj)))
-     {
- 	list_unref(l);
- 	return -1;
-     }
- 
-     while ((item = PyIter_Next(iterator)))
-     {
- 	li = listitem_alloc();
- 	if (li == NULL)
- 	{
- 	    list_unref(l);
- 	    Py_DECREF(iterator);
- 	    PyErr_NoMemory();
- 	    return -1;
- 	}
- 	li->li_tv.v_lock = 0;
- 
- 	if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
- 	{
- 	    list_unref(l);
- 	    listitem_free(li);
- 	    Py_DECREF(item);
- 	    Py_DECREF(iterator);
- 	    return -1;
- 	}
- 
- 	list_append(l, li);
- 
- 	Py_DECREF(item);
-     }
- 
-     Py_DECREF(iterator);
- 
-     /* Iterator may have finished due to an exception */
-     if (PyErr_Occurred())
-     {
- 	list_unref(l);
- 	return -1;
-     }
- 
-     --l->lv_refcount;
-     return 0;
- }
- 
  typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
  
      static int
--- 4679,4684 ----
***************
*** 4867,4875 ****
  	tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
      }
  #endif
!     else if (PyIter_Check(obj))
! 	return convert_dl(obj, tv, pyiter_to_tv, lookup_dict);
!     else if (PySequence_Check(obj))
  	return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
      else if (PyMapping_Check(obj))
  	return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
--- 4859,4865 ----
  	tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
      }
  #endif
!     else if (PyIter_Check(obj) || PySequence_Check(obj))
  	return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
      else if (PyMapping_Check(obj))
  	return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
***************
*** 4902,4908 ****
  	    return PyFloat_FromDouble((double) tv->vval.v_float);
  #endif
  	case VAR_LIST:
! 	    return ListNew(tv->vval.v_list);
  	case VAR_DICT:
  	    return NEW_DICTIONARY(tv->vval.v_dict);
  	case VAR_FUNC:
--- 4892,4898 ----
  	    return PyFloat_FromDouble((double) tv->vval.v_float);
  #endif
  	case VAR_LIST:
! 	    return NEW_LIST(tv->vval.v_list);
  	case VAR_DICT:
  	    return NEW_DICTIONARY(tv->vval.v_dict);
  	case VAR_FUNC:
***************
*** 5097,5106 ****
      ListType.tp_basicsize = sizeof(ListObject);
      ListType.tp_as_sequence = &ListAsSeq;
      ListType.tp_as_mapping = &ListAsMapping;
!     ListType.tp_flags = Py_TPFLAGS_DEFAULT;
      ListType.tp_doc = "list pushing modifications to vim structure";
      ListType.tp_methods = ListMethods;
      ListType.tp_iter = (getiterfunc)ListIter;
  #if PY_MAJOR_VERSION >= 3
      ListType.tp_getattro = (getattrofunc)ListGetattro;
      ListType.tp_setattro = (setattrofunc)ListSetattro;
--- 5087,5098 ----
      ListType.tp_basicsize = sizeof(ListObject);
      ListType.tp_as_sequence = &ListAsSeq;
      ListType.tp_as_mapping = &ListAsMapping;
!     ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
      ListType.tp_doc = "list pushing modifications to vim structure";
      ListType.tp_methods = ListMethods;
      ListType.tp_iter = (getiterfunc)ListIter;
+     ListType.tp_new = (newfunc)ListConstructor;
+     ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
  #if PY_MAJOR_VERSION >= 3
      ListType.tp_getattro = (getattrofunc)ListGetattro;
      ListType.tp_setattro = (setattrofunc)ListSetattro;
diff -cr vim.570cdbf800e8/src/testdir/test86.in vim.f7c3343a64a7/src/testdir/test86.in
*** vim.570cdbf800e8/src/testdir/test86.in	2013-05-26 16:21:42.517997768 +0400
--- vim.f7c3343a64a7/src/testdir/test86.in	2013-05-26 16:21:42.527997637 +0400
***************
*** 735,740 ****
--- 735,742 ----
  :$put =string(pyeval('vim.Dictionary({})'))
  :$put =string(pyeval('vim.Dictionary(a=1)'))
  :$put =string(pyeval('vim.Dictionary(((''a'', 1),))'))
+ :$put =string(pyeval('vim.List()'))
+ :$put =string(pyeval('vim.List(iter(''abc''))'))
  :"
  :" Test stdout/stderr
  :redir => messages
***************
*** 752,759 ****
--- 754,771 ----
          super(DupDict, self).__setitem__('dup_' + key, value)
  dd = DupDict()
  dd['a'] = 'b'
+ 
+ class DupList(vim.List):
+     def __getitem__(self, idx):
+         return [super(DupList, self).__getitem__(idx)] * 2
+ 
+ dl = DupList()
+ dl2 = DupList(iter('abc'))
+ dl.extend(dl2[0])
  EOF
  :$put =string(sort(keys(pyeval('dd'))))
+ :$put =string(pyeval('dl'))
+ :$put =string(pyeval('dl2'))
  :"
  :" Test exceptions
  :fun Exe(e)
diff -cr vim.570cdbf800e8/src/testdir/test86.ok vim.f7c3343a64a7/src/testdir/test86.ok
*** vim.570cdbf800e8/src/testdir/test86.ok	2013-05-26 16:21:42.510997859 +0400
--- vim.f7c3343a64a7/src/testdir/test86.ok	2013-05-26 16:21:42.520997728 +0400
***************
*** 412,417 ****
--- 412,419 ----
  {}
  {'a': 1}
  {'a': 1}
+ []
+ ['a', 'b', 'c']
  '
  abcdef
  line  :
***************
*** 420,425 ****
--- 422,429 ----
  line  :
  abc'
  ['a', 'dup_a']
+ ['a', 'a']
+ ['a', 'b', 'c']
  (<class 'vim.error'>, error('abc',))
  (<class 'vim.error'>, error('def',))
  (<class 'vim.error'>, error('ghi',))
diff -cr vim.570cdbf800e8/src/testdir/test87.in vim.f7c3343a64a7/src/testdir/test87.in
*** vim.570cdbf800e8/src/testdir/test87.in	2013-05-26 16:21:42.511997847 +0400
--- vim.f7c3343a64a7/src/testdir/test87.in	2013-05-26 16:21:42.521997716 +0400
***************
*** 692,701 ****
  del o
  EOF
  :"
! :" Test vim.Dictionary.__new__
  :$put =string(py3eval('vim.Dictionary({})'))
  :$put =string(py3eval('vim.Dictionary(a=1)'))
  :$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
  :"
  :" Test stdout/stderr
  :redir => messages
--- 692,703 ----
  del o
  EOF
  :"
! :" Test vim.*.__new__
  :$put =string(py3eval('vim.Dictionary({})'))
  :$put =string(py3eval('vim.Dictionary(a=1)'))
  :$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
+ :$put =string(py3eval('vim.List()'))
+ :$put =string(py3eval('vim.List(iter(''abc''))'))
  :"
  :" Test stdout/stderr
  :redir => messages
***************
*** 713,720 ****
--- 715,732 ----
          super(DupDict, self).__setitem__('dup_' + key, value)
  dd = DupDict()
  dd['a'] = 'b'
+ 
+ class DupList(vim.List):
+     def __getitem__(self, idx):
+         return [super(DupList, self).__getitem__(idx)] * 2
+ 
+ dl = DupList()
+ dl2 = DupList(iter('abc'))
+ dl.extend(dl2[0])
  EOF
  :$put =string(sort(keys(py3eval('dd'))))
+ :$put =string(py3eval('dl'))
+ :$put =string(py3eval('dl2'))
  :"
  :" Test exceptions
  :fun Exe(e)
diff -cr vim.570cdbf800e8/src/testdir/test87.ok vim.f7c3343a64a7/src/testdir/test87.ok
*** vim.570cdbf800e8/src/testdir/test87.ok	2013-05-26 16:21:42.512997833 +0400
--- vim.f7c3343a64a7/src/testdir/test87.ok	2013-05-26 16:21:42.522997702 +0400
***************
*** 401,406 ****
--- 401,408 ----
  {}
  {'a': 1}
  {'a': 1}
+ []
+ ['a', 'b', 'c']
  '
  abcdef
  line  :
***************
*** 409,414 ****
--- 411,418 ----
  line  :
  abc'
  ['a', 'dup_a']
+ ['a', 'a']
+ ['a', 'b', 'c']
  (<class 'vim.error'>, error('abc',))
  (<class 'vim.error'>, error('def',))
  (<class 'vim.error'>, error('ghi',))

Raspunde prin e-mail lui