Mercurial > vim
diff src/if_py_both.h @ 4599:89bec74fd793 v7.3.1047
updated for version 7.3.1047
Problem: Python: dir() does not work properly.
Solution: Python patch 8. Add __dir__ method to all objects with custom
tp_getattr supplemented by __members__ attribute for at least
python-2* versions. __members__ is not mentioned in python-3*
dir() output even if it is accessible. (ZyX)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 29 May 2013 22:36:10 +0200 |
parents | 00eecb2f8e3e |
children | 19d406a8509d |
line wrap: on
line diff
--- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -117,6 +117,59 @@ StringToChars(PyObject *object, PyObject return (char_u *) p; } + static int +add_string(PyObject *list, char *s) +{ + PyObject *string; + + if (!(string = PyString_FromString(s))) + return -1; + if (PyList_Append(list, string)) + { + Py_DECREF(string); + return -1; + } + + Py_DECREF(string); + return 0; +} + + static PyObject * +ObjectDir(PyObject *self, char **attributes) +{ + PyMethodDef *method; + char **attr; + PyObject *r; + + if (!(r = PyList_New(0))) + return NULL; + + if (self) + for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method) + if (add_string(r, (char *) method->ml_name)) + { + Py_DECREF(r); + return NULL; + } + + for (attr = attributes ; *attr ; ++attr) + if (add_string(r, *attr)) + { + Py_DECREF(r); + return NULL; + } + +#if PY_MAJOR_VERSION < 3 + if (add_string(r, "__members__")) + { + Py_DECREF(r); + return NULL; + } +#endif + + return r; +} + /* Output buffer management */ @@ -132,6 +185,17 @@ typedef struct long error; } OutputObject; +static char *OutputAttrs[] = { + "softspace", + NULL +}; + + static PyObject * +OutputDir(PyObject *self) +{ + return ObjectDir(self, OutputAttrs); +} + static int OutputSetattr(OutputObject *self, char *name, PyObject *val) { @@ -291,6 +355,7 @@ static struct PyMethodDef OutputMethods[ {"write", (PyCFunction)OutputWrite, METH_VARARGS, ""}, {"writelines", (PyCFunction)OutputWritelines, METH_VARARGS, ""}, {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""}, + {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""}, { NULL, NULL, 0, NULL} }; @@ -826,6 +891,17 @@ DictionaryDestructor(DictionaryObject *s DESTRUCTOR_FINISH(self); } +static char *DictionaryAttrs[] = { + "locked", "scope", + NULL +}; + + static PyObject * +DictionaryDir(PyObject *self) +{ + return ObjectDir(self, DictionaryAttrs); +} + static int DictionarySetattr(DictionaryObject *self, char *name, PyObject *val) { @@ -985,7 +1061,8 @@ static PyMappingMethods DictionaryAsMapp static struct PyMethodDef DictionaryMethods[] = { {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""}, - { NULL, NULL, 0, NULL } + {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; static PyTypeObject ListType; @@ -1331,6 +1408,17 @@ ListConcatInPlace(ListObject *self, PyOb return (PyObject *)(self); } +static char *ListAttrs[] = { + "locked", + NULL +}; + + static PyObject * +ListDir(PyObject *self) +{ + return ObjectDir(self, ListAttrs); +} + static int ListSetattr(ListObject *self, char *name, PyObject *val) { @@ -1368,8 +1456,9 @@ ListSetattr(ListObject *self, char *name } static struct PyMethodDef ListMethods[] = { - {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, - { NULL, NULL, 0, NULL } + {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, + {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; typedef struct @@ -1408,6 +1497,17 @@ FunctionDestructor(FunctionObject *self) DESTRUCTOR_FINISH(self); } +static char *FunctionAttrs[] = { + "softspace", + NULL +}; + + static PyObject * +FunctionDir(PyObject *self) +{ + return ObjectDir(self, FunctionAttrs); +} + static PyObject * FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs) { @@ -1472,8 +1572,9 @@ FunctionCall(FunctionObject *self, PyObj } static struct PyMethodDef FunctionMethods[] = { - {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""}, - { NULL, NULL, 0, NULL} + {"__call__",(PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""}, + {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; /* @@ -1842,6 +1943,17 @@ TabPageDestructor(TabPageObject *self) DESTRUCTOR_FINISH(self); } +static char *TabPageAttrs[] = { + "windows", "number", "vars", "window", "valid", + NULL +}; + + static PyObject * +TabPageDir(PyObject *self) +{ + return ObjectDir(self, TabPageAttrs); +} + static PyObject * TabPageAttrValid(TabPageObject *self, char *name) { @@ -1873,6 +1985,8 @@ TabPageAttr(TabPageObject *self, char *n else return WindowNew(self->tab->tp_curwin, self->tab); } + else if (strcmp(name, "__members__") == 0) + return ObjectDir(NULL, TabPageAttrs); return NULL; } @@ -1901,8 +2015,9 @@ TabPageRepr(TabPageObject *self) } static struct PyMethodDef TabPageMethods[] = { - /* name, function, calling, documentation */ - { NULL, NULL, 0, NULL } + /* name, function, calling, documentation */ + {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; /* @@ -2049,6 +2164,17 @@ get_firstwin(TabPageObject *tabObject) else return firstwin; } +static char *WindowAttrs[] = { + "buffer", "cursor", "height", "vars", "options", "number", "row", "col", + "tabpage", "valid", + NULL +}; + + static PyObject * +WindowDir(PyObject *self) +{ + return ObjectDir(self, WindowAttrs); +} static PyObject * WindowAttrValid(WindowObject *self, char *name) @@ -2103,9 +2229,8 @@ WindowAttr(WindowObject *self, char *nam Py_INCREF(self->tabObject); return (PyObject *)(self->tabObject); } - else if (strcmp(name,"__members__") == 0) - return Py_BuildValue("[ssssssssss]", "buffer", "cursor", "height", - "vars", "options", "number", "row", "col", "tabpage", "valid"); + else if (strcmp(name, "__members__") == 0) + return ObjectDir(NULL, WindowAttrs); else return NULL; } @@ -2228,8 +2353,9 @@ WindowRepr(WindowObject *self) } static struct PyMethodDef WindowMethods[] = { - /* name, function, calling, documentation */ - { NULL, NULL, 0, NULL } + /* name, function, calling, documentation */ + {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; /* @@ -3122,6 +3248,17 @@ RangeSlice(RangeObject *self, PyInt lo, return RBSlice(self->buf, lo, hi, self->start, self->end); } +static char *RangeAttrs[] = { + "start", "end", + NULL +}; + + static PyObject * +RangeDir(PyObject *self) +{ + return ObjectDir(self, RangeAttrs); +} + static PyObject * RangeAppend(RangeObject *self, PyObject *args) { @@ -3162,7 +3299,8 @@ RangeRepr(RangeObject *self) static struct PyMethodDef RangeMethods[] = { /* name, function, calling, documentation */ {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" }, - { NULL, NULL, 0, NULL } + {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; static PyTypeObject BufferType; @@ -3239,6 +3377,17 @@ BufferSlice(BufferObject *self, PyInt lo return RBSlice(self, lo, hi, 1, -1); } +static char *BufferAttrs[] = { + "name", "number", "vars", "options", "valid", + NULL +}; + + static PyObject * +BufferDir(PyObject *self) +{ + return ObjectDir(self, BufferAttrs); +} + static PyObject * BufferAttrValid(BufferObject *self, char *name) { @@ -3265,9 +3414,8 @@ BufferAttr(BufferObject *self, char *nam else if (strcmp(name, "options") == 0) return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer, (PyObject *) self); - else if (strcmp(name,"__members__") == 0) - return Py_BuildValue("[sssss]", "name", "number", "vars", "options", - "valid"); + else if (strcmp(name, "__members__") == 0) + return ObjectDir(NULL, BufferAttrs); else return NULL; } @@ -3403,10 +3551,8 @@ static struct PyMethodDef BufferMethods[ {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" }, {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" }, {"range", (PyCFunction)BufferRange, METH_VARARGS, "Return a range object which represents the part of the given buffer between line numbers s and e" }, -#if PY_VERSION_HEX >= 0x03000000 - {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, "List buffer attributes" }, -#endif - { NULL, NULL, 0, NULL } + {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} }; /* @@ -3538,6 +3684,17 @@ static PyMappingMethods BufMapAsMapping /* Current items object */ +static char *CurrentAttrs[] = { + "buffer", "window", "line", "range", "tabpage", + NULL +}; + + static PyObject * +CurrentDir(PyObject *self) +{ + return ObjectDir(self, CurrentAttrs); +} + static PyObject * CurrentGetattr(PyObject *self UNUSED, char *name) { @@ -3551,14 +3708,14 @@ CurrentGetattr(PyObject *self UNUSED, ch return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum); else if (strcmp(name, "range") == 0) return RangeNew(curbuf, RangeStart, RangeEnd); - else if (strcmp(name,"__members__") == 0) - return Py_BuildValue("[sssss]", "buffer", "window", "line", "range", - "tabpage"); + else if (strcmp(name, "__members__") == 0) + return ObjectDir(NULL, CurrentAttrs); else - { - PyErr_SetString(PyExc_AttributeError, name); +#if PY_MAJOR_VERSION < 3 + return Py_FindMethod(WindowMethods, self, name); +#else return NULL; - } +#endif } static int @@ -3661,6 +3818,12 @@ CurrentSetattr(PyObject *self UNUSED, ch } } +static struct PyMethodDef CurrentMethods[] = { + /* name, function, calling, documentation */ + {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL} +}; + static void init_range_cmd(exarg_T *eap) { @@ -4397,6 +4560,7 @@ init_structs(void) CurrentType.tp_basicsize = sizeof(CurrentObject); CurrentType.tp_flags = Py_TPFLAGS_DEFAULT; CurrentType.tp_doc = "vim current object"; + CurrentType.tp_methods = CurrentMethods; #if PY_MAJOR_VERSION >= 3 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro; CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;