0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

updated for version 7.3.1063

Problem:    Python: Function is not standard.
Solution:   Python patch 22: make Function subclassable. (ZyX)
This commit is contained in:
Bram Moolenaar
2013-05-30 13:14:13 +02:00
parent 78cddbe271
commit 355fd9b468
8 changed files with 133 additions and 45 deletions

View File

@@ -21933,6 +21933,15 @@ free_all_functions()
} }
#endif #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. * Return TRUE if a function "name" exists.
*/ */
@@ -21950,12 +21959,7 @@ function_exists(name)
/* Only accept "funcname", "funcname ", "funcname (..." and /* Only accept "funcname", "funcname ", "funcname (..." and
* "funcname(...", not "funcname!...". */ * "funcname(...", not "funcname!...". */
if (p != NULL && (*nm == NUL || *nm == '(')) if (p != NULL && (*nm == NUL || *nm == '('))
{ n = translated_function_exists(p);
if (builtin_function(p))
n = (find_internal_func(p) >= 0);
else
n = (find_func(p) != NULL);
}
vim_free(p); vim_free(p);
return n; return n;
} }
@@ -21971,18 +21975,9 @@ get_expanded_name(name, check)
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL); p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
if (p != NULL && *nm == NUL) if (p != NULL && *nm == NUL)
{ if (!check || translated_function_exists(p))
if (!check)
return 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); vim_free(p);
return NULL; return NULL;
} }

View File

@@ -1991,30 +1991,73 @@ typedef struct
static PyTypeObject FunctionType; static PyTypeObject FunctionType;
#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
static PyObject * static PyObject *
FunctionNew(char_u *name) FunctionNew(PyTypeObject *subtype, char_u *name)
{ {
FunctionObject *self; FunctionObject *self;
self = PyObject_NEW(FunctionObject, &FunctionType); self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
if (self == NULL) if (self == NULL)
return NULL; return NULL;
self->name = PyMem_New(char_u, STRLEN(name) + 1);
if (self->name == NULL) if (isdigit(*name))
{ {
PyErr_NoMemory(); 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;
}
}
}
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; return NULL;
} }
STRCPY(self->name, name);
func_ref(name); if (!PyArg_ParseTuple(args, "s", &name))
return (PyObject *)(self); return NULL;
self = FunctionNew(subtype, name);
return self;
} }
static void static void
FunctionDestructor(FunctionObject *self) FunctionDestructor(FunctionObject *self)
{ {
func_unref(self->name); func_unref(self->name);
PyMem_Free(self->name); vim_free(self->name);
DESTRUCTOR_FINISH(self); DESTRUCTOR_FINISH(self);
} }
@@ -2093,7 +2136,6 @@ FunctionRepr(FunctionObject *self)
} }
static struct PyMethodDef FunctionMethods[] = { static struct PyMethodDef FunctionMethods[] = {
{"__call__",(PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
{"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""}, {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
{ NULL, NULL, 0, NULL} { NULL, NULL, 0, NULL}
}; };
@@ -4895,7 +4937,7 @@ ConvertToPyObject(typval_T *tv)
case VAR_DICT: case VAR_DICT:
return NEW_DICTIONARY(tv->vval.v_dict); return NEW_DICTIONARY(tv->vval.v_dict);
case VAR_FUNC: case VAR_FUNC:
return FunctionNew(tv->vval.v_string == NULL return NEW_FUNCTION(tv->vval.v_string == NULL
? (char_u *)"" : tv->vval.v_string); ? (char_u *)"" : tv->vval.v_string);
case VAR_UNKNOWN: case VAR_UNKNOWN:
Py_INCREF(Py_None); Py_INCREF(Py_None);
@@ -5105,10 +5147,12 @@ init_structs(void)
FunctionType.tp_basicsize = sizeof(FunctionObject); FunctionType.tp_basicsize = sizeof(FunctionObject);
FunctionType.tp_dealloc = (destructor)FunctionDestructor; FunctionType.tp_dealloc = (destructor)FunctionDestructor;
FunctionType.tp_call = (ternaryfunc)FunctionCall; 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_doc = "object that calls vim function";
FunctionType.tp_methods = FunctionMethods; FunctionType.tp_methods = FunctionMethods;
FunctionType.tp_repr = (reprfunc)FunctionRepr; FunctionType.tp_repr = (reprfunc)FunctionRepr;
FunctionType.tp_new = (newfunc)FunctionConstructor;
FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
FunctionType.tp_getattro = (getattrofunc)FunctionGetattro; FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
#else #else

View 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_function_name __ARGS((expand_T *xp, int idx));
char_u *get_expr_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)); 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)); 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)); 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)); 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));

View File

@@ -31,6 +31,9 @@ STARTTEST
:" :"
:" Extending Dictionary directly with different types :" Extending Dictionary directly with different types
:let d = {} :let d = {}
:fun d.f()
: return 1
:endfun
py << EOF py << EOF
d=vim.bindeval('d') d=vim.bindeval('d')
d['1']='asd' d['1']='asd'
@@ -44,12 +47,13 @@ dk.sort(key=repr)
dv.sort(key=repr) dv.sort(key=repr)
di.sort(key=repr) di.sort(key=repr)
EOF EOF
:$put =pyeval('d[''f''](self={})')
:$put =pyeval('repr(dk)') :$put =pyeval('repr(dk)')
:$put =substitute(pyeval('repr(dv)'),'0x\x\+','','g') :$put =substitute(pyeval('repr(dv)'),'0x\x\+','','g')
:$put =substitute(pyeval('repr(di)'),'0x\x\+','','g') :$put =substitute(pyeval('repr(di)'),'0x\x\+','','g')
:for [key, val] in sort(items(d)) :for [key, Val] in sort(items(d))
: $put =string(key) . ' : ' . string(val) : $put =string(key) . ' : ' . string(Val)
: unlet key val : unlet key Val
:endfor :endfor
:" :"
:" removing items with del :" removing items with del
@@ -66,6 +70,7 @@ EOF
:$put =string(l) :$put =string(l)
:" :"
:py del d['-1'] :py del d['-1']
:py del d['f']
:$put =string(pyeval('d.get(''b'', 1)')) :$put =string(pyeval('d.get(''b'', 1)'))
:$put =string(pyeval('d.pop(''b'')')) :$put =string(pyeval('d.pop(''b'')'))
:$put =string(pyeval('d.get(''b'', 1)')) :$put =string(pyeval('d.get(''b'', 1)'))
@@ -187,9 +192,10 @@ EOF
:catch :catch
: $put =v:exception[:16] : $put =v:exception[:16]
:endtry :endtry
:py f=l[0]
:delfunction New :delfunction New
:try :try
: py l[0](1, 2, 3) : py f(1, 2, 3)
:catch :catch
: $put =v:exception[:16] : $put =v:exception[:16]
:endtry :endtry
@@ -737,6 +743,7 @@ EOF
:$put =string(pyeval('vim.Dictionary(((''a'', 1),))')) :$put =string(pyeval('vim.Dictionary(((''a'', 1),))'))
:$put =string(pyeval('vim.List()')) :$put =string(pyeval('vim.List()'))
:$put =string(pyeval('vim.List(iter(''abc''))')) :$put =string(pyeval('vim.List(iter(''abc''))'))
:$put =string(pyeval('vim.Function(''tr'')'))
:" :"
:" Test stdout/stderr :" Test stdout/stderr
:redir => messages :redir => messages
@@ -747,6 +754,10 @@ EOF
:redir END :redir END
:$put =string(substitute(messages, '\d\+', '', 'g')) :$put =string(substitute(messages, '\d\+', '', 'g'))
:" Test subclassing :" Test subclassing
:fun Put(...)
: $put =string(a:000)
: return a:000
:endfun
py << EOF py << EOF
class DupDict(vim.Dictionary): class DupDict(vim.Dictionary):
def __setitem__(self, key, value): def __setitem__(self, key, value):
@@ -762,10 +773,17 @@ class DupList(vim.List):
dl = DupList() dl = DupList()
dl2 = DupList(iter('abc')) dl2 = DupList(iter('abc'))
dl.extend(dl2[0]) dl.extend(dl2[0])
class DupFun(vim.Function):
def __call__(self, arg):
return super(DupFun, self).__call__(arg, arg)
df = DupFun('Put')
EOF EOF
:$put =string(sort(keys(pyeval('dd')))) :$put =string(sort(keys(pyeval('dd'))))
:$put =string(pyeval('dl')) :$put =string(pyeval('dl'))
:$put =string(pyeval('dl2')) :$put =string(pyeval('dl2'))
:$put =string(pyeval('df(2)'))
:" :"
:" Test exceptions :" Test exceptions
:fun Exe(e) :fun Exe(e)

View File

@@ -4,13 +4,15 @@ start:
Vim(put):E684: Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]] [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
['-1', '0', '1', 'b'] 1
['asd', -1L, <vim.dictionary object at >, <vim.list object at >] ['-1', '0', '1', 'b', 'f']
[('-1', <vim.dictionary object at >), ('0', -1L), ('1', 'asd'), ('b', <vim.list object at >)] ['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} '-1' : {'a': 1}
'0' : -1 '0' : -1
'1' : 'asd' '1' : 'asd'
'b' : [1, 2, function('strlen')] 'b' : [1, 2, function('strlen')]
'f' : function('1')
[0, function('strlen')] [0, function('strlen')]
[3] [3]
[1, 2, function('strlen')] [1, 2, function('strlen')]
@@ -407,13 +409,14 @@ tabpage:__dir__,__members__,number,valid,vars,window,windows
range:__dir__,__members__,append,end,start range:__dir__,__members__,append,end,start
dictionary:__dir__,__members__,get,has_key,items,keys,locked,pop,popitem,scope,update,values dictionary:__dir__,__members__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
list:__dir__,__members__,extend,locked list:__dir__,__members__,extend,locked
function:__call__,__dir__,__members__,softspace function:__dir__,__members__,softspace
output:__dir__,__members__,flush,softspace,write,writelines output:__dir__,__members__,flush,softspace,write,writelines
{} {}
{'a': 1} {'a': 1}
{'a': 1} {'a': 1}
[] []
['a', 'b', 'c'] ['a', 'b', 'c']
function('tr')
' '
abcdef abcdef
line : line :
@@ -424,6 +427,8 @@ abc'
['a', 'dup_a'] ['a', 'dup_a']
['a', 'a'] ['a', 'a']
['a', 'b', 'c'] ['a', 'b', 'c']
[2, 2]
[2, 2]
(<class 'vim.error'>, error('abc',)) (<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',)) (<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',)) (<class 'vim.error'>, error('ghi',))

View File

@@ -26,6 +26,9 @@ STARTTEST
:" :"
:" Extending Dictionary directly with different types :" Extending Dictionary directly with different types
:let d = {} :let d = {}
:fun d.f()
: return 1
:endfun
py3 << EOF py3 << EOF
d=vim.bindeval('d') d=vim.bindeval('d')
d['1']='asd' d['1']='asd'
@@ -39,12 +42,13 @@ dk.sort(key=repr)
dv.sort(key=repr) dv.sort(key=repr)
di.sort(key=repr) di.sort(key=repr)
EOF EOF
:$put =py3eval('d[''f''](self={})')
:$put =py3eval('repr(dk)') :$put =py3eval('repr(dk)')
:$put =substitute(py3eval('repr(dv)'),'0x\x\+','','g') :$put =substitute(py3eval('repr(dv)'),'0x\x\+','','g')
:$put =substitute(py3eval('repr(di)'),'0x\x\+','','g') :$put =substitute(py3eval('repr(di)'),'0x\x\+','','g')
:for [key, val] in sort(items(d)) :for [key, Val] in sort(items(d))
: $put =string(key) . ' : ' . string(val) : $put =string(key) . ' : ' . string(Val)
: unlet key val : unlet key Val
:endfor :endfor
:" :"
:" removing items with del :" removing items with del
@@ -61,6 +65,7 @@ EOF
:$put =string(l) :$put =string(l)
:" :"
:py3 del d['-1'] :py3 del d['-1']
:py3 del d['f']
:$put =string(py3eval('d.get(''b'', 1)')) :$put =string(py3eval('d.get(''b'', 1)'))
:$put =string(py3eval('d.pop(''b'')')) :$put =string(py3eval('d.pop(''b'')'))
:$put =string(py3eval('d.get(''b'', 1)')) :$put =string(py3eval('d.get(''b'', 1)'))
@@ -182,9 +187,10 @@ EOF
:catch :catch
: $put =v:exception[:13] : $put =v:exception[:13]
:endtry :endtry
:py3 f=l[0]
:delfunction New :delfunction New
:try :try
: py3 l[0](1, 2, 3) : py3 f(1, 2, 3)
:catch :catch
: $put =v:exception[:13] : $put =v:exception[:13]
:endtry :endtry
@@ -698,6 +704,7 @@ EOF
:$put =string(py3eval('vim.Dictionary(((''a'', 1),))')) :$put =string(py3eval('vim.Dictionary(((''a'', 1),))'))
:$put =string(py3eval('vim.List()')) :$put =string(py3eval('vim.List()'))
:$put =string(py3eval('vim.List(iter(''abc''))')) :$put =string(py3eval('vim.List(iter(''abc''))'))
:$put =string(py3eval('vim.Function(''tr'')'))
:" :"
:" Test stdout/stderr :" Test stdout/stderr
:redir => messages :redir => messages
@@ -708,6 +715,10 @@ EOF
:redir END :redir END
:$put =string(substitute(messages, '\d\+', '', 'g')) :$put =string(substitute(messages, '\d\+', '', 'g'))
:" Test subclassing :" Test subclassing
:fun Put(...)
: $put =string(a:000)
: return a:000
:endfun
py3 << EOF py3 << EOF
class DupDict(vim.Dictionary): class DupDict(vim.Dictionary):
def __setitem__(self, key, value): def __setitem__(self, key, value):
@@ -723,10 +734,17 @@ class DupList(vim.List):
dl = DupList() dl = DupList()
dl2 = DupList(iter('abc')) dl2 = DupList(iter('abc'))
dl.extend(dl2[0]) dl.extend(dl2[0])
class DupFun(vim.Function):
def __call__(self, arg):
return super(DupFun, self).__call__(arg, arg)
df = DupFun('Put')
EOF EOF
:$put =string(sort(keys(py3eval('dd')))) :$put =string(sort(keys(py3eval('dd'))))
:$put =string(py3eval('dl')) :$put =string(py3eval('dl'))
:$put =string(py3eval('dl2')) :$put =string(py3eval('dl2'))
:$put =string(py3eval('df(2)'))
:" :"
:" Test exceptions :" Test exceptions
:fun Exe(e) :fun Exe(e)

View File

@@ -4,13 +4,15 @@ start:
Vim(put):E684: Vim(put):E684:
[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]] [0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]] [0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
[b'-1', b'0', b'1', b'b'] 1
[-1, <vim.dictionary object at >, <vim.list object at >, b'asd'] [b'-1', b'0', b'1', b'b', b'f']
[(b'-1', <vim.dictionary object at >), (b'0', -1), (b'1', b'asd'), (b'b', <vim.list object at >)] [-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} '-1' : {'a': 1}
'0' : -1 '0' : -1
'1' : 'asd' '1' : 'asd'
'b' : [1, 2, function('strlen')] 'b' : [1, 2, function('strlen')]
'f' : function('1')
[0, function('strlen')] [0, function('strlen')]
[3] [3]
[1, 2, function('strlen')] [1, 2, function('strlen')]
@@ -396,13 +398,14 @@ tabpage:__dir__,number,valid,vars,window,windows
range:__dir__,append,end,start range:__dir__,append,end,start
dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
list:__dir__,extend,locked list:__dir__,extend,locked
function:__call__,__dir__,softspace function:__dir__,softspace
output:__dir__,flush,softspace,write,writelines output:__dir__,flush,softspace,write,writelines
{} {}
{'a': 1} {'a': 1}
{'a': 1} {'a': 1}
[] []
['a', 'b', 'c'] ['a', 'b', 'c']
function('tr')
' '
abcdef abcdef
line : line :
@@ -413,6 +416,8 @@ abc'
['a', 'dup_a'] ['a', 'dup_a']
['a', 'a'] ['a', 'a']
['a', 'b', 'c'] ['a', 'b', 'c']
[2, 2]
[2, 2]
(<class 'vim.error'>, error('abc',)) (<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',)) (<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',)) (<class 'vim.error'>, error('ghi',))

View File

@@ -728,6 +728,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 */
/**/
1063,
/**/ /**/
1062, 1062,
/**/ /**/