]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
updated for version 7.3.1063 v7.3.1063
authorBram Moolenaar <Bram@vim.org>
Thu, 30 May 2013 11:14:13 +0000 (13:14 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 30 May 2013 11:14:13 +0000 (13:14 +0200)
Problem:    Python: Function is not standard.
Solution:   Python patch 22: make Function subclassable. (ZyX)

src/eval.c
src/if_py_both.h
src/proto/eval.pro
src/testdir/test86.in
src/testdir/test86.ok
src/testdir/test87.in
src/testdir/test87.ok
src/version.c

index 25785b777669eb3217cb8dcf8780c832e800c4ff..06cf4882ac1089e4a7dad6a234a55b387bd412fd 100644 (file)
@@ -21933,6 +21933,15 @@ free_all_functions()
 }
 #endif
 
+    int
+translated_function_exists(name)
+    char_u     *name;
+{
+    if (builtin_function(name))
+       return find_internal_func(name) >= 0;
+    return find_func(name) != NULL;
+}
+
 /*
  * Return TRUE if a function "name" exists.
  */
@@ -21950,12 +21959,7 @@ function_exists(name)
     /* Only accept "funcname", "funcname ", "funcname (..." and
      * "funcname(...", not "funcname!...". */
     if (p != NULL && (*nm == NUL || *nm == '('))
-    {
-       if (builtin_function(p))
-           n = (find_internal_func(p) >= 0);
-       else
-           n = (find_func(p) != NULL);
-    }
+       n = translated_function_exists(p);
     vim_free(p);
     return n;
 }
@@ -21971,18 +21975,9 @@ get_expanded_name(name, check)
     p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
 
     if (p != NULL && *nm == NUL)
-    {
-       if (!check)
+       if (!check || translated_function_exists(p))
            return p;
-       else if (builtin_function(p))
-       {
-           if (find_internal_func(p) >= 0)
-               return p;
-       }
-       else
-           if (find_func(p) != NULL)
-               return p;
-    }
+
     vim_free(p);
     return NULL;
 }
index bf7110d5ebfb58f4964e3a48a4100796b46563f3..f19feda277ee879c2cf9dc6dfa4f88f55accff37 100644 (file)
@@ -1991,30 +1991,73 @@ typedef struct
 
 static PyTypeObject FunctionType;
 
+#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
+
     static PyObject *
-FunctionNew(char_u *name)
+FunctionNew(PyTypeObject *subtype, char_u *name)
 {
     FunctionObject     *self;
 
-    self = PyObject_NEW(FunctionObject, &FunctionType);
+    self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
+
     if (self == NULL)
        return NULL;
-    self->name = PyMem_New(char_u, STRLEN(name) + 1);
-    if (self->name == NULL)
+
+    if (isdigit(*name))
     {
-       PyErr_NoMemory();
-       return NULL;
+       if (!translated_function_exists(name))
+       {
+           PyErr_SetString(PyExc_ValueError,
+                   _("unnamed function does not exist"));
+           return NULL;
+       }
+       self->name = vim_strsave(name);
+       func_ref(self->name);
+    }
+    else
+    {
+       self->name = get_expanded_name(name, TRUE);
+       if (self->name == NULL)
+       {
+           if (script_autoload(name, TRUE) && !aborting())
+               self->name = get_expanded_name(name, TRUE);
+           if (self->name == NULL)
+           {
+               PyErr_SetString(PyExc_ValueError, _("function does not exist"));
+               return NULL;
+           }
+       }
     }
-    STRCPY(self->name, name);
-    func_ref(name);
+
     return (PyObject *)(self);
 }
 
+    static PyObject *
+FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+{
+    PyObject   *self;
+    char_u     *name;
+
+    if (kwargs)
+    {
+       PyErr_SetString(PyExc_TypeError,
+               _("function constructor does not accept keyword arguments"));
+       return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, "s", &name))
+       return NULL;
+
+    self = FunctionNew(subtype, name);
+
+    return self;
+}
+
     static void
 FunctionDestructor(FunctionObject *self)
 {
     func_unref(self->name);
-    PyMem_Free(self->name);
+    vim_free(self->name);
 
     DESTRUCTOR_FINISH(self);
 }
@@ -2093,7 +2136,6 @@ FunctionRepr(FunctionObject *self)
 }
 
 static struct PyMethodDef FunctionMethods[] = {
-    {"__call__",(PyCFunction)FunctionCall,  METH_VARARGS|METH_KEYWORDS,        ""},
     {"__dir__",        (PyCFunction)FunctionDir,   METH_NOARGS,                ""},
     { NULL,    NULL,                   0,                              NULL}
 };
@@ -4895,7 +4937,7 @@ ConvertToPyObject(typval_T *tv)
        case VAR_DICT:
            return NEW_DICTIONARY(tv->vval.v_dict);
        case VAR_FUNC:
-           return FunctionNew(tv->vval.v_string == NULL
+           return NEW_FUNCTION(tv->vval.v_string == NULL
                                          ? (char_u *)"" : tv->vval.v_string);
        case VAR_UNKNOWN:
            Py_INCREF(Py_None);
@@ -5105,10 +5147,12 @@ init_structs(void)
     FunctionType.tp_basicsize = sizeof(FunctionObject);
     FunctionType.tp_dealloc = (destructor)FunctionDestructor;
     FunctionType.tp_call = (ternaryfunc)FunctionCall;
-    FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
+    FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
     FunctionType.tp_doc = "object that calls vim function";
     FunctionType.tp_methods = FunctionMethods;
     FunctionType.tp_repr = (reprfunc)FunctionRepr;
+    FunctionType.tp_new = (newfunc)FunctionConstructor;
+    FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
 #if PY_MAJOR_VERSION >= 3
     FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
 #else
index 8cb0dd6b952532a89c6bb98634da6f7d481d62ef..56f91bba48f0ba16a49300ecb71c90870d7a0e1f 100644 (file)
@@ -79,6 +79,7 @@ void dict_extend __ARGS((dict_T *d1, dict_T *d2, char_u *action));
 char_u *get_function_name __ARGS((expand_T *xp, int idx));
 char_u *get_expr_name __ARGS((expand_T *xp, int idx));
 char_u *get_expanded_name __ARGS((char_u *name, int check));
+int translated_function_exists __ARGS((char_u *name));
 int func_call __ARGS((char_u *name, typval_T *args, dict_T *selfdict, typval_T *rettv));
 void mzscheme_call_vim __ARGS((char_u *name, typval_T *args, typval_T *rettv));
 long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit));
index dfba65de9b6065bebcded185f537f6aa2fad10fa..981d5e5739da0fdb98e9a8f0f251ba74e5ca82c1 100644 (file)
@@ -31,6 +31,9 @@ STARTTEST
 :"
 :" Extending Dictionary directly with different types
 :let d = {}
+:fun d.f()
+:  return 1
+:endfun
 py << EOF
 d=vim.bindeval('d')
 d['1']='asd'
@@ -44,12 +47,13 @@ dk.sort(key=repr)
 dv.sort(key=repr)
 di.sort(key=repr)
 EOF
+:$put =pyeval('d[''f''](self={})')
 :$put =pyeval('repr(dk)')
 :$put =substitute(pyeval('repr(dv)'),'0x\x\+','','g')
 :$put =substitute(pyeval('repr(di)'),'0x\x\+','','g')
-:for [key, val] in sort(items(d))
-:  $put =string(key) . ' : ' . string(val)
-:  unlet key val
+:for [key, Val] in sort(items(d))
+:  $put =string(key) . ' : ' . string(Val)
+:  unlet key Val
 :endfor
 :"
 :" removing items with del
@@ -66,6 +70,7 @@ EOF
 :$put =string(l)
 :"
 :py del d['-1']
+:py del d['f']
 :$put =string(pyeval('d.get(''b'', 1)'))
 :$put =string(pyeval('d.pop(''b'')'))
 :$put =string(pyeval('d.get(''b'', 1)'))
@@ -187,9 +192,10 @@ EOF
 :catch
 :   $put =v:exception[:16]
 :endtry
+:py f=l[0]
 :delfunction New
 :try
-:   py l[0](1, 2, 3)
+:   py f(1, 2, 3)
 :catch
 :   $put =v:exception[:16]
 :endtry
@@ -737,6 +743,7 @@ EOF
 :$put =string(pyeval('vim.Dictionary(((''a'', 1),))'))
 :$put =string(pyeval('vim.List()'))
 :$put =string(pyeval('vim.List(iter(''abc''))'))
+:$put =string(pyeval('vim.Function(''tr'')'))
 :"
 :" Test stdout/stderr
 :redir => messages
@@ -747,6 +754,10 @@ EOF
 :redir END
 :$put =string(substitute(messages, '\d\+', '', 'g'))
 :" Test subclassing
+:fun Put(...)
+:   $put =string(a:000)
+:   return a:000
+:endfun
 py << EOF
 class DupDict(vim.Dictionary):
     def __setitem__(self, key, value):
@@ -762,10 +773,17 @@ class DupList(vim.List):
 dl = DupList()
 dl2 = DupList(iter('abc'))
 dl.extend(dl2[0])
+
+class DupFun(vim.Function):
+    def __call__(self, arg):
+        return super(DupFun, self).__call__(arg, arg)
+
+df = DupFun('Put')
 EOF
 :$put =string(sort(keys(pyeval('dd'))))
 :$put =string(pyeval('dl'))
 :$put =string(pyeval('dl2'))
+:$put =string(pyeval('df(2)'))
 :"
 :" Test exceptions
 :fun Exe(e)
index b484ec62e2da4d91022aab3f06a6a644edc258f5..34e1e68525963664ac59fa69457cd1ea8de818e6 100644 (file)
@@ -4,13 +4,15 @@ start:
 Vim(put):E684:
 [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
 [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
-['-1', '0', '1', 'b']
-['asd', -1L, <vim.dictionary object at >, <vim.list object at >]
-[('-1', <vim.dictionary object at >), ('0', -1L), ('1', 'asd'), ('b', <vim.list object at >)]
+1
+['-1', '0', '1', 'b', 'f']
+['asd', -1L, <vim.Function '1'>, <vim.dictionary object at >, <vim.list object at >]
+[('-1', <vim.dictionary object at >), ('0', -1L), ('1', 'asd'), ('b', <vim.list object at >), ('f', <vim.Function '1'>)]
 '-1' : {'a': 1}
 '0' : -1
 '1' : 'asd'
 'b' : [1, 2, function('strlen')]
+'f' : function('1')
 [0, function('strlen')]
 [3]
 [1, 2, function('strlen')]
@@ -407,13 +409,14 @@ tabpage:__dir__,__members__,number,valid,vars,window,windows
 range:__dir__,__members__,append,end,start
 dictionary:__dir__,__members__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
 list:__dir__,__members__,extend,locked
-function:__call__,__dir__,__members__,softspace
+function:__dir__,__members__,softspace
 output:__dir__,__members__,flush,softspace,write,writelines
 {}
 {'a': 1}
 {'a': 1}
 []
 ['a', 'b', 'c']
+function('tr')
 '
 abcdef
 line  :
@@ -424,6 +427,8 @@ abc'
 ['a', 'dup_a']
 ['a', 'a']
 ['a', 'b', 'c']
+[2, 2]
+[2, 2]
 (<class 'vim.error'>, error('abc',))
 (<class 'vim.error'>, error('def',))
 (<class 'vim.error'>, error('ghi',))
index 82edc8badecd2d96129ccb41edc7d5623f60de1e..776d53a37038b020aed63f8637157e36b04ff0a1 100644 (file)
@@ -26,6 +26,9 @@ STARTTEST
 :"
 :" Extending Dictionary directly with different types
 :let d = {}
+:fun d.f()
+:  return 1
+:endfun
 py3 << EOF
 d=vim.bindeval('d')
 d['1']='asd'
@@ -39,12 +42,13 @@ dk.sort(key=repr)
 dv.sort(key=repr)
 di.sort(key=repr)
 EOF
+:$put =py3eval('d[''f''](self={})')
 :$put =py3eval('repr(dk)')
 :$put =substitute(py3eval('repr(dv)'),'0x\x\+','','g')
 :$put =substitute(py3eval('repr(di)'),'0x\x\+','','g')
-:for [key, val] in sort(items(d))
-:  $put =string(key) . ' : ' . string(val)
-:  unlet key val
+:for [key, Val] in sort(items(d))
+:  $put =string(key) . ' : ' . string(Val)
+:  unlet key Val
 :endfor
 :"
 :" removing items with del
@@ -61,6 +65,7 @@ EOF
 :$put =string(l)
 :"
 :py3 del d['-1']
+:py3 del d['f']
 :$put =string(py3eval('d.get(''b'', 1)'))
 :$put =string(py3eval('d.pop(''b'')'))
 :$put =string(py3eval('d.get(''b'', 1)'))
@@ -182,9 +187,10 @@ EOF
 :catch
 :   $put =v:exception[:13]
 :endtry
+:py3 f=l[0]
 :delfunction New
 :try
-:   py3 l[0](1, 2, 3)
+:   py3 f(1, 2, 3)
 :catch
 :   $put =v:exception[:13]
 :endtry
@@ -698,6 +704,7 @@ EOF
 :$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
 :$put =string(py3eval('vim.List()'))
 :$put =string(py3eval('vim.List(iter(''abc''))'))
+:$put =string(py3eval('vim.Function(''tr'')'))
 :"
 :" Test stdout/stderr
 :redir => messages
@@ -708,6 +715,10 @@ EOF
 :redir END
 :$put =string(substitute(messages, '\d\+', '', 'g'))
 :" Test subclassing
+:fun Put(...)
+:   $put =string(a:000)
+:   return a:000
+:endfun
 py3 << EOF
 class DupDict(vim.Dictionary):
     def __setitem__(self, key, value):
@@ -723,10 +734,17 @@ class DupList(vim.List):
 dl = DupList()
 dl2 = DupList(iter('abc'))
 dl.extend(dl2[0])
+
+class DupFun(vim.Function):
+    def __call__(self, arg):
+        return super(DupFun, self).__call__(arg, arg)
+
+df = DupFun('Put')
 EOF
 :$put =string(sort(keys(py3eval('dd'))))
 :$put =string(py3eval('dl'))
 :$put =string(py3eval('dl2'))
+:$put =string(py3eval('df(2)'))
 :"
 :" Test exceptions
 :fun Exe(e)
index 0945396d6cf6619c7e72e28e04e323191eb005e1..2d732fdcdedded21574488d8e0f389e95bc5af1c 100644 (file)
@@ -4,13 +4,15 @@ start:
 Vim(put):E684:
 [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
 [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
-[b'-1', b'0', b'1', b'b']
-[-1, <vim.dictionary object at >, <vim.list object at >, b'asd']
-[(b'-1', <vim.dictionary object at >), (b'0', -1), (b'1', b'asd'), (b'b', <vim.list object at >)]
+1
+[b'-1', b'0', b'1', b'b', b'f']
+[-1, <vim.Function '1'>, <vim.dictionary object at >, <vim.list object at >, b'asd']
+[(b'-1', <vim.dictionary object at >), (b'0', -1), (b'1', b'asd'), (b'b', <vim.list object at >), (b'f', <vim.Function '1'>)]
 '-1' : {'a': 1}
 '0' : -1
 '1' : 'asd'
 'b' : [1, 2, function('strlen')]
+'f' : function('1')
 [0, function('strlen')]
 [3]
 [1, 2, function('strlen')]
@@ -396,13 +398,14 @@ tabpage:__dir__,number,valid,vars,window,windows
 range:__dir__,append,end,start
 dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
 list:__dir__,extend,locked
-function:__call__,__dir__,softspace
+function:__dir__,softspace
 output:__dir__,flush,softspace,write,writelines
 {}
 {'a': 1}
 {'a': 1}
 []
 ['a', 'b', 'c']
+function('tr')
 '
 abcdef
 line  :
@@ -413,6 +416,8 @@ abc'
 ['a', 'dup_a']
 ['a', 'a']
 ['a', 'b', 'c']
+[2, 2]
+[2, 2]
 (<class 'vim.error'>, error('abc',))
 (<class 'vim.error'>, error('def',))
 (<class 'vim.error'>, error('ghi',))
index fa27fade52d897abe359830a9c2f4ea106a55d8e..b05dc0e1a8572702452e0d33b81e6770a1ae90f3 100644 (file)
@@ -728,6 +728,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1063,
 /**/
     1062,
 /**/