diff options
author | Simon Feltman <s.feltman@gmail.com> | 2012-03-18 15:59:58 -0700 |
---|---|---|
committer | Martin Pitt <martinpitt@gnome.org> | 2012-04-09 14:44:53 +0200 |
commit | 0fd900d351c8d7d57dc6a1b049ee05f342f6ab1d (patch) | |
tree | 5cd598ed77ec1e1569c527c7e141f0b2a1780998 /tests/test_gobject.py | |
parent | c0922589964c1d8bffe5a56d2f56df96eedfac10 (diff) | |
download | pygobject-0fd900d351c8d7d57dc6a1b049ee05f342f6ab1d.tar.gz |
Add context management to freeze_notify() and handler_block().
These methods now return a context manager object. Within the __exit__ method
thaw_notify() and handler_unblock() are called respectively. This allows
statements like the following:
with obj.freeze_notify():
obj.props.width = 100
obj.props.height = 100
obj.props.opacity = 0.5
This does not affect standard usage of these methods.
https://bugzilla.gnome.org/show_bug.cgi?id=672324
Signed-off-by: Martin Pitt <martinpitt@gnome.org>
Diffstat (limited to 'tests/test_gobject.py')
-rw-r--r-- | tests/test_gobject.py | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/tests/test_gobject.py b/tests/test_gobject.py index 80725b34..ecd67cf2 100644 --- a/tests/test_gobject.py +++ b/tests/test_gobject.py @@ -190,3 +190,161 @@ class TestPythonReferenceCounting(unittest.TestCase): def testNewSubclassInstanceHasTwoRefsUsingGObjectNew(self): obj = GObject.new(A) self.assertEquals(sys.getrefcount(obj), 2) + + +class TestContextManagers(unittest.TestCase): + class ContextTestObject(GObject.GObject): + prop = GObject.Property(default=0, type=int) + + def on_prop_set(self, obj, prop): + # Handler which tracks property changed notifications. + self.tracking.append(obj.get_property(prop.name)) + + def setUp(self): + self.tracking = [] + self.obj = self.ContextTestObject() + self.handler = self.obj.connect('notify::prop', self.on_prop_set) + + def testFreezeNotifyContext(self): + # Verify prop tracking list + self.assertEqual(self.tracking, []) + self.obj.props.prop = 1 + self.assertEqual(self.tracking, [1]) + self.obj.props.prop = 2 + self.assertEqual(self.tracking, [1, 2]) + self.assertEqual(self.obj.__grefcount__, 1) + + # Using the context manager the tracking list should not be affected + # and the GObject reference count should go up. + with self.obj.freeze_notify(): + self.assertEqual(self.obj.__grefcount__, 2) + self.obj.props.prop = 3 + self.assertEqual(self.obj.props.prop, 3) + self.assertEqual(self.tracking, [1, 2]) + + # After the context manager, the prop should have been modified, + # the tracking list will be modified, and the GObject ref + # count goes back down. + self.assertEqual(self.obj.props.prop, 3) + self.assertEqual(self.tracking, [1, 2, 3]) + self.assertEqual(self.obj.__grefcount__, 1) + + def testHandlerBlockContext(self): + # Verify prop tracking list + self.assertEqual(self.tracking, []) + self.obj.props.prop = 1 + self.assertEqual(self.tracking, [1]) + self.obj.props.prop = 2 + self.assertEqual(self.tracking, [1, 2]) + self.assertEqual(self.obj.__grefcount__, 1) + + # Using the context manager the tracking list should not be affected + # and the GObject reference count should go up. + with self.obj.handler_block(self.handler): + self.assertEqual(self.obj.__grefcount__, 2) + self.obj.props.prop = 3 + self.assertEqual(self.obj.props.prop, 3) + self.assertEqual(self.tracking, [1, 2]) + + # After the context manager, the prop should have been modified + # the tracking list should have stayed the same and the GObject ref + # count goes back down. + self.assertEqual(self.obj.props.prop, 3) + self.assertEqual(self.tracking, [1, 2]) + self.assertEqual(self.obj.__grefcount__, 1) + + def testFreezeNotifyContextNested(self): + self.assertEqual(self.tracking, []) + with self.obj.freeze_notify(): + self.obj.props.prop = 1 + self.assertEqual(self.tracking, []) + + with self.obj.freeze_notify(): + self.obj.props.prop = 2 + self.assertEqual(self.tracking, []) + + with self.obj.freeze_notify(): + self.obj.props.prop = 3 + self.assertEqual(self.tracking, []) + self.assertEqual(self.tracking, []) + self.assertEqual(self.tracking, []) + + # Finally after last context, the notifications should have collapsed + # and the last one sent. + self.assertEqual(self.tracking, [3]) + + def testHandlerBlockContextNested(self): + self.assertEqual(self.tracking, []) + with self.obj.handler_block(self.handler): + self.obj.props.prop = 1 + self.assertEqual(self.tracking, []) + + with self.obj.handler_block(self.handler): + self.obj.props.prop = 2 + self.assertEqual(self.tracking, []) + + with self.obj.handler_block(self.handler): + self.obj.props.prop = 3 + self.assertEqual(self.tracking, []) + self.assertEqual(self.tracking, []) + self.assertEqual(self.tracking, []) + + # Finally after last context, the notifications should have collapsed + # and the last one sent. + self.assertEqual(self.obj.props.prop, 3) + self.assertEqual(self.tracking, []) + + def testFreezeNotifyNormalUsageRefCounts(self): + # Ensure ref counts without using methods as context managers + # maintain the same count. + self.assertEqual(self.obj.__grefcount__, 1) + self.obj.freeze_notify() + self.assertEqual(self.obj.__grefcount__, 1) + self.obj.thaw_notify() + self.assertEqual(self.obj.__grefcount__, 1) + + def testHandlerBlockNormalUsageRefCounts(self): + self.assertEqual(self.obj.__grefcount__, 1) + self.obj.handler_block(self.handler) + self.assertEqual(self.obj.__grefcount__, 1) + self.obj.handler_unblock(self.handler) + self.assertEqual(self.obj.__grefcount__, 1) + + def testFreezeNotifyContextError(self): + # Test an exception occurring within a freeze context exits the context + try: + with self.obj.freeze_notify(): + self.obj.props.prop = 1 + self.assertEqual(self.tracking, []) + raise ValueError('Simulation') + except ValueError: + pass + + # Verify the property set within the context called notify. + self.assertEqual(self.obj.props.prop, 1) + self.assertEqual(self.tracking, [1]) + + # Verify we are still not in a frozen context. + self.obj.props.prop = 2 + self.assertEqual(self.tracking, [1, 2]) + + def testHandlerBlockContextError(self): + # Test an exception occurring within a handler block exits the context + try: + with self.obj.handler_block(self.handler): + self.obj.props.prop = 1 + self.assertEqual(self.tracking, []) + raise ValueError('Simulation') + except ValueError: + pass + + # Verify the property set within the context didn't call notify. + self.assertEqual(self.obj.props.prop, 1) + self.assertEqual(self.tracking, []) + + # Verify we are still not in a handler block context. + self.obj.props.prop = 2 + self.assertEqual(self.tracking, [2]) + +if __name__ == '__main__': + unittest.main() |