# HG changeset patch
# User ZyX <[email protected]>
# Date 1370102113 -14400
# Branch python-extended-4
# Node ID 807b755f9898d68e4d93f18e7964783b207826b2
# Parent  0ee8bb6bd07f29fd51c7b753492ac727b69ac7ae
Add vim.chdir and vim.fchdir functions, record them as attributes of os module

diff -r 0ee8bb6bd07f -r 807b755f9898 runtime/doc/if_pyth.txt
--- a/runtime/doc/if_pyth.txt   Sat Jun 01 17:22:00 2013 +0400
+++ b/runtime/doc/if_pyth.txt   Sat Jun 01 19:55:13 2013 +0400
@@ -180,6 +180,13 @@
        Like |strwidth()|: returns number of display cells str occupies, tab 
        is counted as one cell.
 
+vim.chdir(*args, **kwargs)                             *python-chdir*
+vim.fchdir(*args, **kwargs)                            *python-fchdir*
+       Run os.chdir or os.fchdir, then all appropriate vim stuff.
+       Note: you should not use these functions directly, use os.chdir and 
+             os.fchdir instead. Behavior of vim.fchdir is undefined in case 
+             os.fchdir does not exist.
+
 Error object of the "vim" module
 
 vim.error                                              *python-error*
diff -r 0ee8bb6bd07f -r 807b755f9898 src/ex_docmd.c
--- a/src/ex_docmd.c    Sat Jun 01 17:22:00 2013 +0400
+++ b/src/ex_docmd.c    Sat Jun 01 19:55:13 2013 +0400
@@ -8182,6 +8182,33 @@
 }
 #endif
 
+    void
+post_chdir(local)
+    int                local;
+{
+    vim_free(curwin->w_localdir);
+    if (local)
+    {
+       /* If still in global directory, need to remember current
+        * directory as global directory. */
+       if (globaldir == NULL && prev_dir != NULL)
+           globaldir = vim_strsave(prev_dir);
+       /* Remember this local directory for the window. */
+       if (mch_dirname(NameBuff, MAXPATHL) == OK)
+           curwin->w_localdir = vim_strsave(NameBuff);
+    }
+    else
+    {
+       /* We are now in the global directory, no need to remember its
+        * name. */
+       vim_free(globaldir);
+       globaldir = NULL;
+       curwin->w_localdir = NULL;
+    }
+
+    shorten_fnames(TRUE);
+}
+
 
 /*
  * ":cd", ":lcd", ":chdir" and ":lchdir".
@@ -8253,27 +8280,7 @@
            EMSG(_(e_failed));
        else
        {
-           vim_free(curwin->w_localdir);
-           if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
-           {
-               /* If still in global directory, need to remember current
-                * directory as global directory. */
-               if (globaldir == NULL && prev_dir != NULL)
-                   globaldir = vim_strsave(prev_dir);
-               /* Remember this local directory for the window. */
-               if (mch_dirname(NameBuff, MAXPATHL) == OK)
-                   curwin->w_localdir = vim_strsave(NameBuff);
-           }
-           else
-           {
-               /* We are now in the global directory, no need to remember its
-                * name. */
-               vim_free(globaldir);
-               globaldir = NULL;
-               curwin->w_localdir = NULL;
-           }
-
-           shorten_fnames(TRUE);
+           post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir);
 
            /* Echo the new current directory if the command was typed. */
            if (KeyTyped || p_verbose >= 5)
diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_py_both.h
--- a/src/if_py_both.h  Sat Jun 01 17:22:00 2013 +0400
+++ b/src/if_py_both.h  Sat Jun 01 19:55:13 2013 +0400
@@ -52,6 +52,10 @@
 
 static PyObject *globals;
 
+static PyObject *py_chdir;
+static PyObject *py_fchdir;
+static PyObject *py_getcwd;
+
 /*
  * obtain a lock on the Vim data structures
  */
@@ -706,17 +710,84 @@
            );
 }
 
+    static PyObject *
+_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
+{
+    PyObject   *r;
+    PyObject   *newwd;
+    PyObject   *todecref;
+    char_u     *new_dir;
+
+    if (!(r = PyObject_Call(_chdir, args, kwargs)))
+       return NULL;
+
+    if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
+    {
+       Py_DECREF(r);
+       return NULL;
+    }
+
+    if (!(new_dir = StringToChars(newwd, &todecref)))
+    {
+       Py_DECREF(r);
+       Py_DECREF(newwd);
+       return NULL;
+    }
+
+    VimTryStart();
+
+    if (vim_chdir(new_dir))
+    {
+       Py_DECREF(r);
+       Py_DECREF(newwd);
+       Py_XDECREF(todecref);
+
+       if (VimTryEnd())
+           return NULL;
+
+       PyErr_SetVim(_("failed to change directory"));
+       return NULL;
+    }
+
+    Py_DECREF(newwd);
+    Py_XDECREF(todecref);
+
+    post_chdir(FALSE);
+
+    if (VimTryEnd())
+    {
+       Py_DECREF(r);
+       return NULL;
+    }
+
+    return r;
+}
+
+    static PyObject *
+VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
+{
+    return _VimChdir(py_chdir, args, kwargs);
+}
+
+    static PyObject *
+VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
+{
+    return _VimChdir(py_fchdir, args, kwargs);
+}
+
 /*
  * Vim module - Definitions
  */
 
 static struct PyMethodDef VimMethods[] = {
-    /* name,        function,          calling,        documentation */
-    {"command",             VimCommand,        METH_VARARGS,   "Execute a Vim 
ex-mode command" },
-    {"eval",        VimEval,           METH_VARARGS,   "Evaluate an expression 
using Vim evaluator" },
-    {"bindeval",     VimEvalPy,                METH_VARARGS,   "Like eval(), 
but returns objects attached to vim ones"},
-    {"strwidth",     VimStrwidth,      METH_VARARGS,   "Screen string width, 
counts <Tab> as having width 1"},
-    { NULL,         NULL,              0,              NULL }
+    /* name,        function,                  calling,                        
documentation */
+    {"command",             VimCommand,                METH_VARARGS,           
        "Execute a Vim ex-mode command" },
+    {"eval",        VimEval,                   METH_VARARGS,                   
"Evaluate an expression using Vim evaluator" },
+    {"bindeval",     VimEvalPy,                        METH_VARARGS,           
        "Like eval(), but returns objects attached to vim ones"},
+    {"strwidth",     VimStrwidth,              METH_VARARGS,                   
"Screen string width, counts <Tab> as having width 1"},
+    {"chdir",       (PyCFunction)VimChdir,     METH_VARARGS|METH_KEYWORDS,     
"Change directory"},
+    {"fchdir",      (PyCFunction)VimFchdir,    METH_VARARGS|METH_KEYWORDS,     
"Change directory"},
+    { NULL,         NULL,                      0,                              
NULL }
 };
 
 /*
@@ -5262,6 +5333,7 @@
 };
 
 typedef int (*object_adder)(PyObject *, const char *, PyObject *);
+typedef PyObject *(*attr_getter)(PyObject *, const char *);
 
 #define ADD_OBJECT(m, name, obj) \
     if (add_object(m, name, obj)) \
@@ -5276,9 +5348,10 @@
     }
 
     static int
-populate_module(PyObject *m, object_adder add_object)
+populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
 {
     int i;
+    PyObject   *os;
 
     for (i = 0; i < (int)(sizeof(numeric_constants)
                                           / sizeof(struct numeric_constant));
@@ -5305,5 +5378,27 @@
     ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
     ADD_CHECKED_OBJECT(m, "options",
            OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
+
+    if (!(os = PyImport_ImportModule("os")))
+       return -1;
+    ADD_OBJECT(m, "os", os);
+
+    if (!(py_getcwd = PyObject_GetAttrString(os, "getcwd")))
+       return -1;
+    ADD_OBJECT(m, "_getcwd", py_getcwd)
+
+    if (!(py_chdir = PyObject_GetAttrString(os, "chdir")))
+       return -1;
+    ADD_OBJECT(m, "_chdir", py_chdir);
+    if (PyObject_SetAttrString(os, "chdir", get_attr(m, "chdir")))
+       return -1;
+
+    if ((py_fchdir = PyObject_GetAttrString(os, "fchdir")))
+    {
+       ADD_OBJECT(m, "_fchdir", py_fchdir);
+       if (PyObject_SetAttrString(os, "fchdir", get_attr(m, "fchdir")))
+           return -1;
+    }
+
     return 0;
 }
diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_python.c
--- a/src/if_python.c   Sat Jun 01 17:22:00 2013 +0400
+++ b/src/if_python.c   Sat Jun 01 19:55:13 2013 +0400
@@ -213,6 +213,7 @@
 # define PyObject_HasAttrString dll_PyObject_HasAttrString
 # define PyObject_SetAttrString dll_PyObject_SetAttrString
 # define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
+# define PyObject_Call dll_PyObject_Call
 # define PyString_AsString dll_PyString_AsString
 # define PyString_AsStringAndSize dll_PyString_AsStringAndSize
 # define PyString_FromString dll_PyString_FromString
@@ -346,6 +347,7 @@
 static int (*dll_PyObject_HasAttrString)(PyObject *, const char *);
 static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, 
PyObject *);
 static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+static PyObject* (*dll_PyObject_Call)(PyObject *, PyObject *, PyObject *);
 static char*(*dll_PyString_AsString)(PyObject *);
 static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
 static PyObject*(*dll_PyString_FromString)(const char *);
@@ -510,6 +512,7 @@
     {"PyObject_HasAttrString", (PYTHON_PROC*)&dll_PyObject_HasAttrString},
     {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
     {"PyObject_CallFunctionObjArgs", 
(PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
+    {"PyObject_Call", (PYTHON_PROC*)&dll_PyObject_Call},
     {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
     {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
     {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
@@ -1364,6 +1367,7 @@
 {
     PyObject *mod;
     PyObject *dict;
+    PyObject *os;
 
     /* The special value is removed from sys.path in Python_Init(). */
     static char *(argv[2]) = {"/must>not&exist/foo", NULL};
@@ -1374,10 +1378,11 @@
     /* Set sys.argv[] to avoid a crash in warn(). */
     PySys_SetArgv(1, argv);
 
-    mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, 
PYTHON_API_VERSION);
+    mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL,
+                           PYTHON_API_VERSION);
     dict = PyModule_GetDict(mod);
 
-    return populate_module(dict, add_object);
+    return populate_module(dict, add_object, PyDict_GetItemString);
 }
 
 /*************************************************************************
diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_python3.c
--- a/src/if_python3.c  Sat Jun 01 17:22:00 2013 +0400
+++ b/src/if_python3.c  Sat Jun 01 19:55:13 2013 +0400
@@ -174,6 +174,7 @@
 # define PyObject_HasAttrString py3_PyObject_HasAttrString
 # define PyObject_SetAttrString py3_PyObject_SetAttrString
 # define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs
+# define PyObject_Call py3_PyObject_Call
 # define PyEval_GetLocals py3_PyEval_GetLocals
 # define PyEval_GetGlobals py3_PyEval_GetGlobals
 # define PySys_SetObject py3_PySys_SetObject
@@ -290,6 +291,7 @@
 static int (*py3_PyObject_HasAttrString)(PyObject *, const char *);
 static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, 
PyObject *);
 static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+static PyObject* (*py3_PyObject_Call)(PyObject *, PyObject *, PyObject *);
 static PyObject* (*py3_PyEval_GetGlobals)();
 static PyObject* (*py3_PyEval_GetLocals)();
 static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
@@ -446,6 +448,7 @@
     {"PyObject_HasAttrString", (PYTHON_PROC*)&py3_PyObject_HasAttrString},
     {"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString},
     {"PyObject_CallFunctionObjArgs", 
(PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs},
+    {"PyObject_Call", (PYTHON_PROC*)&py3_PyObject_Call},
     {"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals},
     {"PyEval_GetLocals", (PYTHON_PROC*)&py3_PyEval_GetLocals},
     {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
@@ -1586,6 +1589,7 @@
 Py3Init_vim(void)
 {
     PyObject *mod;
+    PyObject *os;
 
     /* The special value is removed from sys.path in Python3_Init(). */
     static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};
@@ -1600,7 +1604,7 @@
     if (mod == NULL)
        return NULL;
 
-    if (populate_module(mod, PyModule_AddObject))
+    if (populate_module(mod, PyModule_AddObject, PyObject_GetAttrString))
        return NULL;
 
     return mod;
diff -r 0ee8bb6bd07f -r 807b755f9898 src/proto/ex_docmd.pro
--- a/src/proto/ex_docmd.pro    Sat Jun 01 17:22:00 2013 +0400
+++ b/src/proto/ex_docmd.pro    Sat Jun 01 19:55:13 2013 +0400
@@ -53,4 +53,5 @@
 int put_line __ARGS((FILE *fd, char *s));
 void dialog_msg __ARGS((char_u *buff, char *format, char_u *fname));
 char_u *get_behave_arg __ARGS((expand_T *xp, int idx));
+void post_chdir __ARGS((int local));
 /* vim: set ft=c : */
diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test86.in
--- a/src/testdir/test86.in     Sat Jun 01 17:22:00 2013 +0400
+++ b/src/testdir/test86.in     Sat Jun 01 19:55:13 2013 +0400
@@ -788,6 +788,20 @@
 :$put =string(pyeval('dl2'))
 :$put =string(pyeval('df(2)'))
 :"
+:" Test chdir
+py << EOF
+import os
+fnamemodify = vim.Function('fnamemodify')
+cb.append(fnamemodify('.', ':p:h:t'))
+cb.append(vim.eval('@%'))
+os.chdir('..')
+cb.append(fnamemodify('.', ':p:h:t'))
+cb.append(vim.eval('@%').replace(os.path.sep, '/'))
+os.chdir('testdir')
+cb.append(fnamemodify('.', ':p:h:t'))
+cb.append(vim.eval('@%'))
+EOF
+:"
 :" Test errors
 :fun F() dict
 :endfun
diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test86.ok
--- a/src/testdir/test86.ok     Sat Jun 01 17:22:00 2013 +0400
+++ b/src/testdir/test86.ok     Sat Jun 01 19:55:13 2013 +0400
@@ -429,6 +429,12 @@
 ['a', 'b', 'c']
 [2, 2]
 [2, 2]
+testdir
+test86.in
+src
+testdir/test86.in
+testdir
+test86.in
 > Output
 >> OutputSetattr
 del sys.stdout.softspace:(<type 'exceptions.AttributeError'>, 
AttributeError("can't delete OutputObject attributes",))
diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test87.in
--- a/src/testdir/test87.in     Sat Jun 01 17:22:00 2013 +0400
+++ b/src/testdir/test87.in     Sat Jun 01 19:55:13 2013 +0400
@@ -748,6 +748,20 @@
 :$put =string(py3eval('dl2'))
 :$put =string(py3eval('df(2)'))
 :"
+:" Test chdir
+py3 << EOF
+import os
+fnamemodify = vim.Function('fnamemodify')
+cb.append(str(fnamemodify('.', ':p:h:t')))
+cb.append(vim.eval('@%'))
+os.chdir('..')
+cb.append(str(fnamemodify('.', ':p:h:t')))
+cb.append(vim.eval('@%').replace(os.path.sep, '/'))
+os.chdir('testdir')
+cb.append(str(fnamemodify('.', ':p:h:t')))
+cb.append(vim.eval('@%'))
+EOF
+:"
 :" Test errors
 :fun F() dict
 :endfun
diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test87.ok
--- a/src/testdir/test87.ok     Sat Jun 01 17:22:00 2013 +0400
+++ b/src/testdir/test87.ok     Sat Jun 01 19:55:13 2013 +0400
@@ -418,6 +418,12 @@
 ['a', 'b', 'c']
 [2, 2]
 [2, 2]
+b'testdir'
+test87.in
+b'src'
+testdir/test87.in
+b'testdir'
+test87.in
 > Output
 >> OutputSetattr
 del sys.stdout.softspace:(<class 'AttributeError'>, AttributeError("can't 
delete OutputObject attributes",))

-- 
-- 
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.0ee8bb6bd07f/runtime/doc/if_pyth.txt vim.807b755f9898/runtime/doc/if_pyth.txt
*** vim.0ee8bb6bd07f/runtime/doc/if_pyth.txt	2013-06-01 20:13:49.813598490 +0400
--- vim.807b755f9898/runtime/doc/if_pyth.txt	2013-06-01 20:13:49.844598179 +0400
***************
*** 180,185 ****
--- 180,192 ----
  	Like |strwidth()|: returns number of display cells str occupies, tab 
  	is counted as one cell.
  
+ vim.chdir(*args, **kwargs)				*python-chdir*
+ vim.fchdir(*args, **kwargs)				*python-fchdir*
+ 	Run os.chdir or os.fchdir, then all appropriate vim stuff.
+ 	Note: you should not use these functions directly, use os.chdir and 
+ 	      os.fchdir instead. Behavior of vim.fchdir is undefined in case 
+ 	      os.fchdir does not exist.
+ 
  Error object of the "vim" module
  
  vim.error						*python-error*
diff -cr vim.0ee8bb6bd07f/src/ex_docmd.c vim.807b755f9898/src/ex_docmd.c
*** vim.0ee8bb6bd07f/src/ex_docmd.c	2013-06-01 20:13:49.824598380 +0400
--- vim.807b755f9898/src/ex_docmd.c	2013-06-01 20:13:49.856598059 +0400
***************
*** 8182,8187 ****
--- 8182,8214 ----
  }
  #endif
  
+     void
+ post_chdir(local)
+     int		local;
+ {
+     vim_free(curwin->w_localdir);
+     if (local)
+     {
+ 	/* If still in global directory, need to remember current
+ 	 * directory as global directory. */
+ 	if (globaldir == NULL && prev_dir != NULL)
+ 	    globaldir = vim_strsave(prev_dir);
+ 	/* Remember this local directory for the window. */
+ 	if (mch_dirname(NameBuff, MAXPATHL) == OK)
+ 	    curwin->w_localdir = vim_strsave(NameBuff);
+     }
+     else
+     {
+ 	/* We are now in the global directory, no need to remember its
+ 	 * name. */
+ 	vim_free(globaldir);
+ 	globaldir = NULL;
+ 	curwin->w_localdir = NULL;
+     }
+ 
+     shorten_fnames(TRUE);
+ }
+ 
  
  /*
   * ":cd", ":lcd", ":chdir" and ":lchdir".
***************
*** 8253,8279 ****
  	    EMSG(_(e_failed));
  	else
  	{
! 	    vim_free(curwin->w_localdir);
! 	    if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
! 	    {
! 		/* If still in global directory, need to remember current
! 		 * directory as global directory. */
! 		if (globaldir == NULL && prev_dir != NULL)
! 		    globaldir = vim_strsave(prev_dir);
! 		/* Remember this local directory for the window. */
! 		if (mch_dirname(NameBuff, MAXPATHL) == OK)
! 		    curwin->w_localdir = vim_strsave(NameBuff);
! 	    }
! 	    else
! 	    {
! 		/* We are now in the global directory, no need to remember its
! 		 * name. */
! 		vim_free(globaldir);
! 		globaldir = NULL;
! 		curwin->w_localdir = NULL;
! 	    }
! 
! 	    shorten_fnames(TRUE);
  
  	    /* Echo the new current directory if the command was typed. */
  	    if (KeyTyped || p_verbose >= 5)
--- 8280,8286 ----
  	    EMSG(_(e_failed));
  	else
  	{
! 	    post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir);
  
  	    /* Echo the new current directory if the command was typed. */
  	    if (KeyTyped || p_verbose >= 5)
diff -cr vim.0ee8bb6bd07f/src/if_py_both.h vim.807b755f9898/src/if_py_both.h
*** vim.0ee8bb6bd07f/src/if_py_both.h	2013-06-01 20:13:49.831598310 +0400
--- vim.807b755f9898/src/if_py_both.h	2013-06-01 20:13:49.863597989 +0400
***************
*** 52,57 ****
--- 52,61 ----
  
  static PyObject *globals;
  
+ static PyObject *py_chdir;
+ static PyObject *py_fchdir;
+ static PyObject *py_getcwd;
+ 
  /*
   * obtain a lock on the Vim data structures
   */
***************
*** 706,722 ****
  	    );
  }
  
  /*
   * Vim module - Definitions
   */
  
  static struct PyMethodDef VimMethods[] = {
!     /* name,	     function,		calling,	documentation */
!     {"command",	     VimCommand,	METH_VARARGS,	"Execute a Vim ex-mode command" },
!     {"eval",	     VimEval,		METH_VARARGS,	"Evaluate an expression using Vim evaluator" },
!     {"bindeval",     VimEvalPy,		METH_VARARGS,	"Like eval(), but returns objects attached to vim ones"},
!     {"strwidth",     VimStrwidth,	METH_VARARGS,	"Screen string width, counts <Tab> as having width 1"},
!     { NULL,	     NULL,		0,		NULL }
  };
  
  /*
--- 710,793 ----
  	    );
  }
  
+     static PyObject *
+ _VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
+ {
+     PyObject	*r;
+     PyObject	*newwd;
+     PyObject	*todecref;
+     char_u	*new_dir;
+ 
+     if (!(r = PyObject_Call(_chdir, args, kwargs)))
+ 	return NULL;
+ 
+     if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
+     {
+ 	Py_DECREF(r);
+ 	return NULL;
+     }
+ 
+     if (!(new_dir = StringToChars(newwd, &todecref)))
+     {
+ 	Py_DECREF(r);
+ 	Py_DECREF(newwd);
+ 	return NULL;
+     }
+ 
+     VimTryStart();
+ 
+     if (vim_chdir(new_dir))
+     {
+ 	Py_DECREF(r);
+ 	Py_DECREF(newwd);
+ 	Py_XDECREF(todecref);
+ 
+ 	if (VimTryEnd())
+ 	    return NULL;
+ 
+ 	PyErr_SetVim(_("failed to change directory"));
+ 	return NULL;
+     }
+ 
+     Py_DECREF(newwd);
+     Py_XDECREF(todecref);
+ 
+     post_chdir(FALSE);
+ 
+     if (VimTryEnd())
+     {
+ 	Py_DECREF(r);
+ 	return NULL;
+     }
+ 
+     return r;
+ }
+ 
+     static PyObject *
+ VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
+ {
+     return _VimChdir(py_chdir, args, kwargs);
+ }
+ 
+     static PyObject *
+ VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
+ {
+     return _VimChdir(py_fchdir, args, kwargs);
+ }
+ 
  /*
   * Vim module - Definitions
   */
  
  static struct PyMethodDef VimMethods[] = {
!     /* name,	     function,			calling,			documentation */
!     {"command",	     VimCommand,		METH_VARARGS,			"Execute a Vim ex-mode command" },
!     {"eval",	     VimEval,			METH_VARARGS,			"Evaluate an expression using Vim evaluator" },
!     {"bindeval",     VimEvalPy,			METH_VARARGS,			"Like eval(), but returns objects attached to vim ones"},
!     {"strwidth",     VimStrwidth,		METH_VARARGS,			"Screen string width, counts <Tab> as having width 1"},
!     {"chdir",	     (PyCFunction)VimChdir,	METH_VARARGS|METH_KEYWORDS,	"Change directory"},
!     {"fchdir",	     (PyCFunction)VimFchdir,	METH_VARARGS|METH_KEYWORDS,	"Change directory"},
!     { NULL,	     NULL,			0,				NULL }
  };
  
  /*
***************
*** 5262,5267 ****
--- 5333,5339 ----
  };
  
  typedef int (*object_adder)(PyObject *, const char *, PyObject *);
+ typedef PyObject *(*attr_getter)(PyObject *, const char *);
  
  #define ADD_OBJECT(m, name, obj) \
      if (add_object(m, name, obj)) \
***************
*** 5276,5284 ****
      }
  
      static int
! populate_module(PyObject *m, object_adder add_object)
  {
      int i;
  
      for (i = 0; i < (int)(sizeof(numeric_constants)
  					   / sizeof(struct numeric_constant));
--- 5348,5357 ----
      }
  
      static int
! populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
  {
      int i;
+     PyObject	*os;
  
      for (i = 0; i < (int)(sizeof(numeric_constants)
  					   / sizeof(struct numeric_constant));
***************
*** 5305,5309 ****
--- 5378,5404 ----
      ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
      ADD_CHECKED_OBJECT(m, "options",
  	    OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
+ 
+     if (!(os = PyImport_ImportModule("os")))
+ 	return -1;
+     ADD_OBJECT(m, "os", os);
+ 
+     if (!(py_getcwd = PyObject_GetAttrString(os, "getcwd")))
+ 	return -1;
+     ADD_OBJECT(m, "_getcwd", py_getcwd)
+ 
+     if (!(py_chdir = PyObject_GetAttrString(os, "chdir")))
+ 	return -1;
+     ADD_OBJECT(m, "_chdir", py_chdir);
+     if (PyObject_SetAttrString(os, "chdir", get_attr(m, "chdir")))
+ 	return -1;
+ 
+     if ((py_fchdir = PyObject_GetAttrString(os, "fchdir")))
+     {
+ 	ADD_OBJECT(m, "_fchdir", py_fchdir);
+ 	if (PyObject_SetAttrString(os, "fchdir", get_attr(m, "fchdir")))
+ 	    return -1;
+     }
+ 
      return 0;
  }
diff -cr vim.0ee8bb6bd07f/src/if_python3.c vim.807b755f9898/src/if_python3.c
*** vim.0ee8bb6bd07f/src/if_python3.c	2013-06-01 20:13:49.838598239 +0400
--- vim.807b755f9898/src/if_python3.c	2013-06-01 20:13:49.870597918 +0400
***************
*** 174,179 ****
--- 174,180 ----
  # define PyObject_HasAttrString py3_PyObject_HasAttrString
  # define PyObject_SetAttrString py3_PyObject_SetAttrString
  # define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs
+ # define PyObject_Call py3_PyObject_Call
  # define PyEval_GetLocals py3_PyEval_GetLocals
  # define PyEval_GetGlobals py3_PyEval_GetGlobals
  # define PySys_SetObject py3_PySys_SetObject
***************
*** 290,295 ****
--- 291,297 ----
  static int (*py3_PyObject_HasAttrString)(PyObject *, const char *);
  static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
  static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+ static PyObject* (*py3_PyObject_Call)(PyObject *, PyObject *, PyObject *);
  static PyObject* (*py3_PyEval_GetGlobals)();
  static PyObject* (*py3_PyEval_GetLocals)();
  static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
***************
*** 446,451 ****
--- 448,454 ----
      {"PyObject_HasAttrString", (PYTHON_PROC*)&py3_PyObject_HasAttrString},
      {"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString},
      {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs},
+     {"PyObject_Call", (PYTHON_PROC*)&py3_PyObject_Call},
      {"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals},
      {"PyEval_GetLocals", (PYTHON_PROC*)&py3_PyEval_GetLocals},
      {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
***************
*** 1586,1591 ****
--- 1589,1595 ----
  Py3Init_vim(void)
  {
      PyObject *mod;
+     PyObject *os;
  
      /* The special value is removed from sys.path in Python3_Init(). */
      static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};
***************
*** 1600,1606 ****
      if (mod == NULL)
  	return NULL;
  
!     if (populate_module(mod, PyModule_AddObject))
  	return NULL;
  
      return mod;
--- 1604,1610 ----
      if (mod == NULL)
  	return NULL;
  
!     if (populate_module(mod, PyModule_AddObject, PyObject_GetAttrString))
  	return NULL;
  
      return mod;
diff -cr vim.0ee8bb6bd07f/src/if_python.c vim.807b755f9898/src/if_python.c
*** vim.0ee8bb6bd07f/src/if_python.c	2013-06-01 20:13:49.816598460 +0400
--- vim.807b755f9898/src/if_python.c	2013-06-01 20:13:49.848598139 +0400
***************
*** 213,218 ****
--- 213,219 ----
  # define PyObject_HasAttrString dll_PyObject_HasAttrString
  # define PyObject_SetAttrString dll_PyObject_SetAttrString
  # define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
+ # define PyObject_Call dll_PyObject_Call
  # define PyString_AsString dll_PyString_AsString
  # define PyString_AsStringAndSize dll_PyString_AsStringAndSize
  # define PyString_FromString dll_PyString_FromString
***************
*** 346,351 ****
--- 347,353 ----
  static int (*dll_PyObject_HasAttrString)(PyObject *, const char *);
  static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
  static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+ static PyObject* (*dll_PyObject_Call)(PyObject *, PyObject *, PyObject *);
  static char*(*dll_PyString_AsString)(PyObject *);
  static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
  static PyObject*(*dll_PyString_FromString)(const char *);
***************
*** 510,515 ****
--- 512,518 ----
      {"PyObject_HasAttrString", (PYTHON_PROC*)&dll_PyObject_HasAttrString},
      {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
      {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
+     {"PyObject_Call", (PYTHON_PROC*)&dll_PyObject_Call},
      {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
      {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
      {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
***************
*** 1364,1369 ****
--- 1367,1373 ----
  {
      PyObject *mod;
      PyObject *dict;
+     PyObject *os;
  
      /* The special value is removed from sys.path in Python_Init(). */
      static char *(argv[2]) = {"/must>not&exist/foo", NULL};
***************
*** 1374,1383 ****
      /* Set sys.argv[] to avoid a crash in warn(). */
      PySys_SetArgv(1, argv);
  
!     mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION);
      dict = PyModule_GetDict(mod);
  
!     return populate_module(dict, add_object);
  }
  
  /*************************************************************************
--- 1378,1388 ----
      /* Set sys.argv[] to avoid a crash in warn(). */
      PySys_SetArgv(1, argv);
  
!     mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL,
! 			    PYTHON_API_VERSION);
      dict = PyModule_GetDict(mod);
  
!     return populate_module(dict, add_object, PyDict_GetItemString);
  }
  
  /*************************************************************************
diff -cr vim.0ee8bb6bd07f/src/proto/ex_docmd.pro vim.807b755f9898/src/proto/ex_docmd.pro
*** vim.0ee8bb6bd07f/src/proto/ex_docmd.pro	2013-06-01 20:13:49.810598520 +0400
--- vim.807b755f9898/src/proto/ex_docmd.pro	2013-06-01 20:13:49.842598199 +0400
***************
*** 53,56 ****
--- 53,57 ----
  int put_line __ARGS((FILE *fd, char *s));
  void dialog_msg __ARGS((char_u *buff, char *format, char_u *fname));
  char_u *get_behave_arg __ARGS((expand_T *xp, int idx));
+ void post_chdir __ARGS((int local));
  /* vim: set ft=c : */
diff -cr vim.0ee8bb6bd07f/src/testdir/test86.in vim.807b755f9898/src/testdir/test86.in
*** vim.0ee8bb6bd07f/src/testdir/test86.in	2013-06-01 20:13:49.833598289 +0400
--- vim.807b755f9898/src/testdir/test86.in	2013-06-01 20:13:49.865597968 +0400
***************
*** 788,793 ****
--- 788,807 ----
  :$put =string(pyeval('dl2'))
  :$put =string(pyeval('df(2)'))
  :"
+ :" Test chdir
+ py << EOF
+ import os
+ fnamemodify = vim.Function('fnamemodify')
+ cb.append(fnamemodify('.', ':p:h:t'))
+ cb.append(vim.eval('@%'))
+ os.chdir('..')
+ cb.append(fnamemodify('.', ':p:h:t'))
+ cb.append(vim.eval('@%').replace(os.path.sep, '/'))
+ os.chdir('testdir')
+ cb.append(fnamemodify('.', ':p:h:t'))
+ cb.append(vim.eval('@%'))
+ EOF
+ :"
  :" Test errors
  :fun F() dict
  :endfun
diff -cr vim.0ee8bb6bd07f/src/testdir/test86.ok vim.807b755f9898/src/testdir/test86.ok
*** vim.0ee8bb6bd07f/src/testdir/test86.ok	2013-06-01 20:13:49.834598279 +0400
--- vim.807b755f9898/src/testdir/test86.ok	2013-06-01 20:13:49.867597949 +0400
***************
*** 429,434 ****
--- 429,440 ----
  ['a', 'b', 'c']
  [2, 2]
  [2, 2]
+ testdir
+ test86.in
+ src
+ testdir/test86.in
+ testdir
+ test86.in
  > Output
  >> OutputSetattr
  del sys.stdout.softspace:(<type 'exceptions.AttributeError'>, AttributeError("can't delete OutputObject attributes",))
diff -cr vim.0ee8bb6bd07f/src/testdir/test87.in vim.807b755f9898/src/testdir/test87.in
*** vim.0ee8bb6bd07f/src/testdir/test87.in	2013-06-01 20:13:49.818598440 +0400
--- vim.807b755f9898/src/testdir/test87.in	2013-06-01 20:13:49.849598129 +0400
***************
*** 748,753 ****
--- 748,767 ----
  :$put =string(py3eval('dl2'))
  :$put =string(py3eval('df(2)'))
  :"
+ :" Test chdir
+ py3 << EOF
+ import os
+ fnamemodify = vim.Function('fnamemodify')
+ cb.append(str(fnamemodify('.', ':p:h:t')))
+ cb.append(vim.eval('@%'))
+ os.chdir('..')
+ cb.append(str(fnamemodify('.', ':p:h:t')))
+ cb.append(vim.eval('@%').replace(os.path.sep, '/'))
+ os.chdir('testdir')
+ cb.append(str(fnamemodify('.', ':p:h:t')))
+ cb.append(vim.eval('@%'))
+ EOF
+ :"
  :" Test errors
  :fun F() dict
  :endfun
diff -cr vim.0ee8bb6bd07f/src/testdir/test87.ok vim.807b755f9898/src/testdir/test87.ok
*** vim.0ee8bb6bd07f/src/testdir/test87.ok	2013-06-01 20:13:49.810598520 +0400
--- vim.807b755f9898/src/testdir/test87.ok	2013-06-01 20:13:49.841598209 +0400
***************
*** 418,423 ****
--- 418,429 ----
  ['a', 'b', 'c']
  [2, 2]
  [2, 2]
+ b'testdir'
+ test87.in
+ b'src'
+ testdir/test87.in
+ b'testdir'
+ test87.in
  > Output
  >> OutputSetattr
  del sys.stdout.softspace:(<class 'AttributeError'>, AttributeError("can't delete OutputObject attributes",))

Raspunde prin e-mail lui