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 <mstahl@redhat.com>
Tested-by: Michael Stahl <mstahl@redhat.com>
This commit is contained in:
David Bolen 2013-08-09 23:35:27 -04:00 committed by Michael Stahl
parent 87b5ac652d
commit 1be8e912ba
3 changed files with 45 additions and 24 deletions

View File

@ -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<OUString> 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<OUString> 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 ) );

View File

@ -188,6 +188,8 @@ typedef ::boost::unordered_map
typedef ::boost::unordered_set< PyRef , PyRef::Hash , std::equal_to<PyRef> > ClassSet;
int PyUNO_initType();
PyObject* PyUNO_new(
const com::sun::star::uno::Any & targetInterface,
const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);

View File

@ -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);
}