mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
updated for version 7.3.1163
Problem: Not easy to load Python modules. Solution: Search "python2", "python3" and "pythonx" directories in 'runtimepath' for Python modules. (ZyX)
This commit is contained in:
267
src/if_py_both.h
267
src/if_py_both.h
@@ -24,6 +24,8 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
|
||||
#endif
|
||||
#define DOPY_FUNC "_vim_pydo"
|
||||
|
||||
static const char *vim_special_path = "_vim_path_";
|
||||
|
||||
#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
|
||||
|
||||
#define RAISE_NO_EMPTY_KEYS PyErr_SetString(PyExc_ValueError, \
|
||||
@@ -55,6 +57,8 @@ static PyObject *globals;
|
||||
static PyObject *py_chdir;
|
||||
static PyObject *py_fchdir;
|
||||
static PyObject *py_getcwd;
|
||||
static PyObject *vim_module;
|
||||
static PyObject *vim_special_path_object;
|
||||
|
||||
/*
|
||||
* obtain a lock on the Vim data structures
|
||||
@@ -779,19 +783,168 @@ VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
|
||||
return _VimChdir(py_fchdir, args, kwargs);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PyObject *callable;
|
||||
PyObject *result;
|
||||
} map_rtp_data;
|
||||
|
||||
static void
|
||||
map_rtp_callback(char_u *path, void *_data)
|
||||
{
|
||||
void **data = (void **) _data;
|
||||
PyObject *pathObject;
|
||||
map_rtp_data *mr_data = *((map_rtp_data **) data);
|
||||
|
||||
if (!(pathObject = PyString_FromString((char *) path)))
|
||||
{
|
||||
*data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
|
||||
pathObject, NULL);
|
||||
|
||||
Py_DECREF(pathObject);
|
||||
|
||||
if (!mr_data->result || mr_data->result != Py_None)
|
||||
*data = NULL;
|
||||
else
|
||||
{
|
||||
Py_DECREF(mr_data->result);
|
||||
mr_data->result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
VimForeachRTP(PyObject *self UNUSED, PyObject *args)
|
||||
{
|
||||
map_rtp_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &data.callable))
|
||||
return NULL;
|
||||
|
||||
data.result = NULL;
|
||||
|
||||
do_in_runtimepath(NULL, FALSE, &map_rtp_callback, &data);
|
||||
|
||||
if (data.result == NULL)
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
}
|
||||
return data.result;
|
||||
}
|
||||
|
||||
/*
|
||||
* _vim_runtimepath_ special path implementation.
|
||||
*/
|
||||
|
||||
static void
|
||||
map_finder_callback(char_u *path, void *_data)
|
||||
{
|
||||
void **data = (void **) _data;
|
||||
PyObject *list = *((PyObject **) data);
|
||||
PyObject *pathObject1, *pathObject2;
|
||||
char *pathbuf;
|
||||
size_t pathlen;
|
||||
|
||||
pathlen = STRLEN(path);
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
# define PY_MAIN_DIR_STRING "python2"
|
||||
#else
|
||||
# define PY_MAIN_DIR_STRING "python3"
|
||||
#endif
|
||||
#define PY_ALTERNATE_DIR_STRING "pythonx"
|
||||
|
||||
#define PYTHONX_STRING_LENGTH 7 /* STRLEN("pythonx") */
|
||||
if (!(pathbuf = PyMem_New(char,
|
||||
pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
|
||||
{
|
||||
PyErr_NoMemory();
|
||||
*data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
mch_memmove(pathbuf, path, pathlen + 1);
|
||||
add_pathsep((char_u *) pathbuf);
|
||||
|
||||
pathlen = STRLEN(pathbuf);
|
||||
mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
|
||||
PYTHONX_STRING_LENGTH + 1);
|
||||
|
||||
if (!(pathObject1 = PyString_FromString(pathbuf)))
|
||||
{
|
||||
*data = NULL;
|
||||
PyMem_Free(pathbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
|
||||
PYTHONX_STRING_LENGTH + 1);
|
||||
|
||||
if (!(pathObject2 = PyString_FromString(pathbuf)))
|
||||
{
|
||||
Py_DECREF(pathObject1);
|
||||
PyMem_Free(pathbuf);
|
||||
*data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
PyMem_Free(pathbuf);
|
||||
|
||||
if (PyList_Append(list, pathObject1)
|
||||
|| PyList_Append(list, pathObject2))
|
||||
*data = NULL;
|
||||
|
||||
Py_DECREF(pathObject1);
|
||||
Py_DECREF(pathObject2);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Vim_GetPaths(PyObject *self UNUSED)
|
||||
{
|
||||
PyObject *r;
|
||||
|
||||
if (!(r = PyList_New(0)))
|
||||
return NULL;
|
||||
|
||||
do_in_runtimepath(NULL, FALSE, &map_finder_callback, r);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
Py_DECREF(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 }
|
||||
/* 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"},
|
||||
{"foreach_rtp", VimForeachRTP, METH_VARARGS, "Call given callable for each path in &rtp"},
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
{"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
|
||||
{"load_module", LoaderLoadModule, METH_VARARGS, "Internal use only, tries importing the given module from &rtp by temporary mocking sys.path (to an rtp-based one) and unsetting sys.meta_path and sys.path_hooks"},
|
||||
#endif
|
||||
{"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
|
||||
{"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
|
||||
{ NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -5036,6 +5189,14 @@ typedef struct
|
||||
} CurrentObject;
|
||||
static PyTypeObject CurrentType;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
typedef struct
|
||||
{
|
||||
PyObject_HEAD
|
||||
} FinderObject;
|
||||
static PyTypeObject FinderType;
|
||||
#endif
|
||||
|
||||
static void
|
||||
init_structs(void)
|
||||
{
|
||||
@@ -5281,6 +5442,81 @@ init_types()
|
||||
PYTYPE_READY(FunctionType);
|
||||
PYTYPE_READY(OptionsType);
|
||||
PYTYPE_READY(OutputType);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PYTYPE_READY(FinderType);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_sys_path()
|
||||
{
|
||||
PyObject *path;
|
||||
PyObject *path_hook;
|
||||
PyObject *path_hooks;
|
||||
|
||||
if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
|
||||
return -1;
|
||||
|
||||
if (!(path_hooks = PySys_GetObject("path_hooks")))
|
||||
{
|
||||
PyErr_Clear();
|
||||
path_hooks = PyList_New(1);
|
||||
PyList_SET_ITEM(path_hooks, 0, path_hook);
|
||||
if (PySys_SetObject("path_hooks", path_hooks))
|
||||
{
|
||||
Py_DECREF(path_hooks);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(path_hooks);
|
||||
}
|
||||
else if (PyList_Check(path_hooks))
|
||||
{
|
||||
if (PyList_Append(path_hooks, path_hook))
|
||||
{
|
||||
Py_DECREF(path_hook);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(path_hook);
|
||||
}
|
||||
else
|
||||
{
|
||||
VimTryStart();
|
||||
EMSG(_("Failed to set path hook: sys.path_hooks is not a list\n"
|
||||
"You should now do the following:\n"
|
||||
"- append vim.path_hook to sys.path_hooks\n"
|
||||
"- append vim.VIM_SPECIAL_PATH to sys.path\n"));
|
||||
VimTryEnd(); /* Discard the error */
|
||||
Py_DECREF(path_hook);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(path = PySys_GetObject("path")))
|
||||
{
|
||||
PyErr_Clear();
|
||||
path = PyList_New(1);
|
||||
Py_INCREF(vim_special_path_object);
|
||||
PyList_SET_ITEM(path, 0, vim_special_path_object);
|
||||
if (PySys_SetObject("path", path))
|
||||
{
|
||||
Py_DECREF(path);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(path);
|
||||
}
|
||||
else if (PyList_Check(path))
|
||||
{
|
||||
if (PyList_Append(path, vim_special_path_object))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
VimTryStart();
|
||||
EMSG(_("Failed to set path: sys.path is not a list\n"
|
||||
"You should now append vim.VIM_SPECIAL_PATH to sys.path"));
|
||||
VimTryEnd(); /* Discard the error */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5332,6 +5568,9 @@ static struct object_constant {
|
||||
{"List", (PyObject *)&ListType},
|
||||
{"Function", (PyObject *)&FunctionType},
|
||||
{"Options", (PyObject *)&OptionsType},
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
{"Finder", (PyObject *)&FinderType},
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef int (*object_adder)(PyObject *, const char *, PyObject *);
|
||||
@@ -5417,5 +5656,17 @@ populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
|
||||
else
|
||||
PyErr_Clear();
|
||||
|
||||
if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
|
||||
return -1;
|
||||
|
||||
ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
ADD_OBJECT(m, "_PathFinder", path_finder);
|
||||
ADD_CHECKED_OBJECT(m, "_find_module",
|
||||
(py_find_module = PyObject_GetAttrString(path_finder,
|
||||
"find_module")));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user