8 from gi.repository import GObject
9 from gi.repository.GObject import GType, new, PARAM_READWRITE, \
10 PARAM_CONSTRUCT, PARAM_READABLE, PARAM_WRITABLE, PARAM_CONSTRUCT_ONLY
11 from gi.repository.GObject import \
12 TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, \
13 TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE, TYPE_STRV, \
14 TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_FLOAT, \
15 TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
16 TYPE_STRING, TYPE_PYOBJECT, TYPE_VARIANT
18 from gi.repository.GObject import \
19 G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, G_MAXULONG, \
20 G_MAXUINT64, G_MAXINT64, G_MININT64
22 from gi.repository import Gio
23 from gi.repository import GLib
24 from gi.repository import Regress
25 from gi.repository import GIMarshallingTests
26 from gi._gobject import propertyhelper
28 if sys.version_info < (3, 0):
29 TEST_UTF8 = "\xe2\x99\xa5"
30 UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
33 UNICODE_UTF8 = TEST_UTF8
35 from compathelper import _long
38 class PropertyObject(GObject.GObject):
39 normal = GObject.Property(type=str)
40 construct = GObject.Property(
42 flags=PARAM_READWRITE | PARAM_CONSTRUCT, default='default')
43 construct_only = GObject.Property(
45 flags=PARAM_READWRITE | PARAM_CONSTRUCT_ONLY)
46 uint64 = GObject.Property(
47 type=TYPE_UINT64, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
49 enum = GObject.Property(
50 type=Gio.SocketType, default=Gio.SocketType.STREAM)
52 boxed = GObject.Property(
53 type=GLib.Regex, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
55 flags = GObject.Property(
56 type=GIMarshallingTests.Flags, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
57 default=GIMarshallingTests.Flags.VALUE1)
59 gtype = GObject.Property(
60 type=TYPE_GTYPE, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
62 strings = GObject.Property(
63 type=TYPE_STRV, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
65 variant = GObject.Property(
66 type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
68 variant_def = GObject.Property(
69 type=TYPE_VARIANT, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
70 default=GLib.Variant('i', 42))
73 class PropertyInheritanceObject(Regress.TestObj):
74 # override property from the base class, with a different type
75 string = GObject.Property(type=int)
77 # a property entirely defined at the Python level
78 python_prop = GObject.Property(type=str)
81 class PropertySubClassObject(PropertyInheritanceObject):
82 # override property from the base class, with a different type
83 python_prop = GObject.Property(type=int)
86 class TestPropertyInheritanceObject(unittest.TestCase):
87 def test_override_gi_property(self):
88 self.assertNotEqual(Regress.TestObj.props.string.value_type,
89 PropertyInheritanceObject.props.string.value_type)
90 obj = PropertyInheritanceObject()
91 self.assertEqual(type(obj.props.string), int)
93 self.assertEqual(obj.props.string, 4)
95 def test_override_python_property(self):
96 obj = PropertySubClassObject()
97 self.assertEqual(type(obj.props.python_prop), int)
98 obj.props.python_prop = 5
99 self.assertEqual(obj.props.python_prop, 5)
102 class TestPropertyObject(unittest.TestCase):
103 def test_get_set(self):
104 obj = PropertyObject()
105 obj.props.normal = "value"
106 self.assertEqual(obj.props.normal, "value")
108 def test_hasattr_on_object(self):
109 obj = PropertyObject()
110 self.assertTrue(hasattr(obj.props, "normal"))
112 def test_hasattr_on_class(self):
113 self.assertTrue(hasattr(PropertyObject.props, "normal"))
115 def test_set_on_class(self):
117 obj.props.normal = "foobar"
119 self.assertRaises(TypeError, set, PropertyObject)
121 def test_iteration(self):
122 for obj in (PropertyObject.props, PropertyObject().props):
126 self.assertEqual(gtype.parent.name, 'GParam')
127 names.append(pspec.name)
130 self.assertEqual(names, ['boxed',
142 def test_normal(self):
143 obj = new(PropertyObject, normal="123")
144 self.assertEqual(obj.props.normal, "123")
145 obj.set_property('normal', '456')
146 self.assertEqual(obj.props.normal, "456")
147 obj.props.normal = '789'
148 self.assertEqual(obj.props.normal, "789")
150 def test_construct(self):
151 obj = new(PropertyObject, construct="123")
152 self.assertEqual(obj.props.construct, "123")
153 obj.set_property('construct', '456')
154 self.assertEqual(obj.props.construct, "456")
155 obj.props.construct = '789'
156 self.assertEqual(obj.props.construct, "789")
159 obj = new(PropertyObject, construct_only=UNICODE_UTF8)
160 self.assertEqual(obj.props.construct_only, TEST_UTF8)
161 obj.set_property('construct', UNICODE_UTF8)
162 self.assertEqual(obj.props.construct, TEST_UTF8)
163 obj.props.normal = UNICODE_UTF8
164 self.assertEqual(obj.props.normal, TEST_UTF8)
166 def test_int_to_str(self):
167 obj = new(PropertyObject, construct_only=1)
168 self.assertEqual(obj.props.construct_only, '1')
169 obj.set_property('construct', '2')
170 self.assertEqual(obj.props.construct, '2')
172 self.assertEqual(obj.props.normal, '3')
174 def test_construct_only(self):
175 obj = new(PropertyObject, construct_only="123")
176 self.assertEqual(obj.props.construct_only, "123")
177 self.assertRaises(TypeError,
178 setattr, obj.props, 'construct_only', '456')
179 self.assertRaises(TypeError,
180 obj.set_property, 'construct-only', '456')
182 def test_uint64(self):
183 obj = new(PropertyObject)
184 self.assertEqual(obj.props.uint64, 0)
185 obj.props.uint64 = _long(1)
186 self.assertEqual(obj.props.uint64, _long(1))
188 self.assertEqual(obj.props.uint64, _long(1))
190 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
191 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
193 def test_uint64_default_value(self):
195 class TimeControl(GObject.GObject):
197 'time': (TYPE_UINT64, 'Time', 'Time',
198 _long(0), (1 << 64) - 1, _long(0),
201 except OverflowError:
202 (etype, ex) = sys.exc_info()[2:]
206 obj = new(PropertyObject)
207 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
208 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
209 obj.enum = Gio.SocketType.DATAGRAM
210 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
211 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
212 obj.props.enum = Gio.SocketType.STREAM
213 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
214 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
216 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
217 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
219 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
220 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
222 self.assertRaises(TypeError, setattr, obj, 'enum', 'foo')
223 self.assertRaises(TypeError, setattr, obj, 'enum', object())
225 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType)
226 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
227 default=Gio.SocketProtocol.TCP)
228 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
230 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
233 def test_flags(self):
234 obj = new(PropertyObject)
235 self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE1)
236 self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE1)
238 obj.flags = GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3
239 self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
240 self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
242 self.assertRaises(TypeError, setattr, obj, 'flags', 'foo')
243 self.assertRaises(TypeError, setattr, obj, 'flags', object())
244 self.assertRaises(TypeError, setattr, obj, 'flags', None)
246 self.assertRaises(TypeError, GObject.Property,
247 type=GIMarshallingTests.Flags, default='foo')
248 self.assertRaises(TypeError, GObject.Property,
249 type=GIMarshallingTests.Flags, default=object())
250 self.assertRaises(TypeError, GObject.Property,
251 type=GIMarshallingTests.Flags, default=None)
253 def test_gtype(self):
254 obj = new(PropertyObject)
256 self.assertEqual(obj.props.gtype, TYPE_NONE)
257 self.assertEqual(obj.gtype, TYPE_NONE)
259 obj.gtype = TYPE_UINT64
260 self.assertEqual(obj.props.gtype, TYPE_UINT64)
261 self.assertEqual(obj.gtype, TYPE_UINT64)
263 obj.gtype = TYPE_INVALID
264 self.assertEqual(obj.props.gtype, TYPE_INVALID)
265 self.assertEqual(obj.gtype, TYPE_INVALID)
267 # GType parameters do not support defaults in GLib
268 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
272 self.assertRaises(TypeError, setattr, obj, 'gtype', 'foo')
273 self.assertRaises(TypeError, setattr, obj, 'gtype', object())
275 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
277 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
281 obj = new(PropertyObject, gtype=TYPE_UINT)
282 self.assertEqual(obj.props.gtype, TYPE_UINT)
283 self.assertEqual(obj.gtype, TYPE_UINT)
285 def test_boxed(self):
286 obj = new(PropertyObject)
288 regex = GLib.Regex.new('[a-z]*', 0, 0)
289 obj.props.boxed = regex
290 self.assertEqual(obj.props.boxed.get_pattern(), '[a-z]*')
291 self.assertEqual(obj.boxed.get_pattern(), '[a-z]*')
293 self.assertRaises(TypeError, setattr, obj, 'boxed', 'foo')
294 self.assertRaises(TypeError, setattr, obj, 'boxed', object())
296 def test_strings(self):
297 obj = new(PropertyObject)
299 # Should work with actual GStrv objects as well as
300 # Python string lists
302 __gtype__ = GObject.TYPE_STRV
304 self.assertEqual(obj.props.strings, GStrv([]))
305 self.assertEqual(obj.strings, GStrv([]))
306 self.assertEqual(obj.props.strings, [])
307 self.assertEqual(obj.strings, [])
309 obj.strings = ['hello', 'world']
310 self.assertEqual(obj.props.strings, ['hello', 'world'])
311 self.assertEqual(obj.strings, ['hello', 'world'])
313 obj.strings = GStrv(['hello', 'world'])
314 self.assertEqual(obj.props.strings, GStrv(['hello', 'world']))
315 self.assertEqual(obj.strings, GStrv(['hello', 'world']))
318 self.assertEqual(obj.strings, [])
319 obj.strings = GStrv([])
320 self.assertEqual(obj.strings, GStrv([]))
322 p = GObject.Property(type=TYPE_STRV, default=['hello', '1'])
323 self.assertEqual(p.default, ['hello', '1'])
324 self.assertEqual(p.type, TYPE_STRV)
325 p = GObject.Property(type=TYPE_STRV, default=GStrv(['hello', '1']))
326 self.assertEqual(p.default, ['hello', '1'])
327 self.assertEqual(p.type, TYPE_STRV)
330 obj = new(PropertyObject, strings=['hello', 'world'])
331 self.assertEqual(obj.props.strings, ['hello', 'world'])
332 self.assertEqual(obj.strings, ['hello', 'world'])
335 self.assertRaises(TypeError, setattr, obj, 'strings', 1)
336 self.assertRaises(TypeError, setattr, obj, 'strings', 'foo')
337 self.assertRaises(TypeError, setattr, obj, 'strings', ['foo', 1])
339 self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
341 self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
343 self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
344 default=['hello', 1])
346 def test_variant(self):
347 obj = new(PropertyObject)
349 self.assertEqual(obj.props.variant, None)
350 self.assertEqual(obj.variant, None)
352 obj.variant = GLib.Variant('s', 'hello')
353 self.assertEqual(obj.variant.print_(True), "'hello'")
355 obj.variant = GLib.Variant('b', True)
356 self.assertEqual(obj.variant.print_(True), "true")
358 obj.props.variant = GLib.Variant('y', 2)
359 self.assertEqual(obj.variant.print_(True), "byte 0x02")
362 self.assertEqual(obj.variant, None)
365 obj = new(PropertyObject, variant=GLib.Variant('u', 5))
366 self.assertEqual(obj.props.variant.print_(True), 'uint32 5')
368 GObject.Property(type=TYPE_VARIANT, default=GLib.Variant('i', 1))
371 self.assertRaises(TypeError, setattr, obj, 'variant', 'foo')
372 self.assertRaises(TypeError, setattr, obj, 'variant', 42)
374 self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
376 self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
379 def test_variant_default(self):
380 obj = new(PropertyObject)
382 self.assertEqual(obj.props.variant_def.print_(True), '42')
383 self.assertEqual(obj.variant_def.print_(True), '42')
385 obj.props.variant_def = GLib.Variant('y', 2)
386 self.assertEqual(obj.variant_def.print_(True), "byte 0x02")
389 obj = new(PropertyObject, variant_def=GLib.Variant('u', 5))
390 self.assertEqual(obj.props.variant_def.print_(True), 'uint32 5')
392 def test_range(self):
395 return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
398 return 2 ** (8 * struct.calcsize(c)) - 1
404 minlong = -maxlong - 1
407 minint64 = -maxint64 - 1
408 maxuint64 = umax('Q')
410 types_ = dict(int=(TYPE_INT, minint, maxint),
411 uint=(TYPE_UINT, 0, maxuint),
412 long=(TYPE_LONG, minlong, maxlong),
413 ulong=(TYPE_ULONG, 0, maxulong),
414 int64=(TYPE_INT64, minint64, maxint64),
415 uint64=(TYPE_UINT64, 0, maxuint64))
417 def build_gproperties(types_):
419 for key, (gtype, min, max) in types_.items():
420 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
421 PARAM_READABLE | PARAM_WRITABLE)
424 class RangeCheck(GObject.GObject):
425 __gproperties__ = build_gproperties(types_)
429 GObject.GObject.__init__(self)
431 def do_set_property(self, pspec, value):
432 self.values[pspec.name] = value
434 def do_get_property(self, pspec):
435 return self.values.get(pspec.name, pspec.default_value)
437 self.assertEqual(RangeCheck.props.int.minimum, minint)
438 self.assertEqual(RangeCheck.props.int.maximum, maxint)
439 self.assertEqual(RangeCheck.props.uint.minimum, 0)
440 self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
441 self.assertEqual(RangeCheck.props.long.minimum, minlong)
442 self.assertEqual(RangeCheck.props.long.maximum, maxlong)
443 self.assertEqual(RangeCheck.props.ulong.minimum, 0)
444 self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
445 self.assertEqual(RangeCheck.props.int64.minimum, minint64)
446 self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
447 self.assertEqual(RangeCheck.props.uint64.minimum, 0)
448 self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
451 for key, (gtype, min, max) in types_.items():
452 self.assertEqual(obj.get_property(key),
453 getattr(RangeCheck.props, key).default_value)
455 obj.set_property(key, min)
456 self.assertEqual(obj.get_property(key), min)
458 obj.set_property(key, max)
459 self.assertEqual(obj.get_property(key), max)
461 def test_multi(self):
462 obj = PropertyObject()
463 obj.set_properties(normal="foo",
465 normal, uint64 = obj.get_properties("normal", "uint64")
466 self.assertEqual(normal, "foo")
467 self.assertEqual(uint64, 7)
470 class TestProperty(unittest.TestCase):
471 def test_simple(self):
472 class C(GObject.GObject):
473 str = GObject.Property(type=str)
474 int = GObject.Property(type=int)
475 float = GObject.Property(type=float)
476 long = GObject.Property(type=_long)
478 self.assertTrue(hasattr(C.props, 'str'))
479 self.assertTrue(hasattr(C.props, 'int'))
480 self.assertTrue(hasattr(C.props, 'float'))
481 self.assertTrue(hasattr(C.props, 'long'))
484 self.assertEqual(o.str, '')
486 self.assertEqual(o.str, 'str')
488 self.assertEqual(o.int, 0)
490 self.assertEqual(o.int, 1138)
492 self.assertEqual(o.float, 0.0)
494 self.assertEqual(o.float, 3.14)
496 self.assertEqual(o.long, _long(0))
498 self.assertEqual(o.long, _long(100))
500 def test_custom_getter(self):
501 class C(GObject.GObject):
504 prop = GObject.Property(getter=get_prop)
507 self.assertEqual(o.prop, 'value')
508 self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
510 def test_custom_setter(self):
511 class C(GObject.GObject):
512 def set_prop(self, value):
514 prop = GObject.Property(setter=set_prop)
518 GObject.GObject.__init__(self)
521 self.assertEqual(o._value, None)
523 self.assertEqual(o._value, 'bar')
524 self.assertRaises(TypeError, getattr, o, 'prop')
526 def test_decorator_default(self):
527 class C(GObject.GObject):
535 def value_setter(self, value):
539 self.assertEqual(o.value, 'value')
541 self.assertEqual(o.value, 'blah')
542 self.assertEqual(o.props.value, 'blah')
544 def test_decorator_private_setter(self):
545 class C(GObject.GObject):
553 def _set_value(self, value):
557 self.assertEqual(o.value, 'value')
559 self.assertEqual(o.value, 'blah')
560 self.assertEqual(o.props.value, 'blah')
562 def test_decorator_with_call(self):
563 class C(GObject.GObject):
566 @GObject.Property(type=int, default=1, minimum=1, maximum=10)
567 def typedValue(self):
571 def typedValue_setter(self, value):
575 self.assertEqual(o.typedValue, 1)
577 self.assertEqual(o.typedValue, 5)
578 self.assertEqual(o.props.typedValue, 5)
580 def test_errors(self):
581 self.assertRaises(TypeError, GObject.Property, type='str')
582 self.assertRaises(TypeError, GObject.Property, nick=False)
583 self.assertRaises(TypeError, GObject.Property, blurb=False)
584 # this never fail while bool is a subclass of int
587 # self.assertRaises(TypeError, GObject.Property, type=bool, default=0)
588 self.assertRaises(TypeError, GObject.Property, type=bool, default='ciao mamma')
589 self.assertRaises(TypeError, GObject.Property, type=bool)
590 self.assertRaises(TypeError, GObject.Property, type=object, default=0)
591 self.assertRaises(TypeError, GObject.Property, type=complex)
592 self.assertRaises(TypeError, GObject.Property, flags=-10)
594 def test_defaults(self):
595 GObject.Property(type=bool, default=True)
596 GObject.Property(type=bool, default=False)
598 def test_name_with_underscore(self):
599 class C(GObject.GObject):
600 prop_name = GObject.Property(type=int)
603 self.assertEqual(o.prop_name, 10)
605 def test_range(self):
607 (TYPE_INT, G_MININT, G_MAXINT),
608 (TYPE_UINT, 0, G_MAXUINT),
609 (TYPE_LONG, G_MINLONG, G_MAXLONG),
610 (TYPE_ULONG, 0, G_MAXULONG),
611 (TYPE_INT64, G_MININT64, G_MAXINT64),
612 (TYPE_UINT64, 0, G_MAXUINT64),
615 for gtype, min, max in types_:
616 # Normal, everything is alright
617 prop = GObject.Property(type=gtype, minimum=min, maximum=max)
618 subtype = type('', (GObject.GObject,), dict(prop=prop))
619 self.assertEqual(subtype.props.prop.minimum, min)
620 self.assertEqual(subtype.props.prop.maximum, max)
623 self.assertRaises(TypeError,
624 GObject.Property, type=gtype, minimum=min - 1,
627 # Higher than maximum
628 self.assertRaises(TypeError,
629 GObject.Property, type=gtype, minimum=min,
632 def test_min_max(self):
633 class C(GObject.GObject):
634 prop_int = GObject.Property(type=int, minimum=1, maximum=100, default=1)
635 prop_float = GObject.Property(type=float, minimum=0.1, maximum=10.5, default=1.1)
638 GObject.GObject.__init__(self)
640 # we test known-bad values here which cause Gtk-WARNING logs.
641 # Explicitly allow these for this test.
642 old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
645 self.assertEqual(o.prop_int, 1)
648 self.assertEqual(o.prop_int, 5)
651 self.assertEqual(o.prop_int, 5)
654 self.assertEqual(o.prop_int, 5)
656 self.assertEqual(o.prop_float, 1.1)
659 self.assertEqual(o.prop_float, 7.75)
662 self.assertEqual(o.prop_float, 7.75)
665 self.assertEqual(o.prop_float, 7.75)
667 GLib.log_set_always_fatal(old_mask)
669 def test_multiple_instances(self):
670 class C(GObject.GObject):
671 prop = GObject.Property(type=str, default='default')
675 self.assertEqual(o1.prop, 'default')
676 self.assertEqual(o2.prop, 'default')
678 self.assertEqual(o1.prop, 'value')
679 self.assertEqual(o2.prop, 'default')
681 def test_object_property(self):
682 class PropertyObject(GObject.GObject):
683 obj = GObject.Property(type=GObject.GObject)
685 pobj1 = PropertyObject()
686 obj1_hash = hash(pobj1)
687 pobj2 = PropertyObject()
692 self.assertEqual(hash(pobj1), obj1_hash)
694 def test_object_subclass_property(self):
695 class ObjectSubclass(GObject.GObject):
696 __gtype_name__ = 'ObjectSubclass'
698 class PropertyObjectSubclass(GObject.GObject):
699 obj = GObject.Property(type=ObjectSubclass)
701 PropertyObjectSubclass(obj=ObjectSubclass())
703 def test_property_subclass(self):
705 class A(GObject.GObject):
706 prop1 = GObject.Property(type=int)
709 prop2 = GObject.Property(type=int)
713 self.assertEqual(b.prop2, 10)
715 self.assertEqual(b.prop1, 20)
717 def test_property_subclass_c(self):
718 class A(GIMarshallingTests.PropertiesObject):
719 prop1 = GObject.Property(type=int)
723 self.assertEqual(a.prop1, 10)
725 # also has parent properties
726 a.props.some_int = 20
727 self.assertEqual(a.props.some_int, 20)
729 def test_property_subclass_custom_setter(self):
731 class A(GObject.GObject):
734 first = GObject.Property(type=str, getter=get_first)
737 def get_second(self):
739 second = GObject.Property(type=str, getter=get_second)
742 self.assertEqual(a.first, 'first')
743 self.assertRaises(TypeError, setattr, a, 'first', 'foo')
746 self.assertEqual(b.first, 'first')
747 self.assertRaises(TypeError, setattr, b, 'first', 'foo')
748 self.assertEqual(b.second, 'second')
749 self.assertRaises(TypeError, setattr, b, 'second', 'foo')
751 def test_property_subclass_custom_setter_error(self):
753 class A(GObject.GObject):
756 first = GObject.Property(type=str, getter=get_first)
758 def do_get_property(self, pspec):
767 def test_float_min(self):
768 GObject.Property(type=float, minimum=-1)
769 GObject.Property(type=GObject.TYPE_FLOAT, minimum=-1)
770 GObject.Property(type=GObject.TYPE_DOUBLE, minimum=-1)
774 def test_reference_count(self):
775 # We can check directly if an object gets finalized, so we will
776 # observe it indirectly through the refcount of a member object.
778 # We create our dummy object and store its current refcount
780 rc = sys.getrefcount(o)
782 # We add our object as a member to our newly created object we
783 # want to observe. Its refcount is increased by one.
784 t = PropertyObject(normal="test")
786 self.assertEqual(sys.getrefcount(o), rc + 1)
788 # Now we want to ensure we do not leak any references to our
789 # object with properties. If no ref is leaked, then when deleting
790 # the local reference to this object, its reference count shoud
791 # drop to zero, and our dummy object should loose one reference.
793 self.assertEqual(sys.getrefcount(o), rc)
795 def test_doc_strings(self):
796 class C(GObject.GObject):
797 foo_blurbed = GObject.Property(type=int, blurb='foo_blurbed doc string')
800 def foo_getter(self):
801 """foo_getter doc string"""
804 self.assertEqual(C.foo_blurbed.blurb, 'foo_blurbed doc string')
805 self.assertEqual(C.foo_blurbed.__doc__, 'foo_blurbed doc string')
807 self.assertEqual(C.foo_getter.blurb, 'foo_getter doc string')
808 self.assertEqual(C.foo_getter.__doc__, 'foo_getter doc string')
810 def test_python_to_glib_type_mapping(self):
811 tester = GObject.Property()
812 self.assertEqual(tester._type_from_python(int), GObject.TYPE_INT)
813 if sys.version_info < (3, 0):
814 self.assertEqual(tester._type_from_python(long), GObject.TYPE_LONG)
815 self.assertEqual(tester._type_from_python(bool), GObject.TYPE_BOOLEAN)
816 self.assertEqual(tester._type_from_python(float), GObject.TYPE_DOUBLE)
817 self.assertEqual(tester._type_from_python(str), GObject.TYPE_STRING)
818 self.assertEqual(tester._type_from_python(object), GObject.TYPE_PYOBJECT)
820 self.assertEqual(tester._type_from_python(GObject.GObject), GObject.GObject.__gtype__)
821 self.assertEqual(tester._type_from_python(GObject.GEnum), GObject.GEnum.__gtype__)
822 self.assertEqual(tester._type_from_python(GObject.GFlags), GObject.GFlags.__gtype__)
823 self.assertEqual(tester._type_from_python(GObject.GBoxed), GObject.GBoxed.__gtype__)
825 for type_ in [TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR,
826 TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG,
827 TYPE_ULONG, TYPE_INT64, TYPE_UINT64,
828 TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER,
829 TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING,
830 TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV]:
831 self.assertEqual(tester._type_from_python(type_), type_)
833 self.assertRaises(TypeError, tester._type_from_python, types.CodeType)
836 class TestInstallProperties(unittest.TestCase):
837 # These tests only test how signalhelper.install_signals works
838 # with the __gsignals__ dict and therefore does not need to use
839 # GObject as a base class because that would automatically call
840 # install_signals within the meta-class.
842 __gproperties__ = {'test': (0, '', '', 0, 0, 0, 0)}
848 @GObject.Property(type=int)
852 class ClassWithPropertyAndGetterVFunc(object):
853 @GObject.Property(type=int)
857 def do_get_property(self, name):
860 class ClassWithPropertyRedefined(object):
861 __gproperties__ = {'test': (0, '', '', 0, 0, 0, 0)}
862 test = GObject.Property(type=int)
865 self.assertEqual(len(self.Base.__gproperties__), 1)
866 propertyhelper.install_properties(self.Base)
867 self.assertEqual(len(self.Base.__gproperties__), 1)
869 def test_subclass_without_properties_is_not_modified(self):
870 self.assertFalse('__gproperties__' in self.Sub1.__dict__)
871 propertyhelper.install_properties(self.Sub1)
872 self.assertFalse('__gproperties__' in self.Sub1.__dict__)
874 def test_subclass_with_decorator_gets_gproperties_dict(self):
875 # Sub2 has Property instances but will not have a __gproperties__
876 # until install_properties is called
877 self.assertFalse('__gproperties__' in self.Sub2.__dict__)
878 self.assertFalse('do_get_property' in self.Sub2.__dict__)
879 self.assertFalse('do_set_property' in self.Sub2.__dict__)
881 propertyhelper.install_properties(self.Sub2)
882 self.assertTrue('__gproperties__' in self.Sub2.__dict__)
883 self.assertEqual(len(self.Base.__gproperties__), 1)
884 self.assertEqual(len(self.Sub2.__gproperties__), 1)
885 self.assertTrue('sub2test' in self.Sub2.__gproperties__)
887 # get/set vfuncs should have been added
888 self.assertTrue('do_get_property' in self.Sub2.__dict__)
889 self.assertTrue('do_set_property' in self.Sub2.__dict__)
891 def test_object_with_property_and_do_get_property_vfunc_raises(self):
892 self.assertRaises(TypeError, propertyhelper.install_properties,
893 self.ClassWithPropertyAndGetterVFunc)
895 def test_same_name_property_definitions_raises(self):
896 self.assertRaises(ValueError, propertyhelper.install_properties,
897 self.ClassWithPropertyRedefined)
899 if __name__ == '__main__':