mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.1538: Python: iteration over vim objects fails to keep reference
Problem: Python: iteration over vim objects fails to keep reference. Solution: Keep a reference for the object. (Paul Ollis, closes #6803, closes #6806)
This commit is contained in:
parent
b06a6d59d1
commit
423a85a11a
@ -1442,11 +1442,12 @@ typedef struct
|
|||||||
destructorfun destruct;
|
destructorfun destruct;
|
||||||
traversefun traverse;
|
traversefun traverse;
|
||||||
clearfun clear;
|
clearfun clear;
|
||||||
|
PyObject *iter_object;
|
||||||
} IterObject;
|
} IterObject;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
||||||
clearfun clear)
|
clearfun clear, PyObject *iter_object)
|
||||||
{
|
{
|
||||||
IterObject *self;
|
IterObject *self;
|
||||||
|
|
||||||
@ -1456,6 +1457,10 @@ IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
|||||||
self->destruct = destruct;
|
self->destruct = destruct;
|
||||||
self->traverse = traverse;
|
self->traverse = traverse;
|
||||||
self->clear = clear;
|
self->clear = clear;
|
||||||
|
self->iter_object = iter_object;
|
||||||
|
|
||||||
|
if (iter_object)
|
||||||
|
Py_INCREF(iter_object);
|
||||||
|
|
||||||
return (PyObject *)(self);
|
return (PyObject *)(self);
|
||||||
}
|
}
|
||||||
@ -1463,6 +1468,8 @@ IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
|||||||
static void
|
static void
|
||||||
IterDestructor(IterObject *self)
|
IterDestructor(IterObject *self)
|
||||||
{
|
{
|
||||||
|
if (self->iter_object)
|
||||||
|
Py_DECREF(self->iter_object);
|
||||||
PyObject_GC_UnTrack((void *)(self));
|
PyObject_GC_UnTrack((void *)(self));
|
||||||
self->destruct(self->cur);
|
self->destruct(self->cur);
|
||||||
PyObject_GC_Del((void *)(self));
|
PyObject_GC_Del((void *)(self));
|
||||||
@ -1844,7 +1851,7 @@ DictionaryIter(DictionaryObject *self)
|
|||||||
|
|
||||||
return IterNew(dii,
|
return IterNew(dii,
|
||||||
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
|
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
|
||||||
NULL, NULL);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyInt
|
static PyInt
|
||||||
@ -2842,7 +2849,7 @@ ListIter(ListObject *self)
|
|||||||
|
|
||||||
return IterNew(lii,
|
return IterNew(lii,
|
||||||
(destructorfun) ListIterDestruct, (nextfun) ListIterNext,
|
(destructorfun) ListIterDestruct, (nextfun) ListIterNext,
|
||||||
NULL, NULL);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ListAttrs[] = {
|
static char *ListAttrs[] = {
|
||||||
@ -3491,7 +3498,7 @@ OptionsIter(OptionsObject *self)
|
|||||||
|
|
||||||
return IterNew(oii,
|
return IterNew(oii,
|
||||||
(destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
|
(destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
|
||||||
NULL, NULL);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -5488,14 +5495,15 @@ BufMapIterNext(PyObject **buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
BufMapIter(PyObject *self UNUSED)
|
BufMapIter(PyObject *self)
|
||||||
{
|
{
|
||||||
PyObject *buffer;
|
PyObject *buffer;
|
||||||
|
|
||||||
buffer = BufferNew(firstbuf);
|
buffer = BufferNew(firstbuf);
|
||||||
return IterNew(buffer,
|
return IterNew(buffer,
|
||||||
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
|
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
|
||||||
(traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
|
(traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear,
|
||||||
|
(PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMappingMethods BufMapAsMapping = {
|
static PyMappingMethods BufMapAsMapping = {
|
||||||
|
@ -4,6 +4,15 @@ source check.vim
|
|||||||
CheckFeature python3
|
CheckFeature python3
|
||||||
source shared.vim
|
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
|
" This function should be called first. This sets up python functions used by
|
||||||
" the other tests.
|
" the other tests.
|
||||||
func Test_AAA_python3_setup()
|
func Test_AAA_python3_setup()
|
||||||
@ -3944,4 +3953,47 @@ func Test_python3_keyboard_interrupt()
|
|||||||
close!
|
close!
|
||||||
endfunc
|
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: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1538,
|
||||||
/**/
|
/**/
|
||||||
1537,
|
1537,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user