Patch 8.2.1538
Problem: Python: iteration over vim objects fails to keep reference.
Solution: Keep a reference for the object. (Paul Ollis, closes #6803,
closes #6806)
Files: src/if_py_both.h, src/testdir/test_python3.vim
*** ../vim-8.2.1537/src/if_py_both.h 2020-07-14 21:08:44.350001848 +0200
--- src/if_py_both.h 2020-08-29 12:54:00.708370457 +0200
***************
*** 1442,1452 ****
destructorfun destruct;
traversefun traverse;
clearfun clear;
} IterObject;
static PyObject *
IterNew(void *start, destructorfun destruct, nextfun next, traversefun
traverse,
! clearfun clear)
{
IterObject *self;
--- 1442,1453 ----
destructorfun destruct;
traversefun traverse;
clearfun clear;
+ PyObject *iter_object;
} IterObject;
static PyObject *
IterNew(void *start, destructorfun destruct, nextfun next, traversefun
traverse,
! clearfun clear, PyObject *iter_object)
{
IterObject *self;
***************
*** 1456,1461 ****
--- 1457,1466 ----
self->destruct = destruct;
self->traverse = traverse;
self->clear = clear;
+ self->iter_object = iter_object;
+
+ if (iter_object)
+ Py_INCREF(iter_object);
return (PyObject *)(self);
}
***************
*** 1463,1468 ****
--- 1468,1475 ----
static void
IterDestructor(IterObject *self)
{
+ if (self->iter_object)
+ Py_DECREF(self->iter_object);
PyObject_GC_UnTrack((void *)(self));
self->destruct(self->cur);
PyObject_GC_Del((void *)(self));
***************
*** 1844,1850 ****
return IterNew(dii,
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
! NULL, NULL);
}
static PyInt
--- 1851,1857 ----
return IterNew(dii,
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
! NULL, NULL, (PyObject *)self);
}
static PyInt
***************
*** 2842,2848 ****
return IterNew(lii,
(destructorfun) ListIterDestruct, (nextfun) ListIterNext,
! NULL, NULL);
}
static char *ListAttrs[] = {
--- 2849,2855 ----
return IterNew(lii,
(destructorfun) ListIterDestruct, (nextfun) ListIterNext,
! NULL, NULL, (PyObject *)self);
}
static char *ListAttrs[] = {
***************
*** 3491,3497 ****
return IterNew(oii,
(destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
! NULL, NULL);
}
static int
--- 3498,3504 ----
return IterNew(oii,
(destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
! NULL, NULL, (PyObject *)self);
}
static int
***************
*** 5488,5501 ****
}
static PyObject *
! BufMapIter(PyObject *self UNUSED)
{
PyObject *buffer;
buffer = BufferNew(firstbuf);
return IterNew(buffer,
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
! (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
}
static PyMappingMethods BufMapAsMapping = {
--- 5495,5509 ----
}
static PyObject *
! BufMapIter(PyObject *self)
{
PyObject *buffer;
buffer = BufferNew(firstbuf);
return IterNew(buffer,
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
! (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear,
! (PyObject *)self);
}
static PyMappingMethods BufMapAsMapping = {
*** ../vim-8.2.1537/src/testdir/test_python3.vim 2020-07-11
22:14:54.314422214 +0200
--- src/testdir/test_python3.vim 2020-08-29 12:54:00.712370444 +0200
***************
*** 4,9 ****
--- 4,18 ----
CheckFeature python3
source shared.vim
+ func Create_vim_list()
+ return [1]
+ endfunction
+
+ func Create_vim_dict()
+ return {'a': 1}
+ endfunction
+
+
" This function should be called first. This sets up python functions used by
" the other tests.
func Test_AAA_python3_setup()
***************
*** 3944,3947 ****
--- 3953,3999 ----
close!
endfunc
+ " Regression: Iterator for a Vim object should hold a reference.
+ func Test_python3_iter_ref()
+ let g:list_iter_ref_count_increase = -1
+ let g:dict_iter_ref_count_increase = -1
+ let g:bufmap_iter_ref_count_increase = -1
+ let g:options_iter_ref_count_increase = -1
+
+ py3 << trim EOF
+ import sys
+ import vim
+
+ def test_python3_iter_ref():
+ create_list = vim.Function('Create_vim_list')
+ v = create_list()
+ base_ref_count = sys.getrefcount(v)
+ for el in v:
+ vim.vars['list_iter_ref_count_increase'] = sys.getrefcount(v) -
base_ref_count
+
+ create_dict = vim.Function('Create_vim_dict')
+ v = create_dict()
+ base_ref_count = sys.getrefcount(v)
+ for el in v:
+ vim.vars['dict_iter_ref_count_increase'] = sys.getrefcount(v) -
base_ref_count
+
+ v = vim.buffers
+ base_ref_count = sys.getrefcount(v)
+ for el in v:
+ vim.vars['bufmap_iter_ref_count_increase'] = sys.getrefcount(v) -
base_ref_count
+
+ v = vim.options
+ base_ref_count = sys.getrefcount(v)
+ for el in v:
+ vim.vars['options_iter_ref_count_increase'] = sys.getrefcount(v) -
base_ref_count
+
+ test_python3_iter_ref()
+ EOF
+
+ call assert_equal(1, g:list_iter_ref_count_increase)
+ call assert_equal(1, g:dict_iter_ref_count_increase)
+ call assert_equal(1, g:bufmap_iter_ref_count_increase)
+ call assert_equal(1, g:options_iter_ref_count_increase)
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.1537/src/version.c 2020-08-28 23:27:16.932923997 +0200
--- src/version.c 2020-08-29 12:56:15.951977902 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 1538,
/**/
--
GALAHAD: No. Look, I can tackle this lot single-handed!
GIRLS: Yes, yes, let him Tackle us single-handed!
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202008291057.07TAvp6D2502812%40masaka.moolenaar.net.