From a910b2003c7e96beb589af32317ad9fdf1eef5eb Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Wed, 23 Jan 2002 13:55:56 +0000 Subject: fill in __doc__ descriptor 2002-01-23 James Henstridge * pygtype.c (object_doc_descr_get): fill in __doc__ descriptor * gobjectmodule.c (initgobject): add __doc__ descriptor to GObject and GInterface. Add __gdoc__ as a synonym because type.__doc__ masks our descriptor sometimes :( * pygtype.c (object_doc_descr_get): skeleton of the __doc__ descriptor. (PyGObjectDoc_Type): type definition. (pyg_object_descr_doc_get): function to create and return the __doc__ descriptor (we only need one for all classes). --- ChangeLog | 11 +++ gobject/gobjectmodule.c | 8 ++ gobject/pygobject-private.h | 2 + gobject/pygtype.c | 191 +++++++++++++++++++++++++++++++++++++++++++- gobjectmodule.c | 8 ++ pygobject-private.h | 2 + pygtype.c | 191 +++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 411 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e31b74b2..19a79052 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-01-23 James Henstridge + + * gobjectmodule.c (initgobject): add __doc__ descriptor to GObject + and GInterface. + + * pygtype.c (object_doc_descr_get): skeleton of the __doc__ + descriptor. + (PyGObjectDoc_Type): type definition. + (pyg_object_descr_doc_get): function to create and return the + __doc__ descriptor (we only need one for all classes). + 2002-01-22 James Henstridge * pygobject.c: move GObject wrapper stuff here. diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 1bb47de9..d2f39477 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -1353,6 +1353,10 @@ initgobject(void) pygobject_register_class(d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); + PyDict_SetItemString(PyGObject_Type.tp_dict, "__doc__", + pyg_object_descr_doc_get()); + PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__", + pyg_object_descr_doc_get()); PyGInterface_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGInterface_Type)) @@ -1361,6 +1365,10 @@ initgobject(void) PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_INTERFACE)); Py_DECREF(o); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__", + pyg_object_descr_doc_get()); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__", + pyg_object_descr_doc_get()); PyGBoxed_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGBoxed_Type)) diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h index e556c64c..6390fc6c 100644 --- a/gobject/pygobject-private.h +++ b/gobject/pygobject-private.h @@ -45,6 +45,8 @@ PyObject *pyg_value_as_pyobject(const GValue *value); GClosure *pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data); GClosure *pyg_signal_class_closure_get(void); +PyObject *pyg_object_descr_doc_get(void); + /* from pygobject.h */ extern PyTypeObject PyGObject_Type; diff --git a/gobject/pygtype.c b/gobject/pygtype.c index fc2d15f7..33985fd9 100644 --- a/gobject/pygtype.c +++ b/gobject/pygtype.c @@ -29,7 +29,7 @@ pyg_type_wrapper_repr(PyGTypeWrapper *self) char buf[80]; const gchar *name = g_type_name(self->type); - g_snprintf(buf, sizeof(buf), "", + g_snprintf(buf, sizeof(buf), "", name?name:"invalid", self->type); return PyString_FromString(buf); } @@ -761,3 +761,192 @@ pyg_signal_class_closure_get(void) return closure; } +/* ----- __doc__ descriptor for GObject and GInterface ----- */ + +static void +object_doc_dealloc(PyObject *self) +{ + PyObject_FREE(self); +} + +/* append information about signals of a particular gtype */ +static void +add_signal_docs(GType gtype, GString *string) +{ + GTypeClass *class; + guint *signal_ids, n_ids = 0, i; + + class = g_type_class_ref(gtype); + signal_ids = g_signal_list_ids(gtype, &n_ids); + + if (n_ids > 0) { + g_string_append(string, "Signals from "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, ":\n"); + + for (i = 0; i < n_ids; i++) { + GSignalQuery query; + guint j; + + g_signal_query(signal_ids[i], &query); + + g_string_append(string, " "); + g_string_append(string, query.signal_name); + g_string_append(string, " ("); + for (j = 0; j < query.n_params; j++) { + g_string_append(string, g_type_name(query.param_types[j])); + if (j != query.n_params - 1) + g_string_append(string, ", "); + } + g_string_append(string, ")"); + if (query.return_type && query.return_type != G_TYPE_NONE) { + g_string_append(string, " -> "); + g_string_append(string, g_type_name(query.return_type)); + } + g_string_append(string, "\n"); + } + g_free(signal_ids); + g_string_append(string, "\n"); + } + g_type_class_unref(class); +} + +static void +add_property_docs(GType gtype, GString *string) +{ + GObjectClass *class; + GParamSpec **props; + guint *n_props = 0, i; + + class = g_type_class_ref(gtype); + props = g_object_class_list_properties(class, &n_props); + + if (n_props > 0) { + g_string_append(string, "Properties from "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, ":\n"); + + for (i = 0; i < n_props; i++) { + g_string_append(string, " "); + g_string_append(string, g_param_spec_get_name(props[i])); + g_string_append(string, " -> "); + g_string_append(string, g_type_name(props[i]->value_type)); + g_string_append(string, ": "); + g_string_append(string, g_param_spec_get_nick(props[i])); + g_string_append(string, "\n "); + g_string_append(string, g_param_spec_get_blurb(props[i])); + g_string_append(string, "\n"); + } + g_free(props); + g_string_append(string, "\n"); + } + g_type_class_unref(class); +} + +static PyObject * +object_doc_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + GType gtype = 0; + GString *string; + PyObject *pystring; + + if (obj && pygobject_check(obj, &PyGObject_Type)) { + gtype = G_OBJECT_TYPE(pygobject_get(obj)); + if (!gtype) + PyErr_SetString(PyExc_RuntimeError, "could not get object type"); + } else { + gtype = pyg_type_from_object(type); + } + if (!gtype) + return NULL; + + string = g_string_new_len(NULL, 512); + + if (g_type_is_a(gtype, G_TYPE_INTERFACE)) + g_string_append(string, "Interface "); + else if (g_type_is_a(gtype, G_TYPE_OBJECT)) + g_string_append(string, "Object "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, "\n\n"); + + if (g_type_is_a(gtype, G_TYPE_OBJECT)) { + GType parent = G_TYPE_OBJECT; + + while (parent) { + GType *interfaces; + guint n_interfaces, i; + + add_signal_docs(parent, string); + + /* add docs for implemented interfaces */ + interfaces = g_type_interfaces(parent, &n_interfaces); + for (i = 0; i < n_interfaces; i++) + add_signal_docs(interfaces[i], string); + g_free(interfaces); + + parent = g_type_next_base(gtype, parent); + } + parent = G_TYPE_OBJECT; + while (parent) { + add_property_docs(parent, string); + parent = g_type_next_base(gtype, parent); + } + } else if (g_type_is_a(gtype, G_TYPE_OBJECT)) { + add_signal_docs(gtype, string); + } + + pystring = PyString_FromStringAndSize(string->str, string->len); + g_string_free(string, TRUE); + return pystring; +} + +static PyTypeObject PyGObjectDoc_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "gobject.GObject__doc__", + sizeof(PyObject), + 0, + (destructor)object_doc_dealloc, + (printfunc)0, + (getattrfunc)0, + (setattrfunc)0, + (cmpfunc)0, + (reprfunc)0, + 0, + 0, + 0, + (hashfunc)0, + (ternaryfunc)0, + (reprfunc)0, + (getattrofunc)0, + (setattrofunc)0, + 0, + Py_TPFLAGS_DEFAULT, + NULL, + (traverseproc)0, + (inquiry)0, + (richcmpfunc)0, + 0, + (getiterfunc)0, + (iternextfunc)0, + 0, + 0, + 0, + (PyTypeObject *)0, + (PyObject *)0, + (descrgetfunc)object_doc_descr_get, + (descrsetfunc)0 +}; + +PyObject * +pyg_object_descr_doc_get(void) +{ + static PyObject *doc_descr = NULL; + + if (!doc_descr) { + doc_descr = PyObject_NEW(PyObject, &PyGObjectDoc_Type); + if (doc_descr == NULL) + return NULL; + } + return doc_descr; +} diff --git a/gobjectmodule.c b/gobjectmodule.c index 1bb47de9..d2f39477 100644 --- a/gobjectmodule.c +++ b/gobjectmodule.c @@ -1353,6 +1353,10 @@ initgobject(void) pygobject_register_class(d, "GObject", G_TYPE_OBJECT, &PyGObject_Type, NULL); + PyDict_SetItemString(PyGObject_Type.tp_dict, "__doc__", + pyg_object_descr_doc_get()); + PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__", + pyg_object_descr_doc_get()); PyGInterface_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGInterface_Type)) @@ -1361,6 +1365,10 @@ initgobject(void) PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gtype__", o=pyg_type_wrapper_new(G_TYPE_INTERFACE)); Py_DECREF(o); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__doc__", + pyg_object_descr_doc_get()); + PyDict_SetItemString(PyGInterface_Type.tp_dict, "__gdoc__", + pyg_object_descr_doc_get()); PyGBoxed_Type.ob_type = &PyType_Type; if (PyType_Ready(&PyGBoxed_Type)) diff --git a/pygobject-private.h b/pygobject-private.h index e556c64c..6390fc6c 100644 --- a/pygobject-private.h +++ b/pygobject-private.h @@ -45,6 +45,8 @@ PyObject *pyg_value_as_pyobject(const GValue *value); GClosure *pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data); GClosure *pyg_signal_class_closure_get(void); +PyObject *pyg_object_descr_doc_get(void); + /* from pygobject.h */ extern PyTypeObject PyGObject_Type; diff --git a/pygtype.c b/pygtype.c index fc2d15f7..33985fd9 100644 --- a/pygtype.c +++ b/pygtype.c @@ -29,7 +29,7 @@ pyg_type_wrapper_repr(PyGTypeWrapper *self) char buf[80]; const gchar *name = g_type_name(self->type); - g_snprintf(buf, sizeof(buf), "", + g_snprintf(buf, sizeof(buf), "", name?name:"invalid", self->type); return PyString_FromString(buf); } @@ -761,3 +761,192 @@ pyg_signal_class_closure_get(void) return closure; } +/* ----- __doc__ descriptor for GObject and GInterface ----- */ + +static void +object_doc_dealloc(PyObject *self) +{ + PyObject_FREE(self); +} + +/* append information about signals of a particular gtype */ +static void +add_signal_docs(GType gtype, GString *string) +{ + GTypeClass *class; + guint *signal_ids, n_ids = 0, i; + + class = g_type_class_ref(gtype); + signal_ids = g_signal_list_ids(gtype, &n_ids); + + if (n_ids > 0) { + g_string_append(string, "Signals from "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, ":\n"); + + for (i = 0; i < n_ids; i++) { + GSignalQuery query; + guint j; + + g_signal_query(signal_ids[i], &query); + + g_string_append(string, " "); + g_string_append(string, query.signal_name); + g_string_append(string, " ("); + for (j = 0; j < query.n_params; j++) { + g_string_append(string, g_type_name(query.param_types[j])); + if (j != query.n_params - 1) + g_string_append(string, ", "); + } + g_string_append(string, ")"); + if (query.return_type && query.return_type != G_TYPE_NONE) { + g_string_append(string, " -> "); + g_string_append(string, g_type_name(query.return_type)); + } + g_string_append(string, "\n"); + } + g_free(signal_ids); + g_string_append(string, "\n"); + } + g_type_class_unref(class); +} + +static void +add_property_docs(GType gtype, GString *string) +{ + GObjectClass *class; + GParamSpec **props; + guint *n_props = 0, i; + + class = g_type_class_ref(gtype); + props = g_object_class_list_properties(class, &n_props); + + if (n_props > 0) { + g_string_append(string, "Properties from "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, ":\n"); + + for (i = 0; i < n_props; i++) { + g_string_append(string, " "); + g_string_append(string, g_param_spec_get_name(props[i])); + g_string_append(string, " -> "); + g_string_append(string, g_type_name(props[i]->value_type)); + g_string_append(string, ": "); + g_string_append(string, g_param_spec_get_nick(props[i])); + g_string_append(string, "\n "); + g_string_append(string, g_param_spec_get_blurb(props[i])); + g_string_append(string, "\n"); + } + g_free(props); + g_string_append(string, "\n"); + } + g_type_class_unref(class); +} + +static PyObject * +object_doc_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + GType gtype = 0; + GString *string; + PyObject *pystring; + + if (obj && pygobject_check(obj, &PyGObject_Type)) { + gtype = G_OBJECT_TYPE(pygobject_get(obj)); + if (!gtype) + PyErr_SetString(PyExc_RuntimeError, "could not get object type"); + } else { + gtype = pyg_type_from_object(type); + } + if (!gtype) + return NULL; + + string = g_string_new_len(NULL, 512); + + if (g_type_is_a(gtype, G_TYPE_INTERFACE)) + g_string_append(string, "Interface "); + else if (g_type_is_a(gtype, G_TYPE_OBJECT)) + g_string_append(string, "Object "); + g_string_append(string, g_type_name(gtype)); + g_string_append(string, "\n\n"); + + if (g_type_is_a(gtype, G_TYPE_OBJECT)) { + GType parent = G_TYPE_OBJECT; + + while (parent) { + GType *interfaces; + guint n_interfaces, i; + + add_signal_docs(parent, string); + + /* add docs for implemented interfaces */ + interfaces = g_type_interfaces(parent, &n_interfaces); + for (i = 0; i < n_interfaces; i++) + add_signal_docs(interfaces[i], string); + g_free(interfaces); + + parent = g_type_next_base(gtype, parent); + } + parent = G_TYPE_OBJECT; + while (parent) { + add_property_docs(parent, string); + parent = g_type_next_base(gtype, parent); + } + } else if (g_type_is_a(gtype, G_TYPE_OBJECT)) { + add_signal_docs(gtype, string); + } + + pystring = PyString_FromStringAndSize(string->str, string->len); + g_string_free(string, TRUE); + return pystring; +} + +static PyTypeObject PyGObjectDoc_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "gobject.GObject__doc__", + sizeof(PyObject), + 0, + (destructor)object_doc_dealloc, + (printfunc)0, + (getattrfunc)0, + (setattrfunc)0, + (cmpfunc)0, + (reprfunc)0, + 0, + 0, + 0, + (hashfunc)0, + (ternaryfunc)0, + (reprfunc)0, + (getattrofunc)0, + (setattrofunc)0, + 0, + Py_TPFLAGS_DEFAULT, + NULL, + (traverseproc)0, + (inquiry)0, + (richcmpfunc)0, + 0, + (getiterfunc)0, + (iternextfunc)0, + 0, + 0, + 0, + (PyTypeObject *)0, + (PyObject *)0, + (descrgetfunc)object_doc_descr_get, + (descrsetfunc)0 +}; + +PyObject * +pyg_object_descr_doc_get(void) +{ + static PyObject *doc_descr = NULL; + + if (!doc_descr) { + doc_descr = PyObject_NEW(PyObject, &PyGObjectDoc_Type); + if (doc_descr == NULL) + return NULL; + } + return doc_descr; +} -- cgit v1.2.1