[pygobject] Fix setting pointer fields/arguments to NULL using None.



commit 21b1d17d2ada2edf4063a4262b3436c279da3dc2
Author: Simon Feltman <s feltman gmail com>
Date:   Sat Sep 1 03:40:31 2012 -0700

    Fix setting pointer fields/arguments to NULL using None.
    
    Setting gi pointers will set them to the address of the python object.
    This is good except in the case of None which should be used to NULL
    the pointer out as a special case.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=683150

 gi/pygi-argument.c      |    8 +++++++-
 tests/test_overrides.py |   41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index b7cab1a..3527002 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -867,7 +867,13 @@ _pygi_argument_from_object (PyObject   *object,
     switch (type_tag) {
         case GI_TYPE_TAG_VOID:
             g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
-            arg.v_pointer = object;
+            if (object == Py_None) {
+                Py_DECREF(Py_None);
+                arg.v_pointer = NULL;
+            } else {
+                /* This will leak a reference to the python object. */
+                arg.v_pointer = object;
+            }
             break;
         case GI_TYPE_TAG_BOOLEAN:
         {
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index f6fcf5a..a0defce 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -2,6 +2,8 @@
 # vim: tabstop=4 shiftwidth=4 expandtab
 
 import unittest
+import ctypes
+import sys
 
 from compathelper import _long, _unicode, _bytes
 
@@ -620,6 +622,19 @@ class TestGdk(unittest.TestCase):
         self.assertRaises(ValueError, Gdk.Cursor, 1, 2, 3)
 
 
+class RawTreeIter(ctypes.Structure):
+    """Class used for testing Gtk.TreeIter raw data."""
+    _fields_ = [('stamp', ctypes.c_int),
+                ('user_data', ctypes.c_void_p),
+                ('user_data2', ctypes.c_void_p),
+                ('user_data3', ctypes.c_void_p)]
+
+    @classmethod
+    def from_iter(cls, iter):
+        offset = sys.getsizeof(object())  # size of PyObject_HEAD
+        return ctypes.POINTER(cls).from_address(id(iter) + offset)
+
+
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestGtk(unittest.TestCase):
 
@@ -1748,6 +1763,32 @@ class TestGtk(unittest.TestCase):
         self.assertEqual(m, store)
         self.assertEqual(store.get_path(s), firstpath)
 
+    def test_tree_iter_user_data_int(self):
+        pyiter = Gtk.TreeIter()
+        rawiter = RawTreeIter.from_iter(pyiter)
+
+        initial_ref_count = sys.getrefcount(1)
+        pyiter.user_data = 1
+
+        # verify setting int value increases refcount of the "1" object
+        self.assertEqual(sys.getrefcount(1), initial_ref_count + 1)
+        # verify the address of the '1' object is what user_data is actually set to.
+        self.assertEqual(id(1), rawiter.contents.user_data)
+
+    def test_tree_iter_user_data_null(self):
+        pyiter = Gtk.TreeIter()
+        rawiter = RawTreeIter.from_iter(pyiter)
+
+        self.assertEqual(pyiter.user_data, None)
+        self.assertEqual(rawiter.contents.user_data, None)
+
+        # Setting user_data to None should not increase None's ref count.
+        # and the raw iters user_data should also come back as None/NULL.
+        initial_ref_count = sys.getrefcount(None)
+        pyiter.user_data = None
+        self.assertEqual(sys.getrefcount(None), initial_ref_count)
+        self.assertEqual(rawiter.contents.user_data, None)
+
     def test_text_buffer(self):
         self.assertEqual(Gtk.TextBuffer, overrides.Gtk.TextBuffer)
         buffer = Gtk.TextBuffer()



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