home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / patches / 7.3 / 7.3.1047 < prev    next >
Encoding:
Internet Message Format  |  2013-05-28  |  19.8 KB

  1. To: vim_dev@googlegroups.com
  2. Subject: Patch 7.3.1047
  3. Fcc: outbox
  4. From: Bram Moolenaar <Bram@moolenaar.net>
  5. Mime-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. ------------
  9.  
  10. Patch 7.3.1047
  11. Problem:    Python: dir() does not work properly.
  12. Solution:   Python patch 8.  Add __dir__ method to all objects with custom
  13.         tp_getattr supplemented by __members__ attribute for at least
  14.         python-2* versions.  __members__ is not mentioned in python-3*
  15.         dir() output even if it is accessible. (ZyX)
  16. Files:        src/if_py_both.h, src/if_python3.c, src/if_python.c,
  17.         src/testdir/test86.in, src/testdir/test86.ok,
  18.         src/testdir/test87.in, src/testdir/test87.ok
  19.  
  20.  
  21. *** ../vim-7.3.1046/src/if_py_both.h    2013-05-29 22:26:15.000000000 +0200
  22. --- src/if_py_both.h    2013-05-29 22:29:26.000000000 +0200
  23. ***************
  24. *** 117,122 ****
  25. --- 117,175 ----
  26.       return (char_u *) p;
  27.   }
  28.   
  29. +     static int
  30. + add_string(PyObject *list, char *s)
  31. + {
  32. +     PyObject    *string;
  33. +     if (!(string = PyString_FromString(s)))
  34. +     return -1;
  35. +     if (PyList_Append(list, string))
  36. +     {
  37. +     Py_DECREF(string);
  38. +     return -1;
  39. +     }
  40. +     Py_DECREF(string);
  41. +     return 0;
  42. + }
  43. +     static PyObject *
  44. + ObjectDir(PyObject *self, char **attributes)
  45. + {
  46. +     PyMethodDef    *method;
  47. +     char    **attr;
  48. +     PyObject    *r;
  49. +     if (!(r = PyList_New(0)))
  50. +     return NULL;
  51. +     if (self)
  52. +     for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
  53. +         if (add_string(r, (char *) method->ml_name))
  54. +         {
  55. +         Py_DECREF(r);
  56. +         return NULL;
  57. +         }
  58. +     for (attr = attributes ; *attr ; ++attr)
  59. +     if (add_string(r, *attr))
  60. +     {
  61. +         Py_DECREF(r);
  62. +         return NULL;
  63. +     }
  64. + #if PY_MAJOR_VERSION < 3
  65. +     if (add_string(r, "__members__"))
  66. +     {
  67. +     Py_DECREF(r);
  68. +     return NULL;
  69. +     }
  70. + #endif
  71. +     return r;
  72. + }
  73.   /* Output buffer management
  74.    */
  75.   
  76. ***************
  77. *** 132,137 ****
  78. --- 185,201 ----
  79.       long error;
  80.   } OutputObject;
  81.   
  82. + static char *OutputAttrs[] = {
  83. +     "softspace",
  84. +     NULL
  85. + };
  86. +     static PyObject *
  87. + OutputDir(PyObject *self)
  88. + {
  89. +     return ObjectDir(self, OutputAttrs);
  90. + }
  91.       static int
  92.   OutputSetattr(OutputObject *self, char *name, PyObject *val)
  93.   {
  94. ***************
  95. *** 291,296 ****
  96. --- 355,361 ----
  97.       {"write",        (PyCFunction)OutputWrite,        METH_VARARGS,    ""},
  98.       {"writelines",  (PyCFunction)OutputWritelines,    METH_VARARGS,    ""},
  99.       {"flush",        (PyCFunction)OutputFlush,        METH_NOARGS,    ""},
  100. +     {"__dir__",        (PyCFunction)OutputDir,        METH_NOARGS,    ""},
  101.       { NULL,        NULL,                0,        NULL}
  102.   };
  103.   
  104. ***************
  105. *** 826,831 ****
  106. --- 891,907 ----
  107.       DESTRUCTOR_FINISH(self);
  108.   }
  109.   
  110. + static char *DictionaryAttrs[] = {
  111. +     "locked", "scope",
  112. +     NULL
  113. + };
  114. +     static PyObject *
  115. + DictionaryDir(PyObject *self)
  116. + {
  117. +     return ObjectDir(self, DictionaryAttrs);
  118. + }
  119.       static int
  120.   DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
  121.   {
  122. ***************
  123. *** 985,991 ****
  124.   
  125.   static struct PyMethodDef DictionaryMethods[] = {
  126.       {"keys",    (PyCFunction)DictionaryListKeys,    METH_NOARGS,    ""},
  127. !     { NULL,    NULL,                    0,        NULL }
  128.   };
  129.   
  130.   static PyTypeObject ListType;
  131. --- 1061,1068 ----
  132.   
  133.   static struct PyMethodDef DictionaryMethods[] = {
  134.       {"keys",    (PyCFunction)DictionaryListKeys,    METH_NOARGS,    ""},
  135. !     {"__dir__",    (PyCFunction)DictionaryDir,        METH_NOARGS,    ""},
  136. !     { NULL,    NULL,                    0,        NULL}
  137.   };
  138.   
  139.   static PyTypeObject ListType;
  140. ***************
  141. *** 1331,1336 ****
  142. --- 1408,1424 ----
  143.       return (PyObject *)(self);
  144.   }
  145.   
  146. + static char *ListAttrs[] = {
  147. +     "locked",
  148. +     NULL
  149. + };
  150. +     static PyObject *
  151. + ListDir(PyObject *self)
  152. + {
  153. +     return ObjectDir(self, ListAttrs);
  154. + }
  155.       static int
  156.   ListSetattr(ListObject *self, char *name, PyObject *val)
  157.   {
  158. ***************
  159. *** 1368,1375 ****
  160.   }
  161.   
  162.   static struct PyMethodDef ListMethods[] = {
  163. !     {"extend",    (PyCFunction)ListConcatInPlace,    METH_O,    ""},
  164. !     { NULL,    NULL,                0,    NULL }
  165.   };
  166.   
  167.   typedef struct
  168. --- 1456,1464 ----
  169.   }
  170.   
  171.   static struct PyMethodDef ListMethods[] = {
  172. !     {"extend",    (PyCFunction)ListConcatInPlace,    METH_O,        ""},
  173. !     {"__dir__",    (PyCFunction)ListDir,        METH_NOARGS,    ""},
  174. !     { NULL,    NULL,                0,        NULL}
  175.   };
  176.   
  177.   typedef struct
  178. ***************
  179. *** 1408,1413 ****
  180. --- 1497,1513 ----
  181.       DESTRUCTOR_FINISH(self);
  182.   }
  183.   
  184. + static char *FunctionAttrs[] = {
  185. +     "softspace",
  186. +     NULL
  187. + };
  188. +     static PyObject *
  189. + FunctionDir(PyObject *self)
  190. + {
  191. +     return ObjectDir(self, FunctionAttrs);
  192. + }
  193.       static PyObject *
  194.   FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
  195.   {
  196. ***************
  197. *** 1472,1479 ****
  198.   }
  199.   
  200.   static struct PyMethodDef FunctionMethods[] = {
  201. !     {"__call__",    (PyCFunction)FunctionCall,    METH_VARARGS|METH_KEYWORDS, ""},
  202. !     { NULL,        NULL,            0,               NULL}
  203.   };
  204.   
  205.   /*
  206. --- 1572,1580 ----
  207.   }
  208.   
  209.   static struct PyMethodDef FunctionMethods[] = {
  210. !     {"__call__",(PyCFunction)FunctionCall,  METH_VARARGS|METH_KEYWORDS,    ""},
  211. !     {"__dir__",    (PyCFunction)FunctionDir,   METH_NOARGS,        ""},
  212. !     { NULL,    NULL,            0,                NULL}
  213.   };
  214.   
  215.   /*
  216. ***************
  217. *** 1842,1847 ****
  218. --- 1943,1959 ----
  219.       DESTRUCTOR_FINISH(self);
  220.   }
  221.   
  222. + static char *TabPageAttrs[] = {
  223. +     "windows", "number", "vars", "window", "valid",
  224. +     NULL
  225. + };
  226. +     static PyObject *
  227. + TabPageDir(PyObject *self)
  228. + {
  229. +     return ObjectDir(self, TabPageAttrs);
  230. + }
  231.       static PyObject *
  232.   TabPageAttrValid(TabPageObject *self, char *name)
  233.   {
  234. ***************
  235. *** 1873,1878 ****
  236. --- 1985,1992 ----
  237.       else
  238.           return WindowNew(self->tab->tp_curwin, self->tab);
  239.       }
  240. +     else if (strcmp(name, "__members__") == 0)
  241. +     return ObjectDir(NULL, TabPageAttrs);
  242.       return NULL;
  243.   }
  244.   
  245. ***************
  246. *** 1901,1908 ****
  247.   }
  248.   
  249.   static struct PyMethodDef TabPageMethods[] = {
  250. !     /* name,        function,        calling,    documentation */
  251. !     { NULL,        NULL,        0,        NULL }
  252.   };
  253.   
  254.   /*
  255. --- 2015,2023 ----
  256.   }
  257.   
  258.   static struct PyMethodDef TabPageMethods[] = {
  259. !     /* name,        function,            calling,    documentation */
  260. !     {"__dir__",        (PyCFunction)TabPageDir,    METH_NOARGS,    ""},
  261. !     { NULL,        NULL,            0,        NULL}
  262.   };
  263.   
  264.   /*
  265. ***************
  266. *** 2049,2054 ****
  267. --- 2164,2180 ----
  268.       else
  269.       return firstwin;
  270.   }
  271. + static char *WindowAttrs[] = {
  272. +     "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
  273. +     "tabpage", "valid",
  274. +     NULL
  275. + };
  276. +     static PyObject *
  277. + WindowDir(PyObject *self)
  278. + {
  279. +     return ObjectDir(self, WindowAttrs);
  280. + }
  281.   
  282.       static PyObject *
  283.   WindowAttrValid(WindowObject *self, char *name)
  284. ***************
  285. *** 2103,2111 ****
  286.       Py_INCREF(self->tabObject);
  287.       return (PyObject *)(self->tabObject);
  288.       }
  289. !     else if (strcmp(name,"__members__") == 0)
  290. !     return Py_BuildValue("[ssssssssss]", "buffer", "cursor", "height",
  291. !         "vars", "options", "number", "row", "col", "tabpage", "valid");
  292.       else
  293.       return NULL;
  294.   }
  295. --- 2229,2236 ----
  296.       Py_INCREF(self->tabObject);
  297.       return (PyObject *)(self->tabObject);
  298.       }
  299. !     else if (strcmp(name, "__members__") == 0)
  300. !     return ObjectDir(NULL, WindowAttrs);
  301.       else
  302.       return NULL;
  303.   }
  304. ***************
  305. *** 2228,2235 ****
  306.   }
  307.   
  308.   static struct PyMethodDef WindowMethods[] = {
  309. !     /* name,        function,        calling,    documentation */
  310. !     { NULL,        NULL,        0,        NULL }
  311.   };
  312.   
  313.   /*
  314. --- 2353,2361 ----
  315.   }
  316.   
  317.   static struct PyMethodDef WindowMethods[] = {
  318. !     /* name,        function,            calling,    documentation */
  319. !     {"__dir__",        (PyCFunction)WindowDir,    METH_NOARGS,    ""},
  320. !     { NULL,        NULL,            0,        NULL}
  321.   };
  322.   
  323.   /*
  324. ***************
  325. *** 3122,3127 ****
  326. --- 3248,3264 ----
  327.       return RBSlice(self->buf, lo, hi, self->start, self->end);
  328.   }
  329.   
  330. + static char *RangeAttrs[] = {
  331. +     "start", "end",
  332. +     NULL
  333. + };
  334. +     static PyObject *
  335. + RangeDir(PyObject *self)
  336. + {
  337. +     return ObjectDir(self, RangeAttrs);
  338. + }
  339.       static PyObject *
  340.   RangeAppend(RangeObject *self, PyObject *args)
  341.   {
  342. ***************
  343. *** 3162,3168 ****
  344.   static struct PyMethodDef RangeMethods[] = {
  345.       /* name,    function,            calling,    documentation */
  346.       {"append",    (PyCFunction)RangeAppend,    METH_VARARGS,    "Append data to the Vim range" },
  347. !     { NULL,    NULL,                0,        NULL }
  348.   };
  349.   
  350.   static PyTypeObject BufferType;
  351. --- 3299,3306 ----
  352.   static struct PyMethodDef RangeMethods[] = {
  353.       /* name,    function,            calling,    documentation */
  354.       {"append",    (PyCFunction)RangeAppend,    METH_VARARGS,    "Append data to the Vim range" },
  355. !     {"__dir__",    (PyCFunction)RangeDir,        METH_NOARGS,    ""},
  356. !     { NULL,    NULL,                0,        NULL}
  357.   };
  358.   
  359.   static PyTypeObject BufferType;
  360. ***************
  361. *** 3239,3244 ****
  362. --- 3377,3393 ----
  363.       return RBSlice(self, lo, hi, 1, -1);
  364.   }
  365.   
  366. + static char *BufferAttrs[] = {
  367. +     "name", "number", "vars", "options", "valid",
  368. +     NULL
  369. + };
  370. +     static PyObject *
  371. + BufferDir(PyObject *self)
  372. + {
  373. +     return ObjectDir(self, BufferAttrs);
  374. + }
  375.       static PyObject *
  376.   BufferAttrValid(BufferObject *self, char *name)
  377.   {
  378. ***************
  379. *** 3265,3273 ****
  380.       else if (strcmp(name, "options") == 0)
  381.       return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
  382.               (PyObject *) self);
  383. !     else if (strcmp(name,"__members__") == 0)
  384. !     return Py_BuildValue("[sssss]", "name", "number", "vars", "options",
  385. !         "valid");
  386.       else
  387.       return NULL;
  388.   }
  389. --- 3414,3421 ----
  390.       else if (strcmp(name, "options") == 0)
  391.       return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
  392.               (PyObject *) self);
  393. !     else if (strcmp(name, "__members__") == 0)
  394. !     return ObjectDir(NULL, BufferAttrs);
  395.       else
  396.       return NULL;
  397.   }
  398. ***************
  399. *** 3403,3412 ****
  400.       {"append",        (PyCFunction)BufferAppend,    METH_VARARGS,    "Append data to Vim buffer" },
  401.       {"mark",        (PyCFunction)BufferMark,    METH_VARARGS,    "Return (row,col) representing position of named mark" },
  402.       {"range",        (PyCFunction)BufferRange,    METH_VARARGS,    "Return a range object which represents the part of the given buffer between line numbers s and e" },
  403. ! #if PY_VERSION_HEX >= 0x03000000
  404. !     {"__dir__",        (PyCFunction)BufferDir,    METH_NOARGS,    "List buffer attributes" },
  405. ! #endif
  406. !     { NULL,        NULL,            0,        NULL }
  407.   };
  408.   
  409.   /*
  410. --- 3551,3558 ----
  411.       {"append",        (PyCFunction)BufferAppend,    METH_VARARGS,    "Append data to Vim buffer" },
  412.       {"mark",        (PyCFunction)BufferMark,    METH_VARARGS,    "Return (row,col) representing position of named mark" },
  413.       {"range",        (PyCFunction)BufferRange,    METH_VARARGS,    "Return a range object which represents the part of the given buffer between line numbers s and e" },
  414. !     {"__dir__",        (PyCFunction)BufferDir,    METH_NOARGS,    ""},
  415. !     { NULL,        NULL,            0,        NULL}
  416.   };
  417.   
  418.   /*
  419. ***************
  420. *** 3538,3543 ****
  421. --- 3684,3700 ----
  422.   /* Current items object
  423.    */
  424.   
  425. + static char *CurrentAttrs[] = {
  426. +     "buffer", "window", "line", "range", "tabpage",
  427. +     NULL
  428. + };
  429. +     static PyObject *
  430. + CurrentDir(PyObject *self)
  431. + {
  432. +     return ObjectDir(self, CurrentAttrs);
  433. + }
  434.       static PyObject *
  435.   CurrentGetattr(PyObject *self UNUSED, char *name)
  436.   {
  437. ***************
  438. *** 3551,3564 ****
  439.       return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
  440.       else if (strcmp(name, "range") == 0)
  441.       return RangeNew(curbuf, RangeStart, RangeEnd);
  442. !     else if (strcmp(name,"__members__") == 0)
  443. !     return Py_BuildValue("[sssss]", "buffer", "window", "line", "range",
  444. !         "tabpage");
  445.       else
  446. !     {
  447. !     PyErr_SetString(PyExc_AttributeError, name);
  448.       return NULL;
  449. !     }
  450.   }
  451.   
  452.       static int
  453. --- 3708,3721 ----
  454.       return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
  455.       else if (strcmp(name, "range") == 0)
  456.       return RangeNew(curbuf, RangeStart, RangeEnd);
  457. !     else if (strcmp(name, "__members__") == 0)
  458. !     return ObjectDir(NULL, CurrentAttrs);
  459.       else
  460. ! #if PY_MAJOR_VERSION < 3
  461. !     return Py_FindMethod(WindowMethods, self, name);
  462. ! #else
  463.       return NULL;
  464. ! #endif
  465.   }
  466.   
  467.       static int
  468. ***************
  469. *** 3661,3666 ****
  470. --- 3818,3829 ----
  471.       }
  472.   }
  473.   
  474. + static struct PyMethodDef CurrentMethods[] = {
  475. +     /* name,        function,            calling,    documentation */
  476. +     {"__dir__",        (PyCFunction)CurrentDir,    METH_NOARGS,    ""},
  477. +     { NULL,        NULL,            0,        NULL}
  478. + };
  479.       static void
  480.   init_range_cmd(exarg_T *eap)
  481.   {
  482. ***************
  483. *** 4397,4402 ****
  484. --- 4560,4566 ----
  485.       CurrentType.tp_basicsize = sizeof(CurrentObject);
  486.       CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
  487.       CurrentType.tp_doc = "vim current object";
  488. +     CurrentType.tp_methods = CurrentMethods;
  489.   #if PY_MAJOR_VERSION >= 3
  490.       CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
  491.       CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
  492. *** ../vim-7.3.1046/src/if_python3.c    2013-05-29 22:15:26.000000000 +0200
  493. --- src/if_python3.c    2013-05-29 22:29:26.000000000 +0200
  494. ***************
  495. *** 666,672 ****
  496.       return PyType_GenericAlloc(type,nitems);
  497.   }
  498.   
  499. - static PyObject *BufferDir(PyObject *);
  500.   static PyObject *OutputGetattro(PyObject *, PyObject *);
  501.   static int OutputSetattro(PyObject *, PyObject *, PyObject *);
  502.   static PyObject *BufferGetattro(PyObject *, PyObject *);
  503. --- 666,671 ----
  504. ***************
  505. *** 1094,1107 ****
  506.       return BufferSetattr((BufferObject *)(self), name, val);
  507.   }
  508.   
  509. -     static PyObject *
  510. - BufferDir(PyObject *self UNUSED)
  511. - {
  512. -     return Py_BuildValue("[ssssssss]",
  513. -         "name", "number", "vars", "options", "valid",
  514. -         "append", "mark", "range");
  515. - }
  516.   /******************/
  517.   
  518.       static PyObject *
  519. --- 1093,1098 ----
  520. ***************
  521. *** 1368,1375 ****
  522.       static PyObject *
  523.   CurrentGetattro(PyObject *self, PyObject *nameobj)
  524.   {
  525.       GET_ATTR_STRING(name, nameobj);
  526. !     return CurrentGetattr(self, name);
  527.   }
  528.   
  529.       static int
  530. --- 1359,1369 ----
  531.       static PyObject *
  532.   CurrentGetattro(PyObject *self, PyObject *nameobj)
  533.   {
  534. +     PyObject    *r;
  535.       GET_ATTR_STRING(name, nameobj);
  536. !     if (!(r = CurrentGetattr(self, name)))
  537. !     return PyObject_GenericGetAttr(self, nameobj);
  538. !     return r;
  539.   }
  540.   
  541.       static int
  542. *** ../vim-7.3.1046/src/if_python.c    2013-05-29 22:15:26.000000000 +0200
  543. --- src/if_python.c    2013-05-29 22:29:26.000000000 +0200
  544. ***************
  545. *** 1066,1071 ****
  546. --- 1066,1073 ----
  547.   {
  548.       if (strcmp(name, "softspace") == 0)
  549.       return PyInt_FromLong(((OutputObject *)(self))->softspace);
  550. +     else if (strcmp(name, "__members__") == 0)
  551. +     return ObjectDir(NULL, OutputAttrs);
  552.   
  553.       return Py_FindMethod(OutputMethods, self, name);
  554.   }
  555. ***************
  556. *** 1177,1182 ****
  557. --- 1179,1186 ----
  558.       return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start - 1);
  559.       else if (strcmp(name, "end") == 0)
  560.       return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1);
  561. +     else if (strcmp(name, "__members__") == 0)
  562. +     return ObjectDir(NULL, RangeAttrs);
  563.       else
  564.       return Py_FindMethod(RangeMethods, self, name);
  565.   }
  566. ***************
  567. *** 1396,1401 ****
  568. --- 1400,1407 ----
  569.       return PyInt_FromLong(this->dict->dv_lock);
  570.       else if (strcmp(name, "scope") == 0)
  571.       return PyInt_FromLong(this->dict->dv_scope);
  572. +     else if (strcmp(name, "__members__") == 0)
  573. +     return ObjectDir(NULL, DictionaryAttrs);
  574.   
  575.       return Py_FindMethod(DictionaryMethods, self, name);
  576.   }
  577. ***************
  578. *** 1420,1425 ****
  579. --- 1426,1433 ----
  580.   {
  581.       if (strcmp(name, "locked") == 0)
  582.       return PyInt_FromLong(((ListObject *)(self))->list->lv_lock);
  583. +     else if (strcmp(name, "__members__") == 0)
  584. +     return ObjectDir(NULL, ListAttrs);
  585.   
  586.       return Py_FindMethod(ListMethods, self, name);
  587.   }
  588. ***************
  589. *** 1431,1436 ****
  590. --- 1439,1446 ----
  591.   
  592.       if (strcmp(name, "name") == 0)
  593.       return PyString_FromString((char *)(this->name));
  594. +     else if (strcmp(name, "__members__") == 0)
  595. +     return ObjectDir(NULL, FunctionAttrs);
  596.       else
  597.       return Py_FindMethod(FunctionMethods, self, name);
  598.   }
  599. *** ../vim-7.3.1046/src/testdir/test86.in    2013-05-29 22:15:26.000000000 +0200
  600. --- src/testdir/test86.in    2013-05-29 22:29:26.000000000 +0200
  601. ***************
  602. *** 691,696 ****
  603. --- 691,714 ----
  604.       cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
  605.   EOF
  606.   :"
  607. + :" Test __dir__() method
  608. + py << EOF
  609. + for name, o in (
  610. +         ('current',    vim.current),
  611. +         ('buffer',     vim.current.buffer),
  612. +         ('window',     vim.current.window),
  613. +         ('tabpage',    vim.current.tabpage),
  614. +         ('range',      vim.current.range),
  615. +         ('dictionary', vim.bindeval('{}')),
  616. +         ('list',       vim.bindeval('[]')),
  617. +         ('function',   vim.bindeval('function("tr")')),
  618. +         ('output',     sys.stdout),
  619. +     ):
  620. +     cb.append(name + ':' + ','.join(dir(o)))
  621. + del name
  622. + del o
  623. + EOF
  624. + :"
  625.   :" Test exceptions
  626.   :fun Exe(e)
  627.   :   execute a:e
  628. *** ../vim-7.3.1046/src/testdir/test86.ok    2013-05-29 22:15:26.000000000 +0200
  629. --- src/testdir/test86.ok    2013-05-29 22:29:26.000000000 +0200
  630. ***************
  631. *** 382,387 ****
  632. --- 382,396 ----
  633.   vim.current.range:Range:True
  634.   vim.current.window:Window:True
  635.   vim.current.tabpage:TabPage:True
  636. + current:__dir__,__members__,buffer,line,range,tabpage,window
  637. + buffer:__dir__,__members__,append,mark,name,number,options,range,valid,vars
  638. + window:__dir__,__members__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
  639. + tabpage:__dir__,__members__,number,valid,vars,window,windows
  640. + range:__dir__,__members__,append,end,start
  641. + dictionary:__dir__,__members__,keys,locked,scope
  642. + list:__dir__,__members__,extend,locked
  643. + function:__call__,__dir__,__members__,softspace
  644. + output:__dir__,__members__,flush,softspace,write,writelines
  645.   (<class 'vim.error'>, error('abc',))
  646.   (<class 'vim.error'>, error('def',))
  647.   (<class 'vim.error'>, error('ghi',))
  648. *** ../vim-7.3.1046/src/testdir/test87.in    2013-05-29 22:15:26.000000000 +0200
  649. --- src/testdir/test87.in    2013-05-29 22:29:26.000000000 +0200
  650. ***************
  651. *** 669,674 ****
  652. --- 669,692 ----
  653.       cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
  654.   EOF
  655.   :"
  656. + :" Test __dir__() method
  657. + py3 << EOF
  658. + for name, o in (
  659. +         ('current',    vim.current),
  660. +         ('buffer',     vim.current.buffer),
  661. +         ('window',     vim.current.window),
  662. +         ('tabpage',    vim.current.tabpage),
  663. +         ('range',      vim.current.range),
  664. +         ('dictionary', vim.bindeval('{}')),
  665. +         ('list',       vim.bindeval('[]')),
  666. +         ('function',   vim.bindeval('function("tr")')),
  667. +         ('output',     sys.stdout),
  668. +     ):
  669. +     cb.append(name + ':' + ','.join(dir(o)))
  670. + del name
  671. + del o
  672. + EOF
  673. + :"
  674.   :" Test exceptions
  675.   :fun Exe(e)
  676.   :   execute a:e
  677. *** ../vim-7.3.1046/src/testdir/test87.ok    2013-05-29 22:15:26.000000000 +0200
  678. --- src/testdir/test87.ok    2013-05-29 22:29:26.000000000 +0200
  679. ***************
  680. *** 371,376 ****
  681. --- 371,385 ----
  682.   vim.current.range:Range:True
  683.   vim.current.window:Window:True
  684.   vim.current.tabpage:TabPage:True
  685. + current:__dir__,buffer,line,range,tabpage,window
  686. + buffer:__dir__,append,mark,name,number,options,range,valid,vars
  687. + window:__dir__,buffer,col,cursor,height,number,options,row,tabpage,valid,vars
  688. + tabpage:__dir__,number,valid,vars,window,windows
  689. + range:__dir__,append,end,start
  690. + dictionary:__dir__,keys,locked,scope
  691. + list:__dir__,extend,locked
  692. + function:__call__,__dir__,softspace
  693. + output:__dir__,flush,softspace,write,writelines
  694.   (<class 'vim.error'>, error('abc',))
  695.   (<class 'vim.error'>, error('def',))
  696.   (<class 'vim.error'>, error('ghi',))
  697. *** ../vim-7.3.1046/src/version.c    2013-05-29 22:26:15.000000000 +0200
  698. --- src/version.c    2013-05-29 22:35:24.000000000 +0200
  699. ***************
  700. *** 730,731 ****
  701. --- 730,733 ----
  702.   {   /* Add new patch number below this line */
  703. + /**/
  704. +     1047,
  705.   /**/
  706.  
  707. -- 
  708. hundred-and-one symptoms of being an internet addict:
  709. 22. You've already visited all the links at Yahoo and you're halfway through
  710.     Lycos.
  711.  
  712.  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
  713. ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
  714. \\\  an exciting new programming language -- http://www.Zimbu.org        ///
  715.  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
  716.