updated for version 7.4.107
Problem: Python: When vim.eval() encounters a Vim error, a try/catch in the
Python code doesn't catch it. (Yggdroot Chen)
Solution: Throw exceptions on errors in vim.eval(). (ZyX)
diff --git a/src/testdir/test86.in b/src/testdir/test86.in
index 91f771d..128055b 100644
--- a/src/testdir/test86.in
+++ b/src/testdir/test86.in
@@ -179,6 +179,32 @@
:unlockvar! l
:"
:" Function calls
+py << EOF
+import sys
+def ee(expr, g=globals(), l=locals()):
+ try:
+ exec(expr, g, l)
+ except:
+ ei = sys.exc_info()
+ msg = sys.exc_info()[0].__name__ + ':' + repr(sys.exc_info()[1].args)
+ msg = msg.replace('TypeError:(\'argument 1 ', 'TypeError:(\'')
+ if expr.find('None') > -1:
+ msg = msg.replace('TypeError:(\'iteration over non-sequence\',)',
+ 'TypeError:("\'NoneType\' object is not iterable",)')
+ if expr.find('FailingNumber') > -1:
+ msg = msg.replace(', not \'FailingNumber\'', '').replace('"', '\'')
+ msg = msg.replace('TypeError:(\'iteration over non-sequence\',)',
+ 'TypeError:("\'FailingNumber\' object is not iterable",)')
+ if msg.find('(\'\'') > -1 or msg.find('(\'can\'t') > -1:
+ msg = msg.replace('(\'', '("').replace('\',)', '",)')
+ if expr == 'fd(self=[])':
+ # HACK: PyMapping_Check changed meaning
+ msg = msg.replace('AttributeError:(\'keys\',)',
+ 'TypeError:(\'unable to convert list to vim dictionary\',)')
+ vim.current.buffer.append(expr + ':' + msg)
+ else:
+ vim.current.buffer.append(expr + ':NOT FAILED')
+EOF
:fun New(...)
: return ['NewStart']+a:000+['NewEnd']
:endfun
@@ -193,18 +219,10 @@
:$put =string(l)
:py l.extend([l[0].name])
:$put =string(l)
-:try
-: py l[1](1, 2, 3)
-:catch
-: $put =v:exception[:16]
-:endtry
+:py ee('l[1](1, 2, 3)')
:py f=l[0]
:delfunction New
-:try
-: py f(1, 2, 3)
-:catch
-: $put =v:exception[:16]
-:endtry
+:py ee('f(1, 2, 3)')
:if has('float')
: let l=[0.0]
: py l=vim.bindeval('l')
@@ -216,7 +234,6 @@
:let messages=[]
:delfunction DictNew
py <<EOF
-import sys
d=vim.bindeval('{}')
m=vim.bindeval('messages')
def em(expr, g=globals(), l=locals()):
@@ -323,6 +340,7 @@
:py l[0] = t.t > 8 # check if the background thread is working
:py del time
:py del threading
+:py del t
:$put =string(l)
:"
:" settrace
@@ -882,29 +900,6 @@
:fun D()
:endfun
py << EOF
-def ee(expr, g=globals(), l=locals()):
- try:
- exec(expr, g, l)
- except:
- ei = sys.exc_info()
- msg = sys.exc_info()[0].__name__ + ':' + repr(sys.exc_info()[1].args)
- msg = msg.replace('TypeError:(\'argument 1 ', 'TypeError:(\'')
- if expr.find('None') > -1:
- msg = msg.replace('TypeError:(\'iteration over non-sequence\',)',
- 'TypeError:("\'NoneType\' object is not iterable",)')
- if expr.find('FailingNumber') > -1:
- msg = msg.replace(', not \'FailingNumber\'', '').replace('"', '\'')
- msg = msg.replace('TypeError:(\'iteration over non-sequence\',)',
- 'TypeError:("\'FailingNumber\' object is not iterable",)')
- if msg.find('(\'\'') > -1 or msg.find('(\'can\'t') > -1:
- msg = msg.replace('(\'', '("').replace('\',)', '",)')
- if expr == 'fd(self=[])':
- # HACK: PyMapping_Check changed meaning
- msg = msg.replace('AttributeError:(\'keys\',)',
- 'TypeError:(\'unable to convert list to vim dictionary\',)')
- cb.append(expr + ':' + msg)
- else:
- cb.append(expr + ':NOT FAILED')
d = vim.Dictionary()
ned = vim.Dictionary(foo='bar', baz='abcD')
dl = vim.Dictionary(a=1)
@@ -1276,6 +1271,7 @@
ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.eval("xxx_unknown_function_xxx()")')
ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
del Exe
EOF
diff --git a/src/testdir/test86.ok b/src/testdir/test86.ok
index 2d5b161..9ef21db 100644
--- a/src/testdir/test86.ok
+++ b/src/testdir/test86.ok
@@ -53,8 +53,8 @@
[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'}]
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}, 'New']
-Vim(python):E725:
-Vim(python):E117:
+l[1](1, 2, 3):error:('Vim:E725: Calling dict function without Dictionary: DictNew',)
+f(1, 2, 3):error:('Vim:E117: Unknown function: New',)
[0.0, 0.0]
KeyError
TypeError
@@ -1197,6 +1197,7 @@
vim.eval("Exe('throw ''ghi''')"):error:('ghi',)
vim.eval("Exe('echoerr ''jkl''')"):error:('Vim(echoerr):jkl',)
vim.eval("Exe('xxx_non_existent_command_xxx')"):error:('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',)
+vim.eval("xxx_unknown_function_xxx()"):error:('Vim:E117: Unknown function: xxx_unknown_function_xxx',)
vim.bindeval("Exe('xxx_non_existent_command_xxx')"):error:('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',)
Caught KeyboardInterrupt
Running :put
diff --git a/src/testdir/test87.in b/src/testdir/test87.in
index 899e4f3..9abc17b 100644
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -172,6 +172,36 @@
:unlockvar! l
:"
:" Function calls
+py3 << EOF
+import sys
+import re
+
+py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$')
+
+def ee(expr, g=globals(), l=locals()):
+ cb = vim.current.buffer
+ try:
+ try:
+ exec(expr, g, l)
+ except Exception as e:
+ if sys.version_info >= (3, 3) and e.__class__ is AttributeError and str(e).find('has no attribute')>=0 and not str(e).startswith("'vim."):
+ cb.append(expr + ':' + repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1]))))
+ elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0:
+ cb.append(expr + ':' + repr((e.__class__, ImportError(str(e).replace("'", '')))))
+ elif sys.version_info >= (3, 3) and e.__class__ is TypeError:
+ m = py33_type_error_pattern.search(str(e))
+ if m:
+ msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2))
+ cb.append(expr + ':' + repr((e.__class__, TypeError(msg))))
+ else:
+ cb.append(expr + ':' + repr((e.__class__, e)))
+ else:
+ cb.append(expr + ':' + repr((e.__class__, e)))
+ else:
+ cb.append(expr + ':NOT FAILED')
+ except Exception as e:
+ cb.append(expr + '::' + repr((e.__class__, e)))
+EOF
:fun New(...)
: return ['NewStart']+a:000+['NewEnd']
:endfun
@@ -186,18 +216,10 @@
:$put =string(l)
:py3 l+=[l[0].name]
:$put =string(l)
-:try
-: py3 l[1](1, 2, 3)
-:catch
-: $put =v:exception[:13]
-:endtry
+:py3 ee('l[1](1, 2, 3)')
:py3 f=l[0]
:delfunction New
-:try
-: py3 f(1, 2, 3)
-:catch
-: $put =v:exception[:13]
-:endtry
+:py3 ee('f(1, 2, 3)')
:if has('float')
: let l=[0.0]
: py3 l=vim.bindeval('l')
@@ -315,6 +337,7 @@
:py3 l[0] = t.t > 8 # check if the background thread is working
:py3 del time
:py3 del threading
+:py3 del t
:$put =string(l)
:"
:" settrace
@@ -829,33 +852,6 @@
:fun D()
:endfun
py3 << EOF
-import re
-
-py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$')
-
-def ee(expr, g=globals(), l=locals()):
- try:
- try:
- exec(expr, g, l)
- except Exception as e:
- if sys.version_info >= (3, 3) and e.__class__ is AttributeError and str(e).find('has no attribute')>=0 and not str(e).startswith("'vim."):
- cb.append(expr + ':' + repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1]))))
- elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0:
- cb.append(expr + ':' + repr((e.__class__, ImportError(str(e).replace("'", '')))))
- elif sys.version_info >= (3, 3) and e.__class__ is TypeError:
- m = py33_type_error_pattern.search(str(e))
- if m:
- msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2))
- cb.append(expr + ':' + repr((e.__class__, TypeError(msg))))
- else:
- cb.append(expr + ':' + repr((e.__class__, e)))
- else:
- cb.append(expr + ':' + repr((e.__class__, e)))
- else:
- cb.append(expr + ':NOT FAILED')
- except Exception as e:
- cb.append(expr + '::' + repr((e.__class__, e)))
-
d = vim.Dictionary()
ned = vim.Dictionary(foo='bar', baz='abcD')
dl = vim.Dictionary(a=1)
@@ -1227,6 +1223,7 @@
ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.eval("xxx_unknown_function_xxx()")')
ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
del Exe
EOF
diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok
index 970818c..d970d5f 100644
--- a/src/testdir/test87.ok
+++ b/src/testdir/test87.ok
@@ -53,8 +53,8 @@
[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'}]
[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}, 'New']
-Vim(py3):E725:
-Vim(py3):E117:
+l[1](1, 2, 3):(<class 'vim.error'>, error('Vim:E725: Calling dict function without Dictionary: DictNew',))
+f(1, 2, 3):(<class 'vim.error'>, error('Vim:E117: Unknown function: New',))
[0.0, 0.0]
KeyError
TypeError
@@ -1186,6 +1186,7 @@
vim.eval("Exe('throw ''ghi''')"):(<class 'vim.error'>, error('ghi',))
vim.eval("Exe('echoerr ''jkl''')"):(<class 'vim.error'>, error('Vim(echoerr):jkl',))
vim.eval("Exe('xxx_non_existent_command_xxx')"):(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
+vim.eval("xxx_unknown_function_xxx()"):(<class 'vim.error'>, error('Vim:E117: Unknown function: xxx_unknown_function_xxx',))
vim.bindeval("Exe('xxx_non_existent_command_xxx')"):(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
Caught KeyboardInterrupt
Running :put