changeset 15234:ee63f4fe3d45 v8.1.0627

patch 8.1.0627: Python cannot handle function name of script-local function commit https://github.com/vim/vim/commit/9123c0b31a283f460ed2b6af95080120cf528118 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Dec 22 18:59:06 2018 +0100 patch 8.1.0627: Python cannot handle function name of script-local function Problem: Python cannot handle function name of script-local function. Solution: Use <SNR> instead of the special byte code. (Ozaki Kiichi, closes #3681)
author Bram Moolenaar <Bram@vim.org>
date Sat, 22 Dec 2018 19:00:06 +0100
parents 5e7515dbf871
children d7614198c4b7
files src/if_py_both.h src/testdir/test_python2.vim src/testdir/test_python3.vim src/version.c
diffstat 4 files changed, 81 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -2922,8 +2922,7 @@ FunctionNew(PyTypeObject *subtype, char_
 {
     FunctionObject	*self;
 
-    self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
-
+    self = (FunctionObject *)subtype->tp_alloc(subtype, 0);
     if (self == NULL)
 	return NULL;
 
@@ -2938,15 +2937,36 @@ FunctionNew(PyTypeObject *subtype, char_
 	self->name = vim_strsave(name);
     }
     else
-	if ((self->name = get_expanded_name(name,
-				    vim_strchr(name, AUTOLOAD_CHAR) == NULL))
-		== NULL)
+    {
+	char_u *p;
+
+	if ((p = get_expanded_name(name,
+			    vim_strchr(name, AUTOLOAD_CHAR) == NULL)) == NULL)
 	{
 	    PyErr_FORMAT(PyExc_ValueError,
 		    N_("function %s does not exist"), name);
 	    return NULL;
 	}
 
+	if (p[0] == K_SPECIAL && p[1] == KS_EXTRA && p[2] == (int)KE_SNR)
+	{
+	    char_u *np;
+	    size_t len = STRLEN(p) + 1;
+
+	    if ((np = alloc(len + 2)) == NULL)
+	    {
+		vim_free(p);
+		return NULL;
+	    }
+	    mch_memmove(np, "<SNR>", 5);
+	    mch_memmove(np + 5, p + 3, len - 3);
+	    vim_free(p);
+	    self->name = np;
+	}
+	else
+	    self->name = p;
+    }
+
     func_ref(self->name);
     self->argc = argc;
     self->argv = argv;
--- a/src/testdir/test_python2.vim
+++ b/src/testdir/test_python2.vim
@@ -36,3 +36,30 @@ func Test_set_cursor()
   normal j
   call assert_equal([2, 6], [line('.'), col('.')])
 endfunc
+
+func Test_vim_function()
+  " Check creating vim.Function object
+  py import vim
+
+  func s:foo()
+    return matchstr(expand('<sfile>'), '<SNR>\zs\d\+_foo$')
+  endfunc
+  let name = '<SNR>' . s:foo()
+
+  try
+    py f = vim.bindeval('function("s:foo")')
+    call assert_equal(name, pyeval('f.name'))
+  catch
+    call assert_false(v:exception)
+  endtry
+
+  try
+    py f = vim.Function('\x80\xfdR' + vim.eval('s:foo()'))
+    call assert_equal(name, pyeval('f.name'))
+  catch
+    call assert_false(v:exception)
+  endtry
+
+  py del f
+  delfunc s:foo
+endfunc
--- a/src/testdir/test_python3.vim
+++ b/src/testdir/test_python3.vim
@@ -36,3 +36,30 @@ func Test_set_cursor()
   normal j
   call assert_equal([2, 6], [line('.'), col('.')])
 endfunc
+
+func Test_vim_function()
+  " Check creating vim.Function object
+  py3 import vim
+
+  func s:foo()
+    return matchstr(expand('<sfile>'), '<SNR>\zs\d\+_foo$')
+  endfunc
+  let name = '<SNR>' . s:foo()
+
+  try
+    py3 f = vim.bindeval('function("s:foo")')
+    call assert_equal(name, py3eval('f.name'))
+  catch
+    call assert_false(v:exception)
+  endtry
+
+  try
+    py3 f = vim.Function(b'\x80\xfdR' + vim.eval('s:foo()').encode())
+    call assert_equal(name, py3eval('f.name'))
+  catch
+    call assert_false(v:exception)
+  endtry
+
+  py3 del f
+  delfunc s:foo
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -800,6 +800,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    627,
+/**/
     626,
 /**/
     625,