import sys
import gc
import weakref
import unittest

from gi.repository import Gtk

UI = """
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkButton" id="button">
    <property name="label" translatable="yes">button</property>
    <property name="visible">True</property>
    <property name="can_focus">True</property>
    <property name="receives_default">True</property>
    <signal name="clicked" handler="button_clicked_cb" swapped="no"/>
  </object>
</interface>
"""


def callback(*args):
    pass


class TestBuilder(unittest.TestCase):
    def test_connect_signals_callback_ref_count(self):
        callbacks_lookup = {"button_clicked_cb": callback}

        lookup_ref_count = sys.getrefcount(callbacks_lookup)
        callback_ref_count = sys.getrefcount(callback)

        ui = Gtk.Builder()
        ui.add_from_string(UI)
        ui.connect_signals(callbacks_lookup)
        button = ui.get_object("button")

        # The callback will have an increased ref count due the signal binding.
        self.assertEqual(sys.getrefcount(callback),
                         callback_ref_count + 1)
        # The lookup should be back at the same ref count we started.
        self.assertEqual(sys.getrefcount(callbacks_lookup),
                         lookup_ref_count)

        button_ref = weakref.ref(button)
        ui_ref = weakref.ref(ui)

        button.destroy()  # Unclear why this is needed.
        button = None
        ui = None
        gc.collect()

        # Verify the weak references to button and ui are dead.
        self.assertEqual(button_ref(), None)
        self.assertEqual(ui_ref(), None)

        # The callback should be back at the same ref count we started.
        self.assertEqual(sys.getrefcount(callback),
                         callback_ref_count)



if __name__ == '__main__':
    unittest.main()
