[pygobject] Add dir method to GObject props accessor



commit a2fa531b4dee73c193cac92fa3e870808688b5d7
Author: Simon Feltman <sfeltman src gnome org>
Date:   Mon Oct 14 20:38:13 2013 -0700

    Add dir method to GObject props accessor
    
    Remove special case __members__ attribute from the props accessor
    objects getattr method. This has been deprecated since Python 2.3 and
    removed in Python 3. Replace this with a __dir__ method making use of the
    old members list building code. Additionally fix error where the
    GObjectClass was being unref'd too many times when using dir(Object.props),
    causing a GLib critical.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705754

 gi/_gobject/pygobject.c |   29 +++++++++++++++++++++--------
 tests/test_gi.py        |   14 ++++++++++++++
 2 files changed, 35 insertions(+), 8 deletions(-)
---
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index c107a17..f78b7f5 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -241,14 +241,13 @@ build_parameter_list(GObjectClass *class)
        g_free(name);
     }
 
-    g_type_class_unref(class);
-
     if (props)
         g_free(props);
     
     return props_list;
 }
 
+
 static PyObject*
 PyGProps_getattro(PyGProps *self, PyObject *attr)
 {
@@ -265,12 +264,6 @@ PyGProps_getattro(PyGProps *self, PyObject *attr)
     }
 
     class = g_type_class_ref(self->gtype);
-    
-    if (!strcmp(attr_name, "__members__")) {
-        ret = build_parameter_list(class);
-        g_type_class_unref(class);
-       return ret;
-    }
 
     /* g_object_class_find_property recurses through the class hierarchy,
      * so the resulting pspec tells us the owner_type that owns the property
@@ -440,6 +433,25 @@ pygobject_props_get_iter(PyGProps *self)
     return (PyObject *) iter;
 }
 
+static PyObject*
+pygobject_props_dir(PyGProps *self)
+{
+    PyObject *ret;
+    GObjectClass *class;
+
+    class = g_type_class_ref (self->gtype);
+    ret = build_parameter_list (class);
+    g_type_class_unref (class);
+
+    return ret;
+}
+
+static PyMethodDef pygobject_props_methods[] = {
+    { "__dir__", (PyCFunction)pygobject_props_dir, METH_NOARGS},
+    { NULL, NULL, 0}
+};
+
+
 static Py_ssize_t
 PyGProps_length(PyGProps *self)
 {
@@ -2413,6 +2425,7 @@ pygobject_object_register_types(PyObject *d)
        "Python attributes.";
     PyGProps_Type.tp_traverse = (traverseproc)pygobject_props_traverse;
     PyGProps_Type.tp_iter = (getiterfunc)pygobject_props_get_iter;
+    PyGProps_Type.tp_methods = pygobject_props_methods;
     if (PyType_Ready(&PyGProps_Type) < 0)
         return;
 
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 4f66c23..43c226e 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -2893,6 +2893,20 @@ class TestPropertiesObject(unittest.TestCase):
         self.assertEqual(42, obj.props.some_int)
         self.assertEqual(54, obj.props.some_uchar)
 
+    def test_props_accessor_dir(self):
+        # Test class
+        props = dir(GIMarshallingTests.PropertiesObject.props)
+        self.assertTrue('some_float' in props)
+        self.assertTrue('some_double' in props)
+        self.assertTrue('some_variant' in props)
+
+        # Test instance
+        obj = GIMarshallingTests.PropertiesObject()
+        props = dir(obj.props)
+        self.assertTrue('some_float' in props)
+        self.assertTrue('some_double' in props)
+        self.assertTrue('some_variant' in props)
+
 
 class TestKeywords(unittest.TestCase):
     def test_method(self):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]