Hi,

El dom, 10-08-2003 a las 01:04, Jan Weil escribió:
> I don't like this idea either.
> Especially because it's quite easy to emulate this behaviour in Python 
> (see example attached).
Well, as long as I can write the Python code as I want, I don't care
much about the underlying implementation :-) So I'm OK if I can do what
you suggest (or if I have to do 'from gtk import iñaki_is_on_crack', as
another message suggested).

That said, and inspired by bug 81879 in gnome-python bugzilla, attached
goes a descriptor implementation of the same behavior (hey, we can all
have some fun coding weird stuff ;-)).

This should make the binding of the properties rather elegant, now you
can do help(gtk.Label) and you get a list with the attributes with their
corresponding documentation (in case gtk provides any),
gtk.Label.label.__doc__ works too, of course. This means less confusion
if things don't behave as expected.

dir(gtk.Label) lists the attributes as regular attributes, which it
didn't do in my previous patch.

In three words, completely transparent access.

I would do the 'from gtk import crack' thingie but I have no clue on how
to do that.

Enjoy,
Iñaki
--- ../pygobject.c      Thu Jul 31 15:10:16 2003
+++ pygobject.c Sun Aug 10 20:28:51 2003
@@ -80,6 +80,87 @@
     g_array_append_val(sink_funcs, sf);
 }
 
+static PyObject *
+pygobject_get_prop_descr(PyGObject *self, char *param_name)
+{
+    GParamSpec *pspec;
+    GValue value = { 0, };
+    PyObject *ret;
+
+    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
+                                        param_name);
+    if (!pspec) {
+       PyErr_SetString(PyExc_TypeError,
+                       "the object does not support the given parameter");
+       return NULL;
+    }
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+    g_object_get_property(self->obj, param_name, &value);
+    ret = pyg_value_as_pyobject(&value, TRUE);
+    g_value_unset(&value);
+    return ret;
+}
+
+static int
+pygobject_set_prop_descr(PyGObject *self, PyObject *pvalue, char *param_name)
+{
+    GParamSpec *pspec;
+    GValue value = { 0, };
+
+    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
+                                        param_name);
+    if (!pspec) {
+       PyErr_SetString(PyExc_TypeError,
+                       "the object does not support the given parameter");
+       return -1;
+    }
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+    if (pyg_value_from_pyobject(&value, pvalue) < 0) {
+       PyErr_SetString(PyExc_TypeError,
+                       "could not convert argument to correct param type");
+       return -1;
+    }
+    g_object_set_property(self->obj, param_name, &value);
+    g_value_unset(&value);
+    return 0;
+}
+
+static void
+pygobject_add_class_properties_as_descriptors (GType gtype,
+                                              PyTypeObject *type)
+{
+    GObjectClass *class;
+    GParamSpec **props;
+    guint n_props = 0, i;
+    PyObject *descr;
+    char *name, *prop_name;
+    PyGetSetDef *def;
+
+    class = g_type_class_ref(gtype);
+    props = g_object_class_list_properties(class, &n_props);
+    for (i=0; i<n_props; i++) {
+       if (props[i]->owner_type != gtype)
+           continue;
+
+       /* Python won't make a copy so we need the strdup */
+       prop_name = g_strdup(g_param_spec_get_name(props[i]));
+       name = g_strdup(prop_name);
+       /* Convert '-' to '_' */
+       g_strdelimit(name, "-", '_');
+       def = g_new(struct PyGetSetDef, 1);
+       def->name = name;
+       def->doc = g_strdup(g_param_spec_get_blurb(props[i]));
+       def->closure = prop_name;
+       def->get = (getter)pygobject_get_prop_descr;
+       def->set = (setter)pygobject_set_prop_descr;
+       descr = PyDescr_NewGetSet(type, def);
+       PyDict_SetItemString(type->tp_dict, name, descr);
+       Py_DECREF(descr);
+    }
+    g_free (props);
+    g_type_class_unref (class);
+}
+
 /**
  * pygobject_register_class:
  * @dict: the module dictionary.  A reference to the type will be stored here.
@@ -122,6 +203,7 @@
     type->tp_weaklistoffset = offsetof(PyGObject, weakreflist);
     type->tp_dictoffset = offsetof(PyGObject, inst_dict);
 
+
     if (PyType_Ready(type) < 0) {
        g_warning ("couldn't make the type `%s' ready", type->tp_name);
        return;
@@ -135,6 +217,9 @@
        /* stash a pointer to the python class with the GType */
        Py_INCREF(type);
        g_type_set_qdata(gtype, pygobject_class_key, type);
+
+       /* add the class properties as member descriptors */
+       pygobject_add_class_properties_as_descriptors(gtype, type);
     }
 
     /* set up __doc__ descriptor on type */
@@ -508,52 +593,26 @@
 pygobject_get_property(PyGObject *self, PyObject *args)
 {
     gchar *param_name;
-    GParamSpec *pspec;
-    GValue value = { 0, };
-    PyObject *ret;
 
     if (!PyArg_ParseTuple(args, "s:GObject.get_property", &param_name))
        return NULL;
-    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
-                                        param_name);
-    if (!pspec) {
-       PyErr_SetString(PyExc_TypeError,
-                       "the object does not support the given parameter");
-       return NULL;
-    }
-    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
-    g_object_get_property(self->obj, param_name, &value);
-    ret = pyg_value_as_pyobject(&value, TRUE);
-    g_value_unset(&value);
-    return ret;
+    
+    return pygobject_get_prop_descr(self, param_name);
 }
 
 static PyObject *
 pygobject_set_property(PyGObject *self, PyObject *args)
 {
     gchar *param_name;
-    GParamSpec *pspec;
-    GValue value = { 0, };
     PyObject *pvalue;
 
     if (!PyArg_ParseTuple(args, "sO:GObject.set_property", &param_name,
                          &pvalue))
        return NULL;
-    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
-                                        param_name);
-    if (!pspec) {
-       PyErr_SetString(PyExc_TypeError,
-                       "the object does not support the given parameter");
-       return NULL;
-    }
-    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
-    if (pyg_value_from_pyobject(&value, pvalue) < 0) {
-       PyErr_SetString(PyExc_TypeError,
-                       "could not convert argument to correct param type");
+
+    if (pygobject_set_prop_descr(self, pvalue, param_name))
        return NULL;
-    }
-    g_object_set_property(self->obj, param_name, &value);
-    g_value_unset(&value);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to