7 from gi.repository import GObject
8 from gi.repository.GObject import GType, new, PARAM_READWRITE, \
9 PARAM_CONSTRUCT, PARAM_READABLE, PARAM_WRITABLE, PARAM_CONSTRUCT_ONLY
10 from gi.repository.GObject import \
11 TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, \
12 TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE
13 from gi.repository.GObject import \
14 G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, \
17 from gi.repository import Gio
18 from gi.repository import GLib
19 from gi.repository import GIMarshallingTests
21 if sys.version_info < (3, 0):
22 TEST_UTF8 = "\xe2\x99\xa5"
23 UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
26 UNICODE_UTF8 = TEST_UTF8
28 from compathelper import _long
31 class PropertyObject(GObject.GObject):
32 normal = GObject.Property(type=str)
33 construct = GObject.Property(
35 flags=PARAM_READWRITE | PARAM_CONSTRUCT, default='default')
36 construct_only = GObject.Property(
38 flags=PARAM_READWRITE | PARAM_CONSTRUCT_ONLY)
39 uint64 = GObject.Property(
40 type=TYPE_UINT64, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
42 enum = GObject.Property(
43 type=Gio.SocketType, default=Gio.SocketType.STREAM)
45 boxed = GObject.Property(
46 type=GLib.Regex, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
48 flags = GObject.Property(
49 type=GIMarshallingTests.Flags, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
50 default=GIMarshallingTests.Flags.VALUE1)
52 gtype = GObject.Property(
53 type=TYPE_GTYPE, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
56 class TestProperties(unittest.TestCase):
58 obj = PropertyObject()
59 obj.props.normal = "value"
60 self.assertEqual(obj.props.normal, "value")
62 def testListWithInstance(self):
63 obj = PropertyObject()
64 self.assertTrue(hasattr(obj.props, "normal"))
66 def testListWithoutInstance(self):
67 self.assertTrue(hasattr(PropertyObject.props, "normal"))
69 def testSetNoInstance(self):
71 obj.props.normal = "foobar"
73 self.assertRaises(TypeError, set, PropertyObject)
75 def testIterator(self):
76 for obj in (PropertyObject.props, PropertyObject().props):
79 self.assertEqual(gtype.parent.name, 'GParam')
80 self.assertTrue(pspec.name in ['normal',
88 self.assertEqual(len(obj), 8)
91 obj = new(PropertyObject, normal="123")
92 self.assertEqual(obj.props.normal, "123")
93 obj.set_property('normal', '456')
94 self.assertEqual(obj.props.normal, "456")
95 obj.props.normal = '789'
96 self.assertEqual(obj.props.normal, "789")
98 def testConstruct(self):
99 obj = new(PropertyObject, construct="123")
100 self.assertEqual(obj.props.construct, "123")
101 obj.set_property('construct', '456')
102 self.assertEqual(obj.props.construct, "456")
103 obj.props.construct = '789'
104 self.assertEqual(obj.props.construct, "789")
107 obj = new(PropertyObject, construct_only=UNICODE_UTF8)
108 self.assertEqual(obj.props.construct_only, TEST_UTF8)
109 obj.set_property('construct', UNICODE_UTF8)
110 self.assertEqual(obj.props.construct, TEST_UTF8)
111 obj.props.normal = UNICODE_UTF8
112 self.assertEqual(obj.props.normal, TEST_UTF8)
114 def testIntToStr(self):
115 obj = new(PropertyObject, construct_only=1)
116 self.assertEqual(obj.props.construct_only, '1')
117 obj.set_property('construct', '2')
118 self.assertEqual(obj.props.construct, '2')
120 self.assertEqual(obj.props.normal, '3')
122 def testConstructOnly(self):
123 obj = new(PropertyObject, construct_only="123")
124 self.assertEqual(obj.props.construct_only, "123")
125 self.assertRaises(TypeError,
126 setattr, obj.props, 'construct_only', '456')
127 self.assertRaises(TypeError,
128 obj.set_property, 'construct-only', '456')
130 def testUint64(self):
131 obj = new(PropertyObject)
132 self.assertEqual(obj.props.uint64, 0)
133 obj.props.uint64 = _long(1)
134 self.assertEqual(obj.props.uint64, _long(1))
136 self.assertEqual(obj.props.uint64, _long(1))
138 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
139 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
141 def testUInt64DefaultValue(self):
143 class TimeControl(GObject.GObject):
145 'time': (TYPE_UINT64, 'Time', 'Time',
146 _long(0), (1 << 64) - 1, _long(0),
149 except OverflowError:
150 (etype, ex) = sys.exc_info()[2:]
154 obj = new(PropertyObject)
155 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
156 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
157 obj.enum = Gio.SocketType.DATAGRAM
158 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
159 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
160 obj.props.enum = Gio.SocketType.STREAM
161 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
162 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
164 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
165 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
167 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
168 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
170 self.assertRaises(TypeError, setattr, obj, 'enum', 'foo')
171 self.assertRaises(TypeError, setattr, obj, 'enum', object())
173 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType)
174 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
175 default=Gio.SocketProtocol.TCP)
176 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
178 self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
182 obj = new(PropertyObject)
183 self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE1)
184 self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE1)
186 obj.flags = GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3
187 self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
188 self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
190 self.assertRaises(TypeError, setattr, obj, 'flags', 'foo')
191 self.assertRaises(TypeError, setattr, obj, 'flags', object())
192 self.assertRaises(TypeError, setattr, obj, 'flags', None)
194 self.assertRaises(TypeError, GObject.Property,
195 type=GIMarshallingTests.Flags, default='foo')
196 self.assertRaises(TypeError, GObject.Property,
197 type=GIMarshallingTests.Flags, default=object())
198 self.assertRaises(TypeError, GObject.Property,
199 type=GIMarshallingTests.Flags, default=None)
202 obj = new(PropertyObject)
204 self.assertEqual(obj.props.gtype, TYPE_NONE)
205 self.assertEqual(obj.gtype, TYPE_NONE)
207 obj.gtype = TYPE_UINT64
208 self.assertEqual(obj.props.gtype, TYPE_UINT64)
209 self.assertEqual(obj.gtype, TYPE_UINT64)
211 obj.gtype = TYPE_INVALID
212 self.assertEqual(obj.props.gtype, TYPE_INVALID)
213 self.assertEqual(obj.gtype, TYPE_INVALID)
215 # GType parameters do not support defaults in GLib
216 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
220 self.assertRaises(TypeError, setattr, obj, 'gtype', 'foo')
221 self.assertRaises(TypeError, setattr, obj, 'gtype', object())
223 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
225 self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
229 obj = new(PropertyObject, gtype=TYPE_UINT)
230 self.assertEqual(obj.props.gtype, TYPE_UINT)
231 self.assertEqual(obj.gtype, TYPE_UINT)
234 obj = new(PropertyObject)
236 regex = GLib.Regex.new('[a-z]*', 0, 0)
237 obj.props.boxed = regex
238 self.assertEqual(obj.props.boxed.get_pattern(), '[a-z]*')
239 self.assertEqual(obj.boxed.get_patttern(), '[a-z]*')
241 self.assertRaises(TypeError, setattr, obj, 'boxed', 'foo')
242 self.assertRaises(TypeError, setattr, obj, 'boxed', object())
247 return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
250 return 2 ** (8 * struct.calcsize(c)) - 1
256 minlong = -maxlong - 1
259 minint64 = -maxint64 - 1
260 maxuint64 = umax('Q')
262 types = dict(int=(TYPE_INT, minint, maxint),
263 uint=(TYPE_UINT, 0, maxuint),
264 long=(TYPE_LONG, minlong, maxlong),
265 ulong=(TYPE_ULONG, 0, maxulong),
266 int64=(TYPE_INT64, minint64, maxint64),
267 uint64=(TYPE_UINT64, 0, maxuint64))
269 def build_gproperties(types):
271 for key, (gtype, min, max) in types.items():
272 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
273 PARAM_READABLE | PARAM_WRITABLE)
276 class RangeCheck(GObject.GObject):
277 __gproperties__ = build_gproperties(types)
281 GObject.GObject.__init__(self)
283 def do_set_property(self, pspec, value):
284 self.values[pspec.name] = value
286 def do_get_property(self, pspec):
287 return self.values.get(pspec.name, pspec.default_value)
289 self.assertEqual(RangeCheck.props.int.minimum, minint)
290 self.assertEqual(RangeCheck.props.int.maximum, maxint)
291 self.assertEqual(RangeCheck.props.uint.minimum, 0)
292 self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
293 self.assertEqual(RangeCheck.props.long.minimum, minlong)
294 self.assertEqual(RangeCheck.props.long.maximum, maxlong)
295 self.assertEqual(RangeCheck.props.ulong.minimum, 0)
296 self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
297 self.assertEqual(RangeCheck.props.int64.minimum, minint64)
298 self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
299 self.assertEqual(RangeCheck.props.uint64.minimum, 0)
300 self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
303 for key, (gtype, min, max) in types.items():
304 self.assertEqual(obj.get_property(key),
305 getattr(RangeCheck.props, key).default_value)
307 obj.set_property(key, min)
308 self.assertEqual(obj.get_property(key), min)
310 obj.set_property(key, max)
311 self.assertEqual(obj.get_property(key), max)
314 obj = PropertyObject()
315 obj.set_properties(normal="foo",
317 normal, uint64 = obj.get_properties("normal", "uint64")
318 self.assertEqual(normal, "foo")
319 self.assertEqual(uint64, 7)
322 class TestProperty(unittest.TestCase):
323 def testSimple(self):
324 class C(GObject.GObject):
325 str = GObject.Property(type=str)
326 int = GObject.Property(type=int)
327 float = GObject.Property(type=float)
328 long = GObject.Property(type=_long)
330 self.assertTrue(hasattr(C.props, 'str'))
331 self.assertTrue(hasattr(C.props, 'int'))
332 self.assertTrue(hasattr(C.props, 'float'))
333 self.assertTrue(hasattr(C.props, 'long'))
336 self.assertEqual(o.str, '')
338 self.assertEqual(o.str, 'str')
340 self.assertEqual(o.int, 0)
342 self.assertEqual(o.int, 1138)
344 self.assertEqual(o.float, 0.0)
346 self.assertEqual(o.float, 3.14)
348 self.assertEqual(o.long, _long(0))
350 self.assertEqual(o.long, _long(100))
352 def testCustomGetter(self):
353 class C(GObject.GObject):
356 prop = GObject.Property(getter=get_prop)
359 self.assertEqual(o.prop, 'value')
360 self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
362 def testCustomSetter(self):
363 class C(GObject.GObject):
364 def set_prop(self, value):
366 prop = GObject.Property(setter=set_prop)
370 GObject.GObject.__init__(self)
373 self.assertEqual(o._value, None)
375 self.assertEqual(o._value, 'bar')
376 self.assertRaises(TypeError, getattr, o, 'prop')
378 def testDecoratorDefault(self):
379 class C(GObject.GObject):
387 def value_setter(self, value):
391 self.assertEqual(o.value, 'value')
393 self.assertEqual(o.value, 'blah')
394 self.assertEqual(o.props.value, 'blah')
396 def testDecoratorWithCall(self):
397 class C(GObject.GObject):
400 @GObject.Property(type=int, default=1, minimum=1, maximum=10)
401 def typedValue(self):
405 def typedValue_setter(self, value):
409 self.assertEqual(o.typedValue, 1)
411 self.assertEqual(o.typedValue, 5)
412 self.assertEqual(o.props.typedValue, 5)
414 def testErrors(self):
415 self.assertRaises(TypeError, GObject.Property, type='str')
416 self.assertRaises(TypeError, GObject.Property, nick=False)
417 self.assertRaises(TypeError, GObject.Property, blurb=False)
418 # this never fail while bool is a subclass of int
421 # self.assertRaises(TypeError, GObject.Property, type=bool, default=0)
422 self.assertRaises(TypeError, GObject.Property, type=bool, default='ciao mamma')
423 self.assertRaises(TypeError, GObject.Property, type=bool)
424 self.assertRaises(TypeError, GObject.Property, type=object, default=0)
425 self.assertRaises(TypeError, GObject.Property, type=complex)
426 self.assertRaises(TypeError, GObject.Property, flags=-10)
428 def testDefaults(self):
429 GObject.Property(type=bool, default=True)
430 GObject.Property(type=bool, default=False)
432 def testNameWithUnderscore(self):
433 class C(GObject.GObject):
434 prop_name = GObject.Property(type=int)
437 self.assertEqual(o.prop_name, 10)
440 maxint64 = 2 ** 62 - 1
441 minint64 = -2 ** 62 - 1
442 maxuint64 = 2 ** 63 - 1
445 (TYPE_INT, G_MININT, G_MAXINT),
446 (TYPE_UINT, 0, G_MAXUINT),
447 (TYPE_LONG, G_MINLONG, G_MAXLONG),
448 (TYPE_ULONG, 0, G_MAXULONG),
449 (TYPE_INT64, minint64, maxint64),
450 (TYPE_UINT64, 0, maxuint64),
453 for gtype, min, max in types:
454 # Normal, everything is alright
455 prop = GObject.Property(type=gtype, minimum=min, maximum=max)
456 subtype = type('', (GObject.GObject,),
458 self.assertEqual(subtype.props.prop.minimum, min)
459 self.assertEqual(subtype.props.prop.maximum, max)
462 self.assertRaises(TypeError,
463 GObject.Property, type=gtype, minimum=min - 1,
466 # Higher than maximum
467 self.assertRaises(TypeError,
468 GObject.Property, type=gtype, minimum=min,
471 def testMinMax(self):
472 class C(GObject.GObject):
473 prop_int = GObject.Property(type=int, minimum=1, maximum=100, default=1)
474 prop_float = GObject.Property(type=float, minimum=0.1, maximum=10.5, default=1.1)
477 GObject.GObject.__init__(self)
479 # we test known-bad values here which cause Gtk-WARNING logs.
480 # Explicitly allow these for this test.
481 old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
484 self.assertEqual(o.prop_int, 1)
487 self.assertEqual(o.prop_int, 5)
490 self.assertEqual(o.prop_int, 5)
493 self.assertEqual(o.prop_int, 5)
495 self.assertEqual(o.prop_float, 1.1)
498 self.assertEqual(o.prop_float, 7.75)
501 self.assertEqual(o.prop_float, 7.75)
504 self.assertEqual(o.prop_float, 7.75)
506 GLib.log_set_always_fatal(old_mask)
508 def testMultipleInstances(self):
509 class C(GObject.GObject):
510 prop = GObject.Property(type=str, default='default')
514 self.assertEqual(o1.prop, 'default')
515 self.assertEqual(o2.prop, 'default')
517 self.assertEqual(o1.prop, 'value')
518 self.assertEqual(o2.prop, 'default')
520 def testObjectProperty(self):
521 class PropertyObject(GObject.GObject):
522 obj = GObject.Property(type=GObject.GObject)
524 pobj1 = PropertyObject()
525 obj1_hash = hash(pobj1)
526 pobj2 = PropertyObject()
531 self.assertEqual(hash(pobj1), obj1_hash)
533 def testObjectSubclassProperty(self):
534 class ObjectSubclass(GObject.GObject):
535 __gtype_name__ = 'ObjectSubclass'
537 class PropertyObjectSubclass(GObject.GObject):
538 obj = GObject.Property(type=ObjectSubclass)
540 PropertyObjectSubclass(obj=ObjectSubclass())
542 def testPropertySubclass(self):
544 class A(GObject.GObject):
545 prop1 = GObject.Property(type=int)
548 prop2 = GObject.Property(type=int)
552 self.assertEqual(b.prop2, 10)
554 self.assertEqual(b.prop1, 20)
556 def testPropertySubclassCustomSetter(self):
558 class A(GObject.GObject):
561 first = GObject.Property(type=str, getter=get_first)
564 def get_second(self):
566 second = GObject.Property(type=str, getter=get_second)
569 self.assertEqual(a.first, 'first')
570 self.assertRaises(TypeError, setattr, a, 'first', 'foo')
573 self.assertEqual(b.first, 'first')
574 self.assertRaises(TypeError, setattr, b, 'first', 'foo')
575 self.assertEqual(b.second, 'second')
576 self.assertRaises(TypeError, setattr, b, 'second', 'foo')
578 def testPropertySubclassCustomSetterError(self):
580 class A(GObject.GObject):
583 first = GObject.Property(type=str, getter=get_first)
585 def do_get_property(self, pspec):
594 def test_float_min(self):
595 GObject.Property(type=float, minimum=-1)
596 GObject.Property(type=GObject.TYPE_FLOAT, minimum=-1)
597 GObject.Property(type=GObject.TYPE_DOUBLE, minimum=-1)
601 def testReferenceCount(self):
602 # We can check directly if an object gets finalized, so we will
603 # observe it indirectly through the refcount of a member object.
605 # We create our dummy object and store its current refcount
607 rc = sys.getrefcount(o)
609 # We add our object as a member to our newly created object we
610 # want to observe. Its refcount is increased by one.
611 t = PropertyObject(normal="test")
613 self.assertEqual(sys.getrefcount(o), rc + 1)
615 # Now we want to ensure we do not leak any references to our
616 # object with properties. If no ref is leaked, then when deleting
617 # the local reference to this object, its reference count shoud
618 # drop to zero, and our dummy object should loose one reference.
620 self.assertEqual(sys.getrefcount(o), rc)
622 def testDocStringAsBlurb(self):
623 class C(GObject.GObject):
626 """blurbed doc string"""
629 self.assertEqual(C.blurbed.blurb, 'blurbed doc string')
632 if __name__ == '__main__':