7 from gi.repository import GObject
8 from gi.repository.GObject import GType, GEnum, 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, \
12 TYPE_ULONG, TYPE_INT64, TYPE_UINT64
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
20 if sys.version_info < (3, 0):
21 TEST_UTF8 = "\xe2\x99\xa5"
22 UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
25 UNICODE_UTF8 = TEST_UTF8
27 from compathelper import _long
29 class PropertyObject(GObject.GObject):
30 normal = GObject.property(type=str)
31 construct = GObject.property(
33 flags=PARAM_READWRITE|PARAM_CONSTRUCT, default='default')
34 construct_only = GObject.property(
36 flags=PARAM_READWRITE|PARAM_CONSTRUCT_ONLY)
37 uint64 = GObject.property(
38 type=TYPE_UINT64, flags=PARAM_READWRITE|PARAM_CONSTRUCT)
40 enum = GObject.property(
41 type=Gio.SocketType, default=Gio.SocketType.STREAM)
43 boxed = GObject.property(
44 type=GLib.Regex, flags=PARAM_READWRITE|PARAM_CONSTRUCT)
46 class TestProperties(unittest.TestCase):
48 obj = PropertyObject()
49 obj.props.normal = "value"
50 self.assertEqual(obj.props.normal, "value")
52 def testListWithInstance(self):
53 obj = PropertyObject()
54 self.failUnless(hasattr(obj.props, "normal"))
56 def testListWithoutInstance(self):
57 self.failUnless(hasattr(PropertyObject.props, "normal"))
59 def testSetNoInstance(self):
61 obj.props.normal = "foobar"
63 self.assertRaises(TypeError, set, PropertyObject)
65 def testIterator(self):
66 for obj in (PropertyObject.props, PropertyObject().props):
69 self.assertEqual(gtype.parent.name, 'GParam')
70 self.failUnless(pspec.name in ['normal',
76 self.assertEqual(len(obj), 6)
79 obj = new(PropertyObject, normal="123")
80 self.assertEqual(obj.props.normal, "123")
81 obj.set_property('normal', '456')
82 self.assertEqual(obj.props.normal, "456")
83 obj.props.normal = '789'
84 self.assertEqual(obj.props.normal, "789")
86 def testConstruct(self):
87 obj = new(PropertyObject, construct="123")
88 self.assertEqual(obj.props.construct, "123")
89 obj.set_property('construct', '456')
90 self.assertEqual(obj.props.construct, "456")
91 obj.props.construct = '789'
92 self.assertEqual(obj.props.construct, "789")
95 obj = new(PropertyObject, construct_only=UNICODE_UTF8)
96 self.assertEqual(obj.props.construct_only, TEST_UTF8)
97 obj.set_property('construct', UNICODE_UTF8)
98 self.assertEqual(obj.props.construct, TEST_UTF8)
99 obj.props.normal = UNICODE_UTF8
100 self.assertEqual(obj.props.normal, TEST_UTF8)
102 def testIntToStr(self):
103 obj = new(PropertyObject, construct_only=1)
104 self.assertEqual(obj.props.construct_only, '1')
105 obj.set_property('construct', '2')
106 self.assertEqual(obj.props.construct, '2')
108 self.assertEqual(obj.props.normal, '3')
110 def testConstructOnly(self):
111 obj = new(PropertyObject, construct_only="123")
112 self.assertEqual(obj.props.construct_only, "123")
113 self.assertRaises(TypeError,
114 setattr, obj.props, 'construct_only', '456')
115 self.assertRaises(TypeError,
116 obj.set_property, 'construct-only', '456')
118 def testUint64(self):
119 obj = new(PropertyObject)
120 self.assertEqual(obj.props.uint64, 0)
121 obj.props.uint64 = _long(1)
122 self.assertEqual(obj.props.uint64, _long(1))
124 self.assertEqual(obj.props.uint64, _long(1))
126 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
127 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
129 def testUInt64DefaultValue(self):
131 class TimeControl(GObject.GObject):
133 'time': (TYPE_UINT64, 'Time', 'Time',
134 _long(0), (1<<64) - 1, _long(0),
137 except OverflowError:
138 (etype, ex) = sys.exc_info()[2:]
142 obj = new(PropertyObject)
143 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
144 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
145 obj.enum = Gio.SocketType.DATAGRAM
146 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
147 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
148 obj.props.enum = Gio.SocketType.STREAM
149 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
150 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
152 self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
153 self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
155 self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
156 self.assertEqual(obj.enum, Gio.SocketType.STREAM)
158 self.assertRaises(TypeError, setattr, obj, 'enum', 'foo')
159 self.assertRaises(TypeError, setattr, obj, 'enum', object())
161 self.assertRaises(TypeError, GObject.property, type=Gio.SocketType)
162 self.assertRaises(TypeError, GObject.property, type=Gio.SocketType,
163 default=Gio.SocketProtocol.TCP)
164 self.assertRaises(TypeError, GObject.property, type=Gio.SocketType,
166 self.assertRaises(TypeError, GObject.property, type=Gio.SocketType,
170 obj = new(PropertyObject)
172 regex = GLib.Regex.new('[a-z]*', 0, 0)
173 obj.props.boxed = regex
174 self.assertEqual(obj.props.boxed.get_pattern(), '[a-z]*')
175 self.assertEqual(obj.boxed.get_patttern(), '[a-z]*')
177 self.assertRaises(TypeError, setattr, obj, 'boxed', 'foo')
178 self.assertRaises(TypeError, setattr, obj, 'boxed', object())
183 return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
185 return 2 ** (8 * struct.calcsize(c)) - 1
191 minlong = -maxlong - 1
194 minint64 = -maxint64 - 1
195 maxuint64 = umax('Q')
197 types = dict(int=(TYPE_INT, minint, maxint),
198 uint=(TYPE_UINT, 0, maxuint),
199 long=(TYPE_LONG, minlong, maxlong),
200 ulong=(TYPE_ULONG, 0, maxulong),
201 int64=(TYPE_INT64, minint64, maxint64),
202 uint64=(TYPE_UINT64, 0, maxuint64))
204 def build_gproperties(types):
206 for key, (gtype, min, max) in types.items():
207 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
208 PARAM_READABLE | PARAM_WRITABLE)
211 class RangeCheck(GObject.GObject):
212 __gproperties__ = build_gproperties(types)
216 GObject.GObject.__init__(self)
218 def do_set_property(self, pspec, value):
219 self.values[pspec.name] = value
221 def do_get_property(self, pspec):
222 return self.values.get(pspec.name, pspec.default_value)
224 self.assertEqual(RangeCheck.props.int.minimum, minint)
225 self.assertEqual(RangeCheck.props.int.maximum, maxint)
226 self.assertEqual(RangeCheck.props.uint.minimum, 0)
227 self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
228 self.assertEqual(RangeCheck.props.long.minimum, minlong)
229 self.assertEqual(RangeCheck.props.long.maximum, maxlong)
230 self.assertEqual(RangeCheck.props.ulong.minimum, 0)
231 self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
232 self.assertEqual(RangeCheck.props.int64.minimum, minint64)
233 self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
234 self.assertEqual(RangeCheck.props.uint64.minimum, 0)
235 self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
238 for key, (gtype, min, max) in types.items():
239 self.assertEqual(obj.get_property(key),
240 getattr(RangeCheck.props, key).default_value)
242 obj.set_property(key, min)
243 self.assertEqual(obj.get_property(key), min)
245 obj.set_property(key, max)
246 self.assertEqual(obj.get_property(key), max)
250 obj = PropertyObject()
251 obj.set_properties(normal="foo",
253 normal, uint64 = obj.get_properties("normal", "uint64")
254 self.assertEqual(normal, "foo")
255 self.assertEqual(uint64, 7)
257 class TestProperty(unittest.TestCase):
258 def testSimple(self):
259 class C(GObject.GObject):
260 str = GObject.property(type=str)
261 int = GObject.property(type=int)
262 float = GObject.property(type=float)
263 long = GObject.property(type=_long)
265 self.failUnless(hasattr(C.props, 'str'))
266 self.failUnless(hasattr(C.props, 'int'))
267 self.failUnless(hasattr(C.props, 'float'))
268 self.failUnless(hasattr(C.props, 'long'))
271 self.assertEqual(o.str, '')
273 self.assertEqual(o.str, 'str')
275 self.assertEqual(o.int, 0)
277 self.assertEqual(o.int, 1138)
279 self.assertEqual(o.float, 0.0)
281 self.assertEqual(o.float, 3.14)
283 self.assertEqual(o.long, _long(0))
285 self.assertEqual(o.long, _long(100))
287 def testCustomGetter(self):
288 class C(GObject.GObject):
291 prop = GObject.property(getter=get_prop)
294 self.assertEqual(o.prop, 'value')
295 self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
297 def testCustomSetter(self):
298 class C(GObject.GObject):
299 def set_prop(self, value):
301 prop = GObject.property(setter=set_prop)
305 GObject.GObject.__init__(self)
308 self.assertEquals(o._value, None)
310 self.assertEquals(o._value, 'bar')
311 self.assertRaises(TypeError, getattr, o, 'prop')
313 def testErrors(self):
314 self.assertRaises(TypeError, GObject.property, type='str')
315 self.assertRaises(TypeError, GObject.property, nick=False)
316 self.assertRaises(TypeError, GObject.property, blurb=False)
317 # this never fail while bool is a subclass of int
320 # self.assertRaises(TypeError, GObject.property, type=bool, default=0)
321 self.assertRaises(TypeError, GObject.property, type=bool, default='ciao mamma')
322 self.assertRaises(TypeError, GObject.property, type=bool)
323 self.assertRaises(TypeError, GObject.property, type=object, default=0)
324 self.assertRaises(TypeError, GObject.property, type=complex)
325 self.assertRaises(TypeError, GObject.property, flags=-10)
327 def testDefaults(self):
328 p1 = GObject.property(type=bool, default=True)
329 p2 = GObject.property(type=bool, default=False)
331 def testNameWithUnderscore(self):
332 class C(GObject.GObject):
333 prop_name = GObject.property(type=int)
336 self.assertEqual(o.prop_name, 10)
339 maxint64 = 2 ** 62 - 1
340 minint64 = -2 ** 62 - 1
341 maxuint64 = 2 ** 63 - 1
344 (TYPE_INT, G_MININT, G_MAXINT),
345 (TYPE_UINT, 0, G_MAXUINT),
346 (TYPE_LONG, G_MINLONG, G_MAXLONG),
347 (TYPE_ULONG, 0, G_MAXULONG),
348 (TYPE_INT64, minint64, maxint64),
349 (TYPE_UINT64, 0, maxuint64),
352 for gtype, min, max in types:
353 # Normal, everything is alright
354 prop = GObject.property(type=gtype, minimum=min, maximum=max)
355 subtype = type('', (GObject.GObject,),
357 self.assertEqual(subtype.props.prop.minimum, min)
358 self.assertEqual(subtype.props.prop.maximum, max)
361 self.assertRaises(TypeError,
362 GObject.property, type=gtype, minimum=min-1,
365 # Higher than maximum
366 self.assertRaises(TypeError,
367 GObject.property, type=gtype, minimum=min,
370 def testMinMax(self):
371 class C(GObject.GObject):
372 prop_int = GObject.property(type=int, minimum=1, maximum=100, default=1)
373 prop_float = GObject.property(type=float, minimum=0.1, maximum=10.5, default=1.1)
376 GObject.GObject.__init__(self)
379 self.assertEqual(o.prop_int, 1)
382 self.assertEqual(o.prop_int, 5)
385 self.assertEqual(o.prop_int, 5)
388 self.assertEqual(o.prop_int, 5)
390 self.assertEqual(o.prop_float, 1.1)
393 self.assertEqual(o.prop_float, 7.75)
396 self.assertEqual(o.prop_float, 7.75)
399 self.assertEqual(o.prop_float, 7.75)
401 def testMultipleInstances(self):
402 class C(GObject.GObject):
403 prop = GObject.property(type=str, default='default')
407 self.assertEqual(o1.prop, 'default')
408 self.assertEqual(o2.prop, 'default')
410 self.assertEqual(o1.prop, 'value')
411 self.assertEqual(o2.prop, 'default')
413 def testObjectProperty(self):
414 class PropertyObject(GObject.GObject):
415 obj = GObject.property(type=GObject.GObject)
417 pobj1 = PropertyObject()
418 obj1_hash = hash(pobj1)
419 pobj2 = PropertyObject()
424 self.assertEqual(hash(pobj1), obj1_hash)
426 def testObjectSubclassProperty(self):
427 class ObjectSubclass(GObject.GObject):
428 __gtype_name__ = 'ObjectSubclass'
430 class PropertyObjectSubclass(GObject.GObject):
431 obj = GObject.property(type=ObjectSubclass)
433 obj1 = PropertyObjectSubclass(obj=ObjectSubclass())
435 def testPropertySubclass(self):
437 class A(GObject.GObject):
438 prop1 = GObject.property(type=int)
441 prop2 = GObject.property(type=int)
445 self.assertEquals(b.prop2, 10)
447 self.assertEquals(b.prop1, 20)
449 def testPropertySubclassCustomSetter(self):
451 class A(GObject.GObject):
454 first = GObject.property(type=str, getter=get_first)
457 def get_second(self):
459 second = GObject.property(type=str, getter=get_second)
462 self.assertEquals(a.first, 'first')
463 self.assertRaises(TypeError, setattr, a, 'first', 'foo')
466 self.assertEquals(b.first, 'first')
467 self.assertRaises(TypeError, setattr, b, 'first', 'foo')
468 self.assertEquals(b.second, 'second')
469 self.assertRaises(TypeError, setattr, b, 'second', 'foo')
471 def testPropertySubclassCustomSetterError(self):
473 class A(GObject.GObject):
476 first = GObject.property(type=str, getter=get_first)
478 def do_get_property(self, pspec):
486 def test_float_min(self):
487 GObject.property(type=float, minimum=-1)
488 GObject.property(type=GObject.TYPE_FLOAT, minimum=-1)
489 GObject.property(type=GObject.TYPE_DOUBLE, minimum=-1)
492 def testReferenceCount(self):
493 # We can check directly if an object gets finalized, so we will
494 # observe it indirectly through the refcount of a member object.
496 # We create our dummy object and store its current refcount
498 rc = sys.getrefcount(o)
500 # We add our object as a member to our newly created object we
501 # want to observe. Its refcount is increased by one.
502 t = PropertyObject(normal="test")
504 self.assertEquals(sys.getrefcount(o), rc + 1)
506 # Now we want to ensure we do not leak any references to our
507 # object with properties. If no ref is leaked, then when deleting
508 # the local reference to this object, its reference count shoud
509 # drop to zero, and our dummy object should loose one reference.
511 self.assertEquals(sys.getrefcount(o), rc)
514 if __name__ == '__main__':