# HG changeset patch
# User ZyX <[email protected]>
# Date 1369479301 -14400
# Node ID 920b38ba610a4b9b874a18828a5b13c1a560a583
# Parent df22b77f9a4b8172c6b41745a42a0574ce907d14
Fix dir()
Python documentation says that __members__ attribute is deprecated since
python-2.2, but this does not make dir() work properly without __members__ on
python-2.3.
This patch adds __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.
diff -r df22b77f9a4b -r 920b38ba610a src/if_py_both.h
--- a/src/if_py_both.h Sat May 25 13:43:13 2013 +0400
+++ b/src/if_py_both.h Sat May 25 14:55:01 2013 +0400
@@ -117,6 +117,59 @@
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 @@
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 @@
{"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 @@
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 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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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)
{
@@ -3264,9 +3413,8 @@
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;
}
@@ -3402,10 +3550,8 @@
{"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}
};
/*
@@ -3537,6 +3683,17 @@
/* 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)
{
@@ -3550,14 +3707,14 @@
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
@@ -3660,6 +3817,12 @@
}
}
+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)
{
@@ -4396,6 +4559,7 @@
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;
diff -r df22b77f9a4b -r 920b38ba610a src/if_python.c
--- a/src/if_python.c Sat May 25 13:43:13 2013 +0400
+++ b/src/if_python.c Sat May 25 14:55:01 2013 +0400
@@ -1066,6 +1066,8 @@
{
if (strcmp(name, "softspace") == 0)
return PyInt_FromLong(((OutputObject *)(self))->softspace);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, OutputAttrs);
return Py_FindMethod(OutputMethods, self, name);
}
@@ -1177,6 +1179,8 @@
return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start -
1);
else if (strcmp(name, "end") == 0)
return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, RangeAttrs);
else
return Py_FindMethod(RangeMethods, self, name);
}
@@ -1396,6 +1400,8 @@
return PyInt_FromLong(this->dict->dv_lock);
else if (strcmp(name, "scope") == 0)
return PyInt_FromLong(this->dict->dv_scope);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, DictionaryAttrs);
return Py_FindMethod(DictionaryMethods, self, name);
}
@@ -1420,6 +1426,8 @@
{
if (strcmp(name, "locked") == 0)
return PyInt_FromLong(((ListObject *)(self))->list->lv_lock);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, ListAttrs);
return Py_FindMethod(ListMethods, self, name);
}
@@ -1431,6 +1439,8 @@
if (strcmp(name, "name") == 0)
return PyString_FromString((char *)(this->name));
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, FunctionAttrs);
else
return Py_FindMethod(FunctionMethods, self, name);
}
diff -r df22b77f9a4b -r 920b38ba610a src/if_python3.c
--- a/src/if_python3.c Sat May 25 13:43:13 2013 +0400
+++ b/src/if_python3.c Sat May 25 14:55:01 2013 +0400
@@ -666,7 +666,6 @@
return PyType_GenericAlloc(type,nitems);
}
-static PyObject *BufferDir(PyObject *);
static PyObject *OutputGetattro(PyObject *, PyObject *);
static int OutputSetattro(PyObject *, PyObject *, PyObject *);
static PyObject *BufferGetattro(PyObject *, PyObject *);
@@ -1094,14 +1093,6 @@
return BufferSetattr((BufferObject *)(self), name, val);
}
- static PyObject *
-BufferDir(PyObject *self UNUSED)
-{
- return Py_BuildValue("[ssssssss]",
- "name", "number", "vars", "options", "valid",
- "append", "mark", "range");
-}
-
/******************/
static PyObject *
@@ -1368,8 +1359,11 @@
static PyObject *
CurrentGetattro(PyObject *self, PyObject *nameobj)
{
+ PyObject *r;
GET_ATTR_STRING(name, nameobj);
- return CurrentGetattr(self, name);
+ if (!(r = CurrentGetattr(self, name)))
+ return PyObject_GenericGetAttr(self, nameobj);
+ return r;
}
static int
diff -r df22b77f9a4b -r 920b38ba610a src/testdir/test86.in
--- a/src/testdir/test86.in Sat May 25 13:43:13 2013 +0400
+++ b/src/testdir/test86.in Sat May 25 14:55:01 2013 +0400
@@ -691,6 +691,24 @@
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim,
attr)))
EOF
:"
+:" Test __dir__() method
+py << EOF
+for name, o in (
+ ('current', vim.current),
+ ('buffer', vim.current.buffer),
+ ('window', vim.current.window),
+ ('tabpage', vim.current.tabpage),
+ ('range', vim.current.range),
+ ('dictionary', vim.bindeval('{}')),
+ ('list', vim.bindeval('[]')),
+ ('function', vim.bindeval('function("tr")')),
+ ('output', sys.stdout),
+ ):
+ cb.append(name + ':' + ','.join(dir(o)))
+del name
+del o
+EOF
+:"
:" Test exceptions
:fun Exe(e)
: execute a:e
diff -r df22b77f9a4b -r 920b38ba610a src/testdir/test86.ok
--- a/src/testdir/test86.ok Sat May 25 13:43:13 2013 +0400
+++ b/src/testdir/test86.ok Sat May 25 14:55:01 2013 +0400
@@ -382,6 +382,15 @@
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+current:__dir__,__members__,buffer,line,range,tabpage,window
+buffer:__dir__,__members__,append,mark,name,number,options,range,valid,vars
+window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
+tabpage:__dir__,__members__,number,valid,vars,window,windows
+range:__dir__,__members__,append,end,start
+dictionary:__dir__,__members__,keys,locked,scope
+list:__dir__,__members__,extend,locked
+function:__call__,__dir__,__members__,softspace
+output:__dir__,__members__,flush,softspace,write,writelines
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))
diff -r df22b77f9a4b -r 920b38ba610a src/testdir/test87.in
--- a/src/testdir/test87.in Sat May 25 13:43:13 2013 +0400
+++ b/src/testdir/test87.in Sat May 25 14:55:01 2013 +0400
@@ -669,6 +669,24 @@
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim,
attr)))
EOF
:"
+:" Test __dir__() method
+py3 << EOF
+for name, o in (
+ ('current', vim.current),
+ ('buffer', vim.current.buffer),
+ ('window', vim.current.window),
+ ('tabpage', vim.current.tabpage),
+ ('range', vim.current.range),
+ ('dictionary', vim.bindeval('{}')),
+ ('list', vim.bindeval('[]')),
+ ('function', vim.bindeval('function("tr")')),
+ ('output', sys.stdout),
+ ):
+ cb.append(name + ':' + ','.join(dir(o)))
+del name
+del o
+EOF
+:"
:" Test exceptions
:fun Exe(e)
: execute a:e
diff -r df22b77f9a4b -r 920b38ba610a src/testdir/test87.ok
--- a/src/testdir/test87.ok Sat May 25 13:43:13 2013 +0400
+++ b/src/testdir/test87.ok Sat May 25 14:55:01 2013 +0400
@@ -371,6 +371,15 @@
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+current:__dir__,buffer,line,range,tabpage,window
+buffer:__dir__,append,mark,name,number,options,range,valid,vars
+window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
+tabpage:__dir__,number,valid,vars,window,windows
+range:__dir__,append,end,start
+dictionary:__dir__,keys,locked,scope
+list:__dir__,extend,locked
+function:__call__,__dir__,softspace
+output:__dir__,flush,softspace,write,writelines
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))
--
--
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.df22b77f9a4b/src/if_py_both.h vim.920b38ba610a/src/if_py_both.h
*** vim.df22b77f9a4b/src/if_py_both.h 2013-05-25 15:02:27.054262148 +0400
--- vim.920b38ba610a/src/if_py_both.h 2013-05-25 15:02:27.068255017 +0400
***************
*** 117,122 ****
--- 117,175 ----
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,137 ****
--- 185,201 ----
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,296 ****
--- 355,361 ----
{"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,831 ****
--- 891,907 ----
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,991 ****
static struct PyMethodDef DictionaryMethods[] = {
{"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL }
};
static PyTypeObject ListType;
--- 1061,1068 ----
static struct PyMethodDef DictionaryMethods[] = {
{"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
! {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
static PyTypeObject ListType;
***************
*** 1331,1336 ****
--- 1408,1424 ----
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,1375 ****
}
static struct PyMethodDef ListMethods[] = {
! {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
! { NULL, NULL, 0, NULL }
};
typedef struct
--- 1456,1464 ----
}
static struct PyMethodDef ListMethods[] = {
! {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
! {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
typedef struct
***************
*** 1408,1413 ****
--- 1497,1513 ----
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,1479 ****
}
static struct PyMethodDef FunctionMethods[] = {
! {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
! { NULL, NULL, 0, NULL}
};
/*
--- 1572,1580 ----
}
static struct PyMethodDef FunctionMethods[] = {
! {"__call__",(PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
! {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
/*
***************
*** 1842,1847 ****
--- 1943,1959 ----
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,1878 ****
--- 1985,1992 ----
else
return WindowNew(self->tab->tp_curwin, self->tab);
}
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, TabPageAttrs);
return NULL;
}
***************
*** 1901,1908 ****
}
static struct PyMethodDef TabPageMethods[] = {
! /* name, function, calling, documentation */
! { NULL, NULL, 0, NULL }
};
/*
--- 2015,2023 ----
}
static struct PyMethodDef TabPageMethods[] = {
! /* name, function, calling, documentation */
! {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
/*
***************
*** 2049,2054 ****
--- 2164,2180 ----
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,2111 ****
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
return NULL;
}
--- 2229,2236 ----
Py_INCREF(self->tabObject);
return (PyObject *)(self->tabObject);
}
! else if (strcmp(name, "__members__") == 0)
! return ObjectDir(NULL, WindowAttrs);
else
return NULL;
}
***************
*** 2228,2235 ****
}
static struct PyMethodDef WindowMethods[] = {
! /* name, function, calling, documentation */
! { NULL, NULL, 0, NULL }
};
/*
--- 2353,2361 ----
}
static struct PyMethodDef WindowMethods[] = {
! /* name, function, calling, documentation */
! {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
/*
***************
*** 3122,3127 ****
--- 3248,3264 ----
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,3168 ****
static struct PyMethodDef RangeMethods[] = {
/* name, function, calling, documentation */
{"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
! { NULL, NULL, 0, NULL }
};
static PyTypeObject BufferType;
--- 3299,3306 ----
static struct PyMethodDef RangeMethods[] = {
/* name, function, calling, documentation */
{"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
! {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
static PyTypeObject BufferType;
***************
*** 3239,3244 ****
--- 3377,3393 ----
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)
{
***************
*** 3264,3272 ****
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
return NULL;
}
--- 3413,3420 ----
else if (strcmp(name, "options") == 0)
return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
(PyObject *) self);
! else if (strcmp(name, "__members__") == 0)
! return ObjectDir(NULL, BufferAttrs);
else
return NULL;
}
***************
*** 3402,3411 ****
{"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 }
};
/*
--- 3550,3557 ----
{"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" },
! {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
! { NULL, NULL, 0, NULL}
};
/*
***************
*** 3537,3542 ****
--- 3683,3699 ----
/* 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)
{
***************
*** 3550,3563 ****
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
! {
! PyErr_SetString(PyExc_AttributeError, name);
return NULL;
! }
}
static int
--- 3707,3720 ----
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 ObjectDir(NULL, CurrentAttrs);
else
! #if PY_MAJOR_VERSION < 3
! return Py_FindMethod(WindowMethods, self, name);
! #else
return NULL;
! #endif
}
static int
***************
*** 3660,3665 ****
--- 3817,3828 ----
}
}
+ 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)
{
***************
*** 4396,4401 ****
--- 4559,4565 ----
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;
diff -cr vim.df22b77f9a4b/src/if_python3.c vim.920b38ba610a/src/if_python3.c
*** vim.df22b77f9a4b/src/if_python3.c 2013-05-25 15:02:27.058260110 +0400
--- vim.920b38ba610a/src/if_python3.c 2013-05-25 15:02:27.072252979 +0400
***************
*** 666,672 ****
return PyType_GenericAlloc(type,nitems);
}
- static PyObject *BufferDir(PyObject *);
static PyObject *OutputGetattro(PyObject *, PyObject *);
static int OutputSetattro(PyObject *, PyObject *, PyObject *);
static PyObject *BufferGetattro(PyObject *, PyObject *);
--- 666,671 ----
***************
*** 1094,1107 ****
return BufferSetattr((BufferObject *)(self), name, val);
}
- static PyObject *
- BufferDir(PyObject *self UNUSED)
- {
- return Py_BuildValue("[ssssssss]",
- "name", "number", "vars", "options", "valid",
- "append", "mark", "range");
- }
-
/******************/
static PyObject *
--- 1093,1098 ----
***************
*** 1368,1375 ****
static PyObject *
CurrentGetattro(PyObject *self, PyObject *nameobj)
{
GET_ATTR_STRING(name, nameobj);
! return CurrentGetattr(self, name);
}
static int
--- 1359,1369 ----
static PyObject *
CurrentGetattro(PyObject *self, PyObject *nameobj)
{
+ PyObject *r;
GET_ATTR_STRING(name, nameobj);
! if (!(r = CurrentGetattr(self, name)))
! return PyObject_GenericGetAttr(self, nameobj);
! return r;
}
static int
diff -cr vim.df22b77f9a4b/src/if_python.c vim.920b38ba610a/src/if_python.c
*** vim.df22b77f9a4b/src/if_python.c 2013-05-25 15:02:27.061258582 +0400
--- vim.920b38ba610a/src/if_python.c 2013-05-25 15:02:27.075251451 +0400
***************
*** 1066,1071 ****
--- 1066,1073 ----
{
if (strcmp(name, "softspace") == 0)
return PyInt_FromLong(((OutputObject *)(self))->softspace);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, OutputAttrs);
return Py_FindMethod(OutputMethods, self, name);
}
***************
*** 1177,1182 ****
--- 1179,1186 ----
return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start - 1);
else if (strcmp(name, "end") == 0)
return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, RangeAttrs);
else
return Py_FindMethod(RangeMethods, self, name);
}
***************
*** 1396,1401 ****
--- 1400,1407 ----
return PyInt_FromLong(this->dict->dv_lock);
else if (strcmp(name, "scope") == 0)
return PyInt_FromLong(this->dict->dv_scope);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, DictionaryAttrs);
return Py_FindMethod(DictionaryMethods, self, name);
}
***************
*** 1420,1425 ****
--- 1426,1433 ----
{
if (strcmp(name, "locked") == 0)
return PyInt_FromLong(((ListObject *)(self))->list->lv_lock);
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, ListAttrs);
return Py_FindMethod(ListMethods, self, name);
}
***************
*** 1431,1436 ****
--- 1439,1446 ----
if (strcmp(name, "name") == 0)
return PyString_FromString((char *)(this->name));
+ else if (strcmp(name, "__members__") == 0)
+ return ObjectDir(NULL, FunctionAttrs);
else
return Py_FindMethod(FunctionMethods, self, name);
}
diff -cr vim.df22b77f9a4b/src/testdir/test86.in vim.920b38ba610a/src/testdir/test86.in
*** vim.df22b77f9a4b/src/testdir/test86.in 2013-05-25 15:02:27.055261638 +0400
--- vim.920b38ba610a/src/testdir/test86.in 2013-05-25 15:02:27.069254507 +0400
***************
*** 691,696 ****
--- 691,714 ----
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
EOF
:"
+ :" Test __dir__() method
+ py << EOF
+ for name, o in (
+ ('current', vim.current),
+ ('buffer', vim.current.buffer),
+ ('window', vim.current.window),
+ ('tabpage', vim.current.tabpage),
+ ('range', vim.current.range),
+ ('dictionary', vim.bindeval('{}')),
+ ('list', vim.bindeval('[]')),
+ ('function', vim.bindeval('function("tr")')),
+ ('output', sys.stdout),
+ ):
+ cb.append(name + ':' + ','.join(dir(o)))
+ del name
+ del o
+ EOF
+ :"
:" Test exceptions
:fun Exe(e)
: execute a:e
diff -cr vim.df22b77f9a4b/src/testdir/test86.ok vim.920b38ba610a/src/testdir/test86.ok
*** vim.df22b77f9a4b/src/testdir/test86.ok 2013-05-25 15:02:27.056261129 +0400
--- vim.920b38ba610a/src/testdir/test86.ok 2013-05-25 15:02:27.070253997 +0400
***************
*** 382,387 ****
--- 382,396 ----
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+ current:__dir__,__members__,buffer,line,range,tabpage,window
+ buffer:__dir__,__members__,append,mark,name,number,options,range,valid,vars
+ window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
+ tabpage:__dir__,__members__,number,valid,vars,window,windows
+ range:__dir__,__members__,append,end,start
+ dictionary:__dir__,__members__,keys,locked,scope
+ list:__dir__,__members__,extend,locked
+ function:__call__,__dir__,__members__,softspace
+ output:__dir__,__members__,flush,softspace,write,writelines
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))
diff -cr vim.df22b77f9a4b/src/testdir/test87.in vim.920b38ba610a/src/testdir/test87.in
*** vim.df22b77f9a4b/src/testdir/test87.in 2013-05-25 15:02:27.050264185 +0400
--- vim.920b38ba610a/src/testdir/test87.in 2013-05-25 15:02:27.064257053 +0400
***************
*** 669,674 ****
--- 669,692 ----
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
EOF
:"
+ :" Test __dir__() method
+ py3 << EOF
+ for name, o in (
+ ('current', vim.current),
+ ('buffer', vim.current.buffer),
+ ('window', vim.current.window),
+ ('tabpage', vim.current.tabpage),
+ ('range', vim.current.range),
+ ('dictionary', vim.bindeval('{}')),
+ ('list', vim.bindeval('[]')),
+ ('function', vim.bindeval('function("tr")')),
+ ('output', sys.stdout),
+ ):
+ cb.append(name + ':' + ','.join(dir(o)))
+ del name
+ del o
+ EOF
+ :"
:" Test exceptions
:fun Exe(e)
: execute a:e
diff -cr vim.df22b77f9a4b/src/testdir/test87.ok vim.920b38ba610a/src/testdir/test87.ok
*** vim.df22b77f9a4b/src/testdir/test87.ok 2013-05-25 15:02:27.050264185 +0400
--- vim.920b38ba610a/src/testdir/test87.ok 2013-05-25 15:02:27.064257053 +0400
***************
*** 371,376 ****
--- 371,385 ----
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+ current:__dir__,buffer,line,range,tabpage,window
+ buffer:__dir__,append,mark,name,number,options,range,valid,vars
+ window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
+ tabpage:__dir__,number,valid,vars,window,windows
+ range:__dir__,append,end,start
+ dictionary:__dir__,keys,locked,scope
+ list:__dir__,extend,locked
+ function:__call__,__dir__,softspace
+ output:__dir__,flush,softspace,write,writelines
(<class 'vim.error'>, error('abc',))
(<class 'vim.error'>, error('def',))
(<class 'vim.error'>, error('ghi',))