405375dfd19bc07b86444294c6325ef8509e46d9
[platform/upstream/python-gobject.git] / tests / test_properties.py
1 # coding=utf-8
2
3 import sys
4 import struct
5 import types
6 import unittest
7
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
17
18 from gi.repository.GObject import \
19     G_MININT, G_MAXINT, G_MAXUINT, G_MINLONG, G_MAXLONG, G_MAXULONG
20
21 from gi.repository import Gio
22 from gi.repository import GLib
23 from gi.repository import GIMarshallingTests
24
25 if sys.version_info < (3, 0):
26     TEST_UTF8 = "\xe2\x99\xa5"
27     UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
28 else:
29     TEST_UTF8 = "♥"
30     UNICODE_UTF8 = TEST_UTF8
31
32 from compathelper import _long
33
34
35 class PropertyObject(GObject.GObject):
36     normal = GObject.Property(type=str)
37     construct = GObject.Property(
38         type=str,
39         flags=PARAM_READWRITE | PARAM_CONSTRUCT, default='default')
40     construct_only = GObject.Property(
41         type=str,
42         flags=PARAM_READWRITE | PARAM_CONSTRUCT_ONLY)
43     uint64 = GObject.Property(
44         type=TYPE_UINT64, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
45
46     enum = GObject.Property(
47         type=Gio.SocketType, default=Gio.SocketType.STREAM)
48
49     boxed = GObject.Property(
50         type=GLib.Regex, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
51
52     flags = GObject.Property(
53         type=GIMarshallingTests.Flags, flags=PARAM_READWRITE | PARAM_CONSTRUCT,
54         default=GIMarshallingTests.Flags.VALUE1)
55
56     gtype = GObject.Property(
57         type=TYPE_GTYPE, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
58
59     strings = GObject.Property(
60         type=TYPE_STRV, flags=PARAM_READWRITE | PARAM_CONSTRUCT)
61
62
63 class TestPropertyObject(unittest.TestCase):
64     def test_get_set(self):
65         obj = PropertyObject()
66         obj.props.normal = "value"
67         self.assertEqual(obj.props.normal, "value")
68
69     def test_hasattr_on_object(self):
70         obj = PropertyObject()
71         self.assertTrue(hasattr(obj.props, "normal"))
72
73     def test_hasattr_on_class(self):
74         self.assertTrue(hasattr(PropertyObject.props, "normal"))
75
76     def test_set_on_class(self):
77         def set(obj):
78             obj.props.normal = "foobar"
79
80         self.assertRaises(TypeError, set, PropertyObject)
81
82     def test_iteration(self):
83         for obj in (PropertyObject.props, PropertyObject().props):
84             for pspec in obj:
85                 gtype = GType(pspec)
86                 self.assertEqual(gtype.parent.name, 'GParam')
87                 self.assertTrue(pspec.name in ['normal',
88                                                'construct',
89                                                'construct-only',
90                                                'uint64',
91                                                'enum',
92                                                'flags',
93                                                'gtype',
94                                                'strings',
95                                                'boxed'])
96             self.assertEqual(len(obj), 9)
97
98     def test_normal(self):
99         obj = new(PropertyObject, normal="123")
100         self.assertEqual(obj.props.normal, "123")
101         obj.set_property('normal', '456')
102         self.assertEqual(obj.props.normal, "456")
103         obj.props.normal = '789'
104         self.assertEqual(obj.props.normal, "789")
105
106     def test_construct(self):
107         obj = new(PropertyObject, construct="123")
108         self.assertEqual(obj.props.construct, "123")
109         obj.set_property('construct', '456')
110         self.assertEqual(obj.props.construct, "456")
111         obj.props.construct = '789'
112         self.assertEqual(obj.props.construct, "789")
113
114     def test_utf8(self):
115         obj = new(PropertyObject, construct_only=UNICODE_UTF8)
116         self.assertEqual(obj.props.construct_only, TEST_UTF8)
117         obj.set_property('construct', UNICODE_UTF8)
118         self.assertEqual(obj.props.construct, TEST_UTF8)
119         obj.props.normal = UNICODE_UTF8
120         self.assertEqual(obj.props.normal, TEST_UTF8)
121
122     def test_int_to_str(self):
123         obj = new(PropertyObject, construct_only=1)
124         self.assertEqual(obj.props.construct_only, '1')
125         obj.set_property('construct', '2')
126         self.assertEqual(obj.props.construct, '2')
127         obj.props.normal = 3
128         self.assertEqual(obj.props.normal, '3')
129
130     def test_construct_only(self):
131         obj = new(PropertyObject, construct_only="123")
132         self.assertEqual(obj.props.construct_only, "123")
133         self.assertRaises(TypeError,
134                           setattr, obj.props, 'construct_only', '456')
135         self.assertRaises(TypeError,
136                           obj.set_property, 'construct-only', '456')
137
138     def test_uint64(self):
139         obj = new(PropertyObject)
140         self.assertEqual(obj.props.uint64, 0)
141         obj.props.uint64 = _long(1)
142         self.assertEqual(obj.props.uint64, _long(1))
143         obj.props.uint64 = 1
144         self.assertEqual(obj.props.uint64, _long(1))
145
146         self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
147         self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
148
149     def test_uint64_default_value(self):
150         try:
151             class TimeControl(GObject.GObject):
152                 __gproperties__ = {
153                     'time': (TYPE_UINT64, 'Time', 'Time',
154                              _long(0), (1 << 64) - 1, _long(0),
155                              PARAM_READABLE)
156                     }
157         except OverflowError:
158             (etype, ex) = sys.exc_info()[2:]
159             self.fail(str(ex))
160
161     def test_enum(self):
162         obj = new(PropertyObject)
163         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
164         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
165         obj.enum = Gio.SocketType.DATAGRAM
166         self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
167         self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
168         obj.props.enum = Gio.SocketType.STREAM
169         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
170         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
171         obj.props.enum = 2
172         self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
173         self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
174         obj.enum = 1
175         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
176         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
177
178         self.assertRaises(TypeError, setattr, obj, 'enum', 'foo')
179         self.assertRaises(TypeError, setattr, obj, 'enum', object())
180
181         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType)
182         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
183                           default=Gio.SocketProtocol.TCP)
184         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
185                           default=object())
186         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
187                           default=1)
188
189     def test_flags(self):
190         obj = new(PropertyObject)
191         self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE1)
192         self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE1)
193
194         obj.flags = GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3
195         self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
196         self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
197
198         self.assertRaises(TypeError, setattr, obj, 'flags', 'foo')
199         self.assertRaises(TypeError, setattr, obj, 'flags', object())
200         self.assertRaises(TypeError, setattr, obj, 'flags', None)
201
202         self.assertRaises(TypeError, GObject.Property,
203                           type=GIMarshallingTests.Flags, default='foo')
204         self.assertRaises(TypeError, GObject.Property,
205                           type=GIMarshallingTests.Flags, default=object())
206         self.assertRaises(TypeError, GObject.Property,
207                           type=GIMarshallingTests.Flags, default=None)
208
209     def test_gtype(self):
210         obj = new(PropertyObject)
211
212         self.assertEqual(obj.props.gtype, TYPE_NONE)
213         self.assertEqual(obj.gtype, TYPE_NONE)
214
215         obj.gtype = TYPE_UINT64
216         self.assertEqual(obj.props.gtype, TYPE_UINT64)
217         self.assertEqual(obj.gtype, TYPE_UINT64)
218
219         obj.gtype = TYPE_INVALID
220         self.assertEqual(obj.props.gtype, TYPE_INVALID)
221         self.assertEqual(obj.gtype, TYPE_INVALID)
222
223         # GType parameters do not support defaults in GLib
224         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
225                           default=TYPE_INT)
226
227         # incompatible type
228         self.assertRaises(TypeError, setattr, obj, 'gtype', 'foo')
229         self.assertRaises(TypeError, setattr, obj, 'gtype', object())
230
231         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
232                           default='foo')
233         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
234                           default=object())
235
236         # set in constructor
237         obj = new(PropertyObject, gtype=TYPE_UINT)
238         self.assertEqual(obj.props.gtype, TYPE_UINT)
239         self.assertEqual(obj.gtype, TYPE_UINT)
240
241     def test_boxed(self):
242         obj = new(PropertyObject)
243
244         regex = GLib.Regex.new('[a-z]*', 0, 0)
245         obj.props.boxed = regex
246         self.assertEqual(obj.props.boxed.get_pattern(), '[a-z]*')
247         self.assertEqual(obj.boxed.get_pattern(), '[a-z]*')
248
249         self.assertRaises(TypeError, setattr, obj, 'boxed', 'foo')
250         self.assertRaises(TypeError, setattr, obj, 'boxed', object())
251
252     def test_strings(self):
253         obj = new(PropertyObject)
254
255         # Should work with actual GStrv objects as well as
256         # Python string lists
257         class GStrv(list):
258             __gtype__ = GObject.TYPE_STRV
259
260         self.assertEqual(obj.props.strings, GStrv([]))
261         self.assertEqual(obj.strings, GStrv([]))
262         self.assertEqual(obj.props.strings, [])
263         self.assertEqual(obj.strings, [])
264
265         obj.strings = ['hello', 'world']
266         self.assertEqual(obj.props.strings, ['hello', 'world'])
267         self.assertEqual(obj.strings, ['hello', 'world'])
268
269         obj.strings = GStrv(['hello', 'world'])
270         self.assertEqual(obj.props.strings, GStrv(['hello', 'world']))
271         self.assertEqual(obj.strings, GStrv(['hello', 'world']))
272
273         obj.strings = []
274         self.assertEqual(obj.strings, [])
275         obj.strings = GStrv([])
276         self.assertEqual(obj.strings, GStrv([]))
277
278         p = GObject.Property(type=TYPE_STRV, default=['hello', '1'])
279         self.assertEqual(p.default, ['hello', '1'])
280         self.assertEqual(p.type, TYPE_STRV)
281         p = GObject.Property(type=TYPE_STRV, default=GStrv(['hello', '1']))
282         self.assertEqual(p.default, ['hello', '1'])
283         self.assertEqual(p.type, TYPE_STRV)
284
285         # set in constructor
286         obj = new(PropertyObject, strings=['hello', 'world'])
287         self.assertEqual(obj.props.strings, ['hello', 'world'])
288         self.assertEqual(obj.strings, ['hello', 'world'])
289
290         # wrong types
291         self.assertRaises(TypeError, setattr, obj, 'strings', 1)
292         self.assertRaises(TypeError, setattr, obj, 'strings', 'foo')
293         self.assertRaises(TypeError, setattr, obj, 'strings', ['foo', 1])
294
295         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
296                           default=1)
297         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
298                           default='foo')
299         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
300                           default=['hello', 1])
301
302     def test_range(self):
303         # kiwi code
304         def max(c):
305             return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
306
307         def umax(c):
308             return 2 ** (8 * struct.calcsize(c)) - 1
309
310         maxint = max('i')
311         minint = -maxint - 1
312         maxuint = umax('I')
313         maxlong = max('l')
314         minlong = -maxlong - 1
315         maxulong = umax('L')
316         maxint64 = max('q')
317         minint64 = -maxint64 - 1
318         maxuint64 = umax('Q')
319
320         types_ = dict(int=(TYPE_INT, minint, maxint),
321                       uint=(TYPE_UINT, 0, maxuint),
322                       long=(TYPE_LONG, minlong, maxlong),
323                       ulong=(TYPE_ULONG, 0, maxulong),
324                       int64=(TYPE_INT64, minint64, maxint64),
325                       uint64=(TYPE_UINT64, 0, maxuint64))
326
327         def build_gproperties(types_):
328             d = {}
329             for key, (gtype, min, max) in types_.items():
330                 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
331                           PARAM_READABLE | PARAM_WRITABLE)
332             return d
333
334         class RangeCheck(GObject.GObject):
335             __gproperties__ = build_gproperties(types_)
336
337             def __init__(self):
338                 self.values = {}
339                 GObject.GObject.__init__(self)
340
341             def do_set_property(self, pspec, value):
342                 self.values[pspec.name] = value
343
344             def do_get_property(self, pspec):
345                 return self.values.get(pspec.name, pspec.default_value)
346
347         self.assertEqual(RangeCheck.props.int.minimum, minint)
348         self.assertEqual(RangeCheck.props.int.maximum, maxint)
349         self.assertEqual(RangeCheck.props.uint.minimum, 0)
350         self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
351         self.assertEqual(RangeCheck.props.long.minimum, minlong)
352         self.assertEqual(RangeCheck.props.long.maximum, maxlong)
353         self.assertEqual(RangeCheck.props.ulong.minimum, 0)
354         self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
355         self.assertEqual(RangeCheck.props.int64.minimum, minint64)
356         self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
357         self.assertEqual(RangeCheck.props.uint64.minimum, 0)
358         self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
359
360         obj = RangeCheck()
361         for key, (gtype, min, max) in types_.items():
362             self.assertEqual(obj.get_property(key),
363                              getattr(RangeCheck.props, key).default_value)
364
365             obj.set_property(key, min)
366             self.assertEqual(obj.get_property(key), min)
367
368             obj.set_property(key, max)
369             self.assertEqual(obj.get_property(key), max)
370
371     def test_multi(self):
372         obj = PropertyObject()
373         obj.set_properties(normal="foo",
374                            uint64=7)
375         normal, uint64 = obj.get_properties("normal", "uint64")
376         self.assertEqual(normal, "foo")
377         self.assertEqual(uint64, 7)
378
379
380 class TestProperty(unittest.TestCase):
381     def test_simple(self):
382         class C(GObject.GObject):
383             str = GObject.Property(type=str)
384             int = GObject.Property(type=int)
385             float = GObject.Property(type=float)
386             long = GObject.Property(type=_long)
387
388         self.assertTrue(hasattr(C.props, 'str'))
389         self.assertTrue(hasattr(C.props, 'int'))
390         self.assertTrue(hasattr(C.props, 'float'))
391         self.assertTrue(hasattr(C.props, 'long'))
392
393         o = C()
394         self.assertEqual(o.str, '')
395         o.str = 'str'
396         self.assertEqual(o.str, 'str')
397
398         self.assertEqual(o.int, 0)
399         o.int = 1138
400         self.assertEqual(o.int, 1138)
401
402         self.assertEqual(o.float, 0.0)
403         o.float = 3.14
404         self.assertEqual(o.float, 3.14)
405
406         self.assertEqual(o.long, _long(0))
407         o.long = _long(100)
408         self.assertEqual(o.long, _long(100))
409
410     def test_custom_getter(self):
411         class C(GObject.GObject):
412             def get_prop(self):
413                 return 'value'
414             prop = GObject.Property(getter=get_prop)
415
416         o = C()
417         self.assertEqual(o.prop, 'value')
418         self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
419
420     def test_custom_setter(self):
421         class C(GObject.GObject):
422             def set_prop(self, value):
423                 self._value = value
424             prop = GObject.Property(setter=set_prop)
425
426             def __init__(self):
427                 self._value = None
428                 GObject.GObject.__init__(self)
429
430         o = C()
431         self.assertEqual(o._value, None)
432         o.prop = 'bar'
433         self.assertEqual(o._value, 'bar')
434         self.assertRaises(TypeError, getattr, o, 'prop')
435
436     def test_decorator_default(self):
437         class C(GObject.GObject):
438             _value = 'value'
439
440             @GObject.Property
441             def value(self):
442                 return self._value
443
444             @value.setter
445             def value_setter(self, value):
446                 self._value = value
447
448         o = C()
449         self.assertEqual(o.value, 'value')
450         o.value = 'blah'
451         self.assertEqual(o.value, 'blah')
452         self.assertEqual(o.props.value, 'blah')
453
454     def test_decorator_with_call(self):
455         class C(GObject.GObject):
456             _value = 1
457
458             @GObject.Property(type=int, default=1, minimum=1, maximum=10)
459             def typedValue(self):
460                 return self._value
461
462             @typedValue.setter
463             def typedValue_setter(self, value):
464                 self._value = value
465
466         o = C()
467         self.assertEqual(o.typedValue, 1)
468         o.typedValue = 5
469         self.assertEqual(o.typedValue, 5)
470         self.assertEqual(o.props.typedValue, 5)
471
472     def test_errors(self):
473         self.assertRaises(TypeError, GObject.Property, type='str')
474         self.assertRaises(TypeError, GObject.Property, nick=False)
475         self.assertRaises(TypeError, GObject.Property, blurb=False)
476         # this never fail while bool is a subclass of int
477         # >>> bool.__bases__
478         # (<type 'int'>,)
479         # self.assertRaises(TypeError, GObject.Property, type=bool, default=0)
480         self.assertRaises(TypeError, GObject.Property, type=bool, default='ciao mamma')
481         self.assertRaises(TypeError, GObject.Property, type=bool)
482         self.assertRaises(TypeError, GObject.Property, type=object, default=0)
483         self.assertRaises(TypeError, GObject.Property, type=complex)
484         self.assertRaises(TypeError, GObject.Property, flags=-10)
485
486     def test_defaults(self):
487         GObject.Property(type=bool, default=True)
488         GObject.Property(type=bool, default=False)
489
490     def test_name_with_underscore(self):
491         class C(GObject.GObject):
492             prop_name = GObject.Property(type=int)
493         o = C()
494         o.prop_name = 10
495         self.assertEqual(o.prop_name, 10)
496
497     def test_range(self):
498         maxint64 = 2 ** 62 - 1
499         minint64 = -2 ** 62 - 1
500         maxuint64 = 2 ** 63 - 1
501
502         types_ = [
503             (TYPE_INT, G_MININT, G_MAXINT),
504             (TYPE_UINT, 0, G_MAXUINT),
505             (TYPE_LONG, G_MINLONG, G_MAXLONG),
506             (TYPE_ULONG, 0, G_MAXULONG),
507             (TYPE_INT64, minint64, maxint64),
508             (TYPE_UINT64, 0, maxuint64),
509             ]
510
511         for gtype, min, max in types_:
512             # Normal, everything is alright
513             prop = GObject.Property(type=gtype, minimum=min, maximum=max)
514             subtype = type('', (GObject.GObject,), dict(prop=prop))
515             self.assertEqual(subtype.props.prop.minimum, min)
516             self.assertEqual(subtype.props.prop.maximum, max)
517
518             # Lower than minimum
519             self.assertRaises(TypeError,
520                               GObject.Property, type=gtype, minimum=min - 1,
521                               maximum=max)
522
523             # Higher than maximum
524             self.assertRaises(TypeError,
525                               GObject.Property, type=gtype, minimum=min,
526                               maximum=max + 1)
527
528     def test_min_max(self):
529         class C(GObject.GObject):
530             prop_int = GObject.Property(type=int, minimum=1, maximum=100, default=1)
531             prop_float = GObject.Property(type=float, minimum=0.1, maximum=10.5, default=1.1)
532
533             def __init__(self):
534                 GObject.GObject.__init__(self)
535
536         # we test known-bad values here which cause Gtk-WARNING logs.
537         # Explicitly allow these for this test.
538         old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
539         try:
540             o = C()
541             self.assertEqual(o.prop_int, 1)
542
543             o.prop_int = 5
544             self.assertEqual(o.prop_int, 5)
545
546             o.prop_int = 0
547             self.assertEqual(o.prop_int, 5)
548
549             o.prop_int = 101
550             self.assertEqual(o.prop_int, 5)
551
552             self.assertEqual(o.prop_float, 1.1)
553
554             o.prop_float = 7.75
555             self.assertEqual(o.prop_float, 7.75)
556
557             o.prop_float = 0.09
558             self.assertEqual(o.prop_float, 7.75)
559
560             o.prop_float = 10.51
561             self.assertEqual(o.prop_float, 7.75)
562         finally:
563             GLib.log_set_always_fatal(old_mask)
564
565     def test_multiple_instances(self):
566         class C(GObject.GObject):
567             prop = GObject.Property(type=str, default='default')
568
569         o1 = C()
570         o2 = C()
571         self.assertEqual(o1.prop, 'default')
572         self.assertEqual(o2.prop, 'default')
573         o1.prop = 'value'
574         self.assertEqual(o1.prop, 'value')
575         self.assertEqual(o2.prop, 'default')
576
577     def test_object_property(self):
578         class PropertyObject(GObject.GObject):
579             obj = GObject.Property(type=GObject.GObject)
580
581         pobj1 = PropertyObject()
582         obj1_hash = hash(pobj1)
583         pobj2 = PropertyObject()
584
585         pobj2.obj = pobj1
586         del pobj1
587         pobj1 = pobj2.obj
588         self.assertEqual(hash(pobj1), obj1_hash)
589
590     def test_object_subclass_property(self):
591         class ObjectSubclass(GObject.GObject):
592             __gtype_name__ = 'ObjectSubclass'
593
594         class PropertyObjectSubclass(GObject.GObject):
595             obj = GObject.Property(type=ObjectSubclass)
596
597         PropertyObjectSubclass(obj=ObjectSubclass())
598
599     def test_property_subclass(self):
600         # test for #470718
601         class A(GObject.GObject):
602             prop1 = GObject.Property(type=int)
603
604         class B(A):
605             prop2 = GObject.Property(type=int)
606
607         b = B()
608         b.prop2 = 10
609         self.assertEqual(b.prop2, 10)
610         b.prop1 = 20
611         self.assertEqual(b.prop1, 20)
612
613     def test_property_subclass_c(self):
614         class A(GIMarshallingTests.PropertiesObject):
615             prop1 = GObject.Property(type=int)
616
617         a = A()
618         a.prop1 = 10
619         self.assertEqual(a.prop1, 10)
620
621         # also has parent properties
622         a.props.some_int = 20
623         self.assertEqual(a.props.some_int, 20)
624
625     def test_property_subclass_custom_setter(self):
626         # test for #523352
627         class A(GObject.GObject):
628             def get_first(self):
629                 return 'first'
630             first = GObject.Property(type=str, getter=get_first)
631
632         class B(A):
633             def get_second(self):
634                 return 'second'
635             second = GObject.Property(type=str, getter=get_second)
636
637         a = A()
638         self.assertEqual(a.first, 'first')
639         self.assertRaises(TypeError, setattr, a, 'first', 'foo')
640
641         b = B()
642         self.assertEqual(b.first, 'first')
643         self.assertRaises(TypeError, setattr, b, 'first', 'foo')
644         self.assertEqual(b.second, 'second')
645         self.assertRaises(TypeError, setattr, b, 'second', 'foo')
646
647     def test_property_subclass_custom_setter_error(self):
648         try:
649             class A(GObject.GObject):
650                 def get_first(self):
651                     return 'first'
652                 first = GObject.Property(type=str, getter=get_first)
653
654                 def do_get_property(self, pspec):
655                     pass
656         except TypeError:
657             pass
658         else:
659             raise AssertionError
660
661     # Bug 587637.
662
663     def test_float_min(self):
664         GObject.Property(type=float, minimum=-1)
665         GObject.Property(type=GObject.TYPE_FLOAT, minimum=-1)
666         GObject.Property(type=GObject.TYPE_DOUBLE, minimum=-1)
667
668     # Bug 644039
669
670     def test_reference_count(self):
671         # We can check directly if an object gets finalized, so we will
672         # observe it indirectly through the refcount of a member object.
673
674         # We create our dummy object and store its current refcount
675         o = object()
676         rc = sys.getrefcount(o)
677
678         # We add our object as a member to our newly created object we
679         # want to observe. Its refcount is increased by one.
680         t = PropertyObject(normal="test")
681         t.o = o
682         self.assertEqual(sys.getrefcount(o), rc + 1)
683
684         # Now we want to ensure we do not leak any references to our
685         # object with properties. If no ref is leaked, then when deleting
686         # the local reference to this object, its reference count shoud
687         # drop to zero, and our dummy object should loose one reference.
688         del t
689         self.assertEqual(sys.getrefcount(o), rc)
690
691     def test_doc_string_as_blurb(self):
692         class C(GObject.GObject):
693             @GObject.Property
694             def blurbed(self):
695                 """blurbed doc string"""
696                 return 0
697
698         self.assertEqual(C.blurbed.blurb, 'blurbed doc string')
699
700     def test_python_to_glib_type_mapping(self):
701         tester = GObject.Property()
702         self.assertEqual(tester._type_from_python(int), GObject.TYPE_INT)
703         if sys.version_info < (3, 0):
704             self.assertEqual(tester._type_from_python(long), GObject.TYPE_LONG)
705         self.assertEqual(tester._type_from_python(bool), GObject.TYPE_BOOLEAN)
706         self.assertEqual(tester._type_from_python(float), GObject.TYPE_DOUBLE)
707         self.assertEqual(tester._type_from_python(str), GObject.TYPE_STRING)
708         self.assertEqual(tester._type_from_python(object), GObject.TYPE_PYOBJECT)
709
710         self.assertEqual(tester._type_from_python(GObject.GObject), GObject.GObject.__gtype__)
711         self.assertEqual(tester._type_from_python(GObject.GEnum), GObject.GEnum.__gtype__)
712         self.assertEqual(tester._type_from_python(GObject.GFlags), GObject.GFlags.__gtype__)
713         self.assertEqual(tester._type_from_python(GObject.GBoxed), GObject.GBoxed.__gtype__)
714
715         for type_ in [TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR,
716                       TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG,
717                       TYPE_ULONG, TYPE_INT64, TYPE_UINT64,
718                       TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER,
719                       TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING,
720                       TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV]:
721             self.assertEqual(tester._type_from_python(type_), type_)
722
723         self.assertRaises(TypeError, tester._type_from_python, types.CodeType)
724
725 if __name__ == '__main__':
726     unittest.main()