patch 7.4.1731
Problem: Python: turns partial into simple funcref.
Solution: Use partials like partials. (Nikolai Pavlov, closes #734)
diff --git a/src/testdir/test86.in b/src/testdir/test86.in
index cc76cff..6f47ff6 100644
--- a/src/testdir/test86.in
+++ b/src/testdir/test86.in
@@ -13,6 +13,7 @@
:lang C
:fun Test()
:py import vim
+:py cb = vim.current.buffer
:let l = []
:py l=vim.bindeval('l')
:py f=vim.bindeval('function("strlen")')
@@ -207,7 +208,15 @@
:let l = [0, 1, 2, 3]
:py l=vim.bindeval('l')
:lockvar! l
-:py l[2]='i'
+py << EOF
+def emsg(ei):
+ return ei[0].__name__ + ':' + repr(ei[1].args)
+
+try:
+ l[2]='i'
+except vim.error:
+ cb.append('l[2] threw vim.error: ' + emsg(sys.exc_info()))
+EOF
:$put =string(l)
:unlockvar! l
:"
@@ -219,7 +228,7 @@
exec(expr, g, l)
except:
ei = sys.exc_info()
- msg = sys.exc_info()[0].__name__ + ':' + repr(sys.exc_info()[1].args)
+ msg = emsg(ei)
msg = msg.replace('TypeError:(\'argument 1 ', 'TypeError:(\'')
if expr.find('None') > -1:
msg = msg.replace('TypeError:(\'iteration over non-sequence\',)',
@@ -611,7 +620,6 @@
: autocmd BufFilePre * python cb.append(vim.eval('expand("<abuf>")') + ':BufFilePre:' + vim.eval('bufnr("%")'))
:augroup END
py << EOF
-cb = vim.current.buffer
# Tests BufferAppend and BufferItem
cb.append(b[0])
# Tests BufferSlice and BufferAssSlice
@@ -865,6 +873,175 @@
:$put =string(pyeval('vim.List()'))
:$put =string(pyeval('vim.List(iter(''abc7''))'))
:$put =string(pyeval('vim.Function(''tr'')'))
+:$put =string(pyeval('vim.Function(''tr'', args=[123, 3, 4])'))
+:$put =string(pyeval('vim.Function(''tr'', args=[])'))
+:$put =string(pyeval('vim.Function(''tr'', self={})'))
+:$put =string(pyeval('vim.Function(''tr'', args=[123, 3, 4], self={})'))
+:"
+:" Test vim.Function
+:function Args(...)
+: return a:000
+:endfunction
+:function SelfArgs(...) dict
+: return [a:000, self]
+:endfunction
+:" The following four lines should not crash
+:let Pt = function('tr', [[]], {'l': []})
+:py Pt = vim.bindeval('Pt')
+:unlet Pt
+:py del Pt
+py << EOF
+def ecall(out_prefix, func, *args, **kwargs):
+ line = out_prefix + ': '
+ try:
+ ret = func(*args, **kwargs)
+ except Exception:
+ line += '!exception: ' + emsg(sys.exc_info())
+ else:
+ line += '!result: ' + vim.Function('string')(ret)
+ cb.append(line)
+a = vim.Function('Args')
+pa1 = vim.Function('Args', args=['abcArgsPA1'])
+pa2 = vim.Function('Args', args=[])
+pa3 = vim.Function('Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'})
+pa4 = vim.Function('Args', self={'abcSelfPA4': 'abcSelfPA4Val'})
+cb.append('a: ' + repr(a))
+cb.append('pa1: ' + repr(pa1))
+cb.append('pa2: ' + repr(pa2))
+cb.append('pa3: ' + repr(pa3))
+cb.append('pa4: ' + repr(pa4))
+sa = vim.Function('SelfArgs')
+psa1 = vim.Function('SelfArgs', args=['abcArgsPSA1'])
+psa2 = vim.Function('SelfArgs', args=[])
+psa3 = vim.Function('SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'})
+psa4 = vim.Function('SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'})
+cb.append('sa: ' + repr(sa))
+cb.append('psa1: ' + repr(psa1))
+cb.append('psa2: ' + repr(psa2))
+cb.append('psa3: ' + repr(psa3))
+cb.append('psa4: ' + repr(psa4))
+
+psar = vim.Function('SelfArgs', args=[{'abcArgsPSAr': 'abcArgsPSArVal'}], self={'abcSelfPSAr': 'abcSelfPSArVal'})
+psar.args[0]['abcArgsPSAr2'] = [psar.self, psar.args[0]]
+psar.self['rec'] = psar
+psar.self['self'] = psar.self
+psar.self['args'] = psar.args
+
+try:
+ cb.append('psar: ' + repr(psar))
+except Exception:
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
+EOF
+:$put ='s(a): '.string(pyeval('a'))
+:$put ='s(pa1): '.string(pyeval('pa1'))
+:$put ='s(pa2): '.string(pyeval('pa2'))
+:$put ='s(pa3): '.string(pyeval('pa3'))
+:$put ='s(pa4): '.string(pyeval('pa4'))
+:$put ='s(sa): '.string(pyeval('sa'))
+:$put ='s(psa1): '.string(pyeval('psa1'))
+:$put ='s(psa2): '.string(pyeval('psa2'))
+:$put ='s(psa3): '.string(pyeval('psa3'))
+:$put ='s(psa4): '.string(pyeval('psa4'))
+:
+:py ecall('a()', a, )
+:py ecall('pa1()', pa1, )
+:py ecall('pa2()', pa2, )
+:py ecall('pa3()', pa3, )
+:py ecall('pa4()', pa4, )
+:py ecall('sa()', sa, )
+:py ecall('psa1()', psa1, )
+:py ecall('psa2()', psa2, )
+:py ecall('psa3()', psa3, )
+:py ecall('psa4()', psa4, )
+:
+:py ecall('a(42, 43)', a, 42, 43)
+:py ecall('pa1(42, 43)', pa1, 42, 43)
+:py ecall('pa2(42, 43)', pa2, 42, 43)
+:py ecall('pa3(42, 43)', pa3, 42, 43)
+:py ecall('pa4(42, 43)', pa4, 42, 43)
+:py ecall('sa(42, 43)', sa, 42, 43)
+:py ecall('psa1(42, 43)', psa1, 42, 43)
+:py ecall('psa2(42, 43)', psa2, 42, 43)
+:py ecall('psa3(42, 43)', psa3, 42, 43)
+:py ecall('psa4(42, 43)', psa4, 42, 43)
+:
+:py ecall('a(42, self={"20": 1})', a, 42, self={'20': 1})
+:py ecall('pa1(42, self={"20": 1})', pa1, 42, self={'20': 1})
+:py ecall('pa2(42, self={"20": 1})', pa2, 42, self={'20': 1})
+:py ecall('pa3(42, self={"20": 1})', pa3, 42, self={'20': 1})
+:py ecall('pa4(42, self={"20": 1})', pa4, 42, self={'20': 1})
+:py ecall('sa(42, self={"20": 1})', sa, 42, self={'20': 1})
+:py ecall('psa1(42, self={"20": 1})', psa1, 42, self={'20': 1})
+:py ecall('psa2(42, self={"20": 1})', psa2, 42, self={'20': 1})
+:py ecall('psa3(42, self={"20": 1})', psa3, 42, self={'20': 1})
+:py ecall('psa4(42, self={"20": 1})', psa4, 42, self={'20': 1})
+:
+:py ecall('a(self={"20": 1})', a, self={'20': 1})
+:py ecall('pa1(self={"20": 1})', pa1, self={'20': 1})
+:py ecall('pa2(self={"20": 1})', pa2, self={'20': 1})
+:py ecall('pa3(self={"20": 1})', pa3, self={'20': 1})
+:py ecall('pa4(self={"20": 1})', pa4, self={'20': 1})
+:py ecall('sa(self={"20": 1})', sa, self={'20': 1})
+:py ecall('psa1(self={"20": 1})', psa1, self={'20': 1})
+:py ecall('psa2(self={"20": 1})', psa2, self={'20': 1})
+:py ecall('psa3(self={"20": 1})', psa3, self={'20': 1})
+:py ecall('psa4(self={"20": 1})', psa4, self={'20': 1})
+py << EOF
+def s(v):
+ if v is None:
+ return repr(v)
+ else:
+ return vim.Function('string')(v)
+
+cb.append('a.args: ' + s(a.args))
+cb.append('pa1.args: ' + s(pa1.args))
+cb.append('pa2.args: ' + s(pa2.args))
+cb.append('pa3.args: ' + s(pa3.args))
+cb.append('pa4.args: ' + s(pa4.args))
+cb.append('sa.args: ' + s(sa.args))
+cb.append('psa1.args: ' + s(psa1.args))
+cb.append('psa2.args: ' + s(psa2.args))
+cb.append('psa3.args: ' + s(psa3.args))
+cb.append('psa4.args: ' + s(psa4.args))
+
+cb.append('a.self: ' + s(a.self))
+cb.append('pa1.self: ' + s(pa1.self))
+cb.append('pa2.self: ' + s(pa2.self))
+cb.append('pa3.self: ' + s(pa3.self))
+cb.append('pa4.self: ' + s(pa4.self))
+cb.append('sa.self: ' + s(sa.self))
+cb.append('psa1.self: ' + s(psa1.self))
+cb.append('psa2.self: ' + s(psa2.self))
+cb.append('psa3.self: ' + s(psa3.self))
+cb.append('psa4.self: ' + s(psa4.self))
+
+cb.append('a.name: ' + s(a.name))
+cb.append('pa1.name: ' + s(pa1.name))
+cb.append('pa2.name: ' + s(pa2.name))
+cb.append('pa3.name: ' + s(pa3.name))
+cb.append('pa4.name: ' + s(pa4.name))
+cb.append('sa.name: ' + s(sa.name))
+cb.append('psa1.name: ' + s(psa1.name))
+cb.append('psa2.name: ' + s(psa2.name))
+cb.append('psa3.name: ' + s(psa3.name))
+cb.append('psa4.name: ' + s(psa4.name))
+
+del s
+
+del a
+del pa1
+del pa2
+del pa3
+del pa4
+del sa
+del psa1
+del psa2
+del psa3
+del psa4
+del psar
+
+del ecall
+EOF
:"
:" Test stdout/stderr
:redir => messages
@@ -1140,7 +1317,7 @@
ee('vim.foreach_rtp(int, 2)')
cb.append('> import')
old_rtp = vim.options['rtp']
-vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\')
+vim.options['rtp'] = os.getcwd().replace('\\', '\\\\').replace(',', '\\,')
ee('import xxx_no_such_module_xxx')
ee('import failing_import')
ee('import failing')
@@ -1224,9 +1401,20 @@
ee('l.xxx = True')
cb.append("> Function")
cb.append(">> FunctionConstructor")
+cb.append(">>> FunctionConstructor")
ee('vim.Function("123")')
ee('vim.Function("xxx_non_existent_function_xxx")')
ee('vim.Function("xxx#non#existent#function#xxx")')
+ee('vim.Function("xxx_non_existent_function_xxx2", args=[])')
+ee('vim.Function("xxx_non_existent_function_xxx3", self={})')
+ee('vim.Function("xxx_non_existent_function_xxx4", args=[], self={})')
+cb.append(">>> FunctionNew")
+ee('vim.Function("tr", self="abcFuncSelf")')
+ee('vim.Function("tr", args=427423)')
+ee('vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function(self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function("tr", "")')
cb.append(">> FunctionCall")
convertfrompyobject_test('f(%s)')
convertfrompymapping_test('fd(self=%s)')
@@ -1381,7 +1569,7 @@
except KeyboardInterrupt:
cb.append('Caught KeyboardInterrupt')
except Exception:
- cb.append('!!!!!!!! Caught exception: ' + repr(sys.exc_info))
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
else:
cb.append('!!!!!!!! No exception')
try:
@@ -1389,7 +1577,7 @@
except KeyboardInterrupt:
cb.append('!!!!!!!! Caught KeyboardInterrupt')
except Exception:
- cb.append('!!!!!!!! Caught exception: ' + repr(sys.exc_info))
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
else:
cb.append('No exception')
EOF
@@ -1409,6 +1597,7 @@
py << EOF
del cb
del ee
+del emsg
del sys
del os
del vim
@@ -1441,7 +1630,7 @@
:"
:/^start:/,$wq! test.out
:" vim: et ts=4 isk-=\:
-:call getchar()
+:while getchar(0) isnot 0|endwhile
ENDTEST
start:
diff --git a/src/testdir/test86.ok b/src/testdir/test86.ok
index d103909..fe27c05 100644
--- a/src/testdir/test86.ok
+++ b/src/testdir/test86.ok
@@ -57,6 +57,7 @@
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7]
+l[2] threw vim.error: error:('list is locked',)
[0, 1, 2, 3]
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
@@ -447,7 +448,7 @@
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:__dir__,__members__,softspace
+function:__dir__,__members__,args,self,softspace
output:__dir__,__members__,close,flush,isatty,readable,seekable,softspace,writable,write,writelines
{}
{'a': 1}
@@ -455,12 +456,108 @@
[]
['a', 'b', 'c', '7']
function('tr')
+function('tr', [123, 3, 4])
+function('tr')
+function('tr', {})
+function('tr', [123, 3, 4], {})
+a: <vim.Function 'Args'>
+pa1: <vim.Function 'Args', args=['abcArgsPA1']>
+pa2: <vim.Function 'Args'>
+pa3: <vim.Function 'Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'}>
+pa4: <vim.Function 'Args', self={'abcSelfPA4': 'abcSelfPA4Val'}>
+sa: <vim.Function 'SelfArgs'>
+psa1: <vim.Function 'SelfArgs', args=['abcArgsPSA1']>
+psa2: <vim.Function 'SelfArgs'>
+psa3: <vim.Function 'SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'}>
+psa4: <vim.Function 'SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'}>
+psar: <vim.Function 'SelfArgs', args=[{'abcArgsPSAr2': [{'rec': function('SelfArgs', [{...}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{...}]}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], self={'rec': function('SelfArgs', [{'abcArgsPSAr2': [{...}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{...}]}>
+s(a): function('Args')
+s(pa1): function('Args', ['abcArgsPA1'])
+s(pa2): function('Args')
+s(pa3): function('Args', ['abcArgsPA3'], {'abcSelfPA3': 'abcSelfPA3Val'})
+s(pa4): function('Args', {'abcSelfPA4': 'abcSelfPA4Val'})
+s(sa): function('SelfArgs')
+s(psa1): function('SelfArgs', ['abcArgsPSA1'])
+s(psa2): function('SelfArgs')
+s(psa3): function('SelfArgs', ['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'})
+s(psa4): function('SelfArgs', {'abcSelfPSA4': 'abcSelfPSA4Val'})
+a(): !result: []
+pa1(): !result: ['abcArgsPA1']
+pa2(): !result: []
+pa3(): !result: ['abcArgsPA3']
+pa4(): !result: []
+sa(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa1(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa2(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa3(): !result: [['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
+psa4(): !result: [[], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
+a(42, 43): !result: [42, 43]
+pa1(42, 43): !result: ['abcArgsPA1', 42, 43]
+pa2(42, 43): !result: [42, 43]
+pa3(42, 43): !result: ['abcArgsPA3', 42, 43]
+pa4(42, 43): !result: [42, 43]
+sa(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa1(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa2(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa3(42, 43): !result: [['abcArgsPSA3', 42, 43], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
+psa4(42, 43): !result: [[42, 43], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
+a(42, self={"20": 1}): !result: [42]
+pa1(42, self={"20": 1}): !result: ['abcArgsPA1', 42]
+pa2(42, self={"20": 1}): !result: [42]
+pa3(42, self={"20": 1}): !result: ['abcArgsPA3', 42]
+pa4(42, self={"20": 1}): !result: [42]
+sa(42, self={"20": 1}): !result: [[42], {'20': 1}]
+psa1(42, self={"20": 1}): !result: [['abcArgsPSA1', 42], {'20': 1}]
+psa2(42, self={"20": 1}): !result: [[42], {'20': 1}]
+psa3(42, self={"20": 1}): !result: [['abcArgsPSA3', 42], {'20': 1}]
+psa4(42, self={"20": 1}): !result: [[42], {'20': 1}]
+a(self={"20": 1}): !result: []
+pa1(self={"20": 1}): !result: ['abcArgsPA1']
+pa2(self={"20": 1}): !result: []
+pa3(self={"20": 1}): !result: ['abcArgsPA3']
+pa4(self={"20": 1}): !result: []
+sa(self={"20": 1}): !result: [[], {'20': 1}]
+psa1(self={"20": 1}): !result: [['abcArgsPSA1'], {'20': 1}]
+psa2(self={"20": 1}): !result: [[], {'20': 1}]
+psa3(self={"20": 1}): !result: [['abcArgsPSA3'], {'20': 1}]
+psa4(self={"20": 1}): !result: [[], {'20': 1}]
+a.args: None
+pa1.args: ['abcArgsPA1']
+pa2.args: None
+pa3.args: ['abcArgsPA3']
+pa4.args: None
+sa.args: None
+psa1.args: ['abcArgsPSA1']
+psa2.args: None
+psa3.args: ['abcArgsPSA3']
+psa4.args: None
+a.self: None
+pa1.self: None
+pa2.self: None
+pa3.self: {'abcSelfPA3': 'abcSelfPA3Val'}
+pa4.self: {'abcSelfPA4': 'abcSelfPA4Val'}
+sa.self: None
+psa1.self: None
+psa2.self: None
+psa3.self: {'abcSelfPSA3': 'abcSelfPSA3Val'}
+psa4.self: {'abcSelfPSA4': 'abcSelfPSA4Val'}
+a.name: 'Args'
+pa1.name: 'Args'
+pa2.name: 'Args'
+pa3.name: 'Args'
+pa4.name: 'Args'
+sa.name: 'SelfArgs'
+psa1.name: 'SelfArgs'
+psa2.name: 'SelfArgs'
+psa3.name: 'SelfArgs'
+psa4.name: 'SelfArgs'
'
abcdef
-line :
+Error detected while processing function RunTest[]..Test:
+line :
abcdef
abcA
-line :
+line :
abcB'
['a', 'dup_a']
['a', 'a']
@@ -1046,9 +1143,20 @@
l.xxx = True:AttributeError:('cannot set attribute xxx',)
> Function
>> FunctionConstructor
+>>> FunctionConstructor
vim.Function("123"):ValueError:('unnamed function 123 does not exist',)
vim.Function("xxx_non_existent_function_xxx"):ValueError:('function xxx_non_existent_function_xxx does not exist',)
vim.Function("xxx#non#existent#function#xxx"):NOT FAILED
+vim.Function("xxx_non_existent_function_xxx2", args=[]):ValueError:('function xxx_non_existent_function_xxx2 does not exist',)
+vim.Function("xxx_non_existent_function_xxx3", self={}):ValueError:('function xxx_non_existent_function_xxx3 does not exist',)
+vim.Function("xxx_non_existent_function_xxx4", args=[], self={}):ValueError:('function xxx_non_existent_function_xxx4 does not exist',)
+>>> FunctionNew
+vim.Function("tr", self="abcFuncSelf"):TypeError:('unable to convert str to vim dictionary',)
+vim.Function("tr", args=427423):TypeError:('unable to convert int to vim list',)
+vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2"):TypeError:('unable to convert str to vim dictionary',)
+vim.Function(self="abcFuncSelf2", args="abcFuncArgs2"):TypeError:('unable to convert str to vim dictionary',)
+vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2"):TypeError:('unable to convert str to vim dictionary',)
+vim.Function("tr", ""):TypeError:('function takes exactly 1 argument (2 given)',)
>> FunctionCall
>>> Testing StringToChars using f({%s : 1})
f({1 : 1}):TypeError:('expected str() or unicode() instance, but got int',)
diff --git a/src/testdir/test87.in b/src/testdir/test87.in
index 535a143..e3bc994 100644
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -7,6 +7,7 @@
:lang C
:fun Test()
:py3 import vim
+:py3 cb = vim.current.buffer
:let l = []
:py3 l=vim.bindeval('l')
:py3 f=vim.bindeval('function("strlen")')
@@ -200,7 +201,15 @@
:let l = [0, 1, 2, 3]
:py3 l=vim.bindeval('l')
:lockvar! l
-:py3 l[2]='i'
+py3 << EOF
+def emsg(ei):
+ return ei[0].__name__ + ':' + repr(ei[1].args)
+
+try:
+ l[2]='i'
+except vim.error:
+ cb.append('l[2] threw vim.error: ' + emsg(sys.exc_info()))
+EOF
:$put =string(l)
:unlockvar! l
:"
@@ -614,7 +623,6 @@
: autocmd BufFilePre * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePre:' + vim.eval('bufnr("%")'))
:augroup END
py3 << EOF
-cb = vim.current.buffer
# Tests BufferAppend and BufferItem
cb.append(b[0])
# Tests BufferSlice and BufferAssSlice
@@ -859,6 +867,175 @@
:$put =string(py3eval('vim.List()'))
:$put =string(py3eval('vim.List(iter(''abc7''))'))
:$put =string(py3eval('vim.Function(''tr'')'))
+:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4])'))
+:$put =string(py3eval('vim.Function(''tr'', args=[])'))
+:$put =string(py3eval('vim.Function(''tr'', self={})'))
+:$put =string(py3eval('vim.Function(''tr'', args=[123, 3, 4], self={})'))
+:"
+:" Test vim.Function
+:function Args(...)
+: return a:000
+:endfunction
+:function SelfArgs(...) dict
+: return [a:000, self]
+:endfunction
+:" The following four lines should not crash
+:let Pt = function('tr', [[]], {'l': []})
+:py3 Pt = vim.bindeval('Pt')
+:unlet Pt
+:py3 del Pt
+py3 << EOF
+def ecall(out_prefix, func, *args, **kwargs):
+ line = out_prefix + ': '
+ try:
+ ret = func(*args, **kwargs)
+ except Exception:
+ line += '!exception: ' + emsg(sys.exc_info())
+ else:
+ line += '!result: ' + str(vim.Function('string')(ret), 'utf-8')
+ cb.append(line)
+a = vim.Function('Args')
+pa1 = vim.Function('Args', args=['abcArgsPA1'])
+pa2 = vim.Function('Args', args=[])
+pa3 = vim.Function('Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'})
+pa4 = vim.Function('Args', self={'abcSelfPA4': 'abcSelfPA4Val'})
+cb.append('a: ' + repr(a))
+cb.append('pa1: ' + repr(pa1))
+cb.append('pa2: ' + repr(pa2))
+cb.append('pa3: ' + repr(pa3))
+cb.append('pa4: ' + repr(pa4))
+sa = vim.Function('SelfArgs')
+psa1 = vim.Function('SelfArgs', args=['abcArgsPSA1'])
+psa2 = vim.Function('SelfArgs', args=[])
+psa3 = vim.Function('SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'})
+psa4 = vim.Function('SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'})
+cb.append('sa: ' + repr(sa))
+cb.append('psa1: ' + repr(psa1))
+cb.append('psa2: ' + repr(psa2))
+cb.append('psa3: ' + repr(psa3))
+cb.append('psa4: ' + repr(psa4))
+
+psar = vim.Function('SelfArgs', args=[{'abcArgsPSAr': 'abcArgsPSArVal'}], self={'abcSelfPSAr': 'abcSelfPSArVal'})
+psar.args[0]['abcArgsPSAr2'] = [psar.self, psar.args[0]]
+psar.self['rec'] = psar
+psar.self['self'] = psar.self
+psar.self['args'] = psar.args
+
+try:
+ cb.append('psar: ' + repr(psar))
+except Exception:
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
+EOF
+:$put ='s(a): '.string(py3eval('a'))
+:$put ='s(pa1): '.string(py3eval('pa1'))
+:$put ='s(pa2): '.string(py3eval('pa2'))
+:$put ='s(pa3): '.string(py3eval('pa3'))
+:$put ='s(pa4): '.string(py3eval('pa4'))
+:$put ='s(sa): '.string(py3eval('sa'))
+:$put ='s(psa1): '.string(py3eval('psa1'))
+:$put ='s(psa2): '.string(py3eval('psa2'))
+:$put ='s(psa3): '.string(py3eval('psa3'))
+:$put ='s(psa4): '.string(py3eval('psa4'))
+:
+:py3 ecall('a()', a, )
+:py3 ecall('pa1()', pa1, )
+:py3 ecall('pa2()', pa2, )
+:py3 ecall('pa3()', pa3, )
+:py3 ecall('pa4()', pa4, )
+:py3 ecall('sa()', sa, )
+:py3 ecall('psa1()', psa1, )
+:py3 ecall('psa2()', psa2, )
+:py3 ecall('psa3()', psa3, )
+:py3 ecall('psa4()', psa4, )
+:
+:py3 ecall('a(42, 43)', a, 42, 43)
+:py3 ecall('pa1(42, 43)', pa1, 42, 43)
+:py3 ecall('pa2(42, 43)', pa2, 42, 43)
+:py3 ecall('pa3(42, 43)', pa3, 42, 43)
+:py3 ecall('pa4(42, 43)', pa4, 42, 43)
+:py3 ecall('sa(42, 43)', sa, 42, 43)
+:py3 ecall('psa1(42, 43)', psa1, 42, 43)
+:py3 ecall('psa2(42, 43)', psa2, 42, 43)
+:py3 ecall('psa3(42, 43)', psa3, 42, 43)
+:py3 ecall('psa4(42, 43)', psa4, 42, 43)
+:
+:py3 ecall('a(42, self={"20": 1})', a, 42, self={'20': 1})
+:py3 ecall('pa1(42, self={"20": 1})', pa1, 42, self={'20': 1})
+:py3 ecall('pa2(42, self={"20": 1})', pa2, 42, self={'20': 1})
+:py3 ecall('pa3(42, self={"20": 1})', pa3, 42, self={'20': 1})
+:py3 ecall('pa4(42, self={"20": 1})', pa4, 42, self={'20': 1})
+:py3 ecall('sa(42, self={"20": 1})', sa, 42, self={'20': 1})
+:py3 ecall('psa1(42, self={"20": 1})', psa1, 42, self={'20': 1})
+:py3 ecall('psa2(42, self={"20": 1})', psa2, 42, self={'20': 1})
+:py3 ecall('psa3(42, self={"20": 1})', psa3, 42, self={'20': 1})
+:py3 ecall('psa4(42, self={"20": 1})', psa4, 42, self={'20': 1})
+:
+:py3 ecall('a(self={"20": 1})', a, self={'20': 1})
+:py3 ecall('pa1(self={"20": 1})', pa1, self={'20': 1})
+:py3 ecall('pa2(self={"20": 1})', pa2, self={'20': 1})
+:py3 ecall('pa3(self={"20": 1})', pa3, self={'20': 1})
+:py3 ecall('pa4(self={"20": 1})', pa4, self={'20': 1})
+:py3 ecall('sa(self={"20": 1})', sa, self={'20': 1})
+:py3 ecall('psa1(self={"20": 1})', psa1, self={'20': 1})
+:py3 ecall('psa2(self={"20": 1})', psa2, self={'20': 1})
+:py3 ecall('psa3(self={"20": 1})', psa3, self={'20': 1})
+:py3 ecall('psa4(self={"20": 1})', psa4, self={'20': 1})
+py3 << EOF
+def s(v):
+ if v is None:
+ return repr(v)
+ else:
+ return str(vim.Function('string')(v), 'utf-8')
+
+cb.append('a.args: ' + s(a.args))
+cb.append('pa1.args: ' + s(pa1.args))
+cb.append('pa2.args: ' + s(pa2.args))
+cb.append('pa3.args: ' + s(pa3.args))
+cb.append('pa4.args: ' + s(pa4.args))
+cb.append('sa.args: ' + s(sa.args))
+cb.append('psa1.args: ' + s(psa1.args))
+cb.append('psa2.args: ' + s(psa2.args))
+cb.append('psa3.args: ' + s(psa3.args))
+cb.append('psa4.args: ' + s(psa4.args))
+
+cb.append('a.self: ' + s(a.self))
+cb.append('pa1.self: ' + s(pa1.self))
+cb.append('pa2.self: ' + s(pa2.self))
+cb.append('pa3.self: ' + s(pa3.self))
+cb.append('pa4.self: ' + s(pa4.self))
+cb.append('sa.self: ' + s(sa.self))
+cb.append('psa1.self: ' + s(psa1.self))
+cb.append('psa2.self: ' + s(psa2.self))
+cb.append('psa3.self: ' + s(psa3.self))
+cb.append('psa4.self: ' + s(psa4.self))
+
+cb.append('a.name: ' + s(a.name))
+cb.append('pa1.name: ' + s(pa1.name))
+cb.append('pa2.name: ' + s(pa2.name))
+cb.append('pa3.name: ' + s(pa3.name))
+cb.append('pa4.name: ' + s(pa4.name))
+cb.append('sa.name: ' + s(sa.name))
+cb.append('psa1.name: ' + s(psa1.name))
+cb.append('psa2.name: ' + s(psa2.name))
+cb.append('psa3.name: ' + s(psa3.name))
+cb.append('psa4.name: ' + s(psa4.name))
+
+del s
+
+del a
+del pa1
+del pa2
+del pa3
+del pa4
+del sa
+del psa1
+del psa2
+del psa3
+del psa4
+del psar
+
+del ecall
+EOF
:"
:" Test stdout/stderr
:redir => messages
@@ -1134,7 +1311,7 @@
ee('vim.foreach_rtp(int, 2)')
cb.append('> import')
old_rtp = vim.options['rtp']
-vim.options['rtp'] = os.getcwd().replace(',', '\\,').replace('\\', '\\\\')
+vim.options['rtp'] = os.getcwd().replace('\\', '\\\\').replace(',', '\\,')
ee('import xxx_no_such_module_xxx')
ee('import failing_import')
ee('import failing')
@@ -1218,9 +1395,20 @@
ee('l.xxx = True')
cb.append("> Function")
cb.append(">> FunctionConstructor")
+cb.append(">>> FunctionConstructor")
ee('vim.Function("123")')
ee('vim.Function("xxx_non_existent_function_xxx")')
ee('vim.Function("xxx#non#existent#function#xxx")')
+ee('vim.Function("xxx_non_existent_function_xxx2", args=[])')
+ee('vim.Function("xxx_non_existent_function_xxx3", self={})')
+ee('vim.Function("xxx_non_existent_function_xxx4", args=[], self={})')
+cb.append(">>> FunctionNew")
+ee('vim.Function("tr", self="abcFuncSelf")')
+ee('vim.Function("tr", args=427423)')
+ee('vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function(self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2")')
+ee('vim.Function("tr", "")')
cb.append(">> FunctionCall")
convertfrompyobject_test('f(%s)')
convertfrompymapping_test('fd(self=%s)')
@@ -1374,16 +1562,16 @@
vim.command('while 1 | endwhile')
except KeyboardInterrupt:
cb.append('Caught KeyboardInterrupt')
- except Exception as e:
- cb.append('!!!!!!!! Caught exception: ' + repr(e))
+ except Exception:
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
else:
cb.append('!!!!!!!! No exception')
try:
vim.command('$ put =\'Running :put\'')
except KeyboardInterrupt:
cb.append('!!!!!!!! Caught KeyboardInterrupt')
- except Exception as e:
- cb.append('!!!!!!!! Caught exception: ' + repr(e))
+ except Exception:
+ cb.append('!!!!!!!! Caught exception: ' + emsg(sys.exc_info()))
else:
cb.append('No exception')
EOF
@@ -1403,6 +1591,7 @@
py3 << EOF
del cb
del ee
+del emsg
del sys
del os
del vim
@@ -1434,8 +1623,9 @@
:call garbagecollect(1)
:"
:/^start:/,$wq! test.out
+:/^start:/,$w! test.out
:" vim: et ts=4 isk-=\:
-:call getchar()
+:while getchar(0) isnot 0|endwhile
ENDTEST
start:
diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok
index 1d9b6e2..25c0b51 100644
--- a/src/testdir/test87.ok
+++ b/src/testdir/test87.ok
@@ -57,6 +57,7 @@
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7]
+l[2] threw vim.error: error:('list is locked',)
[0, 1, 2, 3]
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
@@ -447,7 +448,7 @@
range:__dir__,append,end,start
dictionary:__dir__,get,has_key,items,keys,locked,pop,popitem,scope,update,values
list:__dir__,extend,locked
-function:__dir__,softspace
+function:__dir__,args,self,softspace
output:__dir__,close,flush,isatty,readable,seekable,softspace,writable,write,writelines
{}
{'a': 1}
@@ -455,12 +456,108 @@
[]
['a', 'b', 'c', '7']
function('tr')
+function('tr', [123, 3, 4])
+function('tr')
+function('tr', {})
+function('tr', [123, 3, 4], {})
+a: <vim.Function 'Args'>
+pa1: <vim.Function 'Args', args=['abcArgsPA1']>
+pa2: <vim.Function 'Args'>
+pa3: <vim.Function 'Args', args=['abcArgsPA3'], self={'abcSelfPA3': 'abcSelfPA3Val'}>
+pa4: <vim.Function 'Args', self={'abcSelfPA4': 'abcSelfPA4Val'}>
+sa: <vim.Function 'SelfArgs'>
+psa1: <vim.Function 'SelfArgs', args=['abcArgsPSA1']>
+psa2: <vim.Function 'SelfArgs'>
+psa3: <vim.Function 'SelfArgs', args=['abcArgsPSA3'], self={'abcSelfPSA3': 'abcSelfPSA3Val'}>
+psa4: <vim.Function 'SelfArgs', self={'abcSelfPSA4': 'abcSelfPSA4Val'}>
+psar: <vim.Function 'SelfArgs', args=[{'abcArgsPSAr2': [{'rec': function('SelfArgs', [{...}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{...}]}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], self={'rec': function('SelfArgs', [{'abcArgsPSAr2': [{...}, {...}], 'abcArgsPSAr': 'abcArgsPSArVal'}], {...}), 'self': {...}, 'abcSelfPSAr': 'abcSelfPSArVal', 'args': [{...}]}>
+s(a): function('Args')
+s(pa1): function('Args', ['abcArgsPA1'])
+s(pa2): function('Args')
+s(pa3): function('Args', ['abcArgsPA3'], {'abcSelfPA3': 'abcSelfPA3Val'})
+s(pa4): function('Args', {'abcSelfPA4': 'abcSelfPA4Val'})
+s(sa): function('SelfArgs')
+s(psa1): function('SelfArgs', ['abcArgsPSA1'])
+s(psa2): function('SelfArgs')
+s(psa3): function('SelfArgs', ['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'})
+s(psa4): function('SelfArgs', {'abcSelfPSA4': 'abcSelfPSA4Val'})
+a(): !result: []
+pa1(): !result: ['abcArgsPA1']
+pa2(): !result: []
+pa3(): !result: ['abcArgsPA3']
+pa4(): !result: []
+sa(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa1(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa2(): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa3(): !result: [['abcArgsPSA3'], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
+psa4(): !result: [[], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
+a(42, 43): !result: [42, 43]
+pa1(42, 43): !result: ['abcArgsPA1', 42, 43]
+pa2(42, 43): !result: [42, 43]
+pa3(42, 43): !result: ['abcArgsPA3', 42, 43]
+pa4(42, 43): !result: [42, 43]
+sa(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa1(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa2(42, 43): !exception: error:('Vim:E725: Calling dict function without Dictionary: SelfArgs',)
+psa3(42, 43): !result: [['abcArgsPSA3', 42, 43], {'abcSelfPSA3': 'abcSelfPSA3Val'}]
+psa4(42, 43): !result: [[42, 43], {'abcSelfPSA4': 'abcSelfPSA4Val'}]
+a(42, self={"20": 1}): !result: [42]
+pa1(42, self={"20": 1}): !result: ['abcArgsPA1', 42]
+pa2(42, self={"20": 1}): !result: [42]
+pa3(42, self={"20": 1}): !result: ['abcArgsPA3', 42]
+pa4(42, self={"20": 1}): !result: [42]
+sa(42, self={"20": 1}): !result: [[42], {'20': 1}]
+psa1(42, self={"20": 1}): !result: [['abcArgsPSA1', 42], {'20': 1}]
+psa2(42, self={"20": 1}): !result: [[42], {'20': 1}]
+psa3(42, self={"20": 1}): !result: [['abcArgsPSA3', 42], {'20': 1}]
+psa4(42, self={"20": 1}): !result: [[42], {'20': 1}]
+a(self={"20": 1}): !result: []
+pa1(self={"20": 1}): !result: ['abcArgsPA1']
+pa2(self={"20": 1}): !result: []
+pa3(self={"20": 1}): !result: ['abcArgsPA3']
+pa4(self={"20": 1}): !result: []
+sa(self={"20": 1}): !result: [[], {'20': 1}]
+psa1(self={"20": 1}): !result: [['abcArgsPSA1'], {'20': 1}]
+psa2(self={"20": 1}): !result: [[], {'20': 1}]
+psa3(self={"20": 1}): !result: [['abcArgsPSA3'], {'20': 1}]
+psa4(self={"20": 1}): !result: [[], {'20': 1}]
+a.args: None
+pa1.args: ['abcArgsPA1']
+pa2.args: None
+pa3.args: ['abcArgsPA3']
+pa4.args: None
+sa.args: None
+psa1.args: ['abcArgsPSA1']
+psa2.args: None
+psa3.args: ['abcArgsPSA3']
+psa4.args: None
+a.self: None
+pa1.self: None
+pa2.self: None
+pa3.self: {'abcSelfPA3': 'abcSelfPA3Val'}
+pa4.self: {'abcSelfPA4': 'abcSelfPA4Val'}
+sa.self: None
+psa1.self: None
+psa2.self: None
+psa3.self: {'abcSelfPSA3': 'abcSelfPSA3Val'}
+psa4.self: {'abcSelfPSA4': 'abcSelfPSA4Val'}
+a.name: 'Args'
+pa1.name: 'Args'
+pa2.name: 'Args'
+pa3.name: 'Args'
+pa4.name: 'Args'
+sa.name: 'SelfArgs'
+psa1.name: 'SelfArgs'
+psa2.name: 'SelfArgs'
+psa3.name: 'SelfArgs'
+psa4.name: 'SelfArgs'
'
abcdef
-line :
+Error detected while processing function RunTest[]..Test:
+line :
abcdef
abcA
-line :
+line :
abcB'
['a', 'dup_a']
['a', 'a']
@@ -1046,9 +1143,20 @@
l.xxx = True:(<class 'AttributeError'>, AttributeError('cannot set attribute xxx',))
> Function
>> FunctionConstructor
+>>> FunctionConstructor
vim.Function("123"):(<class 'ValueError'>, ValueError('unnamed function 123 does not exist',))
vim.Function("xxx_non_existent_function_xxx"):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx does not exist',))
vim.Function("xxx#non#existent#function#xxx"):NOT FAILED
+vim.Function("xxx_non_existent_function_xxx2", args=[]):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx2 does not exist',))
+vim.Function("xxx_non_existent_function_xxx3", self={}):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx3 does not exist',))
+vim.Function("xxx_non_existent_function_xxx4", args=[], self={}):(<class 'ValueError'>, ValueError('function xxx_non_existent_function_xxx4 does not exist',))
+>>> FunctionNew
+vim.Function("tr", self="abcFuncSelf"):(<class 'AttributeError'>, AttributeError('keys',))
+vim.Function("tr", args=427423):(<class 'TypeError'>, TypeError('unable to convert int to vim list',))
+vim.Function("tr", self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
+vim.Function(self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
+vim.Function("tr", "", self="abcFuncSelf2", args="abcFuncArgs2"):(<class 'AttributeError'>, AttributeError('keys',))
+vim.Function("tr", ""):(<class 'TypeError'>, TypeError('function takes exactly 1 argument (2 given)',))
>> FunctionCall
>>> Testing StringToChars using f({%s : 1})
f({1 : 1}):(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))