[pygobject] Add type checking to positional Gtk.Box and Gtk.Window ctor arguments



commit 7193f0509a0ed7da7c810daa6733e34a22db3180
Author: Martin Pitt <martinpitt gnome org>
Date:   Tue Nov 5 15:28:12 2013 +0100

    Add type checking to positional Gtk.Box and Gtk.Window ctor arguments
    
    Gtk.Box and Gtk.Window are base classes of a lot of widgets. Avoid confusion
    when trying to create a subclass of them through the GObject constructor with
    positional arguments by at least verifying that their type is right. Otherwise
    you can do things like
    
      chooser = Gtk.FileChooserWidget(Gtk.FileChooserAction.SELECT_FOLDER)
    
    which succeeds, but does not have the desired effect (it sets the "homogenous"
    property of the Gtk.Box superclass instead).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=711487

 gi/overrides/Gtk.py         |    7 +++++++
 tests/test_overrides_gtk.py |   18 ++++++++++++++++++
 tests/test_properties.py    |    9 +++++++++
 3 files changed, 34 insertions(+), 0 deletions(-)
---
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index e774c0c..9f08492 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -330,6 +330,10 @@ __all__.append('ComboBox')
 
 class Box(Gtk.Box):
     def __init__(self, homogeneous=False, spacing=0, **kwds):
+        if not isinstance(homogeneous, bool):
+            raise TypeError('homogeneous argument must be of type bool')
+        if not isinstance(spacing, int):
+            raise TypeError('spacing argument must be of type int')
         super(Box, self).__init__(**kwds)
         self.set_homogeneous(homogeneous)
         self.set_spacing(spacing)
@@ -436,6 +440,9 @@ class Window(Gtk.Window):
         if not initialized:
             raise RuntimeError("Gtk couldn't be initialized")
 
+        if not isinstance(type, Gtk.WindowType):
+            raise TypeError('type argument must be of type Gtk.WindowType')
+
         # type is a construct-only property; if it is already set (e. g. by
         # GtkBuilder), do not try to set it again and just ignore it
         try:
diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py
index fefc9a8..145f0f9 100644
--- a/tests/test_overrides_gtk.py
+++ b/tests/test_overrides_gtk.py
@@ -590,6 +590,24 @@ class TestGtk(unittest.TestCase):
         GLib.timeout_add(100, Gtk.main_quit, 'hello')
         Gtk.main()
 
+    def test_gobject_ctor_positional_args(self):
+        # GObject constructor must only allow keyword args, except for the ones
+        # which have overrides
+
+        # overridden, but no custom constructor
+        self.assertRaises(TypeError, Gtk.Widget, 1)
+        self.assertRaises(TypeError, Gtk.Container, 1)
+
+        # no overrides at all
+        self.assertRaises(TypeError, Gtk.FileChooserWidget,
+                          Gtk.FileChooserAction.SELECT_FOLDER)
+        self.assertRaises(TypeError, Gtk.Assistant, 1)
+
+    def test_gobject_ctor_unknown_property(self):
+        # GObject constructor must refuse unknown properties
+        self.assertRaises(TypeError, Gtk.Widget, unknown_prop=1)
+        self.assertRaises(TypeError, Gtk.Button, unknown_prop='a')
+
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestSignals(unittest.TestCase):
diff --git a/tests/test_properties.py b/tests/test_properties.py
index ef6b867..ec9ddf1 100644
--- a/tests/test_properties.py
+++ b/tests/test_properties.py
@@ -481,6 +481,15 @@ class TestPropertyObject(unittest.TestCase):
         self.assertEqual(normal, "foo")
         self.assertEqual(uint64, 7)
 
+    def test_positional_args(self):
+        # GObject constructor must only allow keyword args
+        self.assertRaises(TypeError, new, PropertyObject, None)
+        self.assertRaises(TypeError, new, PropertyObject, "hello", 2)
+
+    def test_unknown_constructor_property(self):
+        # GObject constructor must refuse unknown properties
+        self.assertRaises(TypeError, new, PropertyObject, unknown_prop=1)
+
 
 class TestProperty(unittest.TestCase):
     def test_simple(self):


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