tests: don't test for specific device labels
[pygobject.git] / tests / test_gobject.py
blobbef3e9b56ac62ceeff253f38e1b0333005ce5dd0
1 # -*- Mode: Python -*-
3 from __future__ import absolute_import
5 import sys
6 import gc
7 import unittest
8 import warnings
10 import pytest
12 from gi.repository import GObject, GLib, Gio
13 from gi import PyGIDeprecationWarning
14 from gi.module import get_introspection_module
15 from gi import _gi
17 import testhelper
20 class TestGObjectAPI(unittest.TestCase):
22 def test_call_method_uninitialized_instance(self):
23 obj = GObject.Object.__new__(GObject.Object)
24 with self.assertRaisesRegex(RuntimeError, '.*is not initialized'):
25 obj.notify("foo")
27 def test_gobject_inheritance(self):
28 # GObject.Object is a class hierarchy as follows:
29 # overrides.Object -> introspection.Object -> static.GObject
30 GIObjectModule = get_introspection_module('GObject')
31 self.assertTrue(issubclass(GObject.Object, GIObjectModule.Object))
32 self.assertTrue(issubclass(GIObjectModule.Object, _gi.GObject))
34 self.assertEqual(_gi.GObject.__gtype__, GObject.TYPE_OBJECT)
35 self.assertEqual(GIObjectModule.Object.__gtype__, GObject.TYPE_OBJECT)
36 self.assertEqual(GObject.Object.__gtype__, GObject.TYPE_OBJECT)
38 # The pytype wrapper should hold the outer most Object class from overrides.
39 self.assertEqual(GObject.TYPE_OBJECT.pytype, GObject.Object)
41 def test_gobject_unsupported_overrides(self):
42 obj = GObject.Object()
44 with self.assertRaisesRegex(RuntimeError, 'Data access methods are unsupported.*'):
45 obj.get_data()
47 with self.assertRaisesRegex(RuntimeError, 'This method is currently unsupported.*'):
48 obj.force_floating()
50 def test_compat_api(self):
51 with warnings.catch_warnings(record=True) as w:
52 warnings.simplefilter('always')
53 # GObject formerly exposed a lot of GLib's functions
54 self.assertEqual(GObject.markup_escape_text('foo'), 'foo')
56 ml = GObject.MainLoop()
57 self.assertFalse(ml.is_running())
59 context = GObject.main_context_default()
60 self.assertTrue(context.pending() in [False, True])
62 context = GObject.MainContext()
63 self.assertFalse(context.pending())
65 self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
66 self.assertTrue('GLib.markup_escape_text' in str(w[0]), str(w[0]))
68 self.assertLess(GObject.PRIORITY_HIGH, GObject.PRIORITY_DEFAULT)
70 def test_min_max_int(self):
71 with warnings.catch_warnings():
72 warnings.simplefilter('ignore', PyGIDeprecationWarning)
74 self.assertEqual(GObject.G_MAXINT16, 2 ** 15 - 1)
75 self.assertEqual(GObject.G_MININT16, -2 ** 15)
76 self.assertEqual(GObject.G_MAXUINT16, 2 ** 16 - 1)
78 self.assertEqual(GObject.G_MAXINT32, 2 ** 31 - 1)
79 self.assertEqual(GObject.G_MININT32, -2 ** 31)
80 self.assertEqual(GObject.G_MAXUINT32, 2 ** 32 - 1)
82 self.assertEqual(GObject.G_MAXINT64, 2 ** 63 - 1)
83 self.assertEqual(GObject.G_MININT64, -2 ** 63)
84 self.assertEqual(GObject.G_MAXUINT64, 2 ** 64 - 1)
87 class TestReferenceCounting(unittest.TestCase):
88 def test_regular_object(self):
89 obj = GObject.GObject()
90 self.assertEqual(obj.__grefcount__, 1)
92 obj = GObject.new(GObject.GObject)
93 self.assertEqual(obj.__grefcount__, 1)
95 def test_floating(self):
96 obj = testhelper.Floating()
97 self.assertEqual(obj.__grefcount__, 1)
99 obj = GObject.new(testhelper.Floating)
100 self.assertEqual(obj.__grefcount__, 1)
102 def test_owned_by_library(self):
103 # Upon creation, the refcount of the object should be 2:
104 # - someone already has a reference on the new object.
105 # - the python wrapper should hold its own reference.
106 obj = testhelper.OwnedByLibrary()
107 self.assertEqual(obj.__grefcount__, 2)
109 # We ask the library to release its reference, so the only
110 # remaining ref should be our wrapper's. Once the wrapper
111 # will run out of scope, the object will get finalized.
112 obj.release()
113 self.assertEqual(obj.__grefcount__, 1)
115 def test_owned_by_library_out_of_scope(self):
116 obj = testhelper.OwnedByLibrary()
117 self.assertEqual(obj.__grefcount__, 2)
119 # We are manually taking the object out of scope. This means
120 # that our wrapper has been freed, and its reference dropped. We
121 # cannot check it but the refcount should now be 1 (the ref held
122 # by the library is still there, we didn't call release()
123 obj = None
125 # When we get the object back from the lib, the wrapper is
126 # re-created, so our refcount will be 2 once again.
127 obj = testhelper.owned_by_library_get_instance_list()[0]
128 self.assertEqual(obj.__grefcount__, 2)
130 obj.release()
131 self.assertEqual(obj.__grefcount__, 1)
133 def test_owned_by_library_using_gobject_new(self):
134 # Upon creation, the refcount of the object should be 2:
135 # - someone already has a reference on the new object.
136 # - the python wrapper should hold its own reference.
137 obj = GObject.new(testhelper.OwnedByLibrary)
138 self.assertEqual(obj.__grefcount__, 2)
140 # We ask the library to release its reference, so the only
141 # remaining ref should be our wrapper's. Once the wrapper
142 # will run out of scope, the object will get finalized.
143 obj.release()
144 self.assertEqual(obj.__grefcount__, 1)
146 def test_owned_by_library_out_of_scope_using_gobject_new(self):
147 obj = GObject.new(testhelper.OwnedByLibrary)
148 self.assertEqual(obj.__grefcount__, 2)
150 # We are manually taking the object out of scope. This means
151 # that our wrapper has been freed, and its reference dropped. We
152 # cannot check it but the refcount should now be 1 (the ref held
153 # by the library is still there, we didn't call release()
154 obj = None
156 # When we get the object back from the lib, the wrapper is
157 # re-created, so our refcount will be 2 once again.
158 obj = testhelper.owned_by_library_get_instance_list()[0]
159 self.assertEqual(obj.__grefcount__, 2)
161 obj.release()
162 self.assertEqual(obj.__grefcount__, 1)
164 def test_floating_and_sunk(self):
165 # Upon creation, the refcount of the object should be 2:
166 # - someone already has a reference on the new object.
167 # - the python wrapper should hold its own reference.
168 obj = testhelper.FloatingAndSunk()
169 self.assertEqual(obj.__grefcount__, 2)
171 # We ask the library to release its reference, so the only
172 # remaining ref should be our wrapper's. Once the wrapper
173 # will run out of scope, the object will get finalized.
174 obj.release()
175 self.assertEqual(obj.__grefcount__, 1)
177 def test_floating_and_sunk_out_of_scope(self):
178 obj = testhelper.FloatingAndSunk()
179 self.assertEqual(obj.__grefcount__, 2)
181 # We are manually taking the object out of scope. This means
182 # that our wrapper has been freed, and its reference dropped. We
183 # cannot check it but the refcount should now be 1 (the ref held
184 # by the library is still there, we didn't call release()
185 obj = None
187 # When we get the object back from the lib, the wrapper is
188 # re-created, so our refcount will be 2 once again.
189 obj = testhelper.floating_and_sunk_get_instance_list()[0]
190 self.assertEqual(obj.__grefcount__, 2)
192 obj.release()
193 self.assertEqual(obj.__grefcount__, 1)
195 def test_floating_and_sunk_using_gobject_new(self):
196 # Upon creation, the refcount of the object should be 2:
197 # - someone already has a reference on the new object.
198 # - the python wrapper should hold its own reference.
199 obj = GObject.new(testhelper.FloatingAndSunk)
200 self.assertEqual(obj.__grefcount__, 2)
202 # We ask the library to release its reference, so the only
203 # remaining ref should be our wrapper's. Once the wrapper
204 # will run out of scope, the object will get finalized.
205 obj.release()
206 self.assertEqual(obj.__grefcount__, 1)
208 def test_floating_and_sunk_out_of_scope_using_gobject_new(self):
209 obj = GObject.new(testhelper.FloatingAndSunk)
210 self.assertEqual(obj.__grefcount__, 2)
212 # We are manually taking the object out of scope. This means
213 # that our wrapper has been freed, and its reference dropped. We
214 # cannot check it but the refcount should now be 1 (the ref held
215 # by the library is still there, we didn't call release()
216 obj = None
218 # When we get the object back from the lib, the wrapper is
219 # re-created, so our refcount will be 2 once again.
220 obj = testhelper.floating_and_sunk_get_instance_list()[0]
221 self.assertEqual(obj.__grefcount__, 2)
223 obj.release()
224 self.assertEqual(obj.__grefcount__, 1)
226 def test_uninitialized_object(self):
227 class Obj(GObject.GObject):
228 def __init__(self):
229 x = self.__grefcount__
230 super(Obj, self).__init__()
231 assert x >= 0 # quiesce pyflakes
233 # Accessing __grefcount__ before the object is initialized is wrong.
234 # Ensure we get a proper exception instead of a crash.
235 self.assertRaises(TypeError, Obj)
238 class A(GObject.GObject):
239 def __init__(self):
240 super(A, self).__init__()
243 class TestPythonReferenceCounting(unittest.TestCase):
244 # Newly created instances should alwayshave two references: one for
245 # the GC, and one for the bound variable in the local scope.
247 def test_new_instance_has_two_refs(self):
248 obj = GObject.GObject()
249 if hasattr(sys, "getrefcount"):
250 self.assertEqual(sys.getrefcount(obj), 2)
252 def test_new_instance_has_two_refs_using_gobject_new(self):
253 obj = GObject.new(GObject.GObject)
254 if hasattr(sys, "getrefcount"):
255 self.assertEqual(sys.getrefcount(obj), 2)
257 def test_new_subclass_instance_has_two_refs(self):
258 obj = A()
259 if hasattr(sys, "getrefcount"):
260 self.assertEqual(sys.getrefcount(obj), 2)
262 def test_new_subclass_instance_has_two_refs_using_gobject_new(self):
263 obj = GObject.new(A)
264 if hasattr(sys, "getrefcount"):
265 self.assertEqual(sys.getrefcount(obj), 2)
268 class TestContextManagers(unittest.TestCase):
269 class ContextTestObject(GObject.GObject):
270 prop = GObject.Property(default=0, type=int)
272 def on_prop_set(self, obj, prop):
273 # Handler which tracks property changed notifications.
274 self.tracking.append(obj.get_property(prop.name))
276 def setUp(self):
277 self.tracking = []
278 self.obj = self.ContextTestObject()
279 self.handler = self.obj.connect('notify::prop', self.on_prop_set)
281 def test_freeze_notify_context(self):
282 # Verify prop tracking list
283 self.assertEqual(self.tracking, [])
284 self.obj.props.prop = 1
285 self.assertEqual(self.tracking, [1])
286 self.obj.props.prop = 2
287 self.assertEqual(self.tracking, [1, 2])
288 self.assertEqual(self.obj.__grefcount__, 1)
290 if hasattr(sys, "getrefcount"):
291 pyref_count = sys.getrefcount(self.obj)
293 # Using the context manager the tracking list should not be affected.
294 # The GObject reference count should stay the same and the python
295 # object ref-count should go up.
296 with self.obj.freeze_notify():
297 self.assertEqual(self.obj.__grefcount__, 1)
298 if hasattr(sys, "getrefcount"):
299 self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
300 self.obj.props.prop = 3
301 self.assertEqual(self.obj.props.prop, 3)
302 self.assertEqual(self.tracking, [1, 2])
304 # After the context manager, the prop should have been modified,
305 # the tracking list will be modified, and the python object ref
306 # count goes back down.
307 gc.collect()
308 self.assertEqual(self.obj.props.prop, 3)
309 self.assertEqual(self.tracking, [1, 2, 3])
310 self.assertEqual(self.obj.__grefcount__, 1)
311 if hasattr(sys, "getrefcount"):
312 self.assertEqual(sys.getrefcount(self.obj), pyref_count)
314 def test_handler_block_context(self):
315 # Verify prop tracking list
316 self.assertEqual(self.tracking, [])
317 self.obj.props.prop = 1
318 self.assertEqual(self.tracking, [1])
319 self.obj.props.prop = 2
320 self.assertEqual(self.tracking, [1, 2])
321 self.assertEqual(self.obj.__grefcount__, 1)
323 if hasattr(sys, "getrefcount"):
324 pyref_count = sys.getrefcount(self.obj)
326 # Using the context manager the tracking list should not be affected.
327 # The GObject reference count should stay the same and the python
328 # object ref-count should go up.
329 with self.obj.handler_block(self.handler):
330 self.assertEqual(self.obj.__grefcount__, 1)
331 if hasattr(sys, "getrefcount"):
332 self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
333 self.obj.props.prop = 3
334 self.assertEqual(self.obj.props.prop, 3)
335 self.assertEqual(self.tracking, [1, 2])
337 # After the context manager, the prop should have been modified
338 # the tracking list should have stayed the same and the GObject ref
339 # count goes back down.
340 gc.collect()
341 self.assertEqual(self.obj.props.prop, 3)
342 self.assertEqual(self.tracking, [1, 2])
343 self.assertEqual(self.obj.__grefcount__, 1)
344 if hasattr(sys, "getrefcount"):
345 self.assertEqual(sys.getrefcount(self.obj), pyref_count)
347 def test_freeze_notify_context_nested(self):
348 self.assertEqual(self.tracking, [])
349 with self.obj.freeze_notify():
350 self.obj.props.prop = 1
351 self.assertEqual(self.tracking, [])
353 with self.obj.freeze_notify():
354 self.obj.props.prop = 2
355 self.assertEqual(self.tracking, [])
357 with self.obj.freeze_notify():
358 self.obj.props.prop = 3
359 self.assertEqual(self.tracking, [])
360 self.assertEqual(self.tracking, [])
361 self.assertEqual(self.tracking, [])
363 # Finally after last context, the notifications should have collapsed
364 # and the last one sent.
365 self.assertEqual(self.tracking, [3])
367 def test_handler_block_context_nested(self):
368 self.assertEqual(self.tracking, [])
369 with self.obj.handler_block(self.handler):
370 self.obj.props.prop = 1
371 self.assertEqual(self.tracking, [])
373 with self.obj.handler_block(self.handler):
374 self.obj.props.prop = 2
375 self.assertEqual(self.tracking, [])
377 with self.obj.handler_block(self.handler):
378 self.obj.props.prop = 3
379 self.assertEqual(self.tracking, [])
380 self.assertEqual(self.tracking, [])
381 self.assertEqual(self.tracking, [])
383 # Finally after last context, the notifications should have collapsed
384 # and the last one sent.
385 self.assertEqual(self.obj.props.prop, 3)
386 self.assertEqual(self.tracking, [])
388 def test_freeze_notify_normal_usage_ref_counts(self):
389 # Ensure ref counts without using methods as context managers
390 # maintain the same count.
391 self.assertEqual(self.obj.__grefcount__, 1)
392 self.obj.freeze_notify()
393 self.assertEqual(self.obj.__grefcount__, 1)
394 self.obj.thaw_notify()
395 self.assertEqual(self.obj.__grefcount__, 1)
397 def test_handler_block_normal_usage_ref_counts(self):
398 self.assertEqual(self.obj.__grefcount__, 1)
399 self.obj.handler_block(self.handler)
400 self.assertEqual(self.obj.__grefcount__, 1)
401 self.obj.handler_unblock(self.handler)
402 self.assertEqual(self.obj.__grefcount__, 1)
404 def test_freeze_notify_context_error(self):
405 # Test an exception occurring within a freeze context exits the context
406 try:
407 with self.obj.freeze_notify():
408 self.obj.props.prop = 1
409 self.assertEqual(self.tracking, [])
410 raise ValueError('Simulation')
411 except ValueError:
412 pass
414 # Verify the property set within the context called notify.
415 self.assertEqual(self.obj.props.prop, 1)
416 self.assertEqual(self.tracking, [1])
418 # Verify we are still not in a frozen context.
419 self.obj.props.prop = 2
420 self.assertEqual(self.tracking, [1, 2])
422 def test_handler_block_context_error(self):
423 # Test an exception occurring within a handler block exits the context
424 try:
425 with self.obj.handler_block(self.handler):
426 self.obj.props.prop = 1
427 self.assertEqual(self.tracking, [])
428 raise ValueError('Simulation')
429 except ValueError:
430 pass
432 # Verify the property set within the context didn't call notify.
433 self.assertEqual(self.obj.props.prop, 1)
434 self.assertEqual(self.tracking, [])
436 # Verify we are still not in a handler block context.
437 self.obj.props.prop = 2
438 self.assertEqual(self.tracking, [2])
441 @unittest.skipUnless(hasattr(GObject.Binding, 'unbind'),
442 'Requires newer GLib which has g_binding_unbind')
443 class TestPropertyBindings(unittest.TestCase):
444 class TestObject(GObject.GObject):
445 int_prop = GObject.Property(default=0, type=int)
447 def setUp(self):
448 self.source = self.TestObject()
449 self.target = self.TestObject()
451 def test_default_binding(self):
452 binding = self.source.bind_property('int_prop', self.target, 'int_prop',
453 GObject.BindingFlags.DEFAULT)
454 binding = binding # PyFlakes
456 # Test setting value on source gets pushed to target
457 self.source.int_prop = 1
458 self.assertEqual(self.source.int_prop, 1)
459 self.assertEqual(self.target.int_prop, 1)
461 # Test setting value on target does not change source
462 self.target.props.int_prop = 2
463 self.assertEqual(self.source.int_prop, 1)
464 self.assertEqual(self.target.int_prop, 2)
466 def test_bidirectional_binding(self):
467 binding = self.source.bind_property('int_prop', self.target, 'int_prop',
468 GObject.BindingFlags.BIDIRECTIONAL)
469 binding = binding # PyFlakes
471 # Test setting value on source gets pushed to target
472 self.source.int_prop = 1
473 self.assertEqual(self.source.int_prop, 1)
474 self.assertEqual(self.target.int_prop, 1)
476 # Test setting value on target also changes source
477 self.target.props.int_prop = 2
478 self.assertEqual(self.source.int_prop, 2)
479 self.assertEqual(self.target.int_prop, 2)
481 def test_transform_to_only(self):
482 def transform_to(binding, value, user_data=None):
483 self.assertEqual(user_data, 'test-data')
484 return value * 2
486 binding = self.source.bind_property('int_prop', self.target, 'int_prop',
487 GObject.BindingFlags.DEFAULT,
488 transform_to, None, 'test-data')
489 binding = binding # PyFlakes
491 self.source.int_prop = 1
492 self.assertEqual(self.source.int_prop, 1)
493 self.assertEqual(self.target.int_prop, 2)
495 self.target.props.int_prop = 1
496 self.assertEqual(self.source.int_prop, 1)
497 self.assertEqual(self.target.int_prop, 1)
499 def test_transform_from_only(self):
500 def transform_from(binding, value, user_data=None):
501 self.assertEqual(user_data, None)
502 return value * 2
504 binding = self.source.bind_property('int_prop', self.target, 'int_prop',
505 GObject.BindingFlags.BIDIRECTIONAL,
506 None, transform_from)
507 binding = binding # PyFlakes
509 self.source.int_prop = 1
510 self.assertEqual(self.source.int_prop, 1)
511 self.assertEqual(self.target.int_prop, 1)
513 self.target.props.int_prop = 1
514 self.assertEqual(self.source.int_prop, 2)
515 self.assertEqual(self.target.int_prop, 1)
517 def test_transform_bidirectional(self):
518 test_data = object()
520 def transform_to(binding, value, user_data=None):
521 self.assertEqual(user_data, test_data)
522 return value * 2
524 def transform_from(binding, value, user_data=None):
525 self.assertEqual(user_data, test_data)
526 return value // 2
528 if hasattr(sys, "getrefcount"):
529 test_data_ref_count = sys.getrefcount(test_data)
530 transform_to_ref_count = sys.getrefcount(transform_to)
531 transform_from_ref_count = sys.getrefcount(transform_from)
533 # bidirectional bindings
534 binding = self.source.bind_property('int_prop', self.target, 'int_prop',
535 GObject.BindingFlags.BIDIRECTIONAL,
536 transform_to, transform_from, test_data)
537 binding = binding # PyFlakes
538 if hasattr(sys, "getrefcount"):
539 binding_ref_count = sys.getrefcount(binding)
540 binding_gref_count = binding.__grefcount__
542 self.source.int_prop = 1
543 self.assertEqual(self.source.int_prop, 1)
544 self.assertEqual(self.target.int_prop, 2)
546 self.target.props.int_prop = 4
547 self.assertEqual(self.source.int_prop, 2)
548 self.assertEqual(self.target.int_prop, 4)
550 if hasattr(sys, "getrefcount"):
551 self.assertEqual(sys.getrefcount(binding), binding_ref_count)
552 self.assertEqual(binding.__grefcount__, binding_gref_count)
554 # test_data ref count increases by 2, once for each callback.
555 if hasattr(sys, "getrefcount"):
556 self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2)
557 self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1)
558 self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1)
560 # Unbind should clear out the binding and its transforms
561 binding.unbind()
563 # Setting source or target should not change the other.
564 self.target.int_prop = 3
565 self.source.int_prop = 5
566 self.assertEqual(self.target.int_prop, 3)
567 self.assertEqual(self.source.int_prop, 5)
569 if hasattr(sys, "getrefcount"):
570 self.assertEqual(sys.getrefcount(test_data), test_data_ref_count)
571 self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count)
572 self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count)
574 def test_explicit_unbind_clears_connection(self):
575 self.assertEqual(self.source.int_prop, 0)
576 self.assertEqual(self.target.int_prop, 0)
578 # Test deleting binding reference removes binding.
579 binding = self.source.bind_property('int_prop', self.target, 'int_prop')
580 self.source.int_prop = 1
581 self.assertEqual(self.source.int_prop, 1)
582 self.assertEqual(self.target.int_prop, 1)
584 # unbind should clear out the bindings self reference
585 binding.unbind()
586 self.assertEqual(binding.__grefcount__, 1)
588 self.source.int_prop = 10
589 self.assertEqual(self.source.int_prop, 10)
590 self.assertEqual(self.target.int_prop, 1)
592 glib_version = (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)
594 # calling unbind() on an already unbound binding
595 if glib_version >= (2, 57, 3):
596 # Fixed in newer glib:
597 # https://gitlab.gnome.org/GNOME/glib/merge_requests/244
598 for i in range(10):
599 binding.unbind()
600 else:
601 self.assertRaises(ValueError, binding.unbind)
603 def test_reference_counts(self):
604 self.assertEqual(self.source.__grefcount__, 1)
605 self.assertEqual(self.target.__grefcount__, 1)
607 # Binding ref count will be 2 do to the initial ref implicitly held by
608 # the act of binding and the ref incurred by using __call__ to generate
609 # a wrapper from the weak binding ref within python.
610 binding = self.source.bind_property('int_prop', self.target, 'int_prop')
611 self.assertEqual(binding.__grefcount__, 2)
613 # Creating a binding does not inc refs on source and target (they are weak
614 # on the binding object itself)
615 self.assertEqual(self.source.__grefcount__, 1)
616 self.assertEqual(self.target.__grefcount__, 1)
618 # Use GObject.get_property because the "props" accessor leaks.
619 # Note property names are canonicalized.
620 self.assertEqual(binding.get_property('source'), self.source)
621 self.assertEqual(binding.get_property('source_property'), 'int-prop')
622 self.assertEqual(binding.get_property('target'), self.target)
623 self.assertEqual(binding.get_property('target_property'), 'int-prop')
624 self.assertEqual(binding.get_property('flags'), GObject.BindingFlags.DEFAULT)
626 # Delete reference to source or target and the binding will remove its own
627 # "self reference".
628 ref = self.source.weak_ref()
629 del self.source
630 gc.collect()
631 self.assertEqual(ref(), None)
632 self.assertEqual(binding.__grefcount__, 1)
634 # Finally clear out the last ref held by the python wrapper
635 ref = binding.weak_ref()
636 del binding
637 gc.collect()
638 self.assertEqual(ref(), None)
641 class TestGValue(unittest.TestCase):
642 def test_type_constant(self):
643 self.assertEqual(GObject.TYPE_VALUE, GObject.Value.__gtype__)
644 self.assertEqual(GObject.type_name(GObject.TYPE_VALUE), 'GValue')
646 def test_no_type(self):
647 value = GObject.Value()
648 self.assertEqual(value.g_type, GObject.TYPE_INVALID)
649 self.assertRaises(TypeError, value.set_value, 23)
650 self.assertEqual(value.get_value(), None)
652 def test_int(self):
653 value = GObject.Value(GObject.TYPE_UINT)
654 self.assertEqual(value.g_type, GObject.TYPE_UINT)
655 value.set_value(23)
656 self.assertEqual(value.get_value(), 23)
657 value.set_value(42.0)
658 self.assertEqual(value.get_value(), 42)
660 def test_multi_del(self):
661 value = GObject.Value(str, 'foo_bar')
662 value.__del__()
663 value.__del__()
664 del value
666 def test_string(self):
667 value = GObject.Value(str, 'foo_bar')
668 self.assertEqual(value.g_type, GObject.TYPE_STRING)
669 self.assertEqual(value.get_value(), 'foo_bar')
671 def test_float(self):
672 # python float is G_TYPE_DOUBLE
673 value = GObject.Value(float, 23.4)
674 self.assertEqual(value.g_type, GObject.TYPE_DOUBLE)
675 value.set_value(1e50)
676 self.assertAlmostEqual(value.get_value(), 1e50)
678 value = GObject.Value(GObject.TYPE_FLOAT, 23.4)
679 self.assertEqual(value.g_type, GObject.TYPE_FLOAT)
680 self.assertRaises(TypeError, value.set_value, 'string')
681 self.assertRaises(OverflowError, value.set_value, 1e50)
683 def test_float_inf_nan(self):
684 nan = float('nan')
685 for type_ in [GObject.TYPE_FLOAT, GObject.TYPE_DOUBLE]:
686 for x in [float('inf'), float('-inf'), nan]:
687 value = GObject.Value(type_, x)
688 # assertEqual() is False for (nan, nan)
689 if x is nan:
690 self.assertEqual(str(value.get_value()), 'nan')
691 else:
692 self.assertEqual(value.get_value(), x)
694 def test_enum(self):
695 value = GObject.Value(GLib.FileError, GLib.FileError.FAILED)
696 self.assertEqual(value.get_value(), GLib.FileError.FAILED)
698 def test_flags(self):
699 value = GObject.Value(GLib.IOFlags, GLib.IOFlags.IS_READABLE)
700 self.assertEqual(value.get_value(), GLib.IOFlags.IS_READABLE)
702 def test_object(self):
703 class TestObject(GObject.Object):
704 pass
705 obj = TestObject()
706 value = GObject.Value(GObject.TYPE_OBJECT, obj)
707 self.assertEqual(value.get_value(), obj)
709 def test_value_array(self):
710 value = GObject.Value(GObject.ValueArray)
711 self.assertEqual(value.g_type, GObject.type_from_name('GValueArray'))
712 value.set_value([32, 'foo_bar', 0.3])
713 self.assertEqual(value.get_value(), [32, 'foo_bar', 0.3])
715 def test_value_array_from_gvalue_list(self):
716 value = GObject.Value(GObject.ValueArray, [
717 GObject.Value(GObject.TYPE_UINT, 0xffffffff),
718 GObject.Value(GObject.TYPE_STRING, 'foo_bar')])
719 self.assertEqual(value.g_type, GObject.type_from_name('GValueArray'))
720 self.assertEqual(value.get_value(), [0xffffffff, 'foo_bar'])
721 self.assertEqual(testhelper.value_array_get_nth_type(value, 0), GObject.TYPE_UINT)
722 self.assertEqual(testhelper.value_array_get_nth_type(value, 1), GObject.TYPE_STRING)
724 def test_value_array_append_gvalue(self):
725 with warnings.catch_warnings():
726 warnings.simplefilter('ignore', DeprecationWarning)
728 arr = GObject.ValueArray.new(0)
729 arr.append(GObject.Value(GObject.TYPE_UINT, 0xffffffff))
730 arr.append(GObject.Value(GObject.TYPE_STRING, 'foo_bar'))
731 self.assertEqual(arr.get_nth(0), 0xffffffff)
732 self.assertEqual(arr.get_nth(1), 'foo_bar')
733 self.assertEqual(testhelper.value_array_get_nth_type(arr, 0), GObject.TYPE_UINT)
734 self.assertEqual(testhelper.value_array_get_nth_type(arr, 1), GObject.TYPE_STRING)
736 def test_gerror_boxing(self):
737 error = GLib.Error('test message', domain='mydomain', code=42)
738 value = GObject.Value(GLib.Error, error)
739 self.assertEqual(value.g_type, GObject.type_from_name('GError'))
741 unboxed = value.get_value()
742 self.assertEqual(unboxed.message, error.message)
743 self.assertEqual(unboxed.domain, error.domain)
744 self.assertEqual(unboxed.code, error.code)
746 def test_gerror_novalue(self):
747 GLib.Error('test message', domain='mydomain', code=42)
748 value = GObject.Value(GLib.Error)
749 self.assertEqual(value.g_type, GObject.type_from_name('GError'))
750 self.assertEqual(value.get_value(), None)
753 def test_list_properties():
755 def find_param(l, name):
756 for param in l:
757 if param.name == name:
758 return param
759 return
761 list_props = GObject.list_properties
763 props = list_props(Gio.Action)
764 param = find_param(props, "enabled")
765 assert param
766 assert param.value_type == GObject.TYPE_BOOLEAN
767 assert list_props("GAction") == list_props(Gio.Action)
768 assert list_props(Gio.Action.__gtype__) == list_props(Gio.Action)
770 props = list_props(Gio.SimpleAction)
771 assert find_param(props, "enabled")
773 def names(l):
774 return [p.name for p in l]
776 assert (set(names(list_props(Gio.Action))) <=
777 set(names(list_props(Gio.SimpleAction))))
779 props = list_props(Gio.FileIcon)
780 param = find_param(props, "file")
781 assert param
782 assert param.value_type == Gio.File.__gtype__
784 assert list_props("GFileIcon") == list_props(Gio.FileIcon)
785 assert list_props(Gio.FileIcon.__gtype__) == list_props(Gio.FileIcon)
786 assert list_props(Gio.FileIcon()) == list_props(Gio.FileIcon)
788 for obj in [Gio.ActionEntry, Gio.DBusError, 0, object()]:
789 with pytest.raises(TypeError):
790 list_props(obj)