changeset 4589:fa39483a1363 v7.3.1042

updated for version 7.3.1042 Problem: Python: can't assign to vim.Buffer.name. Solution: Python patch 3. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Wed, 29 May 2013 22:02:22 +0200
parents 15cf120f2a68
children 80261e8d907b
files runtime/doc/if_pyth.txt src/ex_cmds.c src/if_py_both.h src/if_python.c src/if_python3.c src/proto/ex_cmds.pro src/testdir/test86.in src/testdir/test86.ok src/testdir/test87.in src/testdir/test87.ok src/version.c
diffstat 11 files changed, 263 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -250,7 +250,7 @@ vim.windows						*python-windows*
 	object and always use windows from that tab page (or throw vim.error 
 	in case tab page was deleted). You can keep a reference to both 
 	without keeping a reference to vim module object or |python-tabpage|, 
-	they will not loose their properties in this case.
+	they will not lose their properties in this case.
 
 vim.tabpages						*python-tabpages*
 	A sequence object providing access to the list of vim tab pages. The 
@@ -361,6 +361,11 @@ The buffer object attributes are:
 			this object will raise KeyError. If option is 
 			|global-local| and local value is missing getting it 
 			will return None.
+	b.name		String, RW. Contains buffer name (full path).
+			Note: when assigning to b.name |BufFilePre| and 
+			|BufFilePost| autocommands are launched.
+	b.number	Buffer number. Can be used as |python-buffers| key.
+			Read-only.
 
 The buffer object methods are:
 	b.append(str)	Append a line to the buffer
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -784,6 +784,7 @@ do_move(line1, line2, dest)
      */
     last_line = curbuf->b_ml.ml_line_count;
     mark_adjust(line1, line2, last_line - line2, 0L);
+    changed_lines(last_line - num_lines + 1, 0, last_line + 1, num_lines);
     if (dest >= line2)
     {
 	mark_adjust(line2 + 1, dest, -num_lines, 0L);
@@ -799,6 +800,7 @@ do_move(line1, line2, dest)
     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
     mark_adjust(last_line - num_lines + 1, last_line,
 					     -(last_line - dest - extra), 0L);
+    changed_lines(last_line - num_lines + 1, 0, last_line + 1, -extra);
 
     /*
      * Now we delete the original text -- webb
@@ -2414,6 +2416,58 @@ print_line(lnum, use_number, list)
     info_message = FALSE;
 }
 
+    int
+rename_buffer(new_fname)
+    char_u	*new_fname;
+{
+    char_u	*fname, *sfname, *xfname;
+#ifdef FEAT_AUTOCMD
+    buf_T	*buf = curbuf;
+
+    apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, buf);
+    /* buffer changed, don't change name now */
+    if (buf != curbuf)
+	return FAIL;
+# ifdef FEAT_EVAL
+    if (aborting())	    /* autocmds may abort script processing */
+	return FAIL;
+# endif
+#endif
+    /*
+     * The name of the current buffer will be changed.
+     * A new (unlisted) buffer entry needs to be made to hold the old file
+     * name, which will become the alternate file name.
+     * But don't set the alternate file name if the buffer didn't have a
+     * name.
+     */
+    fname = buf->b_ffname;
+    sfname = buf->b_sfname;
+    xfname = buf->b_fname;
+    buf->b_ffname = NULL;
+    buf->b_sfname = NULL;
+    if (setfname(buf, new_fname, NULL, TRUE) == FAIL)
+    {
+	buf->b_ffname = fname;
+	buf->b_sfname = sfname;
+	return FAIL;
+    }
+    buf->b_flags |= BF_NOTEDITED;
+    if (xfname != NULL && *xfname != NUL)
+    {
+	buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
+	if (buf != NULL && !cmdmod.keepalt)
+	    curwin->w_alt_fnum = buf->b_fnum;
+    }
+    vim_free(fname);
+    vim_free(sfname);
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, buf);
+#endif
+    /* Change directories when the 'acd' option is set. */
+    DO_AUTOCHDIR
+    return OK;
+}
+
 /*
  * ":file[!] [fname]".
  */
@@ -2421,9 +2475,6 @@ print_line(lnum, use_number, list)
 ex_file(eap)
     exarg_T	*eap;
 {
-    char_u	*fname, *sfname, *xfname;
-    buf_T	*buf;
-
     /* ":0file" removes the file name.  Check for illegal uses ":3file",
      * "0file name", etc. */
     if (eap->addr_count > 0
@@ -2437,49 +2488,8 @@ ex_file(eap)
 
     if (*eap->arg != NUL || eap->addr_count == 1)
     {
-#ifdef FEAT_AUTOCMD
-	buf = curbuf;
-	apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
-	/* buffer changed, don't change name now */
-	if (buf != curbuf)
-	    return;
-# ifdef FEAT_EVAL
-	if (aborting())	    /* autocmds may abort script processing */
+	if (rename_buffer(eap->arg) == FAIL)
 	    return;
-# endif
-#endif
-	/*
-	 * The name of the current buffer will be changed.
-	 * A new (unlisted) buffer entry needs to be made to hold the old file
-	 * name, which will become the alternate file name.
-	 * But don't set the alternate file name if the buffer didn't have a
-	 * name.
-	 */
-	fname = curbuf->b_ffname;
-	sfname = curbuf->b_sfname;
-	xfname = curbuf->b_fname;
-	curbuf->b_ffname = NULL;
-	curbuf->b_sfname = NULL;
-	if (setfname(curbuf, eap->arg, NULL, TRUE) == FAIL)
-	{
-	    curbuf->b_ffname = fname;
-	    curbuf->b_sfname = sfname;
-	    return;
-	}
-	curbuf->b_flags |= BF_NOTEDITED;
-	if (xfname != NULL && *xfname != NUL)
-	{
-	    buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
-	    if (buf != NULL && !cmdmod.keepalt)
-		curwin->w_alt_fnum = buf->b_fnum;
-	}
-	vim_free(fname);
-	vim_free(sfname);
-#ifdef FEAT_AUTOCMD
-	apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
-#endif
-	/* Change directories when the 'acd' option is set. */
-	DO_AUTOCHDIR
     }
     /* print full file name if :cd used */
     fileinfo(FALSE, FALSE, eap->forceit);
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -30,6 +30,14 @@ typedef int Py_ssize_t;  /* Python 2.4 a
 #define INVALID_WINDOW_VALUE ((win_T *)(-1))
 #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
 
+#define DICTKEY_DECL \
+    PyObject	*dictkey_todecref;
+#define DICTKEY_GET(err) \
+    if (!(key = StringToChars(keyObject, &dictkey_todecref))) \
+	return err;
+#define DICTKEY_UNREF \
+    Py_XDECREF(dictkey_todecref);
+
 typedef void (*rangeinitializer)(void *);
 typedef void (*runner)(const char *, void *
 #ifdef PY_CAN_RECURSE
@@ -64,6 +72,51 @@ Python_Release_Vim(void)
 {
 }
 
+/*
+ * The "todecref" argument holds a pointer to PyObject * that must be
+ * DECREF'ed after returned char_u * is no longer needed or NULL if all what
+ * was needed to generate returned value is object.
+ *
+ * Use Py_XDECREF to decrement reference count.
+ */
+    static char_u *
+StringToChars(PyObject *object, PyObject **todecref)
+{
+    char_u	*p;
+    PyObject	*bytes = NULL;
+
+    if (PyBytes_Check(object))
+    {
+
+	if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1)
+	    return NULL;
+	if (p == NULL)
+	    return NULL;
+
+	*todecref = NULL;
+    }
+    else if (PyUnicode_Check(object))
+    {
+	bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL);
+	if (bytes == NULL)
+	    return NULL;
+
+	if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1)
+	    return NULL;
+	if (p == NULL)
+	    return NULL;
+
+	*todecref = bytes;
+    }
+    else
+    {
+	PyErr_SetString(PyExc_TypeError, _("object must be string"));
+	return NULL;
+    }
+
+    return (char_u *) p;
+}
+
 /* Output buffer management
  */
 
@@ -1586,6 +1639,18 @@ set_option_value_for(key, numval, string
     return VimTryEnd();
 }
 
+    static void *
+py_memsave(void *p, size_t len)
+{
+    void	*r;
+    if (!(r = PyMem_Malloc(len)))
+	return NULL;
+    mch_memmove(r, p, len);
+    return r;
+}
+
+#define PY_STRSAVE(s) ((char_u *) py_memsave(s, STRLEN(s) + 1))
+
     static int
 OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
 {
@@ -1670,57 +1735,16 @@ OptionsAssItem(OptionsObject *self, PyOb
     else
     {
 	char_u	*val;
-	if (PyBytes_Check(valObject))
-	{
-
-	    if (PyString_AsStringAndSize(valObject, (char **) &val, NULL) == -1)
-	    {
-		DICTKEY_UNREF
-		return -1;
-	    }
-	    if (val == NULL)
-	    {
-		DICTKEY_UNREF
-		return -1;
-	    }
-
-	    val = vim_strsave(val);
-	}
-	else if (PyUnicode_Check(valObject))
+	PyObject	*todecref;
+
+	if ((val = StringToChars(valObject, &todecref)))
 	{
-	    PyObject	*bytes;
-
-	    bytes = PyUnicode_AsEncodedString(valObject, (char *)ENC_OPT, NULL);
-	    if (bytes == NULL)
-	    {
-		DICTKEY_UNREF
-		return -1;
-	    }
-
-	    if(PyString_AsStringAndSize(bytes, (char **) &val, NULL) == -1)
-	    {
-		DICTKEY_UNREF
-		return -1;
-	    }
-	    if (val == NULL)
-	    {
-		DICTKEY_UNREF
-		return -1;
-	    }
-
-	    val = vim_strsave(val);
-	    Py_XDECREF(bytes);
+	    r = set_option_value_for(key, 0, val, opt_flags,
+				    self->opt_type, self->from);
+	    Py_XDECREF(todecref);
 	}
 	else
-	{
-	    PyErr_SetString(PyExc_TypeError, _("object must be string"));
-	    DICTKEY_UNREF
-	    return -1;
-	}
-
-	r = set_option_value_for(key, 0, val, opt_flags,
-				self->opt_type, self->from);
-	vim_free(val);
+	    r = -1;
     }
 
     DICTKEY_UNREF
@@ -2541,7 +2565,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, 
 	    array = NULL;
 	else
 	{
-	    array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
+	    array = PyMem_New(char *, new_len);
 	    if (array == NULL)
 	    {
 		PyErr_NoMemory();
@@ -2558,7 +2582,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, 
 	    {
 		while (i)
 		    vim_free(array[--i]);
-		vim_free(array);
+		PyMem_Free(array);
 		return FAIL;
 	    }
 	}
@@ -2635,7 +2659,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, 
 	 * been dealt with (either freed, or the responsibility passed
 	 * to vim.
 	 */
-	vim_free(array);
+	PyMem_Free(array);
 
 	/* Adjust marks. Invalidate any which lie in the
 	 * changed range, and move any in the remainder of the buffer.
@@ -2717,7 +2741,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 	char	**array;
 	buf_T	*savebuf;
 
-	array = (char **)alloc((unsigned)(size * sizeof(char *)));
+	array = PyMem_New(char *, size);
 	if (array == NULL)
 	{
 	    PyErr_NoMemory();
@@ -2733,7 +2757,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 	    {
 		while (i)
 		    vim_free(array[--i]);
-		vim_free(array);
+		PyMem_Free(array);
 		return FAIL;
 	    }
 	}
@@ -2768,7 +2792,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 	/* Free the array of lines. All of its contents have now
 	 * been freed.
 	 */
-	vim_free(array);
+	PyMem_Free(array);
 
 	restore_buffer(savebuf);
 	update_screen(VALID);
@@ -3179,6 +3203,45 @@ BufferAttr(BufferObject *self, char *nam
 	return NULL;
 }
 
+    static int
+BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
+{
+    if (CheckBuffer(self))
+	return -1;
+
+    if (strcmp(name, "name") == 0)
+    {
+	char_u	*val;
+	aco_save_T	aco;
+	int	r;
+	PyObject	*todecref;
+
+	if (!(val = StringToChars(valObject, &todecref)))
+	    return -1;
+
+	VimTryStart();
+	/* Using aucmd_*: autocommands will be executed by rename_buffer */
+	aucmd_prepbuf(&aco, self->buf);
+	r = rename_buffer(val);
+	aucmd_restbuf(&aco);
+	Py_XDECREF(todecref);
+	if (VimTryEnd())
+	    return -1;
+
+	if (r == FAIL)
+	{
+	    PyErr_SetVim(_("failed to rename buffer"));
+	    return -1;
+	}
+	return 0;
+    }
+    else
+    {
+	PyErr_SetString(PyExc_AttributeError, name);
+	return -1;
+    }
+}
+
     static PyObject *
 BufferAppend(BufferObject *self, PyObject *args)
 {
@@ -4040,7 +4103,7 @@ ConvertFromPyObject(PyObject *obj, typva
 	if (result == NULL)
 	    return -1;
 
-	if (set_string_copy(result, tv) == -1)
+	if (set_string_copy(result, tv))
 	{
 	    Py_XDECREF(bytes);
 	    return -1;
@@ -4169,11 +4232,13 @@ init_structs(void)
     BufferType.tp_methods = BufferMethods;
 #if PY_MAJOR_VERSION >= 3
     BufferType.tp_getattro = (getattrofunc)BufferGetattro;
+    BufferType.tp_setattro = (setattrofunc)BufferSetattro;
     BufferType.tp_alloc = call_PyType_GenericAlloc;
     BufferType.tp_new = call_PyType_GenericNew;
     BufferType.tp_free = call_PyObject_Free;
 #else
     BufferType.tp_getattr = (getattrfunc)BufferGetattr;
+    BufferType.tp_setattr = (setattrfunc)BufferSetattr;
 #endif
 
     vim_memset(&WindowType, 0, sizeof(WindowType));
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -676,18 +676,6 @@ get_exceptions(void)
 static int initialised = 0;
 #define PYINITIALISED initialised
 
-#define DICTKEY_GET(err) \
-    if (!PyString_Check(keyObject)) \
-    { \
-	PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \
-	return err; \
-    } \
-    if (PyString_AsStringAndSize(keyObject, (char **) &key, NULL) == -1) \
-	return err;
-
-#define DICTKEY_UNREF
-#define DICTKEY_DECL
-
 #define DESTRUCTOR_FINISH(self) self->ob_type->tp_free((PyObject*)self);
 
 #define WIN_PYTHON_REF(win) win->w_python_ref
@@ -926,7 +914,7 @@ DoPyCommand(const char *cmd, rangeinitia
     else
     {
 	/* Need to make a copy, value may change when setting new locale. */
-	saved_locale = (char *)vim_strsave((char_u *)saved_locale);
+	saved_locale = (char *) PY_STRSAVE(saved_locale);
 	(void)setlocale(LC_NUMERIC, "C");
     }
 #endif
@@ -953,7 +941,7 @@ DoPyCommand(const char *cmd, rangeinitia
     if (saved_locale != NULL)
     {
 	(void)setlocale(LC_NUMERIC, saved_locale);
-	vim_free(saved_locale);
+	PyMem_Free(saved_locale);
     }
 #endif
 
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -638,32 +638,6 @@ static int py3initialised = 0;
 
 #define PYINITIALISED py3initialised
 
-#define DICTKEY_DECL PyObject *bytes = NULL;
-
-#define DICTKEY_GET(err) \
-    if (PyBytes_Check(keyObject)) \
-    { \
-	if (PyString_AsStringAndSize(keyObject, (char **) &key, NULL) == -1) \
-	    return err; \
-    } \
-    else if (PyUnicode_Check(keyObject)) \
-    { \
-	bytes = PyString_AsBytes(keyObject); \
-	if (bytes == NULL) \
-	    return err; \
-	if (PyString_AsStringAndSize(bytes, (char **) &key, NULL) == -1) \
-	    return err; \
-    } \
-    else \
-    { \
-	PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \
-	return err; \
-    }
-
-#define DICTKEY_UNREF \
-    if (bytes != NULL) \
-	Py_XDECREF(bytes);
-
 #define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self)
 
 #define WIN_PYTHON_REF(win) win->w_python3_ref
@@ -696,6 +670,7 @@ static PyObject *BufferDir(PyObject *);
 static PyObject *OutputGetattro(PyObject *, PyObject *);
 static int OutputSetattro(PyObject *, PyObject *, PyObject *);
 static PyObject *BufferGetattro(PyObject *, PyObject *);
+static int BufferSetattro(PyObject *, PyObject *, PyObject *);
 static PyObject *TabPageGetattro(PyObject *, PyObject *);
 static PyObject *WindowGetattro(PyObject *, PyObject *);
 static int WindowSetattro(PyObject *, PyObject *, PyObject *);
@@ -1108,6 +1083,14 @@ BufferGetattro(PyObject *self, PyObject*
 	return PyObject_GenericGetAttr(self, nameobj);
 }
 
+    static int
+BufferSetattro(PyObject *self, PyObject *nameobj, PyObject *val)
+{
+    GET_ATTR_STRING(name, nameobj);
+
+    return BufferSetattr((BufferObject *)(self), name, val);
+}
+
     static PyObject *
 BufferDir(PyObject *self UNUSED)
 {
--- a/src/proto/ex_cmds.pro
+++ b/src/proto/ex_cmds.pro
@@ -19,6 +19,7 @@ void viminfo_writestring __ARGS((FILE *f
 void do_fixdel __ARGS((exarg_T *eap));
 void print_line_no_prefix __ARGS((linenr_T lnum, int use_number, int list));
 void print_line __ARGS((linenr_T lnum, int use_number, int list));
+int rename_buffer __ARGS((char_u *new_fname));
 void ex_file __ARGS((exarg_T *eap));
 void ex_update __ARGS((exarg_T *eap));
 void ex_write __ARGS((exarg_T *eap));
--- a/src/testdir/test86.in
+++ b/src/testdir/test86.in
@@ -476,6 +476,10 @@ EOF
 :py b=vim.current.buffer
 :wincmd w
 :mark a
+:augroup BUFS
+:   autocmd BufFilePost * python cb.append(vim.eval('expand("<abuf>")') + ':BufFilePost:' + vim.eval('bufnr("%")'))
+:   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
@@ -496,9 +500,20 @@ b.append('foo')
 b[0]='bar'
 b[0:0]=['baz']
 vim.command('call append("$", getbufline(%i, 1, "$"))' % b.number)
+# Test assigning to name property
+old_name = cb.name
+cb.name = 'foo'
+cb.append(cb.name[-11:])
+b.name = 'bar'
+cb.append(b.name[-11:])
+cb.name = old_name
+cb.append(cb.name[-17:])
 # Test CheckBuffer
-vim.command('bwipeout! ' + str(b.number))
-for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")'):
+for _b in vim.buffers:
+    if _b is not cb:
+        vim.command('bwipeout! ' + str(_b.number))
+del _b
+for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")', 'b.name = "!"'):
     try:
         exec(expr)
     except vim.error:
@@ -507,7 +522,12 @@ for expr in ('b[1]','b[:] = ["A", "B"]',
         # Usually a SEGV here
         # Should not happen in any case
         cb.append('No exception for ' + expr)
+vim.command('cd .')
 EOF
+:augroup BUFS
+:   autocmd!
+:augroup END
+:augroup! BUFS
 :"
 :" Test vim.buffers object
 :set hidden
@@ -586,7 +606,9 @@ def W(w):
     else:
         return repr(w)
 
-def Cursor(w, start=len(cb)):
+start = len(cb)
+
+def Cursor(w):
     if w.buffer is cb:
         return repr((start - w.cursor[0], w.cursor[1]))
     else:
--- a/src/testdir/test86.ok
+++ b/src/testdir/test86.ok
@@ -319,14 +319,23 @@ bar
 Second line
 Third line
 foo
+1:BufFilePre:1
+6:BufFilePost:1
+testdir/foo
+5:BufFilePre:5
+5:BufFilePost:5
+testdir/bar
+1:BufFilePre:1
+7:BufFilePost:1
+testdir/test86.in
 i:<buffer test86.in>
 i2:<buffer test86.in>
 i:<buffer a>
 i3:<buffer test86.in>
 1:<buffer test86.in>=<buffer test86.in>
-6:<buffer a>=<buffer a>
-7:<buffer b>=<buffer b>
-8:<buffer c>=<buffer c>
+8:<buffer a>=<buffer a>
+9:<buffer b>=<buffer b>
+10:<buffer c>=<buffer c>
 4
 i4:<buffer test86.in>
 i4:<buffer test86.in>
@@ -335,7 +344,7 @@ Number of tabs: 4
 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 (27, 0)
+    <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (36, 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)
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -463,6 +463,10 @@ EOF
 :py3 b=vim.current.buffer
 :wincmd w
 :mark a
+:augroup BUFS
+:   autocmd BufFilePost * python3 cb.append(vim.eval('expand("<abuf>")') + ':BufFilePost:' + vim.eval('bufnr("%")'))
+:   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
@@ -483,8 +487,19 @@ b.append('foo')
 b[0]='bar'
 b[0:0]=['baz']
 vim.command('call append("$", getbufline(%i, 1, "$"))' % b.number)
+# Test assigning to name property
+old_name = cb.name
+cb.name = 'foo'
+cb.append(cb.name[-11:])
+b.name = 'bar'
+cb.append(b.name[-11:])
+cb.name = old_name
+cb.append(cb.name[-17:])
 # Test CheckBuffer
-vim.command('bwipeout! ' + str(b.number))
+for _b in vim.buffers:
+    if _b is not cb:
+        vim.command('bwipeout! ' + str(_b.number))
+del _b
 for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")'):
     try:
         exec(expr)
@@ -494,6 +509,7 @@ for expr in ('b[1]','b[:] = ["A", "B"]',
         # Usually a SEGV here
         # Should not happen in any case
         cb.append('No exception for ' + expr)
+vim.command('cd .')
 EOF
 :"
 :" Test vim.buffers object
--- a/src/testdir/test87.ok
+++ b/src/testdir/test87.ok
@@ -308,14 +308,23 @@ bar
 Second line
 Third line
 foo
+1:BufFilePre:1
+6:BufFilePost:1
+testdir/foo
+5:BufFilePre:5
+5:BufFilePost:5
+testdir/bar
+1:BufFilePre:1
+7:BufFilePost:1
+testdir/test87.in
 i:<buffer test87.in>
 i2:<buffer test87.in>
 i:<buffer a>
 i3:<buffer test87.in>
 1:<buffer test87.in>=<buffer test87.in>
-6:<buffer a>=<buffer a>
-7:<buffer b>=<buffer b>
-8:<buffer c>=<buffer c>
+8:<buffer a>=<buffer a>
+9:<buffer b>=<buffer b>
+10:<buffer c>=<buffer c>
 4
 i4:<buffer test87.in>
 i4:<buffer test87.in>
@@ -324,7 +333,7 @@ Number of tabs: 4
 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 (27, 0)
+    <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (36, 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)
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1042,
+/**/
     1041,
 /**/
     1040,