8 from gobject import GObject, GType, GEnum, new, PARAM_READWRITE, \
9 PARAM_CONSTRUCT, PARAM_READABLE, PARAM_WRITABLE, PARAM_CONSTRUCT_ONLY
10 from gobject.constants import \
11 TYPE_INT, TYPE_UINT, TYPE_LONG, \
12 TYPE_ULONG, TYPE_INT64, TYPE_UINT64
13 from gobject.constants import \
14 G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, \
17 if sys.version_info < (3, 0):
18 TEST_UTF8 = "\xe2\x99\xa5"
19 UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
22 UNICODE_UTF8 = TEST_UTF8
24 from compathelper import _long
26 class PropertyObject(GObject):
27 normal = gobject.property(type=str)
28 construct = gobject.property(
30 flags=PARAM_READWRITE|PARAM_CONSTRUCT, default='default')
31 construct_only = gobject.property(
33 flags=PARAM_READWRITE|PARAM_CONSTRUCT_ONLY)
34 uint64 = gobject.property(
35 type=TYPE_UINT64, flags=PARAM_READWRITE|PARAM_CONSTRUCT)
37 class TestProperties(unittest.TestCase):
39 obj = PropertyObject()
40 obj.props.normal = "value"
41 self.assertEqual(obj.props.normal, "value")
43 def testListWithInstance(self):
44 obj = PropertyObject()
45 self.failUnless(hasattr(obj.props, "normal"))
47 def testListWithoutInstance(self):
48 self.failUnless(hasattr(PropertyObject.props, "normal"))
50 def testSetNoInstance(self):
52 obj.props.normal = "foobar"
54 self.assertRaises(TypeError, set, PropertyObject)
56 def testIterator(self):
57 for obj in (PropertyObject.props, PropertyObject().props):
60 self.assertEqual(gtype.parent.name, 'GParam')
61 self.failUnless(pspec.name in ['normal',
65 self.assertEqual(len(obj), 4)
68 obj = new(PropertyObject, normal="123")
69 self.assertEqual(obj.props.normal, "123")
70 obj.set_property('normal', '456')
71 self.assertEqual(obj.props.normal, "456")
72 obj.props.normal = '789'
73 self.assertEqual(obj.props.normal, "789")
75 def testConstruct(self):
76 obj = new(PropertyObject, construct="123")
77 self.assertEqual(obj.props.construct, "123")
78 obj.set_property('construct', '456')
79 self.assertEqual(obj.props.construct, "456")
80 obj.props.construct = '789'
81 self.assertEqual(obj.props.construct, "789")
84 obj = new(PropertyObject, construct_only=UNICODE_UTF8)
85 self.assertEqual(obj.props.construct_only, TEST_UTF8)
86 obj.set_property('construct', UNICODE_UTF8)
87 self.assertEqual(obj.props.construct, TEST_UTF8)
88 obj.props.normal = UNICODE_UTF8
89 self.assertEqual(obj.props.normal, TEST_UTF8)
91 def testIntToStr(self):
92 obj = new(PropertyObject, construct_only=1)
93 self.assertEqual(obj.props.construct_only, '1')
94 obj.set_property('construct', '2')
95 self.assertEqual(obj.props.construct, '2')
97 self.assertEqual(obj.props.normal, '3')
99 def testConstructOnly(self):
100 obj = new(PropertyObject, construct_only="123")
101 self.assertEqual(obj.props.construct_only, "123")
102 self.assertRaises(TypeError,
103 setattr, obj.props, 'construct_only', '456')
104 self.assertRaises(TypeError,
105 obj.set_property, 'construct-only', '456')
107 def testUint64(self):
108 obj = new(PropertyObject)
109 self.assertEqual(obj.props.uint64, 0)
110 obj.props.uint64 = _long(1)
111 self.assertEqual(obj.props.uint64, _long(1))
113 self.assertEqual(obj.props.uint64, _long(1))
115 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
116 self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
118 def testUInt64DefaultValue(self):
120 class TimeControl(GObject):
122 'time': (TYPE_UINT64, 'Time', 'Time',
123 _long(0), (1<<64) - 1, _long(0),
126 except OverflowError:
127 (etype, ex) = sys.exc_info()[2:]
133 return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
135 return 2 ** (8 * struct.calcsize(c)) - 1
141 minlong = -maxlong - 1
144 minint64 = -maxint64 - 1
145 maxuint64 = umax('Q')
147 types = dict(int=(TYPE_INT, minint, maxint),
148 uint=(TYPE_UINT, 0, maxuint),
149 long=(TYPE_LONG, minlong, maxlong),
150 ulong=(TYPE_ULONG, 0, maxulong),
151 int64=(TYPE_INT64, minint64, maxint64),
152 uint64=(TYPE_UINT64, 0, maxuint64))
154 def build_gproperties(types):
156 for key, (gtype, min, max) in types.items():
157 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
158 PARAM_READABLE | PARAM_WRITABLE)
161 class RangeCheck(GObject):
162 __gproperties__ = build_gproperties(types)
166 GObject.__init__(self)
168 def do_set_property(self, pspec, value):
169 self.values[pspec.name] = value
171 def do_get_property(self, pspec):
172 return self.values.get(pspec.name, pspec.default_value)
174 self.assertEqual(RangeCheck.props.int.minimum, minint)
175 self.assertEqual(RangeCheck.props.int.maximum, maxint)
176 self.assertEqual(RangeCheck.props.uint.minimum, 0)
177 self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
178 self.assertEqual(RangeCheck.props.long.minimum, minlong)
179 self.assertEqual(RangeCheck.props.long.maximum, maxlong)
180 self.assertEqual(RangeCheck.props.ulong.minimum, 0)
181 self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
182 self.assertEqual(RangeCheck.props.int64.minimum, minint64)
183 self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
184 self.assertEqual(RangeCheck.props.uint64.minimum, 0)
185 self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
188 for key, (gtype, min, max) in types.items():
189 self.assertEqual(obj.get_property(key),
190 getattr(RangeCheck.props, key).default_value)
192 obj.set_property(key, min)
193 self.assertEqual(obj.get_property(key), min)
195 obj.set_property(key, max)
196 self.assertEqual(obj.get_property(key), max)
200 obj = PropertyObject()
201 obj.set_properties(normal="foo",
203 normal, uint64 = obj.get_properties("normal", "uint64")
204 self.assertEqual(normal, "foo")
205 self.assertEqual(uint64, 7)
207 class TestProperty(unittest.TestCase):
208 def testSimple(self):
209 class C(gobject.GObject):
210 str = gobject.property(type=str)
211 int = gobject.property(type=int)
212 float = gobject.property(type=float)
213 long = gobject.property(type=_long)
215 self.failUnless(hasattr(C.props, 'str'))
216 self.failUnless(hasattr(C.props, 'int'))
217 self.failUnless(hasattr(C.props, 'float'))
218 self.failUnless(hasattr(C.props, 'long'))
221 self.assertEqual(o.str, '')
223 self.assertEqual(o.str, 'str')
225 self.assertEqual(o.int, 0)
227 self.assertEqual(o.int, 1138)
229 self.assertEqual(o.float, 0.0)
231 self.assertEqual(o.float, 3.14)
233 self.assertEqual(o.long, _long(0))
235 self.assertEqual(o.long, _long(100))
237 def testCustomGetter(self):
238 class C(gobject.GObject):
241 prop = gobject.property(getter=get_prop)
244 self.assertEqual(o.prop, 'value')
245 self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
247 def testCustomSetter(self):
248 class C(gobject.GObject):
249 def set_prop(self, value):
251 prop = gobject.property(setter=set_prop)
255 gobject.GObject.__init__(self)
258 self.assertEquals(o._value, None)
260 self.assertEquals(o._value, 'bar')
261 self.assertRaises(TypeError, getattr, o, 'prop')
263 def testErrors(self):
264 self.assertRaises(TypeError, gobject.property, type='str')
265 self.assertRaises(TypeError, gobject.property, nick=False)
266 self.assertRaises(TypeError, gobject.property, blurb=False)
267 # this never fail while bool is a subclass of int
270 # self.assertRaises(TypeError, gobject.property, type=bool, default=0)
271 self.assertRaises(TypeError, gobject.property, type=bool, default='ciao mamma')
272 self.assertRaises(TypeError, gobject.property, type=bool)
273 self.assertRaises(TypeError, gobject.property, type=GEnum)
274 self.assertRaises(TypeError, gobject.property, type=GEnum, default=0)
275 self.assertRaises(TypeError, gobject.property, type=object, default=0)
276 self.assertRaises(TypeError, gobject.property, type=complex)
277 self.assertRaises(TypeError, gobject.property, flags=-10)
279 def testDefaults(self):
280 p1 = gobject.property(type=bool, default=True)
281 p2 = gobject.property(type=bool, default=False)
283 def testNameWithUnderscore(self):
284 class C(gobject.GObject):
285 prop_name = gobject.property(type=int)
288 self.assertEqual(o.prop_name, 10)
291 maxint64 = 2 ** 62 - 1
292 minint64 = -2 ** 62 - 1
293 maxuint64 = 2 ** 63 - 1
296 (TYPE_INT, G_MININT, G_MAXINT),
297 (TYPE_UINT, 0, G_MAXUINT),
298 (TYPE_LONG, G_MINLONG, G_MAXLONG),
299 (TYPE_ULONG, 0, G_MAXULONG),
300 (TYPE_INT64, minint64, maxint64),
301 (TYPE_UINT64, 0, maxuint64),
304 for gtype, min, max in types:
305 # Normal, everything is alright
306 prop = gobject.property(type=gtype, minimum=min, maximum=max)
307 subtype = type('', (gobject.GObject,),
309 self.assertEqual(subtype.props.prop.minimum, min)
310 self.assertEqual(subtype.props.prop.maximum, max)
313 self.assertRaises(TypeError,
314 gobject.property, type=gtype, minimum=min-1,
317 # Higher than maximum
318 self.assertRaises(TypeError,
319 gobject.property, type=gtype, minimum=min,
322 def testMultipleInstances(self):
323 class C(gobject.GObject):
324 prop = gobject.property(type=str, default='default')
328 self.assertEqual(o1.prop, 'default')
329 self.assertEqual(o2.prop, 'default')
331 self.assertEqual(o1.prop, 'value')
332 self.assertEqual(o2.prop, 'default')
334 def testObjectProperty(self):
335 class PropertyObject(GObject):
336 obj = gobject.property(type=GObject)
338 pobj1 = PropertyObject()
339 obj1_hash = hash(pobj1)
340 pobj2 = PropertyObject()
345 self.assertEqual(hash(pobj1), obj1_hash)
347 def testObjectSubclassProperty(self):
348 class ObjectSubclass(GObject):
349 __gtype_name__ = 'ObjectSubclass'
351 class PropertyObjectSubclass(GObject):
352 obj = gobject.property(type=ObjectSubclass)
354 obj1 = PropertyObjectSubclass(obj=ObjectSubclass())
356 def testPropertySubclass(self):
359 prop1 = gobject.property(type=int)
362 prop2 = gobject.property(type=int)
366 self.assertEquals(b.prop2, 10)
368 self.assertEquals(b.prop1, 20)
370 def testPropertySubclassCustomSetter(self):
375 first = gobject.property(type=str, getter=get_first)
378 def get_second(self):
380 second = gobject.property(type=str, getter=get_second)
383 self.assertEquals(a.first, 'first')
384 self.assertRaises(TypeError, setattr, a, 'first', 'foo')
387 self.assertEquals(b.first, 'first')
388 self.assertRaises(TypeError, setattr, b, 'first', 'foo')
389 self.assertEquals(b.second, 'second')
390 self.assertRaises(TypeError, setattr, b, 'second', 'foo')
392 def testPropertySubclassCustomSetterError(self):
397 first = gobject.property(type=str, getter=get_first)
399 def do_get_property(self, pspec):
407 def test_float_min(self):
408 gobject.property(type=float, minimum=-1)
409 gobject.property(type=gobject.TYPE_FLOAT, minimum=-1)
410 gobject.property(type=gobject.TYPE_DOUBLE, minimum=-1)
413 def testReferenceCount(self):
414 # We can check directly if an object gets finalized, so we will
415 # observe it indirectly through the refcount of a member object.
417 # We create our dummy object and store its current refcount
419 rc = sys.getrefcount(o)
421 # We add our object as a member to our newly created object we
422 # want to observe. Its refcount is increased by one.
423 t = PropertyObject(normal="test")
425 self.assertEquals(sys.getrefcount(o), rc + 1)
427 # Now we want to ensure we do not leak any references to our
428 # object with properties. If no ref is leaked, then when deleting
429 # the local reference to this object, its reference count shoud
430 # drop to zero, and our dummy object should loose one reference.
432 self.assertEquals(sys.getrefcount(o), rc)
435 if __name__ == '__main__':