From 1be8e912ba8a7d1acaf40d5a8597421c104ab39c Mon Sep 17 00:00:00 2001 From: David Bolen Date: Fri, 9 Aug 2013 23:35:27 -0400 Subject: fdo#50470: Restore pyuno object method introspection in Python 3 Switch to __dir__ entry point for introspection as Python 3 dropped support for __members__/__methods__. This is backwards compatible to Python 2.6. Module initialization adjusted to complete type setup (needed for tp_dict) via PyType_Ready. Change-Id: Ie1f7b9dd4279242de89d009eb7acdc8c786dab8f Reviewed-on: https://gerrit.libreoffice.org/5375 Reviewed-by: Michael Stahl Tested-by: Michael Stahl --- pyuno/source/module/pyuno.cxx | 65 +++++++++++++++++++++++------------- pyuno/source/module/pyuno_impl.hxx | 2 ++ pyuno/source/module/pyuno_module.cxx | 2 ++ 3 files changed, 45 insertions(+), 24 deletions(-) (limited to 'pyuno') diff --git a/pyuno/source/module/pyuno.cxx b/pyuno/source/module/pyuno.cxx index 58579ebe3105..7a420a69aa64 100644 --- a/pyuno/source/module/pyuno.cxx +++ b/pyuno/source/module/pyuno.cxx @@ -427,6 +427,32 @@ PyObject *PyUNO_str( PyObject * self ) return PyStr_FromString( buf.getStr()); } +PyObject* PyUNO_dir (PyObject* self) +{ + PyUNO* me = (PyUNO*) self; + + PyObject* member_list = NULL; + Sequence oo_member_list; + + try + { + oo_member_list = me->members->xInvocation->getMemberNames (); + member_list = PyList_New (oo_member_list.getLength ()); + for (int i = 0; i < oo_member_list.getLength (); i++) + { + // setitem steals a reference + PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() ); + } + } + catch( const RuntimeException &e ) + { + raisePyExceptionWithAny( makeAny(e) ); + } + + return member_list; +} + + PyObject* PyUNO_getattr (PyObject* self, char* name) { PyUNO* me; @@ -437,31 +463,10 @@ PyObject* PyUNO_getattr (PyObject* self, char* name) Runtime runtime; me = (PyUNO*) self; - //Handle Python dir () stuff first... - if (strcmp (name, "__members__") == 0) - { - PyObject* member_list; - Sequence oo_member_list; - - oo_member_list = me->members->xInvocation->getMemberNames (); - member_list = PyList_New (oo_member_list.getLength ()); - for (int i = 0; i < oo_member_list.getLength (); i++) - { - // setitem steals a reference - PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() ); - } - return member_list; - } - if (strcmp (name, "__dict__") == 0) { - Py_INCREF (Py_None); - return Py_None; - } - if (strcmp (name, "__methods__") == 0) - { - Py_INCREF (Py_None); - return Py_None; + Py_INCREF (Py_TYPE(me)->tp_dict); + return Py_TYPE(me)->tp_dict; } if (strcmp (name, "__class__") == 0) { @@ -638,6 +643,13 @@ static PyObject* PyUNO_cmp( PyObject *self, PyObject *that, int op ) return result; } +static PyMethodDef PyUNOMethods[] = +{ + {"__dir__", (PyCFunction)PyUNO_dir, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL} +}; + + /* Python 2 has a tp_flags value for rich comparisons. Python 3 does not (on by default) */ #ifdef Py_TPFLAGS_HAVE_RICHCOMPARE #define TP_FLAGS (Py_TPFLAGS_HAVE_RICHCOMPARE) @@ -674,7 +686,7 @@ static PyTypeObject PyUNOType = 0, (getiterfunc)0, (iternextfunc)0, - NULL, + PyUNOMethods, NULL, NULL, NULL, @@ -698,6 +710,11 @@ static PyTypeObject PyUNOType = #endif }; +int PyUNO_initType() +{ + return PyType_Ready(&PyUNOType); +} + PyRef getPyUnoClass() { return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) ); diff --git a/pyuno/source/module/pyuno_impl.hxx b/pyuno/source/module/pyuno_impl.hxx index b114b3c68bbf..1222bf30b333 100644 --- a/pyuno/source/module/pyuno_impl.hxx +++ b/pyuno/source/module/pyuno_impl.hxx @@ -188,6 +188,8 @@ typedef ::boost::unordered_map typedef ::boost::unordered_set< PyRef , PyRef::Hash , std::equal_to > ClassSet; +int PyUNO_initType(); + PyObject* PyUNO_new( const com::sun::star::uno::Any & targetInterface, const com::sun::star::uno::Reference & ssf); diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx index cb8fd95d2543..1e812d1e28b3 100644 --- a/pyuno/source/module/pyuno_module.cxx +++ b/pyuno/source/module/pyuno_module.cxx @@ -867,6 +867,7 @@ extern "C" #if PY_MAJOR_VERSION >= 3 PyObject* PyInit_pyuno() { + PyUNO_initType(); // noop when called already, otherwise needed to allow multiple threads PyEval_InitThreads(); static struct PyModuleDef moduledef = @@ -886,6 +887,7 @@ PyObject* PyInit_pyuno() #else void initpyuno() { + PyUNO_initType(); PyEval_InitThreads(); Py_InitModule ("pyuno", PyUNOModule_methods); } -- cgit