Note: different exception types are still not implemented.

# HG changeset patch
# User ZyX <[email protected]>
# Date 1368995251 -14400
# Branch python-extended-2
# Node ID 7186d7015eb10f23ca656702776806e0706e9fd4
# Parent  0d09bf6b2794ae9d21dd12e891ee0a4644c2d1ed
Add support for vim exceptions (from RFC)

diff -r 0d09bf6b2794 -r 7186d7015eb1 src/if_py_both.h
--- a/src/if_py_both.h  Sun May 19 17:33:31 2013 +0400
+++ b/src/if_py_both.h  Mon May 20 00:27:31 2013 +0400
@@ -272,20 +272,42 @@
 /* Check to see whether a Vim error has been reported, or a keyboard
  * interrupt has been detected.
  */
+
+    static void
+VimTryStart(void)
+{
+    ++trylevel;
+}
+
     static int
-VimErrorCheck(void)
+VimTryEnd(void)
+{
+    --trylevel;
+    if (got_int)
+    {
+       PyErr_SetNone(PyExc_KeyboardInterrupt);
+       return 1;
+    }
+    else if (!did_throw)
+       return 0;
+    else if (PyErr_Occurred())
+       return 1;
+    else
+    {
+       PyErr_SetVim((char *) current_exception->value);
+       discard_current_exception();
+       return 1;
+    }
+}
+
+    static int
+VimCheckInterrupt(void)
 {
     if (got_int)
     {
        PyErr_SetNone(PyExc_KeyboardInterrupt);
        return 1;
     }
-    else if (did_emsg && !PyErr_Occurred())
-    {
-       PyErr_SetNone(VimError);
-       return 1;
-    }
-
     return 0;
 }
 
@@ -306,17 +328,19 @@
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
 
+    VimTryStart();
     do_cmdline_cmd((char_u *)cmd);
     update_screen(VALID);
 
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
-    if (VimErrorCheck())
+    if (VimTryEnd())
        result = NULL;
     else
        result = Py_None;
 
+
     Py_XINCREF(result);
     return result;
 }
@@ -449,11 +473,14 @@
 
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
+    VimTryStart();
     our_tv = eval_expr((char_u *)expr, NULL);
-
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
+    if (VimTryEnd())
+       return NULL;
+
     if (our_tv == NULL)
     {
        PyErr_SetVim(_("invalid expression"));
@@ -490,11 +517,14 @@
 
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
+    VimTryStart();
     our_tv = eval_expr((char_u *)expr, NULL);
-
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
+    if (VimTryEnd())
+       return NULL;
+
     if (our_tv == NULL)
     {
        PyErr_SetVim(_("invalid expression"));
@@ -1324,12 +1354,15 @@
     Py_BEGIN_ALLOW_THREADS
     Python_Lock_Vim();
 
+    VimTryStart();
     error = func_call(name, &args, selfdict, &rettv);
 
     Python_Release_Vim();
     Py_END_ALLOW_THREADS
 
-    if (error != OK)
+    if (VimTryEnd())
+       result = NULL;
+    else if (error != OK)
     {
        result = NULL;
        PyErr_SetVim(_("failed to run function"));
@@ -1488,12 +1521,15 @@
     buf_T      *save_curbuf;
     int                r = 0;
 
+    VimTryStart();
     switch (opt_type)
     {
        case SREQ_WIN:
            if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
                                     win_find_tabpage((win_T *)from)) == FAIL)
            {
+               if (VimTryEnd())
+                   return -1;
                PyErr_SetVim("Problem while switching windows.");
                return -1;
            }
@@ -1509,7 +1545,7 @@
            set_option_value(key, numval, stringval, opt_flags);
            break;
     }
-    return r;
+    return VimTryEnd();
 }
 
     static int
@@ -1961,7 +1997,7 @@
        }
 
        /* Check for keyboard interrupts */
-       if (VimErrorCheck())
+       if (VimCheckInterrupt())
            return -1;
 
        self->win->w_cursor.lnum = lnum;
@@ -1988,11 +2024,11 @@
 #endif
        savewin = curwin;
        curwin = self->win;
+
+       VimTryStart();
        win_setheight(height);
        curwin = savewin;
-
-       /* Check for keyboard interrupts */
-       if (VimErrorCheck())
+       if (VimTryEnd())
            return -1;
 
        return 0;
@@ -2011,11 +2047,11 @@
 #endif
        savewin = curwin;
        curwin = self->win;
+
+       VimTryStart();
        win_setwidth(width);
        curwin = savewin;
-
-       /* Check for keyboard interrupts */
-       if (VimErrorCheck())
+       if (VimTryEnd())
            return -1;
 
        return 0;
@@ -2304,6 +2340,8 @@
        PyErr_Clear();
        switch_buffer(&savebuf, buf);
 
+       VimTryStart();
+
        if (u_savedel((linenr_T)n, 1L) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
        else if (ml_delete((linenr_T)n, FALSE) == FAIL)
@@ -2317,7 +2355,7 @@
 
        restore_buffer(savebuf);
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2333,6 +2371,8 @@
        if (save == NULL)
            return FAIL;
 
+       VimTryStart();
+
        /* We do not need to free "save" if ml_replace() consumes it. */
        PyErr_Clear();
        switch_buffer(&savebuf, buf);
@@ -2356,7 +2396,7 @@
        if (buf == savebuf)
            check_cursor_col();
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2395,6 +2435,7 @@
        buf_T   *savebuf;
 
        PyErr_Clear();
+       VimTryStart();
        switch_buffer(&savebuf, buf);
 
        if (u_savedel((linenr_T)lo, (long)n) == FAIL)
@@ -2416,7 +2457,7 @@
 
        restore_buffer(savebuf);
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2459,6 +2500,7 @@
            }
        }
 
+       VimTryStart();
        PyErr_Clear();
 
        // START of region without "return".  Must call restore_buffer()!
@@ -2545,7 +2587,7 @@
        // END of region without "return".
        restore_buffer(savebuf);
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2583,6 +2625,7 @@
            return FAIL;
 
        PyErr_Clear();
+       VimTryStart();
        switch_buffer(&savebuf, buf);
 
        if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
@@ -2596,7 +2639,7 @@
        restore_buffer(savebuf);
        update_screen(VALID);
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2633,6 +2676,7 @@
        }
 
        PyErr_Clear();
+       VimTryStart();
        switch_buffer(&savebuf, buf);
 
        if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
@@ -2666,7 +2710,7 @@
        restore_buffer(savebuf);
        update_screen(VALID);
 
-       if (PyErr_Occurred() || VimErrorCheck())
+       if (VimTryEnd())
            return FAIL;
 
        if (len_change)
@@ -2896,7 +2940,7 @@
     static void
 RangeDestructor(RangeObject *self)
 {
-    Py_DECREF(self->buf);
+    Py_XDECREF(self->buf);
     DESTRUCTOR_FINISH(self);
 }
 
@@ -3078,9 +3122,12 @@
        return NULL;
     mark = *pmark;
 
+    VimTryStart();
     switch_buffer(&savebuf, self->buf);
     posp = getmark(mark, FALSE);
     restore_buffer(savebuf);
+    if (VimTryEnd())
+       return NULL;
 
     if (posp == NULL)
     {
@@ -3088,10 +3135,6 @@
        return NULL;
     }
 
-    /* Check for keyboard interrupt */
-    if (VimErrorCheck())
-       return NULL;
-
     if (posp->lnum <= 0)
     {
        /* Or raise an error? */
@@ -3330,13 +3373,16 @@
            return -1;
        count = ((BufferObject *)(value))->buf->b_fnum;
 
+       VimTryStart();
        if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
        {
+           if (VimTryEnd())
+               return -1;
            PyErr_SetVim(_("failed to switch to given buffer"));
            return -1;
        }
 
-       return 0;
+       return VimTryEnd();
     }
     else if (strcmp(name, "window") == 0)
     {
@@ -3359,15 +3405,18 @@
            return -1;
        }
 
+       VimTryStart();
        win_goto(((WindowObject *)(value))->win);
        if (((WindowObject *)(value))->win != curwin)
        {
+           if (VimTryEnd())
+               return -1;
            PyErr_SetString(PyExc_RuntimeError,
                    _("did not switch to the specified window"));
            return -1;
        }
 
-       return 0;
+       return VimTryEnd();
     }
     else if (strcmp(name, "tabpage") == 0)
     {
@@ -3380,15 +3429,18 @@
        if (CheckTabPage((TabPageObject *)(value)))
            return -1;
 
+       VimTryStart();
        goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
        if (((TabPageObject *)(value))->tab != curtab)
        {
+           if (VimTryEnd())
+               return -1;
            PyErr_SetString(PyExc_RuntimeError,
                    _("did not switch to the specified tab page"));
            return -1;
        }
 
-       return 0;
+       return VimTryEnd();
     }
     else
     {
diff -r 0d09bf6b2794 -r 7186d7015eb1 src/testdir/test86.in
--- a/src/testdir/test86.in     Sun May 19 17:33:31 2013 +0400
+++ b/src/testdir/test86.in     Mon May 20 00:27:31 2013 +0400
@@ -380,20 +380,24 @@
     try:
         exec(s, g, l)
     except:
-        vim.command('throw ' + repr(sys.exc_type.__name__))
+        vim.command('return ' + repr(sys.exc_type.__name__))
 
 def ev(s, g=globals(), l=locals()):
     try:
         return eval(s, g, l)
     except:
-        vim.command('throw ' + repr(sys.exc_type.__name__))
+        vim.command('let exc=' + repr(sys.exc_type.__name__))
         return 0
 EOF
 :function E(s)
 :   python e(vim.eval('a:s'))
 :endfunction
 :function Ev(s)
-:   return pyeval('ev(vim.eval("a:s"))')
+:   let r=pyeval('ev(vim.eval("a:s"))')
+:   if exists('exc')
+:       throw exc
+:   endif
+:   return r
 :endfunction
 :py gopts1=vim.options
 :py wopts1=vim.windows[2].options
@@ -437,27 +441,24 @@
 :       catch
 :           put ='  p/'.v.'! '.v:exception
 :       endtry
-:       try
-:           call E(v.'["'.oname.'"]=invval')
-:       catch
-:           put ='  inv: '.string(invval).'! '.v:exception
-:       endtry
+:       let r=E(v.'['''.oname.''']=invval')
+:       if r isnot 0
+:           put ='  inv: '.string(invval).'! '.r
+:       endif
 :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
 :           let val=substitute(vv, '^.opts', 'oval', '')
-:           try
-:               call E(vv.'["'.oname.'"]='.val)
-:           catch
-:               put ='  '.vv.'! '.v:exception
-:           endtry
+:           let r=E(vv.'['''.oname.''']='.val)
+:           if r isnot 0
+:               put ='  '.vv.'! '.r
+:           endif
 :       endfor
 :   endfor
 :   call RecVars(oname)
 :   for v in ['wopts3', 'bopts3']
-:       try
-:           call E('del '.v.'["'.oname.'"]')
-:       catch
-:           put ='  del '.v.'! '.v:exception
-:       endtry
+:       let r=E('del '.v.'["'.oname.'"]')
+:       if r isnot 0
+:           put ='  del '.v.'! '.r
+:       endif
 :   endfor
 :   call RecVars(oname)
 :endfor
@@ -651,6 +652,25 @@
 ):
     cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, 
attr)))
 EOF
+:"
+:" Test exceptions
+:fun Exe(e)
+:   execute a:e
+:endfun
+py << EOF
+def ee(expr, g=globals(), l=locals()):
+    try:
+        exec(expr, g, l)
+    except:
+        cb.append(repr(sys.exc_info()[:2]))
+Exe = vim.bindeval('function("Exe")')
+ee('vim.command("throw \'abc\'")')
+ee('Exe("throw \'def\'")')
+ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+EOF
 :endfun
 :"
 :call Test()
diff -r 0d09bf6b2794 -r 7186d7015eb1 src/testdir/test86.ok
--- a/src/testdir/test86.ok     Sun May 19 17:33:31 2013 +0400
+++ b/src/testdir/test86.ok     Mon May 20 00:27:31 2013 +0400
@@ -333,7 +333,7 @@
 Current tab pages:
   <tabpage 0>(1): 1 windows, current is <window object (unknown)>
   Windows:
-    <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor 
is at (970, 0)
+    <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor 
is at (971, 0)
   <tabpage 1>(2): 1 windows, current is <window object (unknown)>
   Windows:
     <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 
0)
@@ -368,3 +368,9 @@
 vim.current.range:Range:True
 vim.current.window:Window:True
 vim.current.tabpage:TabPage:True
+(<class 'vim.error'>, error('abc',))
+(<class 'vim.error'>, error('def',))
+(<class 'vim.error'>, error('ghi',))
+(<class 'vim.error'>, error('Vim(echoerr):jkl',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: 
xxx_non_existent_command_xxx',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: 
xxx_non_existent_command_xxx',))
diff -r 0d09bf6b2794 -r 7186d7015eb1 src/testdir/test87.in
--- a/src/testdir/test87.in     Sun May 19 17:33:31 2013 +0400
+++ b/src/testdir/test87.in     Mon May 20 00:27:31 2013 +0400
@@ -367,20 +367,24 @@
     try:
         exec(s, g, l)
     except Exception as e:
-        vim.command('throw ' + repr(e.__class__.__name__))
+        vim.command('return ' + repr(e.__class__.__name__))
 
 def ev(s, g=globals(), l=locals()):
     try:
         return eval(s, g, l)
     except Exception as e:
-        vim.command('throw ' + repr(e.__class__.__name__))
+        vim.command('let exc=' + repr(e.__class__.__name__))
         return 0
 EOF
 :function E(s)
 :   python3 e(vim.eval('a:s'))
 :endfunction
 :function Ev(s)
-:   return py3eval('ev(vim.eval("a:s"))')
+:   let r=py3eval('ev(vim.eval("a:s"))')
+:   if exists('exc')
+:       throw exc
+:   endif
+:   return r
 :endfunction
 :py3 gopts1=vim.options
 :py3 wopts1=vim.windows[2].options
@@ -424,27 +428,24 @@
 :       catch
 :           put ='  p/'.v.'! '.v:exception
 :       endtry
-:       try
-:           call E(v.'["'.oname.'"]=invval')
-:       catch
-:           put ='  inv: '.string(invval).'! '.v:exception
-:       endtry
+:       let r=E(v.'['''.oname.''']=invval')
+:       if r isnot 0
+:           put ='  inv: '.string(invval).'! '.r
+:       endif
 :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
 :           let val=substitute(vv, '^.opts', 'oval', '')
-:           try
-:               call E(vv.'["'.oname.'"]='.val)
-:           catch
-:               put ='  '.vv.'! '.v:exception
-:           endtry
+:           let r=E(vv.'['''.oname.''']='.val)
+:           if r isnot 0
+:               put ='  '.vv.'! '.r
+:           endif
 :       endfor
 :   endfor
 :   call RecVars(oname)
 :   for v in ['wopts3', 'bopts3']
-:       try
-:           call E('del '.v.'["'.oname.'"]')
-:       catch
-:           put ='  del '.v.'! '.v:exception
-:       endtry
+:       let r=E('del '.v.'["'.oname.'"]')
+:       if r isnot 0
+:           put ='  del '.v.'! '.r
+:       endif
 :   endfor
 :   call RecVars(oname)
 :endfor
@@ -638,6 +639,25 @@
 ):
     cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, 
attr)))
 EOF
+:"
+:" Test exceptions
+:fun Exe(e)
+:   execute a:e
+:endfun
+py3 << EOF
+def ee(expr, g=globals(), l=locals()):
+    try:
+        exec(expr, g, l)
+    except Exception as e:
+        cb.append(repr((e.__class__, e)))
+Exe = vim.bindeval('function("Exe")')
+ee('vim.command("throw \'abc\'")')
+ee('Exe("throw \'def\'")')
+ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+EOF
 :endfun
 :"
 :call Test()
diff -r 0d09bf6b2794 -r 7186d7015eb1 src/testdir/test87.ok
--- a/src/testdir/test87.ok     Sun May 19 17:33:31 2013 +0400
+++ b/src/testdir/test87.ok     Mon May 20 00:27:31 2013 +0400
@@ -322,7 +322,7 @@
 Current tab pages:
   <tabpage 0>(1): 1 windows, current is <window object (unknown)>
   Windows:
-    <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor 
is at (946, 0)
+    <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor 
is at (947, 0)
   <tabpage 1>(2): 1 windows, current is <window object (unknown)>
   Windows:
     <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 
0)
@@ -357,3 +357,9 @@
 vim.current.range:Range:True
 vim.current.window:Window:True
 vim.current.tabpage:TabPage:True
+(<class 'vim.error'>, error('abc',))
+(<class 'vim.error'>, error('def',))
+(<class 'vim.error'>, error('ghi',))
+(<class 'vim.error'>, error('Vim(echoerr):jkl',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: 
xxx_non_existent_command_xxx',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: 
xxx_non_existent_command_xxx',))

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


diff -cr vim.0d09bf6b2794/src/if_py_both.h vim.7186d7015eb1/src/if_py_both.h
*** vim.0d09bf6b2794/src/if_py_both.h	2013-05-20 00:34:23.136853412 +0400
--- vim.7186d7015eb1/src/if_py_both.h	2013-05-20 00:34:23.145853323 +0400
***************
*** 272,291 ****
  /* Check to see whether a Vim error has been reported, or a keyboard
   * interrupt has been detected.
   */
      static int
! VimErrorCheck(void)
  {
      if (got_int)
      {
  	PyErr_SetNone(PyExc_KeyboardInterrupt);
  	return 1;
      }
!     else if (did_emsg && !PyErr_Occurred())
      {
! 	PyErr_SetNone(VimError);
  	return 1;
      }
  
      return 0;
  }
  
--- 272,313 ----
  /* Check to see whether a Vim error has been reported, or a keyboard
   * interrupt has been detected.
   */
+ 
+     static void
+ VimTryStart(void)
+ {
+     ++trylevel;
+ }
+ 
      static int
! VimTryEnd(void)
  {
+     --trylevel;
      if (got_int)
      {
  	PyErr_SetNone(PyExc_KeyboardInterrupt);
  	return 1;
      }
!     else if (!did_throw)
! 	return 0;
!     else if (PyErr_Occurred())
! 	return 1;
!     else
      {
! 	PyErr_SetVim((char *) current_exception->value);
! 	discard_current_exception();
  	return 1;
      }
+ }
  
+     static int
+ VimCheckInterrupt(void)
+ {
+     if (got_int)
+     {
+ 	PyErr_SetNone(PyExc_KeyboardInterrupt);
+ 	return 1;
+     }
      return 0;
  }
  
***************
*** 306,322 ****
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
  
      do_cmdline_cmd((char_u *)cmd);
      update_screen(VALID);
  
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
!     if (VimErrorCheck())
  	result = NULL;
      else
  	result = Py_None;
  
      Py_XINCREF(result);
      return result;
  }
--- 328,346 ----
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
  
+     VimTryStart();
      do_cmdline_cmd((char_u *)cmd);
      update_screen(VALID);
  
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
!     if (VimTryEnd())
  	result = NULL;
      else
  	result = Py_None;
  
+ 
      Py_XINCREF(result);
      return result;
  }
***************
*** 449,459 ****
  
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
      our_tv = eval_expr((char_u *)expr, NULL);
- 
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
      if (our_tv == NULL)
      {
  	PyErr_SetVim(_("invalid expression"));
--- 473,486 ----
  
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
+     VimTryStart();
      our_tv = eval_expr((char_u *)expr, NULL);
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
+     if (VimTryEnd())
+ 	return NULL;
+ 
      if (our_tv == NULL)
      {
  	PyErr_SetVim(_("invalid expression"));
***************
*** 490,500 ****
  
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
      our_tv = eval_expr((char_u *)expr, NULL);
- 
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
      if (our_tv == NULL)
      {
  	PyErr_SetVim(_("invalid expression"));
--- 517,530 ----
  
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
+     VimTryStart();
      our_tv = eval_expr((char_u *)expr, NULL);
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
+     if (VimTryEnd())
+ 	return NULL;
+ 
      if (our_tv == NULL)
      {
  	PyErr_SetVim(_("invalid expression"));
***************
*** 1324,1335 ****
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
  
      error = func_call(name, &args, selfdict, &rettv);
  
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
!     if (error != OK)
      {
  	result = NULL;
  	PyErr_SetVim(_("failed to run function"));
--- 1354,1368 ----
      Py_BEGIN_ALLOW_THREADS
      Python_Lock_Vim();
  
+     VimTryStart();
      error = func_call(name, &args, selfdict, &rettv);
  
      Python_Release_Vim();
      Py_END_ALLOW_THREADS
  
!     if (VimTryEnd())
! 	result = NULL;
!     else if (error != OK)
      {
  	result = NULL;
  	PyErr_SetVim(_("failed to run function"));
***************
*** 1488,1499 ****
--- 1521,1535 ----
      buf_T	*save_curbuf;
      int		r = 0;
  
+     VimTryStart();
      switch (opt_type)
      {
  	case SREQ_WIN:
  	    if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
  				     win_find_tabpage((win_T *)from)) == FAIL)
  	    {
+ 		if (VimTryEnd())
+ 		    return -1;
  		PyErr_SetVim("Problem while switching windows.");
  		return -1;
  	    }
***************
*** 1509,1515 ****
  	    set_option_value(key, numval, stringval, opt_flags);
  	    break;
      }
!     return r;
  }
  
      static int
--- 1545,1551 ----
  	    set_option_value(key, numval, stringval, opt_flags);
  	    break;
      }
!     return VimTryEnd();
  }
  
      static int
***************
*** 1961,1967 ****
  	}
  
  	/* Check for keyboard interrupts */
! 	if (VimErrorCheck())
  	    return -1;
  
  	self->win->w_cursor.lnum = lnum;
--- 1997,2003 ----
  	}
  
  	/* Check for keyboard interrupts */
! 	if (VimCheckInterrupt())
  	    return -1;
  
  	self->win->w_cursor.lnum = lnum;
***************
*** 1988,1998 ****
  #endif
  	savewin = curwin;
  	curwin = self->win;
  	win_setheight(height);
  	curwin = savewin;
! 
! 	/* Check for keyboard interrupts */
! 	if (VimErrorCheck())
  	    return -1;
  
  	return 0;
--- 2024,2034 ----
  #endif
  	savewin = curwin;
  	curwin = self->win;
+ 
+ 	VimTryStart();
  	win_setheight(height);
  	curwin = savewin;
! 	if (VimTryEnd())
  	    return -1;
  
  	return 0;
***************
*** 2011,2021 ****
  #endif
  	savewin = curwin;
  	curwin = self->win;
  	win_setwidth(width);
  	curwin = savewin;
! 
! 	/* Check for keyboard interrupts */
! 	if (VimErrorCheck())
  	    return -1;
  
  	return 0;
--- 2047,2057 ----
  #endif
  	savewin = curwin;
  	curwin = self->win;
+ 
+ 	VimTryStart();
  	win_setwidth(width);
  	curwin = savewin;
! 	if (VimTryEnd())
  	    return -1;
  
  	return 0;
***************
*** 2304,2309 ****
--- 2340,2347 ----
  	PyErr_Clear();
  	switch_buffer(&savebuf, buf);
  
+ 	VimTryStart();
+ 
  	if (u_savedel((linenr_T)n, 1L) == FAIL)
  	    PyErr_SetVim(_("cannot save undo information"));
  	else if (ml_delete((linenr_T)n, FALSE) == FAIL)
***************
*** 2317,2323 ****
  
  	restore_buffer(savebuf);
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2355,2361 ----
  
  	restore_buffer(savebuf);
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2333,2338 ****
--- 2371,2378 ----
  	if (save == NULL)
  	    return FAIL;
  
+ 	VimTryStart();
+ 
  	/* We do not need to free "save" if ml_replace() consumes it. */
  	PyErr_Clear();
  	switch_buffer(&savebuf, buf);
***************
*** 2356,2362 ****
  	if (buf == savebuf)
  	    check_cursor_col();
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2396,2402 ----
  	if (buf == savebuf)
  	    check_cursor_col();
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2395,2400 ****
--- 2435,2441 ----
  	buf_T	*savebuf;
  
  	PyErr_Clear();
+ 	VimTryStart();
  	switch_buffer(&savebuf, buf);
  
  	if (u_savedel((linenr_T)lo, (long)n) == FAIL)
***************
*** 2416,2422 ****
  
  	restore_buffer(savebuf);
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2457,2463 ----
  
  	restore_buffer(savebuf);
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2459,2464 ****
--- 2500,2506 ----
  	    }
  	}
  
+ 	VimTryStart();
  	PyErr_Clear();
  
  	// START of region without "return".  Must call restore_buffer()!
***************
*** 2545,2551 ****
  	// END of region without "return".
  	restore_buffer(savebuf);
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2587,2593 ----
  	// END of region without "return".
  	restore_buffer(savebuf);
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2583,2588 ****
--- 2625,2631 ----
  	    return FAIL;
  
  	PyErr_Clear();
+ 	VimTryStart();
  	switch_buffer(&savebuf, buf);
  
  	if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
***************
*** 2596,2602 ****
  	restore_buffer(savebuf);
  	update_screen(VALID);
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2639,2645 ----
  	restore_buffer(savebuf);
  	update_screen(VALID);
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2633,2638 ****
--- 2676,2682 ----
  	}
  
  	PyErr_Clear();
+ 	VimTryStart();
  	switch_buffer(&savebuf, buf);
  
  	if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
***************
*** 2666,2672 ****
  	restore_buffer(savebuf);
  	update_screen(VALID);
  
! 	if (PyErr_Occurred() || VimErrorCheck())
  	    return FAIL;
  
  	if (len_change)
--- 2710,2716 ----
  	restore_buffer(savebuf);
  	update_screen(VALID);
  
! 	if (VimTryEnd())
  	    return FAIL;
  
  	if (len_change)
***************
*** 2896,2902 ****
      static void
  RangeDestructor(RangeObject *self)
  {
!     Py_DECREF(self->buf);
      DESTRUCTOR_FINISH(self);
  }
  
--- 2940,2946 ----
      static void
  RangeDestructor(RangeObject *self)
  {
!     Py_XDECREF(self->buf);
      DESTRUCTOR_FINISH(self);
  }
  
***************
*** 3078,3086 ****
--- 3122,3133 ----
  	return NULL;
      mark = *pmark;
  
+     VimTryStart();
      switch_buffer(&savebuf, self->buf);
      posp = getmark(mark, FALSE);
      restore_buffer(savebuf);
+     if (VimTryEnd())
+ 	return NULL;
  
      if (posp == NULL)
      {
***************
*** 3088,3097 ****
  	return NULL;
      }
  
-     /* Check for keyboard interrupt */
-     if (VimErrorCheck())
- 	return NULL;
- 
      if (posp->lnum <= 0)
      {
  	/* Or raise an error? */
--- 3135,3140 ----
***************
*** 3330,3342 ****
  	    return -1;
  	count = ((BufferObject *)(value))->buf->b_fnum;
  
  	if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
  	{
  	    PyErr_SetVim(_("failed to switch to given buffer"));
  	    return -1;
  	}
  
! 	return 0;
      }
      else if (strcmp(name, "window") == 0)
      {
--- 3373,3388 ----
  	    return -1;
  	count = ((BufferObject *)(value))->buf->b_fnum;
  
+ 	VimTryStart();
  	if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
  	{
+ 	    if (VimTryEnd())
+ 		return -1;
  	    PyErr_SetVim(_("failed to switch to given buffer"));
  	    return -1;
  	}
  
! 	return VimTryEnd();
      }
      else if (strcmp(name, "window") == 0)
      {
***************
*** 3359,3373 ****
  	    return -1;
  	}
  
  	win_goto(((WindowObject *)(value))->win);
  	if (((WindowObject *)(value))->win != curwin)
  	{
  	    PyErr_SetString(PyExc_RuntimeError,
  		    _("did not switch to the specified window"));
  	    return -1;
  	}
  
! 	return 0;
      }
      else if (strcmp(name, "tabpage") == 0)
      {
--- 3405,3422 ----
  	    return -1;
  	}
  
+ 	VimTryStart();
  	win_goto(((WindowObject *)(value))->win);
  	if (((WindowObject *)(value))->win != curwin)
  	{
+ 	    if (VimTryEnd())
+ 		return -1;
  	    PyErr_SetString(PyExc_RuntimeError,
  		    _("did not switch to the specified window"));
  	    return -1;
  	}
  
! 	return VimTryEnd();
      }
      else if (strcmp(name, "tabpage") == 0)
      {
***************
*** 3380,3394 ****
  	if (CheckTabPage((TabPageObject *)(value)))
  	    return -1;
  
  	goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
  	if (((TabPageObject *)(value))->tab != curtab)
  	{
  	    PyErr_SetString(PyExc_RuntimeError,
  		    _("did not switch to the specified tab page"));
  	    return -1;
  	}
  
! 	return 0;
      }
      else
      {
--- 3429,3446 ----
  	if (CheckTabPage((TabPageObject *)(value)))
  	    return -1;
  
+ 	VimTryStart();
  	goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
  	if (((TabPageObject *)(value))->tab != curtab)
  	{
+ 	    if (VimTryEnd())
+ 		return -1;
  	    PyErr_SetString(PyExc_RuntimeError,
  		    _("did not switch to the specified tab page"));
  	    return -1;
  	}
  
! 	return VimTryEnd();
      }
      else
      {
diff -cr vim.0d09bf6b2794/src/testdir/test86.in vim.7186d7015eb1/src/testdir/test86.in
*** vim.0d09bf6b2794/src/testdir/test86.in	2013-05-20 00:34:23.137853402 +0400
--- vim.7186d7015eb1/src/testdir/test86.in	2013-05-20 00:34:23.146853313 +0400
***************
*** 380,399 ****
      try:
          exec(s, g, l)
      except:
!         vim.command('throw ' + repr(sys.exc_type.__name__))
  
  def ev(s, g=globals(), l=locals()):
      try:
          return eval(s, g, l)
      except:
!         vim.command('throw ' + repr(sys.exc_type.__name__))
          return 0
  EOF
  :function E(s)
  :   python e(vim.eval('a:s'))
  :endfunction
  :function Ev(s)
! :   return pyeval('ev(vim.eval("a:s"))')
  :endfunction
  :py gopts1=vim.options
  :py wopts1=vim.windows[2].options
--- 380,403 ----
      try:
          exec(s, g, l)
      except:
!         vim.command('return ' + repr(sys.exc_type.__name__))
  
  def ev(s, g=globals(), l=locals()):
      try:
          return eval(s, g, l)
      except:
!         vim.command('let exc=' + repr(sys.exc_type.__name__))
          return 0
  EOF
  :function E(s)
  :   python e(vim.eval('a:s'))
  :endfunction
  :function Ev(s)
! :   let r=pyeval('ev(vim.eval("a:s"))')
! :   if exists('exc')
! :       throw exc
! :   endif
! :   return r
  :endfunction
  :py gopts1=vim.options
  :py wopts1=vim.windows[2].options
***************
*** 437,463 ****
  :       catch
  :           put ='  p/'.v.'! '.v:exception
  :       endtry
! :       try
! :           call E(v.'["'.oname.'"]=invval')
! :       catch
! :           put ='  inv: '.string(invval).'! '.v:exception
! :       endtry
  :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
  :           let val=substitute(vv, '^.opts', 'oval', '')
! :           try
! :               call E(vv.'["'.oname.'"]='.val)
! :           catch
! :               put ='  '.vv.'! '.v:exception
! :           endtry
  :       endfor
  :   endfor
  :   call RecVars(oname)
  :   for v in ['wopts3', 'bopts3']
! :       try
! :           call E('del '.v.'["'.oname.'"]')
! :       catch
! :           put ='  del '.v.'! '.v:exception
! :       endtry
  :   endfor
  :   call RecVars(oname)
  :endfor
--- 441,464 ----
  :       catch
  :           put ='  p/'.v.'! '.v:exception
  :       endtry
! :       let r=E(v.'['''.oname.''']=invval')
! :       if r isnot 0
! :           put ='  inv: '.string(invval).'! '.r
! :       endif
  :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
  :           let val=substitute(vv, '^.opts', 'oval', '')
! :           let r=E(vv.'['''.oname.''']='.val)
! :           if r isnot 0
! :               put ='  '.vv.'! '.r
! :           endif
  :       endfor
  :   endfor
  :   call RecVars(oname)
  :   for v in ['wopts3', 'bopts3']
! :       let r=E('del '.v.'["'.oname.'"]')
! :       if r isnot 0
! :           put ='  del '.v.'! '.r
! :       endif
  :   endfor
  :   call RecVars(oname)
  :endfor
***************
*** 651,656 ****
--- 652,676 ----
  ):
      cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
  EOF
+ :"
+ :" Test exceptions
+ :fun Exe(e)
+ :   execute a:e
+ :endfun
+ py << EOF
+ def ee(expr, g=globals(), l=locals()):
+     try:
+         exec(expr, g, l)
+     except:
+         cb.append(repr(sys.exc_info()[:2]))
+ Exe = vim.bindeval('function("Exe")')
+ ee('vim.command("throw \'abc\'")')
+ ee('Exe("throw \'def\'")')
+ ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+ EOF
  :endfun
  :"
  :call Test()
diff -cr vim.0d09bf6b2794/src/testdir/test86.ok vim.7186d7015eb1/src/testdir/test86.ok
*** vim.0d09bf6b2794/src/testdir/test86.ok	2013-05-20 00:34:23.131853462 +0400
--- vim.7186d7015eb1/src/testdir/test86.ok	2013-05-20 00:34:23.140853373 +0400
***************
*** 333,339 ****
  Current tab pages:
    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
    Windows:
!     <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (970, 0)
    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
    Windows:
      <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
--- 333,339 ----
  Current tab pages:
    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
    Windows:
!     <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (971, 0)
    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
    Windows:
      <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
***************
*** 368,370 ****
--- 368,376 ----
  vim.current.range:Range:True
  vim.current.window:Window:True
  vim.current.tabpage:TabPage:True
+ (<class 'vim.error'>, error('abc',))
+ (<class 'vim.error'>, error('def',))
+ (<class 'vim.error'>, error('ghi',))
+ (<class 'vim.error'>, error('Vim(echoerr):jkl',))
+ (<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
+ (<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
diff -cr vim.0d09bf6b2794/src/testdir/test87.in vim.7186d7015eb1/src/testdir/test87.in
*** vim.0d09bf6b2794/src/testdir/test87.in	2013-05-20 00:34:23.131853462 +0400
--- vim.7186d7015eb1/src/testdir/test87.in	2013-05-20 00:34:23.141853362 +0400
***************
*** 367,386 ****
      try:
          exec(s, g, l)
      except Exception as e:
!         vim.command('throw ' + repr(e.__class__.__name__))
  
  def ev(s, g=globals(), l=locals()):
      try:
          return eval(s, g, l)
      except Exception as e:
!         vim.command('throw ' + repr(e.__class__.__name__))
          return 0
  EOF
  :function E(s)
  :   python3 e(vim.eval('a:s'))
  :endfunction
  :function Ev(s)
! :   return py3eval('ev(vim.eval("a:s"))')
  :endfunction
  :py3 gopts1=vim.options
  :py3 wopts1=vim.windows[2].options
--- 367,390 ----
      try:
          exec(s, g, l)
      except Exception as e:
!         vim.command('return ' + repr(e.__class__.__name__))
  
  def ev(s, g=globals(), l=locals()):
      try:
          return eval(s, g, l)
      except Exception as e:
!         vim.command('let exc=' + repr(e.__class__.__name__))
          return 0
  EOF
  :function E(s)
  :   python3 e(vim.eval('a:s'))
  :endfunction
  :function Ev(s)
! :   let r=py3eval('ev(vim.eval("a:s"))')
! :   if exists('exc')
! :       throw exc
! :   endif
! :   return r
  :endfunction
  :py3 gopts1=vim.options
  :py3 wopts1=vim.windows[2].options
***************
*** 424,450 ****
  :       catch
  :           put ='  p/'.v.'! '.v:exception
  :       endtry
! :       try
! :           call E(v.'["'.oname.'"]=invval')
! :       catch
! :           put ='  inv: '.string(invval).'! '.v:exception
! :       endtry
  :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
  :           let val=substitute(vv, '^.opts', 'oval', '')
! :           try
! :               call E(vv.'["'.oname.'"]='.val)
! :           catch
! :               put ='  '.vv.'! '.v:exception
! :           endtry
  :       endfor
  :   endfor
  :   call RecVars(oname)
  :   for v in ['wopts3', 'bopts3']
! :       try
! :           call E('del '.v.'["'.oname.'"]')
! :       catch
! :           put ='  del '.v.'! '.v:exception
! :       endtry
  :   endfor
  :   call RecVars(oname)
  :endfor
--- 428,451 ----
  :       catch
  :           put ='  p/'.v.'! '.v:exception
  :       endtry
! :       let r=E(v.'['''.oname.''']=invval')
! :       if r isnot 0
! :           put ='  inv: '.string(invval).'! '.r
! :       endif
  :       for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
  :           let val=substitute(vv, '^.opts', 'oval', '')
! :           let r=E(vv.'['''.oname.''']='.val)
! :           if r isnot 0
! :               put ='  '.vv.'! '.r
! :           endif
  :       endfor
  :   endfor
  :   call RecVars(oname)
  :   for v in ['wopts3', 'bopts3']
! :       let r=E('del '.v.'["'.oname.'"]')
! :       if r isnot 0
! :           put ='  del '.v.'! '.r
! :       endif
  :   endfor
  :   call RecVars(oname)
  :endfor
***************
*** 638,643 ****
--- 639,663 ----
  ):
      cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
  EOF
+ :"
+ :" Test exceptions
+ :fun Exe(e)
+ :   execute a:e
+ :endfun
+ py3 << EOF
+ def ee(expr, g=globals(), l=locals()):
+     try:
+         exec(expr, g, l)
+     except Exception as e:
+         cb.append(repr((e.__class__, e)))
+ Exe = vim.bindeval('function("Exe")')
+ ee('vim.command("throw \'abc\'")')
+ ee('Exe("throw \'def\'")')
+ ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+ EOF
  :endfun
  :"
  :call Test()
diff -cr vim.0d09bf6b2794/src/testdir/test87.ok vim.7186d7015eb1/src/testdir/test87.ok
*** vim.0d09bf6b2794/src/testdir/test87.ok	2013-05-20 00:34:23.132853452 +0400
--- vim.7186d7015eb1/src/testdir/test87.ok	2013-05-20 00:34:23.141853362 +0400
***************
*** 322,328 ****
  Current tab pages:
    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
    Windows:
!     <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (946, 0)
    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
    Windows:
      <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
--- 322,328 ----
  Current tab pages:
    <tabpage 0>(1): 1 windows, current is <window object (unknown)>
    Windows:
!     <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (947, 0)
    <tabpage 1>(2): 1 windows, current is <window object (unknown)>
    Windows:
      <window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
***************
*** 357,359 ****
--- 357,365 ----
  vim.current.range:Range:True
  vim.current.window:Window:True
  vim.current.tabpage:TabPage:True
+ (<class 'vim.error'>, error('abc',))
+ (<class 'vim.error'>, error('def',))
+ (<class 'vim.error'>, error('ghi',))
+ (<class 'vim.error'>, error('Vim(echoerr):jkl',))
+ (<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
+ (<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))

Raspunde prin e-mail lui