Imported Upstream version 3.15.91
[platform/upstream/pygobject2.git] / tests / test_properties.py
1 # coding=utf-8
2
3 import gc
4 import sys
5 import struct
6 import types
7 import unittest
8
9 import gi
10 from gi.repository import GObject
11 from gi.repository.GObject import ParamFlags, GType, new
12 from gi.repository.GObject import \
13     TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_INT64, \
14     TYPE_UINT64, TYPE_GTYPE, TYPE_INVALID, TYPE_NONE, TYPE_STRV, \
15     TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR, TYPE_BOOLEAN, TYPE_FLOAT, \
16     TYPE_DOUBLE, TYPE_POINTER, TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, \
17     TYPE_STRING, TYPE_PYOBJECT, TYPE_VARIANT
18
19 from gi.repository.GLib import \
20     MININT, MAXINT, MAXUINT, MINLONG, MAXLONG, MAXULONG, \
21     MAXUINT64, MAXINT64, MININT64
22
23 from gi.repository import Gio
24 from gi.repository import GLib
25 gi.require_version('GIMarshallingTests', '1.0')
26 from gi.repository import GIMarshallingTests
27 from gi import _propertyhelper as propertyhelper
28
29 try:
30     gi.require_version('Regress', '1.0')
31     from gi.repository import Regress
32     has_regress = True
33 except (ValueError, ImportError):
34     has_regress = False
35
36 if sys.version_info < (3, 0):
37     TEST_UTF8 = "\xe2\x99\xa5"
38     UNICODE_UTF8 = unicode(TEST_UTF8, 'UTF-8')
39 else:
40     TEST_UTF8 = "♥"
41     UNICODE_UTF8 = TEST_UTF8
42
43 from compathelper import _long
44
45
46 class PropertyObject(GObject.GObject):
47     normal = GObject.Property(type=str)
48     construct = GObject.Property(
49         type=str,
50         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT,
51         default='default')
52
53     construct_only = GObject.Property(
54         type=str,
55         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT_ONLY)
56
57     uint64 = GObject.Property(
58         type=TYPE_UINT64,
59         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
60
61     enum = GObject.Property(
62         type=Gio.SocketType, default=Gio.SocketType.STREAM)
63
64     boxed = GObject.Property(
65         type=GLib.Regex,
66         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
67
68     flags = GObject.Property(
69         type=GIMarshallingTests.Flags,
70         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT,
71         default=GIMarshallingTests.Flags.VALUE1)
72
73     gtype = GObject.Property(
74         type=TYPE_GTYPE,
75         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
76
77     strings = GObject.Property(
78         type=TYPE_STRV,
79         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
80
81     variant = GObject.Property(
82         type=TYPE_VARIANT,
83         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
84
85     variant_def = GObject.Property(
86         type=TYPE_VARIANT,
87         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT,
88         default=GLib.Variant('i', 42))
89
90     interface = GObject.Property(
91         type=Gio.File,
92         flags=ParamFlags.READABLE | ParamFlags.WRITABLE | ParamFlags.CONSTRUCT)
93
94
95 if has_regress:
96     class PropertyInheritanceObject(Regress.TestObj):
97         # override property from the base class, with a different type
98         string = GObject.Property(type=int)
99
100         # a property entirely defined at the Python level
101         python_prop = GObject.Property(type=str)
102
103     class PropertySubClassObject(PropertyInheritanceObject):
104         # override property from the base class, with a different type
105         python_prop = GObject.Property(type=int)
106
107
108 @unittest.skipUnless(has_regress, 'Missing Regress typelib')
109 class TestPropertyInheritanceObject(unittest.TestCase):
110     def test_override_gi_property(self):
111         self.assertNotEqual(Regress.TestObj.props.string.value_type,
112                             PropertyInheritanceObject.props.string.value_type)
113         obj = PropertyInheritanceObject()
114         self.assertEqual(type(obj.props.string), int)
115         obj.props.string = 4
116         self.assertEqual(obj.props.string, 4)
117
118     def test_override_python_property(self):
119         obj = PropertySubClassObject()
120         self.assertEqual(type(obj.props.python_prop), int)
121         obj.props.python_prop = 5
122         self.assertEqual(obj.props.python_prop, 5)
123
124
125 class TestPropertyObject(unittest.TestCase):
126     def test_get_set(self):
127         obj = PropertyObject()
128         obj.props.normal = "value"
129         self.assertEqual(obj.props.normal, "value")
130
131     def test_hasattr_on_object(self):
132         obj = PropertyObject()
133         self.assertTrue(hasattr(obj.props, "normal"))
134
135     def test_hasattr_on_class(self):
136         self.assertTrue(hasattr(PropertyObject.props, "normal"))
137
138     def test_set_on_class(self):
139         def set(obj):
140             obj.props.normal = "foobar"
141
142         self.assertRaises(TypeError, set, PropertyObject)
143
144     def test_iteration(self):
145         for obj in (PropertyObject.props, PropertyObject().props):
146             names = []
147             for pspec in obj:
148                 gtype = GType(pspec)
149                 self.assertEqual(gtype.parent.name, 'GParam')
150                 names.append(pspec.name)
151
152             names.sort()
153             self.assertEqual(names, ['boxed',
154                                      'construct',
155                                      'construct-only',
156                                      'enum',
157                                      'flags',
158                                      'gtype',
159                                      'interface',
160                                      'normal',
161                                      'strings',
162                                      'uint64',
163                                      'variant',
164                                      'variant-def'])
165
166     def test_normal(self):
167         obj = new(PropertyObject, normal="123")
168         self.assertEqual(obj.props.normal, "123")
169         obj.set_property('normal', '456')
170         self.assertEqual(obj.props.normal, "456")
171         obj.props.normal = '789'
172         self.assertEqual(obj.props.normal, "789")
173
174     def test_construct(self):
175         obj = new(PropertyObject, construct="123")
176         self.assertEqual(obj.props.construct, "123")
177         obj.set_property('construct', '456')
178         self.assertEqual(obj.props.construct, "456")
179         obj.props.construct = '789'
180         self.assertEqual(obj.props.construct, "789")
181
182     def test_utf8(self):
183         obj = new(PropertyObject, construct_only=UNICODE_UTF8)
184         self.assertEqual(obj.props.construct_only, TEST_UTF8)
185         obj.set_property('construct', UNICODE_UTF8)
186         self.assertEqual(obj.props.construct, TEST_UTF8)
187         obj.props.normal = UNICODE_UTF8
188         self.assertEqual(obj.props.normal, TEST_UTF8)
189
190     def test_int_to_str(self):
191         obj = new(PropertyObject, construct_only=1)
192         self.assertEqual(obj.props.construct_only, '1')
193         obj.set_property('construct', '2')
194         self.assertEqual(obj.props.construct, '2')
195         obj.props.normal = 3
196         self.assertEqual(obj.props.normal, '3')
197
198     def test_construct_only(self):
199         obj = new(PropertyObject, construct_only="123")
200         self.assertEqual(obj.props.construct_only, "123")
201         self.assertRaises(TypeError,
202                           setattr, obj.props, 'construct_only', '456')
203         self.assertRaises(TypeError,
204                           obj.set_property, 'construct-only', '456')
205
206     def test_uint64(self):
207         obj = new(PropertyObject)
208         self.assertEqual(obj.props.uint64, 0)
209         obj.props.uint64 = _long(1)
210         self.assertEqual(obj.props.uint64, _long(1))
211         obj.props.uint64 = 1
212         self.assertEqual(obj.props.uint64, _long(1))
213
214         self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", _long(-1))
215         self.assertRaises((TypeError, OverflowError), obj.set_property, "uint64", -1)
216
217     def test_uint64_default_value(self):
218         try:
219             class TimeControl(GObject.GObject):
220                 __gproperties__ = {
221                     'time': (TYPE_UINT64, 'Time', 'Time',
222                              _long(0), (1 << 64) - 1, _long(0),
223                              ParamFlags.READABLE)
224                     }
225         except OverflowError:
226             (etype, ex) = sys.exc_info()[2:]
227             self.fail(str(ex))
228
229     def test_enum(self):
230         obj = new(PropertyObject)
231         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
232         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
233         obj.enum = Gio.SocketType.DATAGRAM
234         self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
235         self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
236         obj.props.enum = Gio.SocketType.STREAM
237         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
238         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
239         obj.props.enum = 2
240         self.assertEqual(obj.props.enum, Gio.SocketType.DATAGRAM)
241         self.assertEqual(obj.enum, Gio.SocketType.DATAGRAM)
242         obj.enum = 1
243         self.assertEqual(obj.props.enum, Gio.SocketType.STREAM)
244         self.assertEqual(obj.enum, Gio.SocketType.STREAM)
245
246         self.assertRaises(TypeError, setattr, obj, 'enum', 'foo')
247         self.assertRaises(TypeError, setattr, obj, 'enum', object())
248
249         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType)
250         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
251                           default=Gio.SocketProtocol.TCP)
252         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
253                           default=object())
254         self.assertRaises(TypeError, GObject.Property, type=Gio.SocketType,
255                           default=1)
256
257     def test_flags(self):
258         obj = new(PropertyObject)
259         self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE1)
260         self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE1)
261
262         obj.flags = GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3
263         self.assertEqual(obj.props.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
264         self.assertEqual(obj.flags, GIMarshallingTests.Flags.VALUE2 | GIMarshallingTests.Flags.VALUE3)
265
266         self.assertRaises(TypeError, setattr, obj, 'flags', 'foo')
267         self.assertRaises(TypeError, setattr, obj, 'flags', object())
268         self.assertRaises(TypeError, setattr, obj, 'flags', None)
269
270         self.assertRaises(TypeError, GObject.Property,
271                           type=GIMarshallingTests.Flags, default='foo')
272         self.assertRaises(TypeError, GObject.Property,
273                           type=GIMarshallingTests.Flags, default=object())
274         self.assertRaises(TypeError, GObject.Property,
275                           type=GIMarshallingTests.Flags, default=None)
276
277     def test_gtype(self):
278         obj = new(PropertyObject)
279
280         self.assertEqual(obj.props.gtype, TYPE_NONE)
281         self.assertEqual(obj.gtype, TYPE_NONE)
282
283         obj.gtype = TYPE_UINT64
284         self.assertEqual(obj.props.gtype, TYPE_UINT64)
285         self.assertEqual(obj.gtype, TYPE_UINT64)
286
287         obj.gtype = TYPE_INVALID
288         self.assertEqual(obj.props.gtype, TYPE_INVALID)
289         self.assertEqual(obj.gtype, TYPE_INVALID)
290
291         # GType parameters do not support defaults in GLib
292         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
293                           default=TYPE_INT)
294
295         # incompatible type
296         self.assertRaises(TypeError, setattr, obj, 'gtype', 'foo')
297         self.assertRaises(TypeError, setattr, obj, 'gtype', object())
298
299         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
300                           default='foo')
301         self.assertRaises(TypeError, GObject.Property, type=TYPE_GTYPE,
302                           default=object())
303
304         # set in constructor
305         obj = new(PropertyObject, gtype=TYPE_UINT)
306         self.assertEqual(obj.props.gtype, TYPE_UINT)
307         self.assertEqual(obj.gtype, TYPE_UINT)
308
309     def test_boxed(self):
310         obj = new(PropertyObject)
311
312         regex = GLib.Regex.new('[a-z]*', 0, 0)
313         obj.props.boxed = regex
314         self.assertEqual(obj.props.boxed.get_pattern(), '[a-z]*')
315         self.assertEqual(obj.boxed.get_pattern(), '[a-z]*')
316
317         self.assertRaises(TypeError, setattr, obj, 'boxed', 'foo')
318         self.assertRaises(TypeError, setattr, obj, 'boxed', object())
319
320     def test_strings(self):
321         obj = new(PropertyObject)
322
323         # Should work with actual GStrv objects as well as
324         # Python string lists
325         class GStrv(list):
326             __gtype__ = GObject.TYPE_STRV
327
328         self.assertEqual(obj.props.strings, GStrv([]))
329         self.assertEqual(obj.strings, GStrv([]))
330         self.assertEqual(obj.props.strings, [])
331         self.assertEqual(obj.strings, [])
332
333         obj.strings = ['hello', 'world']
334         self.assertEqual(obj.props.strings, ['hello', 'world'])
335         self.assertEqual(obj.strings, ['hello', 'world'])
336
337         obj.strings = GStrv(['hello', 'world'])
338         self.assertEqual(obj.props.strings, GStrv(['hello', 'world']))
339         self.assertEqual(obj.strings, GStrv(['hello', 'world']))
340
341         obj.strings = []
342         self.assertEqual(obj.strings, [])
343         obj.strings = GStrv([])
344         self.assertEqual(obj.strings, GStrv([]))
345
346         p = GObject.Property(type=TYPE_STRV, default=['hello', '1'])
347         self.assertEqual(p.default, ['hello', '1'])
348         self.assertEqual(p.type, TYPE_STRV)
349         p = GObject.Property(type=TYPE_STRV, default=GStrv(['hello', '1']))
350         self.assertEqual(p.default, ['hello', '1'])
351         self.assertEqual(p.type, TYPE_STRV)
352
353         # set in constructor
354         obj = new(PropertyObject, strings=['hello', 'world'])
355         self.assertEqual(obj.props.strings, ['hello', 'world'])
356         self.assertEqual(obj.strings, ['hello', 'world'])
357
358         # wrong types
359         self.assertRaises(TypeError, setattr, obj, 'strings', 1)
360         self.assertRaises(TypeError, setattr, obj, 'strings', 'foo')
361         self.assertRaises(TypeError, setattr, obj, 'strings', ['foo', 1])
362
363         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
364                           default=1)
365         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
366                           default='foo')
367         self.assertRaises(TypeError, GObject.Property, type=TYPE_STRV,
368                           default=['hello', 1])
369
370     def test_variant(self):
371         obj = new(PropertyObject)
372
373         self.assertEqual(obj.props.variant, None)
374         self.assertEqual(obj.variant, None)
375
376         obj.variant = GLib.Variant('s', 'hello')
377         self.assertEqual(obj.variant.print_(True), "'hello'")
378
379         obj.variant = GLib.Variant('b', True)
380         self.assertEqual(obj.variant.print_(True), "true")
381
382         obj.props.variant = GLib.Variant('y', 2)
383         self.assertEqual(obj.variant.print_(True), "byte 0x02")
384
385         obj.variant = None
386         self.assertEqual(obj.variant, None)
387
388         # set in constructor
389         obj = new(PropertyObject, variant=GLib.Variant('u', 5))
390         self.assertEqual(obj.props.variant.print_(True), 'uint32 5')
391
392         GObject.Property(type=TYPE_VARIANT, default=GLib.Variant('i', 1))
393
394         # incompatible types
395         self.assertRaises(TypeError, setattr, obj, 'variant', 'foo')
396         self.assertRaises(TypeError, setattr, obj, 'variant', 42)
397
398         self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
399                           default='foo')
400         self.assertRaises(TypeError, GObject.Property, type=TYPE_VARIANT,
401                           default=object())
402
403     def test_variant_default(self):
404         obj = new(PropertyObject)
405
406         self.assertEqual(obj.props.variant_def.print_(True), '42')
407         self.assertEqual(obj.variant_def.print_(True), '42')
408
409         obj.props.variant_def = GLib.Variant('y', 2)
410         self.assertEqual(obj.variant_def.print_(True), "byte 0x02")
411
412         # set in constructor
413         obj = new(PropertyObject, variant_def=GLib.Variant('u', 5))
414         self.assertEqual(obj.props.variant_def.print_(True), 'uint32 5')
415
416     def test_interface(self):
417         obj = new(PropertyObject)
418
419         file = Gio.File.new_for_path('/some/path')
420         obj.props.interface = file
421         self.assertEqual(obj.props.interface.get_path(), '/some/path')
422         self.assertEqual(obj.interface.get_path(), '/some/path')
423
424         self.assertRaises(TypeError, setattr, obj, 'interface', 'foo')
425         self.assertRaises(TypeError, setattr, obj, 'interface', object())
426
427     def test_range(self):
428         # kiwi code
429         def max(c):
430             return 2 ** ((8 * struct.calcsize(c)) - 1) - 1
431
432         def umax(c):
433             return 2 ** (8 * struct.calcsize(c)) - 1
434
435         maxint = max('i')
436         minint = -maxint - 1
437         maxuint = umax('I')
438         maxlong = max('l')
439         minlong = -maxlong - 1
440         maxulong = umax('L')
441         maxint64 = max('q')
442         minint64 = -maxint64 - 1
443         maxuint64 = umax('Q')
444
445         types_ = dict(int=(TYPE_INT, minint, maxint),
446                       uint=(TYPE_UINT, 0, maxuint),
447                       long=(TYPE_LONG, minlong, maxlong),
448                       ulong=(TYPE_ULONG, 0, maxulong),
449                       int64=(TYPE_INT64, minint64, maxint64),
450                       uint64=(TYPE_UINT64, 0, maxuint64))
451
452         def build_gproperties(types_):
453             d = {}
454             for key, (gtype, min, max) in types_.items():
455                 d[key] = (gtype, 'blurb', 'desc', min, max, 0,
456                           ParamFlags.READABLE | ParamFlags.WRITABLE)
457             return d
458
459         class RangeCheck(GObject.GObject):
460             __gproperties__ = build_gproperties(types_)
461
462             def __init__(self):
463                 self.values = {}
464                 GObject.GObject.__init__(self)
465
466             def do_set_property(self, pspec, value):
467                 self.values[pspec.name] = value
468
469             def do_get_property(self, pspec):
470                 return self.values.get(pspec.name, pspec.default_value)
471
472         self.assertEqual(RangeCheck.props.int.minimum, minint)
473         self.assertEqual(RangeCheck.props.int.maximum, maxint)
474         self.assertEqual(RangeCheck.props.uint.minimum, 0)
475         self.assertEqual(RangeCheck.props.uint.maximum, maxuint)
476         self.assertEqual(RangeCheck.props.long.minimum, minlong)
477         self.assertEqual(RangeCheck.props.long.maximum, maxlong)
478         self.assertEqual(RangeCheck.props.ulong.minimum, 0)
479         self.assertEqual(RangeCheck.props.ulong.maximum, maxulong)
480         self.assertEqual(RangeCheck.props.int64.minimum, minint64)
481         self.assertEqual(RangeCheck.props.int64.maximum, maxint64)
482         self.assertEqual(RangeCheck.props.uint64.minimum, 0)
483         self.assertEqual(RangeCheck.props.uint64.maximum, maxuint64)
484
485         obj = RangeCheck()
486         for key, (gtype, min, max) in types_.items():
487             self.assertEqual(obj.get_property(key),
488                              getattr(RangeCheck.props, key).default_value)
489
490             obj.set_property(key, min)
491             self.assertEqual(obj.get_property(key), min)
492
493             obj.set_property(key, max)
494             self.assertEqual(obj.get_property(key), max)
495
496     def test_multi(self):
497         obj = PropertyObject()
498         obj.set_properties(normal="foo",
499                            uint64=7)
500         normal, uint64 = obj.get_properties("normal", "uint64")
501         self.assertEqual(normal, "foo")
502         self.assertEqual(uint64, 7)
503
504
505 class TestProperty(unittest.TestCase):
506     def test_simple(self):
507         class C(GObject.GObject):
508             str = GObject.Property(type=str)
509             int = GObject.Property(type=int)
510             float = GObject.Property(type=float)
511             long = GObject.Property(type=_long)
512
513         self.assertTrue(hasattr(C.props, 'str'))
514         self.assertTrue(hasattr(C.props, 'int'))
515         self.assertTrue(hasattr(C.props, 'float'))
516         self.assertTrue(hasattr(C.props, 'long'))
517
518         o = C()
519         self.assertEqual(o.str, '')
520         o.str = 'str'
521         self.assertEqual(o.str, 'str')
522
523         self.assertEqual(o.int, 0)
524         o.int = 1138
525         self.assertEqual(o.int, 1138)
526
527         self.assertEqual(o.float, 0.0)
528         o.float = 3.14
529         self.assertEqual(o.float, 3.14)
530
531         self.assertEqual(o.long, _long(0))
532         o.long = _long(100)
533         self.assertEqual(o.long, _long(100))
534
535     def test_custom_getter(self):
536         class C(GObject.GObject):
537             def get_prop(self):
538                 return 'value'
539             prop = GObject.Property(getter=get_prop)
540
541         o = C()
542         self.assertEqual(o.prop, 'value')
543         self.assertRaises(TypeError, setattr, o, 'prop', 'xxx')
544
545     @unittest.expectedFailure  # https://bugzilla.gnome.org/show_bug.cgi?id=575652
546     def test_getter_exception(self):
547         class C(GObject.Object):
548             @GObject.Property(type=int)
549             def prop(self):
550                 raise ValueError('something bad happend')
551
552         o = C()
553         with self.assertRaisesRegex(ValueError, 'something bad happend'):
554             o.prop
555
556         with self.assertRaisesRegex(ValueError, 'something bad happend'):
557             o.get_property('prop')
558
559         with self.assertRaisesRegex(ValueError, 'something bad happend'):
560             o.props.prop
561
562     def test_custom_setter(self):
563         class C(GObject.GObject):
564             def set_prop(self, value):
565                 self._value = value
566             prop = GObject.Property(setter=set_prop)
567
568             def __init__(self):
569                 self._value = None
570                 GObject.GObject.__init__(self)
571
572         o = C()
573         self.assertEqual(o._value, None)
574         o.prop = 'bar'
575         self.assertEqual(o._value, 'bar')
576         self.assertRaises(TypeError, getattr, o, 'prop')
577
578     def test_decorator_default(self):
579         class C(GObject.GObject):
580             _value = 'value'
581
582             @GObject.Property
583             def value(self):
584                 return self._value
585
586             @value.setter
587             def value_setter(self, value):
588                 self._value = value
589
590         o = C()
591         self.assertEqual(o.value, 'value')
592         o.value = 'blah'
593         self.assertEqual(o.value, 'blah')
594         self.assertEqual(o.props.value, 'blah')
595
596     def test_decorator_private_setter(self):
597         class C(GObject.GObject):
598             _value = 'value'
599
600             @GObject.Property
601             def value(self):
602                 return self._value
603
604             @value.setter
605             def _set_value(self, value):
606                 self._value = value
607
608         o = C()
609         self.assertEqual(o.value, 'value')
610         o.value = 'blah'
611         self.assertEqual(o.value, 'blah')
612         self.assertEqual(o.props.value, 'blah')
613
614     def test_decorator_with_call(self):
615         class C(GObject.GObject):
616             _value = 1
617
618             @GObject.Property(type=int, default=1, minimum=1, maximum=10)
619             def typedValue(self):
620                 return self._value
621
622             @typedValue.setter
623             def typedValue_setter(self, value):
624                 self._value = value
625
626         o = C()
627         self.assertEqual(o.typedValue, 1)
628         o.typedValue = 5
629         self.assertEqual(o.typedValue, 5)
630         self.assertEqual(o.props.typedValue, 5)
631
632     def test_errors(self):
633         self.assertRaises(TypeError, GObject.Property, type='str')
634         self.assertRaises(TypeError, GObject.Property, nick=False)
635         self.assertRaises(TypeError, GObject.Property, blurb=False)
636         # this never fail while bool is a subclass of int
637         # >>> bool.__bases__
638         # (<type 'int'>,)
639         # self.assertRaises(TypeError, GObject.Property, type=bool, default=0)
640         self.assertRaises(TypeError, GObject.Property, type=bool, default='ciao mamma')
641         self.assertRaises(TypeError, GObject.Property, type=bool)
642         self.assertRaises(TypeError, GObject.Property, type=object, default=0)
643         self.assertRaises(TypeError, GObject.Property, type=complex)
644
645     def test_defaults(self):
646         GObject.Property(type=bool, default=True)
647         GObject.Property(type=bool, default=False)
648
649     def test_name_with_underscore(self):
650         class C(GObject.GObject):
651             prop_name = GObject.Property(type=int)
652         o = C()
653         o.prop_name = 10
654         self.assertEqual(o.prop_name, 10)
655
656     def test_range(self):
657         types_ = [
658             (TYPE_INT, MININT, MAXINT),
659             (TYPE_UINT, 0, MAXUINT),
660             (TYPE_LONG, MINLONG, MAXLONG),
661             (TYPE_ULONG, 0, MAXULONG),
662             (TYPE_INT64, MININT64, MAXINT64),
663             (TYPE_UINT64, 0, MAXUINT64),
664             ]
665
666         for gtype, min, max in types_:
667             # Normal, everything is alright
668             prop = GObject.Property(type=gtype, minimum=min, maximum=max)
669             subtype = type('', (GObject.GObject,), dict(prop=prop))
670             self.assertEqual(subtype.props.prop.minimum, min)
671             self.assertEqual(subtype.props.prop.maximum, max)
672
673             # Lower than minimum
674             self.assertRaises(TypeError,
675                               GObject.Property, type=gtype, minimum=min - 1,
676                               maximum=max)
677
678             # Higher than maximum
679             self.assertRaises(TypeError,
680                               GObject.Property, type=gtype, minimum=min,
681                               maximum=max + 1)
682
683     def test_min_max(self):
684         class C(GObject.GObject):
685             prop_int = GObject.Property(type=int, minimum=1, maximum=100, default=1)
686             prop_float = GObject.Property(type=float, minimum=0.1, maximum=10.5, default=1.1)
687
688             def __init__(self):
689                 GObject.GObject.__init__(self)
690
691         # we test known-bad values here which cause Gtk-WARNING logs.
692         # Explicitly allow these for this test.
693         old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL)
694         try:
695             o = C()
696             self.assertEqual(o.prop_int, 1)
697
698             o.prop_int = 5
699             self.assertEqual(o.prop_int, 5)
700
701             o.prop_int = 0
702             self.assertEqual(o.prop_int, 5)
703
704             o.prop_int = 101
705             self.assertEqual(o.prop_int, 5)
706
707             self.assertEqual(o.prop_float, 1.1)
708
709             o.prop_float = 7.75
710             self.assertEqual(o.prop_float, 7.75)
711
712             o.prop_float = 0.09
713             self.assertEqual(o.prop_float, 7.75)
714
715             o.prop_float = 10.51
716             self.assertEqual(o.prop_float, 7.75)
717         finally:
718             GLib.log_set_always_fatal(old_mask)
719
720     def test_multiple_instances(self):
721         class C(GObject.GObject):
722             prop = GObject.Property(type=str, default='default')
723
724         o1 = C()
725         o2 = C()
726         self.assertEqual(o1.prop, 'default')
727         self.assertEqual(o2.prop, 'default')
728         o1.prop = 'value'
729         self.assertEqual(o1.prop, 'value')
730         self.assertEqual(o2.prop, 'default')
731
732     def test_object_property(self):
733         class PropertyObject(GObject.GObject):
734             obj = GObject.Property(type=GObject.GObject)
735
736         pobj1 = PropertyObject()
737         obj1_hash = hash(pobj1)
738         pobj2 = PropertyObject()
739
740         pobj2.obj = pobj1
741         del pobj1
742         pobj1 = pobj2.obj
743         self.assertEqual(hash(pobj1), obj1_hash)
744
745     def test_object_subclass_property(self):
746         class ObjectSubclass(GObject.GObject):
747             __gtype_name__ = 'ObjectSubclass'
748
749         class PropertyObjectSubclass(GObject.GObject):
750             obj = GObject.Property(type=ObjectSubclass)
751
752         PropertyObjectSubclass(obj=ObjectSubclass())
753
754     def test_property_subclass(self):
755         # test for #470718
756         class A(GObject.GObject):
757             prop1 = GObject.Property(type=int)
758
759         class B(A):
760             prop2 = GObject.Property(type=int)
761
762         b = B()
763         b.prop2 = 10
764         self.assertEqual(b.prop2, 10)
765         b.prop1 = 20
766         self.assertEqual(b.prop1, 20)
767
768     @unittest.skipUnless(has_regress, 'Missing regress typelib')
769     def test_property_subclass_c(self):
770         class A(Regress.TestSubObj):
771             prop1 = GObject.Property(type=int)
772
773         a = A()
774         a.prop1 = 10
775         self.assertEqual(a.prop1, 10)
776
777         # also has parent properties
778         a.props.int = 20
779         self.assertEqual(a.props.int, 20)
780
781         # Some of which are unusable without introspection
782         a.props.list = ("str1", "str2")
783         self.assertEqual(a.props.list, ["str1", "str2"])
784
785         a.set_property("list", ("str3", "str4"))
786         self.assertEqual(a.props.list, ["str3", "str4"])
787
788     def test_property_subclass_custom_setter(self):
789         # test for #523352
790         class A(GObject.GObject):
791             def get_first(self):
792                 return 'first'
793             first = GObject.Property(type=str, getter=get_first)
794
795         class B(A):
796             def get_second(self):
797                 return 'second'
798             second = GObject.Property(type=str, getter=get_second)
799
800         a = A()
801         self.assertEqual(a.first, 'first')
802         self.assertRaises(TypeError, setattr, a, 'first', 'foo')
803
804         b = B()
805         self.assertEqual(b.first, 'first')
806         self.assertRaises(TypeError, setattr, b, 'first', 'foo')
807         self.assertEqual(b.second, 'second')
808         self.assertRaises(TypeError, setattr, b, 'second', 'foo')
809
810     def test_property_subclass_custom_setter_error(self):
811         try:
812             class A(GObject.GObject):
813                 def get_first(self):
814                     return 'first'
815                 first = GObject.Property(type=str, getter=get_first)
816
817                 def do_get_property(self, pspec):
818                     pass
819         except TypeError:
820             pass
821         else:
822             raise AssertionError
823
824     # Bug 587637.
825
826     def test_float_min(self):
827         GObject.Property(type=float, minimum=-1)
828         GObject.Property(type=GObject.TYPE_FLOAT, minimum=-1)
829         GObject.Property(type=GObject.TYPE_DOUBLE, minimum=-1)
830
831     # Bug 644039
832
833     def test_reference_count(self):
834         # We can check directly if an object gets finalized, so we will
835         # observe it indirectly through the refcount of a member object.
836
837         # We create our dummy object and store its current refcount
838         o = object()
839         rc = sys.getrefcount(o)
840
841         # We add our object as a member to our newly created object we
842         # want to observe. Its refcount is increased by one.
843         t = PropertyObject(normal="test")
844         t.o = o
845         self.assertEqual(sys.getrefcount(o), rc + 1)
846
847         # Now we want to ensure we do not leak any references to our
848         # object with properties. If no ref is leaked, then when deleting
849         # the local reference to this object, its reference count shoud
850         # drop to zero, and our dummy object should loose one reference.
851         del t
852         self.assertEqual(sys.getrefcount(o), rc)
853
854     def test_doc_strings(self):
855         class C(GObject.GObject):
856             foo_blurbed = GObject.Property(type=int, blurb='foo_blurbed doc string')
857
858             @GObject.Property
859             def foo_getter(self):
860                 """foo_getter doc string"""
861                 return 0
862
863         self.assertEqual(C.foo_blurbed.blurb, 'foo_blurbed doc string')
864         self.assertEqual(C.foo_blurbed.__doc__, 'foo_blurbed doc string')
865
866         self.assertEqual(C.foo_getter.blurb, 'foo_getter doc string')
867         self.assertEqual(C.foo_getter.__doc__, 'foo_getter doc string')
868
869     def test_python_to_glib_type_mapping(self):
870         tester = GObject.Property()
871         self.assertEqual(tester._type_from_python(int), GObject.TYPE_INT)
872         if sys.version_info < (3, 0):
873             self.assertEqual(tester._type_from_python(long), GObject.TYPE_LONG)
874         self.assertEqual(tester._type_from_python(bool), GObject.TYPE_BOOLEAN)
875         self.assertEqual(tester._type_from_python(float), GObject.TYPE_DOUBLE)
876         self.assertEqual(tester._type_from_python(str), GObject.TYPE_STRING)
877         self.assertEqual(tester._type_from_python(object), GObject.TYPE_PYOBJECT)
878
879         self.assertEqual(tester._type_from_python(GObject.GObject), GObject.GObject.__gtype__)
880         self.assertEqual(tester._type_from_python(GObject.GEnum), GObject.GEnum.__gtype__)
881         self.assertEqual(tester._type_from_python(GObject.GFlags), GObject.GFlags.__gtype__)
882         self.assertEqual(tester._type_from_python(GObject.GBoxed), GObject.GBoxed.__gtype__)
883         self.assertEqual(tester._type_from_python(GObject.GInterface), GObject.GInterface.__gtype__)
884
885         for type_ in [TYPE_NONE, TYPE_INTERFACE, TYPE_CHAR, TYPE_UCHAR,
886                       TYPE_INT, TYPE_UINT, TYPE_BOOLEAN, TYPE_LONG,
887                       TYPE_ULONG, TYPE_INT64, TYPE_UINT64,
888                       TYPE_FLOAT, TYPE_DOUBLE, TYPE_POINTER,
889                       TYPE_BOXED, TYPE_PARAM, TYPE_OBJECT, TYPE_STRING,
890                       TYPE_PYOBJECT, TYPE_GTYPE, TYPE_STRV]:
891             self.assertEqual(tester._type_from_python(type_), type_)
892
893         self.assertRaises(TypeError, tester._type_from_python, types.CodeType)
894
895
896 class TestInstallProperties(unittest.TestCase):
897     # These tests only test how signalhelper.install_signals works
898     # with the __gsignals__ dict and therefore does not need to use
899     # GObject as a base class because that would automatically call
900     # install_signals within the meta-class.
901     class Base(object):
902         __gproperties__ = {'test': (0, '', '', 0, 0, 0, 0)}
903
904     class Sub1(Base):
905         pass
906
907     class Sub2(Base):
908         @GObject.Property(type=int)
909         def sub2test(self):
910             return 123
911
912     class ClassWithPropertyAndGetterVFunc(object):
913         @GObject.Property(type=int)
914         def sub2test(self):
915             return 123
916
917         def do_get_property(self, name):
918             return 321
919
920     class ClassWithPropertyRedefined(object):
921         __gproperties__ = {'test': (0, '', '', 0, 0, 0, 0)}
922         test = GObject.Property(type=int)
923
924     def setUp(self):
925         self.assertEqual(len(self.Base.__gproperties__), 1)
926         propertyhelper.install_properties(self.Base)
927         self.assertEqual(len(self.Base.__gproperties__), 1)
928
929     def test_subclass_without_properties_is_not_modified(self):
930         self.assertFalse('__gproperties__' in self.Sub1.__dict__)
931         propertyhelper.install_properties(self.Sub1)
932         self.assertFalse('__gproperties__' in self.Sub1.__dict__)
933
934     def test_subclass_with_decorator_gets_gproperties_dict(self):
935         # Sub2 has Property instances but will not have a __gproperties__
936         # until install_properties is called
937         self.assertFalse('__gproperties__' in self.Sub2.__dict__)
938         self.assertFalse('do_get_property' in self.Sub2.__dict__)
939         self.assertFalse('do_set_property' in self.Sub2.__dict__)
940
941         propertyhelper.install_properties(self.Sub2)
942         self.assertTrue('__gproperties__' in self.Sub2.__dict__)
943         self.assertEqual(len(self.Base.__gproperties__), 1)
944         self.assertEqual(len(self.Sub2.__gproperties__), 1)
945         self.assertTrue('sub2test' in self.Sub2.__gproperties__)
946
947         # get/set vfuncs should have been added
948         self.assertTrue('do_get_property' in self.Sub2.__dict__)
949         self.assertTrue('do_set_property' in self.Sub2.__dict__)
950
951     def test_object_with_property_and_do_get_property_vfunc_raises(self):
952         self.assertRaises(TypeError, propertyhelper.install_properties,
953                           self.ClassWithPropertyAndGetterVFunc)
954
955     def test_same_name_property_definitions_raises(self):
956         self.assertRaises(ValueError, propertyhelper.install_properties,
957                           self.ClassWithPropertyRedefined)
958
959
960 class CPropertiesTestBase(object):
961     # Tests for properties implemented in C not Python.
962
963     def setUp(self):
964         self.obj = GIMarshallingTests.PropertiesObject()
965
966     def get_prop(self, obj, name):
967         raise NotImplementedError
968
969     def set_prop(self, obj, name, value):
970         raise NotImplementedError
971
972     def test_boolean(self):
973         self.assertEqual(self.get_prop(self.obj, 'some-boolean'), False)
974         self.set_prop(self.obj, 'some-boolean', True)
975         self.assertEqual(self.get_prop(self.obj, 'some-boolean'), True)
976
977         obj = GIMarshallingTests.PropertiesObject(some_boolean=True)
978         self.assertEqual(self.get_prop(obj, 'some-boolean'), True)
979
980     def test_char(self):
981         self.assertEqual(self.get_prop(self.obj, 'some-char'), 0)
982         self.set_prop(self.obj, 'some-char', GLib.MAXINT8)
983         self.assertEqual(self.get_prop(self.obj, 'some-char'), GLib.MAXINT8)
984
985         obj = GIMarshallingTests.PropertiesObject(some_char=-42)
986         self.assertEqual(self.get_prop(obj, 'some-char'), -42)
987
988     def test_uchar(self):
989         self.assertEqual(self.get_prop(self.obj, 'some-uchar'), 0)
990         self.set_prop(self.obj, 'some-uchar', GLib.MAXUINT8)
991         self.assertEqual(self.get_prop(self.obj, 'some-uchar'), GLib.MAXUINT8)
992
993         obj = GIMarshallingTests.PropertiesObject(some_uchar=42)
994         self.assertEqual(self.get_prop(obj, 'some-uchar'), 42)
995
996     def test_int(self):
997         self.assertEqual(self.get_prop(self.obj, 'some_int'), 0)
998         self.set_prop(self.obj, 'some-int', GLib.MAXINT)
999         self.assertEqual(self.get_prop(self.obj, 'some_int'), GLib.MAXINT)
1000
1001         obj = GIMarshallingTests.PropertiesObject(some_int=-42)
1002         self.assertEqual(self.get_prop(obj, 'some-int'), -42)
1003
1004         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-int', 'foo')
1005         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-int', None)
1006
1007         self.assertEqual(self.get_prop(obj, 'some-int'), -42)
1008
1009     def test_uint(self):
1010         self.assertEqual(self.get_prop(self.obj, 'some_uint'), 0)
1011         self.set_prop(self.obj, 'some-uint', GLib.MAXUINT)
1012         self.assertEqual(self.get_prop(self.obj, 'some_uint'), GLib.MAXUINT)
1013
1014         obj = GIMarshallingTests.PropertiesObject(some_uint=42)
1015         self.assertEqual(self.get_prop(obj, 'some-uint'), 42)
1016
1017         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-uint', 'foo')
1018         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-uint', None)
1019
1020         self.assertEqual(self.get_prop(obj, 'some-uint'), 42)
1021
1022     def test_long(self):
1023         self.assertEqual(self.get_prop(self.obj, 'some_long'), 0)
1024         self.set_prop(self.obj, 'some-long', GLib.MAXLONG)
1025         self.assertEqual(self.get_prop(self.obj, 'some_long'), GLib.MAXLONG)
1026
1027         obj = GIMarshallingTests.PropertiesObject(some_long=-42)
1028         self.assertEqual(self.get_prop(obj, 'some-long'), -42)
1029
1030         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-long', 'foo')
1031         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-long', None)
1032
1033         self.assertEqual(self.get_prop(obj, 'some-long'), -42)
1034
1035     def test_ulong(self):
1036         self.assertEqual(self.get_prop(self.obj, 'some_ulong'), 0)
1037         self.set_prop(self.obj, 'some-ulong', GLib.MAXULONG)
1038         self.assertEqual(self.get_prop(self.obj, 'some_ulong'), GLib.MAXULONG)
1039
1040         obj = GIMarshallingTests.PropertiesObject(some_ulong=42)
1041         self.assertEqual(self.get_prop(obj, 'some-ulong'), 42)
1042
1043         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-ulong', 'foo')
1044         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-ulong', None)
1045
1046         self.assertEqual(self.get_prop(obj, 'some-ulong'), 42)
1047
1048     def test_int64(self):
1049         self.assertEqual(self.get_prop(self.obj, 'some-int64'), 0)
1050         self.set_prop(self.obj, 'some-int64', GLib.MAXINT64)
1051         self.assertEqual(self.get_prop(self.obj, 'some-int64'), GLib.MAXINT64)
1052
1053         obj = GIMarshallingTests.PropertiesObject(some_int64=-4200000000000000)
1054         self.assertEqual(self.get_prop(obj, 'some-int64'), -4200000000000000)
1055
1056     def test_uint64(self):
1057         self.assertEqual(self.get_prop(self.obj, 'some-uint64'), 0)
1058         self.set_prop(self.obj, 'some-uint64', GLib.MAXUINT64)
1059         self.assertEqual(self.get_prop(self.obj, 'some-uint64'), GLib.MAXUINT64)
1060
1061         obj = GIMarshallingTests.PropertiesObject(some_uint64=4200000000000000)
1062         self.assertEqual(self.get_prop(obj, 'some-uint64'), 4200000000000000)
1063
1064     def test_float(self):
1065         self.assertEqual(self.get_prop(self.obj, 'some-float'), 0)
1066         self.set_prop(self.obj, 'some-float', GLib.MAXFLOAT)
1067         self.assertEqual(self.get_prop(self.obj, 'some-float'), GLib.MAXFLOAT)
1068
1069         obj = GIMarshallingTests.PropertiesObject(some_float=42.42)
1070         self.assertAlmostEqual(self.get_prop(obj, 'some-float'), 42.42, 4)
1071
1072         obj = GIMarshallingTests.PropertiesObject(some_float=42)
1073         self.assertAlmostEqual(self.get_prop(obj, 'some-float'), 42.0, 4)
1074
1075         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-float', 'foo')
1076         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-float', None)
1077
1078         self.assertAlmostEqual(self.get_prop(obj, 'some-float'), 42.0, 4)
1079
1080     def test_double(self):
1081         self.assertEqual(self.get_prop(self.obj, 'some-double'), 0)
1082         self.set_prop(self.obj, 'some-double', GLib.MAXDOUBLE)
1083         self.assertEqual(self.get_prop(self.obj, 'some-double'), GLib.MAXDOUBLE)
1084
1085         obj = GIMarshallingTests.PropertiesObject(some_double=42.42)
1086         self.assertAlmostEqual(self.get_prop(obj, 'some-double'), 42.42)
1087
1088         obj = GIMarshallingTests.PropertiesObject(some_double=42)
1089         self.assertAlmostEqual(self.get_prop(obj, 'some-double'), 42.0)
1090
1091         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-double', 'foo')
1092         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-double', None)
1093
1094         self.assertAlmostEqual(self.get_prop(obj, 'some-double'), 42.0)
1095
1096     def test_strv(self):
1097         self.assertEqual(self.get_prop(self.obj, 'some-strv'), [])
1098         self.set_prop(self.obj, 'some-strv', ['hello', 'world'])
1099         self.assertEqual(self.get_prop(self.obj, 'some-strv'), ['hello', 'world'])
1100
1101         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-strv', 1)
1102         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-strv', 'foo')
1103         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-strv', [1, 2])
1104         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-strv', ['foo', 1])
1105
1106         self.assertEqual(self.get_prop(self.obj, 'some-strv'), ['hello', 'world'])
1107
1108         obj = GIMarshallingTests.PropertiesObject(some_strv=['hello', 'world'])
1109         self.assertEqual(self.get_prop(obj, 'some-strv'), ['hello', 'world'])
1110
1111     def test_boxed_struct(self):
1112         self.assertEqual(self.get_prop(self.obj, 'some-boxed-struct'), None)
1113
1114         class GStrv(list):
1115             __gtype__ = GObject.TYPE_STRV
1116
1117         struct1 = GIMarshallingTests.BoxedStruct()
1118         struct1.long_ = 1
1119
1120         self.set_prop(self.obj, 'some-boxed-struct', struct1)
1121         self.assertEqual(self.get_prop(self.obj, 'some-boxed-struct').long_, 1)
1122         self.assertEqual(self.obj.some_boxed_struct.long_, 1)
1123
1124         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-boxed-struct', 1)
1125         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-boxed-struct', 'foo')
1126
1127         obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1)
1128         self.assertEqual(self.get_prop(obj, 'some-boxed-struct').long_, 1)
1129
1130     def test_boxed_glist(self):
1131         self.assertEqual(self.get_prop(self.obj, 'some-boxed-glist'), [])
1132
1133         l = [GLib.MININT, 42, GLib.MAXINT]
1134         self.set_prop(self.obj, 'some-boxed-glist', l)
1135         self.assertEqual(self.get_prop(self.obj, 'some-boxed-glist'), l)
1136         self.set_prop(self.obj, 'some-boxed-glist', [])
1137         self.assertEqual(self.get_prop(self.obj, 'some-boxed-glist'), [])
1138
1139         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-boxed-glist', 1)
1140         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-boxed-glist', 'foo')
1141         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-boxed-glist', ['a'])
1142
1143     @unittest.skipUnless(has_regress, 'built without cairo support')
1144     def test_annotated_glist(self):
1145         obj = Regress.TestObj()
1146         self.assertEqual(self.get_prop(obj, 'list'), [])
1147
1148         self.set_prop(obj, 'list', ['1', '2', '3'])
1149         self.assertTrue(isinstance(self.get_prop(obj, 'list'), list))
1150         self.assertEqual(self.get_prop(obj, 'list'), ['1', '2', '3'])
1151
1152     @unittest.expectedFailure
1153     def test_boxed_glist_ctor(self):
1154         l = [GLib.MININT, 42, GLib.MAXINT]
1155         obj = GIMarshallingTests.PropertiesObject(some_boxed_glist=l)
1156         self.assertEqual(self.get_prop(obj, 'some-boxed-glist'), l)
1157
1158     def test_variant(self):
1159         self.assertEqual(self.get_prop(self.obj, 'some-variant'), None)
1160
1161         self.set_prop(self.obj, 'some-variant', GLib.Variant('o', '/myobj'))
1162         self.assertEqual(self.get_prop(self.obj, 'some-variant').get_type_string(), 'o')
1163         self.assertEqual(self.get_prop(self.obj, 'some-variant').print_(False), "'/myobj'")
1164
1165         self.set_prop(self.obj, 'some-variant', None)
1166         self.assertEqual(self.get_prop(self.obj, 'some-variant'), None)
1167
1168         obj = GIMarshallingTests.PropertiesObject(some_variant=GLib.Variant('b', True))
1169         self.assertEqual(self.get_prop(obj, 'some-variant').get_type_string(), 'b')
1170         self.assertEqual(self.get_prop(obj, 'some-variant').get_boolean(), True)
1171
1172         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-variant', 'foo')
1173         self.assertRaises(TypeError, self.set_prop, self.obj, 'some-variant', 23)
1174
1175         self.assertEqual(self.get_prop(obj, 'some-variant').get_type_string(), 'b')
1176         self.assertEqual(self.get_prop(obj, 'some-variant').get_boolean(), True)
1177
1178     def test_setting_several_properties(self):
1179         obj = GIMarshallingTests.PropertiesObject()
1180         obj.set_properties(some_uchar=54, some_int=42)
1181         self.assertEqual(42, self.get_prop(obj, 'some-int'))
1182         self.assertEqual(54, self.get_prop(obj, 'some-uchar'))
1183
1184     @unittest.skipUnless(has_regress, 'built without cairo support')
1185     def test_gtype(self):
1186         obj = Regress.TestObj()
1187         self.assertEqual(self.get_prop(obj, 'gtype'), GObject.TYPE_INVALID)
1188         self.set_prop(obj, 'gtype', int)
1189         self.assertEqual(self.get_prop(obj, 'gtype'), GObject.TYPE_INT)
1190
1191         obj = Regress.TestObj(gtype=int)
1192         self.assertEqual(self.get_prop(obj, 'gtype'), GObject.TYPE_INT)
1193         self.set_prop(obj, 'gtype', str)
1194         self.assertEqual(self.get_prop(obj, 'gtype'), GObject.TYPE_STRING)
1195
1196     @unittest.skipUnless(has_regress, 'built without cairo support')
1197     def test_hash_table(self):
1198         obj = Regress.TestObj()
1199         self.assertEqual(self.get_prop(obj, 'hash-table'), None)
1200
1201         self.set_prop(obj, 'hash-table', {'mec': 56})
1202         self.assertTrue(isinstance(self.get_prop(obj, 'hash-table'), dict))
1203         self.assertEqual(list(self.get_prop(obj, 'hash-table').items())[0],
1204                          ('mec', 56))
1205
1206     @unittest.skipUnless(has_regress, 'built without cairo support')
1207     def test_parent_class(self):
1208         class A(Regress.TestObj):
1209             prop1 = GObject.Property(type=int)
1210
1211         a = A()
1212         self.set_prop(a, 'int', 20)
1213         self.assertEqual(self.get_prop(a, 'int'), 20)
1214
1215         # test parent property which needs introspection
1216         self.set_prop(a, 'list', ("str1", "str2"))
1217         self.assertEqual(self.get_prop(a, 'list'), ["str1", "str2"])
1218
1219     def test_held_object_ref_count_getter(self):
1220         holder = GIMarshallingTests.PropertiesObject()
1221         held = GObject.Object()
1222
1223         self.assertEqual(holder.__grefcount__, 1)
1224         self.assertEqual(held.__grefcount__, 1)
1225
1226         self.set_prop(holder, 'some-object', held)
1227         self.assertEqual(holder.__grefcount__, 1)
1228
1229         initial_ref_count = held.__grefcount__
1230         self.get_prop(holder, 'some-object')
1231         gc.collect()
1232         self.assertEqual(held.__grefcount__, initial_ref_count)
1233
1234     def test_held_object_ref_count_setter(self):
1235         holder = GIMarshallingTests.PropertiesObject()
1236         held = GObject.Object()
1237
1238         self.assertEqual(holder.__grefcount__, 1)
1239         self.assertEqual(held.__grefcount__, 1)
1240
1241         # Setting property should only increase ref count by 1
1242         self.set_prop(holder, 'some-object', held)
1243         self.assertEqual(holder.__grefcount__, 1)
1244         self.assertEqual(held.__grefcount__, 2)
1245
1246         # Clearing should pull it back down
1247         self.set_prop(holder, 'some-object', None)
1248         self.assertEqual(held.__grefcount__, 1)
1249
1250     def test_set_object_property_to_invalid_type(self):
1251         obj = GIMarshallingTests.PropertiesObject()
1252         self.assertRaises(TypeError, self.set_prop, obj, 'some-object', 'not_an_object')
1253
1254
1255 class TestCPropsAccessor(CPropertiesTestBase, unittest.TestCase):
1256     # C property tests using the "props" accessor.
1257     def get_prop(self, obj, name):
1258         return getattr(obj.props, name.replace('-', '_'))
1259
1260     def set_prop(self, obj, name, value):
1261         setattr(obj.props, name.replace('-', '_'), value)
1262
1263     def test_props_accessor_dir(self):
1264         # Test class
1265         props = dir(GIMarshallingTests.PropertiesObject.props)
1266         self.assertTrue('some_float' in props)
1267         self.assertTrue('some_double' in props)
1268         self.assertTrue('some_variant' in props)
1269
1270         # Test instance
1271         obj = GIMarshallingTests.PropertiesObject()
1272         props = dir(obj.props)
1273         self.assertTrue('some_float' in props)
1274         self.assertTrue('some_double' in props)
1275         self.assertTrue('some_variant' in props)
1276
1277     def test_param_spec_dir(self):
1278         attrs = dir(GIMarshallingTests.PropertiesObject.props.some_float)
1279         self.assertTrue('name' in attrs)
1280         self.assertTrue('nick' in attrs)
1281         self.assertTrue('blurb' in attrs)
1282         self.assertTrue('flags' in attrs)
1283         self.assertTrue('default_value' in attrs)
1284         self.assertTrue('minimum' in attrs)
1285         self.assertTrue('maximum' in attrs)
1286
1287
1288 class TestCGetPropertyMethod(CPropertiesTestBase, unittest.TestCase):
1289     # C property tests using the "props" accessor.
1290     def get_prop(self, obj, name):
1291         return obj.get_property(name)
1292
1293     def set_prop(self, obj, name, value):
1294         obj.set_property(name, value)
1295
1296
1297 if __name__ == '__main__':
1298     unittest.main()