##// END OF EJS Templates
Test for Union Traitlet
Sylvain Corlay -
Show More
@@ -1,1422 +1,1432 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.traitlets."""
2 """Tests for IPython.utils.traitlets."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6 #
6 #
7 # Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
7 # Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
8 # also under the terms of the Modified BSD License.
8 # also under the terms of the Modified BSD License.
9
9
10 import pickle
10 import pickle
11 import re
11 import re
12 import sys
12 import sys
13 from unittest import TestCase
13 from unittest import TestCase
14
14
15 import nose.tools as nt
15 import nose.tools as nt
16 from nose import SkipTest
16 from nose import SkipTest
17
17
18 from IPython.utils.traitlets import (
18 from IPython.utils.traitlets import (
19 HasTraits, MetaHasTraits, TraitType, Any, CBytes, Dict,
19 HasTraits, MetaHasTraits, TraitType, Any, CBytes, Dict,
20 Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError,
20 Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError,
21 Undefined, Type, This, Instance, TCPAddress, List, Tuple,
21 Union, Undefined, Type, This, Instance, TCPAddress, List, Tuple,
22 ObjectName, DottedObjectName, CRegExp, link, directional_link,
22 ObjectName, DottedObjectName, CRegExp, link, directional_link,
23 EventfulList, EventfulDict, ForwardDeclaredType, ForwardDeclaredInstance,
23 EventfulList, EventfulDict, ForwardDeclaredType, ForwardDeclaredInstance,
24 )
24 )
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26 from IPython.testing.decorators import skipif
26 from IPython.testing.decorators import skipif
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Helper classes for testing
29 # Helper classes for testing
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32
32
33 class HasTraitsStub(HasTraits):
33 class HasTraitsStub(HasTraits):
34
34
35 def _notify_trait(self, name, old, new):
35 def _notify_trait(self, name, old, new):
36 self._notify_name = name
36 self._notify_name = name
37 self._notify_old = old
37 self._notify_old = old
38 self._notify_new = new
38 self._notify_new = new
39
39
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Test classes
42 # Test classes
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45
45
46 class TestTraitType(TestCase):
46 class TestTraitType(TestCase):
47
47
48 def test_get_undefined(self):
48 def test_get_undefined(self):
49 class A(HasTraits):
49 class A(HasTraits):
50 a = TraitType
50 a = TraitType
51 a = A()
51 a = A()
52 self.assertEqual(a.a, Undefined)
52 self.assertEqual(a.a, Undefined)
53
53
54 def test_set(self):
54 def test_set(self):
55 class A(HasTraitsStub):
55 class A(HasTraitsStub):
56 a = TraitType
56 a = TraitType
57
57
58 a = A()
58 a = A()
59 a.a = 10
59 a.a = 10
60 self.assertEqual(a.a, 10)
60 self.assertEqual(a.a, 10)
61 self.assertEqual(a._notify_name, 'a')
61 self.assertEqual(a._notify_name, 'a')
62 self.assertEqual(a._notify_old, Undefined)
62 self.assertEqual(a._notify_old, Undefined)
63 self.assertEqual(a._notify_new, 10)
63 self.assertEqual(a._notify_new, 10)
64
64
65 def test_validate(self):
65 def test_validate(self):
66 class MyTT(TraitType):
66 class MyTT(TraitType):
67 def validate(self, inst, value):
67 def validate(self, inst, value):
68 return -1
68 return -1
69 class A(HasTraitsStub):
69 class A(HasTraitsStub):
70 tt = MyTT
70 tt = MyTT
71
71
72 a = A()
72 a = A()
73 a.tt = 10
73 a.tt = 10
74 self.assertEqual(a.tt, -1)
74 self.assertEqual(a.tt, -1)
75
75
76 def test_default_validate(self):
76 def test_default_validate(self):
77 class MyIntTT(TraitType):
77 class MyIntTT(TraitType):
78 def validate(self, obj, value):
78 def validate(self, obj, value):
79 if isinstance(value, int):
79 if isinstance(value, int):
80 return value
80 return value
81 self.error(obj, value)
81 self.error(obj, value)
82 class A(HasTraits):
82 class A(HasTraits):
83 tt = MyIntTT(10)
83 tt = MyIntTT(10)
84 a = A()
84 a = A()
85 self.assertEqual(a.tt, 10)
85 self.assertEqual(a.tt, 10)
86
86
87 # Defaults are validated when the HasTraits is instantiated
87 # Defaults are validated when the HasTraits is instantiated
88 class B(HasTraits):
88 class B(HasTraits):
89 tt = MyIntTT('bad default')
89 tt = MyIntTT('bad default')
90 self.assertRaises(TraitError, B)
90 self.assertRaises(TraitError, B)
91
91
92 def test_is_valid_for(self):
92 def test_is_valid_for(self):
93 class MyTT(TraitType):
93 class MyTT(TraitType):
94 def is_valid_for(self, value):
94 def is_valid_for(self, value):
95 return True
95 return True
96 class A(HasTraits):
96 class A(HasTraits):
97 tt = MyTT
97 tt = MyTT
98
98
99 a = A()
99 a = A()
100 a.tt = 10
100 a.tt = 10
101 self.assertEqual(a.tt, 10)
101 self.assertEqual(a.tt, 10)
102
102
103 def test_value_for(self):
103 def test_value_for(self):
104 class MyTT(TraitType):
104 class MyTT(TraitType):
105 def value_for(self, value):
105 def value_for(self, value):
106 return 20
106 return 20
107 class A(HasTraits):
107 class A(HasTraits):
108 tt = MyTT
108 tt = MyTT
109
109
110 a = A()
110 a = A()
111 a.tt = 10
111 a.tt = 10
112 self.assertEqual(a.tt, 20)
112 self.assertEqual(a.tt, 20)
113
113
114 def test_info(self):
114 def test_info(self):
115 class A(HasTraits):
115 class A(HasTraits):
116 tt = TraitType
116 tt = TraitType
117 a = A()
117 a = A()
118 self.assertEqual(A.tt.info(), 'any value')
118 self.assertEqual(A.tt.info(), 'any value')
119
119
120 def test_error(self):
120 def test_error(self):
121 class A(HasTraits):
121 class A(HasTraits):
122 tt = TraitType
122 tt = TraitType
123 a = A()
123 a = A()
124 self.assertRaises(TraitError, A.tt.error, a, 10)
124 self.assertRaises(TraitError, A.tt.error, a, 10)
125
125
126 def test_dynamic_initializer(self):
126 def test_dynamic_initializer(self):
127 class A(HasTraits):
127 class A(HasTraits):
128 x = Int(10)
128 x = Int(10)
129 def _x_default(self):
129 def _x_default(self):
130 return 11
130 return 11
131 class B(A):
131 class B(A):
132 x = Int(20)
132 x = Int(20)
133 class C(A):
133 class C(A):
134 def _x_default(self):
134 def _x_default(self):
135 return 21
135 return 21
136
136
137 a = A()
137 a = A()
138 self.assertEqual(a._trait_values, {})
138 self.assertEqual(a._trait_values, {})
139 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
139 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
140 self.assertEqual(a.x, 11)
140 self.assertEqual(a.x, 11)
141 self.assertEqual(a._trait_values, {'x': 11})
141 self.assertEqual(a._trait_values, {'x': 11})
142 b = B()
142 b = B()
143 self.assertEqual(b._trait_values, {'x': 20})
143 self.assertEqual(b._trait_values, {'x': 20})
144 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
144 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
145 self.assertEqual(b.x, 20)
145 self.assertEqual(b.x, 20)
146 c = C()
146 c = C()
147 self.assertEqual(c._trait_values, {})
147 self.assertEqual(c._trait_values, {})
148 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
148 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
149 self.assertEqual(c.x, 21)
149 self.assertEqual(c.x, 21)
150 self.assertEqual(c._trait_values, {'x': 21})
150 self.assertEqual(c._trait_values, {'x': 21})
151 # Ensure that the base class remains unmolested when the _default
151 # Ensure that the base class remains unmolested when the _default
152 # initializer gets overridden in a subclass.
152 # initializer gets overridden in a subclass.
153 a = A()
153 a = A()
154 c = C()
154 c = C()
155 self.assertEqual(a._trait_values, {})
155 self.assertEqual(a._trait_values, {})
156 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
156 self.assertEqual(list(a._trait_dyn_inits.keys()), ['x'])
157 self.assertEqual(a.x, 11)
157 self.assertEqual(a.x, 11)
158 self.assertEqual(a._trait_values, {'x': 11})
158 self.assertEqual(a._trait_values, {'x': 11})
159
159
160
160
161
161
162 class TestHasTraitsMeta(TestCase):
162 class TestHasTraitsMeta(TestCase):
163
163
164 def test_metaclass(self):
164 def test_metaclass(self):
165 self.assertEqual(type(HasTraits), MetaHasTraits)
165 self.assertEqual(type(HasTraits), MetaHasTraits)
166
166
167 class A(HasTraits):
167 class A(HasTraits):
168 a = Int
168 a = Int
169
169
170 a = A()
170 a = A()
171 self.assertEqual(type(a.__class__), MetaHasTraits)
171 self.assertEqual(type(a.__class__), MetaHasTraits)
172 self.assertEqual(a.a,0)
172 self.assertEqual(a.a,0)
173 a.a = 10
173 a.a = 10
174 self.assertEqual(a.a,10)
174 self.assertEqual(a.a,10)
175
175
176 class B(HasTraits):
176 class B(HasTraits):
177 b = Int()
177 b = Int()
178
178
179 b = B()
179 b = B()
180 self.assertEqual(b.b,0)
180 self.assertEqual(b.b,0)
181 b.b = 10
181 b.b = 10
182 self.assertEqual(b.b,10)
182 self.assertEqual(b.b,10)
183
183
184 class C(HasTraits):
184 class C(HasTraits):
185 c = Int(30)
185 c = Int(30)
186
186
187 c = C()
187 c = C()
188 self.assertEqual(c.c,30)
188 self.assertEqual(c.c,30)
189 c.c = 10
189 c.c = 10
190 self.assertEqual(c.c,10)
190 self.assertEqual(c.c,10)
191
191
192 def test_this_class(self):
192 def test_this_class(self):
193 class A(HasTraits):
193 class A(HasTraits):
194 t = This()
194 t = This()
195 tt = This()
195 tt = This()
196 class B(A):
196 class B(A):
197 tt = This()
197 tt = This()
198 ttt = This()
198 ttt = This()
199 self.assertEqual(A.t.this_class, A)
199 self.assertEqual(A.t.this_class, A)
200 self.assertEqual(B.t.this_class, A)
200 self.assertEqual(B.t.this_class, A)
201 self.assertEqual(B.tt.this_class, B)
201 self.assertEqual(B.tt.this_class, B)
202 self.assertEqual(B.ttt.this_class, B)
202 self.assertEqual(B.ttt.this_class, B)
203
203
204 class TestHasTraitsNotify(TestCase):
204 class TestHasTraitsNotify(TestCase):
205
205
206 def setUp(self):
206 def setUp(self):
207 self._notify1 = []
207 self._notify1 = []
208 self._notify2 = []
208 self._notify2 = []
209
209
210 def notify1(self, name, old, new):
210 def notify1(self, name, old, new):
211 self._notify1.append((name, old, new))
211 self._notify1.append((name, old, new))
212
212
213 def notify2(self, name, old, new):
213 def notify2(self, name, old, new):
214 self._notify2.append((name, old, new))
214 self._notify2.append((name, old, new))
215
215
216 def test_notify_all(self):
216 def test_notify_all(self):
217
217
218 class A(HasTraits):
218 class A(HasTraits):
219 a = Int
219 a = Int
220 b = Float
220 b = Float
221
221
222 a = A()
222 a = A()
223 a.on_trait_change(self.notify1)
223 a.on_trait_change(self.notify1)
224 a.a = 0
224 a.a = 0
225 self.assertEqual(len(self._notify1),0)
225 self.assertEqual(len(self._notify1),0)
226 a.b = 0.0
226 a.b = 0.0
227 self.assertEqual(len(self._notify1),0)
227 self.assertEqual(len(self._notify1),0)
228 a.a = 10
228 a.a = 10
229 self.assertTrue(('a',0,10) in self._notify1)
229 self.assertTrue(('a',0,10) in self._notify1)
230 a.b = 10.0
230 a.b = 10.0
231 self.assertTrue(('b',0.0,10.0) in self._notify1)
231 self.assertTrue(('b',0.0,10.0) in self._notify1)
232 self.assertRaises(TraitError,setattr,a,'a','bad string')
232 self.assertRaises(TraitError,setattr,a,'a','bad string')
233 self.assertRaises(TraitError,setattr,a,'b','bad string')
233 self.assertRaises(TraitError,setattr,a,'b','bad string')
234 self._notify1 = []
234 self._notify1 = []
235 a.on_trait_change(self.notify1,remove=True)
235 a.on_trait_change(self.notify1,remove=True)
236 a.a = 20
236 a.a = 20
237 a.b = 20.0
237 a.b = 20.0
238 self.assertEqual(len(self._notify1),0)
238 self.assertEqual(len(self._notify1),0)
239
239
240 def test_notify_one(self):
240 def test_notify_one(self):
241
241
242 class A(HasTraits):
242 class A(HasTraits):
243 a = Int
243 a = Int
244 b = Float
244 b = Float
245
245
246 a = A()
246 a = A()
247 a.on_trait_change(self.notify1, 'a')
247 a.on_trait_change(self.notify1, 'a')
248 a.a = 0
248 a.a = 0
249 self.assertEqual(len(self._notify1),0)
249 self.assertEqual(len(self._notify1),0)
250 a.a = 10
250 a.a = 10
251 self.assertTrue(('a',0,10) in self._notify1)
251 self.assertTrue(('a',0,10) in self._notify1)
252 self.assertRaises(TraitError,setattr,a,'a','bad string')
252 self.assertRaises(TraitError,setattr,a,'a','bad string')
253
253
254 def test_subclass(self):
254 def test_subclass(self):
255
255
256 class A(HasTraits):
256 class A(HasTraits):
257 a = Int
257 a = Int
258
258
259 class B(A):
259 class B(A):
260 b = Float
260 b = Float
261
261
262 b = B()
262 b = B()
263 self.assertEqual(b.a,0)
263 self.assertEqual(b.a,0)
264 self.assertEqual(b.b,0.0)
264 self.assertEqual(b.b,0.0)
265 b.a = 100
265 b.a = 100
266 b.b = 100.0
266 b.b = 100.0
267 self.assertEqual(b.a,100)
267 self.assertEqual(b.a,100)
268 self.assertEqual(b.b,100.0)
268 self.assertEqual(b.b,100.0)
269
269
270 def test_notify_subclass(self):
270 def test_notify_subclass(self):
271
271
272 class A(HasTraits):
272 class A(HasTraits):
273 a = Int
273 a = Int
274
274
275 class B(A):
275 class B(A):
276 b = Float
276 b = Float
277
277
278 b = B()
278 b = B()
279 b.on_trait_change(self.notify1, 'a')
279 b.on_trait_change(self.notify1, 'a')
280 b.on_trait_change(self.notify2, 'b')
280 b.on_trait_change(self.notify2, 'b')
281 b.a = 0
281 b.a = 0
282 b.b = 0.0
282 b.b = 0.0
283 self.assertEqual(len(self._notify1),0)
283 self.assertEqual(len(self._notify1),0)
284 self.assertEqual(len(self._notify2),0)
284 self.assertEqual(len(self._notify2),0)
285 b.a = 10
285 b.a = 10
286 b.b = 10.0
286 b.b = 10.0
287 self.assertTrue(('a',0,10) in self._notify1)
287 self.assertTrue(('a',0,10) in self._notify1)
288 self.assertTrue(('b',0.0,10.0) in self._notify2)
288 self.assertTrue(('b',0.0,10.0) in self._notify2)
289
289
290 def test_static_notify(self):
290 def test_static_notify(self):
291
291
292 class A(HasTraits):
292 class A(HasTraits):
293 a = Int
293 a = Int
294 _notify1 = []
294 _notify1 = []
295 def _a_changed(self, name, old, new):
295 def _a_changed(self, name, old, new):
296 self._notify1.append((name, old, new))
296 self._notify1.append((name, old, new))
297
297
298 a = A()
298 a = A()
299 a.a = 0
299 a.a = 0
300 # This is broken!!!
300 # This is broken!!!
301 self.assertEqual(len(a._notify1),0)
301 self.assertEqual(len(a._notify1),0)
302 a.a = 10
302 a.a = 10
303 self.assertTrue(('a',0,10) in a._notify1)
303 self.assertTrue(('a',0,10) in a._notify1)
304
304
305 class B(A):
305 class B(A):
306 b = Float
306 b = Float
307 _notify2 = []
307 _notify2 = []
308 def _b_changed(self, name, old, new):
308 def _b_changed(self, name, old, new):
309 self._notify2.append((name, old, new))
309 self._notify2.append((name, old, new))
310
310
311 b = B()
311 b = B()
312 b.a = 10
312 b.a = 10
313 b.b = 10.0
313 b.b = 10.0
314 self.assertTrue(('a',0,10) in b._notify1)
314 self.assertTrue(('a',0,10) in b._notify1)
315 self.assertTrue(('b',0.0,10.0) in b._notify2)
315 self.assertTrue(('b',0.0,10.0) in b._notify2)
316
316
317 def test_notify_args(self):
317 def test_notify_args(self):
318
318
319 def callback0():
319 def callback0():
320 self.cb = ()
320 self.cb = ()
321 def callback1(name):
321 def callback1(name):
322 self.cb = (name,)
322 self.cb = (name,)
323 def callback2(name, new):
323 def callback2(name, new):
324 self.cb = (name, new)
324 self.cb = (name, new)
325 def callback3(name, old, new):
325 def callback3(name, old, new):
326 self.cb = (name, old, new)
326 self.cb = (name, old, new)
327
327
328 class A(HasTraits):
328 class A(HasTraits):
329 a = Int
329 a = Int
330
330
331 a = A()
331 a = A()
332 a.on_trait_change(callback0, 'a')
332 a.on_trait_change(callback0, 'a')
333 a.a = 10
333 a.a = 10
334 self.assertEqual(self.cb,())
334 self.assertEqual(self.cb,())
335 a.on_trait_change(callback0, 'a', remove=True)
335 a.on_trait_change(callback0, 'a', remove=True)
336
336
337 a.on_trait_change(callback1, 'a')
337 a.on_trait_change(callback1, 'a')
338 a.a = 100
338 a.a = 100
339 self.assertEqual(self.cb,('a',))
339 self.assertEqual(self.cb,('a',))
340 a.on_trait_change(callback1, 'a', remove=True)
340 a.on_trait_change(callback1, 'a', remove=True)
341
341
342 a.on_trait_change(callback2, 'a')
342 a.on_trait_change(callback2, 'a')
343 a.a = 1000
343 a.a = 1000
344 self.assertEqual(self.cb,('a',1000))
344 self.assertEqual(self.cb,('a',1000))
345 a.on_trait_change(callback2, 'a', remove=True)
345 a.on_trait_change(callback2, 'a', remove=True)
346
346
347 a.on_trait_change(callback3, 'a')
347 a.on_trait_change(callback3, 'a')
348 a.a = 10000
348 a.a = 10000
349 self.assertEqual(self.cb,('a',1000,10000))
349 self.assertEqual(self.cb,('a',1000,10000))
350 a.on_trait_change(callback3, 'a', remove=True)
350 a.on_trait_change(callback3, 'a', remove=True)
351
351
352 self.assertEqual(len(a._trait_notifiers['a']),0)
352 self.assertEqual(len(a._trait_notifiers['a']),0)
353
353
354 def test_notify_only_once(self):
354 def test_notify_only_once(self):
355
355
356 class A(HasTraits):
356 class A(HasTraits):
357 listen_to = ['a']
357 listen_to = ['a']
358
358
359 a = Int(0)
359 a = Int(0)
360 b = 0
360 b = 0
361
361
362 def __init__(self, **kwargs):
362 def __init__(self, **kwargs):
363 super(A, self).__init__(**kwargs)
363 super(A, self).__init__(**kwargs)
364 self.on_trait_change(self.listener1, ['a'])
364 self.on_trait_change(self.listener1, ['a'])
365
365
366 def listener1(self, name, old, new):
366 def listener1(self, name, old, new):
367 self.b += 1
367 self.b += 1
368
368
369 class B(A):
369 class B(A):
370
370
371 c = 0
371 c = 0
372 d = 0
372 d = 0
373
373
374 def __init__(self, **kwargs):
374 def __init__(self, **kwargs):
375 super(B, self).__init__(**kwargs)
375 super(B, self).__init__(**kwargs)
376 self.on_trait_change(self.listener2)
376 self.on_trait_change(self.listener2)
377
377
378 def listener2(self, name, old, new):
378 def listener2(self, name, old, new):
379 self.c += 1
379 self.c += 1
380
380
381 def _a_changed(self, name, old, new):
381 def _a_changed(self, name, old, new):
382 self.d += 1
382 self.d += 1
383
383
384 b = B()
384 b = B()
385 b.a += 1
385 b.a += 1
386 self.assertEqual(b.b, b.c)
386 self.assertEqual(b.b, b.c)
387 self.assertEqual(b.b, b.d)
387 self.assertEqual(b.b, b.d)
388 b.a += 1
388 b.a += 1
389 self.assertEqual(b.b, b.c)
389 self.assertEqual(b.b, b.c)
390 self.assertEqual(b.b, b.d)
390 self.assertEqual(b.b, b.d)
391
391
392
392
393 class TestHasTraits(TestCase):
393 class TestHasTraits(TestCase):
394
394
395 def test_trait_names(self):
395 def test_trait_names(self):
396 class A(HasTraits):
396 class A(HasTraits):
397 i = Int
397 i = Int
398 f = Float
398 f = Float
399 a = A()
399 a = A()
400 self.assertEqual(sorted(a.trait_names()),['f','i'])
400 self.assertEqual(sorted(a.trait_names()),['f','i'])
401 self.assertEqual(sorted(A.class_trait_names()),['f','i'])
401 self.assertEqual(sorted(A.class_trait_names()),['f','i'])
402
402
403 def test_trait_metadata(self):
403 def test_trait_metadata(self):
404 class A(HasTraits):
404 class A(HasTraits):
405 i = Int(config_key='MY_VALUE')
405 i = Int(config_key='MY_VALUE')
406 a = A()
406 a = A()
407 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
407 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
408
408
409 def test_trait_metadata_default(self):
409 def test_trait_metadata_default(self):
410 class A(HasTraits):
410 class A(HasTraits):
411 i = Int()
411 i = Int()
412 a = A()
412 a = A()
413 self.assertEqual(a.trait_metadata('i', 'config_key'), None)
413 self.assertEqual(a.trait_metadata('i', 'config_key'), None)
414 self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
414 self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
415
415
416 def test_traits(self):
416 def test_traits(self):
417 class A(HasTraits):
417 class A(HasTraits):
418 i = Int
418 i = Int
419 f = Float
419 f = Float
420 a = A()
420 a = A()
421 self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
421 self.assertEqual(a.traits(), dict(i=A.i, f=A.f))
422 self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
422 self.assertEqual(A.class_traits(), dict(i=A.i, f=A.f))
423
423
424 def test_traits_metadata(self):
424 def test_traits_metadata(self):
425 class A(HasTraits):
425 class A(HasTraits):
426 i = Int(config_key='VALUE1', other_thing='VALUE2')
426 i = Int(config_key='VALUE1', other_thing='VALUE2')
427 f = Float(config_key='VALUE3', other_thing='VALUE2')
427 f = Float(config_key='VALUE3', other_thing='VALUE2')
428 j = Int(0)
428 j = Int(0)
429 a = A()
429 a = A()
430 self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
430 self.assertEqual(a.traits(), dict(i=A.i, f=A.f, j=A.j))
431 traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
431 traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
432 self.assertEqual(traits, dict(i=A.i))
432 self.assertEqual(traits, dict(i=A.i))
433
433
434 # This passes, but it shouldn't because I am replicating a bug in
434 # This passes, but it shouldn't because I am replicating a bug in
435 # traits.
435 # traits.
436 traits = a.traits(config_key=lambda v: True)
436 traits = a.traits(config_key=lambda v: True)
437 self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
437 self.assertEqual(traits, dict(i=A.i, f=A.f, j=A.j))
438
438
439 def test_init(self):
439 def test_init(self):
440 class A(HasTraits):
440 class A(HasTraits):
441 i = Int()
441 i = Int()
442 x = Float()
442 x = Float()
443 a = A(i=1, x=10.0)
443 a = A(i=1, x=10.0)
444 self.assertEqual(a.i, 1)
444 self.assertEqual(a.i, 1)
445 self.assertEqual(a.x, 10.0)
445 self.assertEqual(a.x, 10.0)
446
446
447 def test_positional_args(self):
447 def test_positional_args(self):
448 class A(HasTraits):
448 class A(HasTraits):
449 i = Int(0)
449 i = Int(0)
450 def __init__(self, i):
450 def __init__(self, i):
451 super(A, self).__init__()
451 super(A, self).__init__()
452 self.i = i
452 self.i = i
453
453
454 a = A(5)
454 a = A(5)
455 self.assertEqual(a.i, 5)
455 self.assertEqual(a.i, 5)
456 # should raise TypeError if no positional arg given
456 # should raise TypeError if no positional arg given
457 self.assertRaises(TypeError, A)
457 self.assertRaises(TypeError, A)
458
458
459 #-----------------------------------------------------------------------------
459 #-----------------------------------------------------------------------------
460 # Tests for specific trait types
460 # Tests for specific trait types
461 #-----------------------------------------------------------------------------
461 #-----------------------------------------------------------------------------
462
462
463
463
464 class TestType(TestCase):
464 class TestType(TestCase):
465
465
466 def test_default(self):
466 def test_default(self):
467
467
468 class B(object): pass
468 class B(object): pass
469 class A(HasTraits):
469 class A(HasTraits):
470 klass = Type
470 klass = Type
471
471
472 a = A()
472 a = A()
473 self.assertEqual(a.klass, None)
473 self.assertEqual(a.klass, None)
474
474
475 a.klass = B
475 a.klass = B
476 self.assertEqual(a.klass, B)
476 self.assertEqual(a.klass, B)
477 self.assertRaises(TraitError, setattr, a, 'klass', 10)
477 self.assertRaises(TraitError, setattr, a, 'klass', 10)
478
478
479 def test_value(self):
479 def test_value(self):
480
480
481 class B(object): pass
481 class B(object): pass
482 class C(object): pass
482 class C(object): pass
483 class A(HasTraits):
483 class A(HasTraits):
484 klass = Type(B)
484 klass = Type(B)
485
485
486 a = A()
486 a = A()
487 self.assertEqual(a.klass, B)
487 self.assertEqual(a.klass, B)
488 self.assertRaises(TraitError, setattr, a, 'klass', C)
488 self.assertRaises(TraitError, setattr, a, 'klass', C)
489 self.assertRaises(TraitError, setattr, a, 'klass', object)
489 self.assertRaises(TraitError, setattr, a, 'klass', object)
490 a.klass = B
490 a.klass = B
491
491
492 def test_allow_none(self):
492 def test_allow_none(self):
493
493
494 class B(object): pass
494 class B(object): pass
495 class C(B): pass
495 class C(B): pass
496 class A(HasTraits):
496 class A(HasTraits):
497 klass = Type(B, allow_none=False)
497 klass = Type(B, allow_none=False)
498
498
499 a = A()
499 a = A()
500 self.assertEqual(a.klass, B)
500 self.assertEqual(a.klass, B)
501 self.assertRaises(TraitError, setattr, a, 'klass', None)
501 self.assertRaises(TraitError, setattr, a, 'klass', None)
502 a.klass = C
502 a.klass = C
503 self.assertEqual(a.klass, C)
503 self.assertEqual(a.klass, C)
504
504
505 def test_validate_klass(self):
505 def test_validate_klass(self):
506
506
507 class A(HasTraits):
507 class A(HasTraits):
508 klass = Type('no strings allowed')
508 klass = Type('no strings allowed')
509
509
510 self.assertRaises(ImportError, A)
510 self.assertRaises(ImportError, A)
511
511
512 class A(HasTraits):
512 class A(HasTraits):
513 klass = Type('rub.adub.Duck')
513 klass = Type('rub.adub.Duck')
514
514
515 self.assertRaises(ImportError, A)
515 self.assertRaises(ImportError, A)
516
516
517 def test_validate_default(self):
517 def test_validate_default(self):
518
518
519 class B(object): pass
519 class B(object): pass
520 class A(HasTraits):
520 class A(HasTraits):
521 klass = Type('bad default', B)
521 klass = Type('bad default', B)
522
522
523 self.assertRaises(ImportError, A)
523 self.assertRaises(ImportError, A)
524
524
525 class C(HasTraits):
525 class C(HasTraits):
526 klass = Type(None, B, allow_none=False)
526 klass = Type(None, B, allow_none=False)
527
527
528 self.assertRaises(TraitError, C)
528 self.assertRaises(TraitError, C)
529
529
530 def test_str_klass(self):
530 def test_str_klass(self):
531
531
532 class A(HasTraits):
532 class A(HasTraits):
533 klass = Type('IPython.utils.ipstruct.Struct')
533 klass = Type('IPython.utils.ipstruct.Struct')
534
534
535 from IPython.utils.ipstruct import Struct
535 from IPython.utils.ipstruct import Struct
536 a = A()
536 a = A()
537 a.klass = Struct
537 a.klass = Struct
538 self.assertEqual(a.klass, Struct)
538 self.assertEqual(a.klass, Struct)
539
539
540 self.assertRaises(TraitError, setattr, a, 'klass', 10)
540 self.assertRaises(TraitError, setattr, a, 'klass', 10)
541
541
542 def test_set_str_klass(self):
542 def test_set_str_klass(self):
543
543
544 class A(HasTraits):
544 class A(HasTraits):
545 klass = Type()
545 klass = Type()
546
546
547 a = A(klass='IPython.utils.ipstruct.Struct')
547 a = A(klass='IPython.utils.ipstruct.Struct')
548 from IPython.utils.ipstruct import Struct
548 from IPython.utils.ipstruct import Struct
549 self.assertEqual(a.klass, Struct)
549 self.assertEqual(a.klass, Struct)
550
550
551 class TestInstance(TestCase):
551 class TestInstance(TestCase):
552
552
553 def test_basic(self):
553 def test_basic(self):
554 class Foo(object): pass
554 class Foo(object): pass
555 class Bar(Foo): pass
555 class Bar(Foo): pass
556 class Bah(object): pass
556 class Bah(object): pass
557
557
558 class A(HasTraits):
558 class A(HasTraits):
559 inst = Instance(Foo)
559 inst = Instance(Foo)
560
560
561 a = A()
561 a = A()
562 self.assertTrue(a.inst is None)
562 self.assertTrue(a.inst is None)
563 a.inst = Foo()
563 a.inst = Foo()
564 self.assertTrue(isinstance(a.inst, Foo))
564 self.assertTrue(isinstance(a.inst, Foo))
565 a.inst = Bar()
565 a.inst = Bar()
566 self.assertTrue(isinstance(a.inst, Foo))
566 self.assertTrue(isinstance(a.inst, Foo))
567 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
567 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
568 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
568 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
569 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
569 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
570
570
571 def test_default_klass(self):
571 def test_default_klass(self):
572 class Foo(object): pass
572 class Foo(object): pass
573 class Bar(Foo): pass
573 class Bar(Foo): pass
574 class Bah(object): pass
574 class Bah(object): pass
575
575
576 class FooInstance(Instance):
576 class FooInstance(Instance):
577 klass = Foo
577 klass = Foo
578
578
579 class A(HasTraits):
579 class A(HasTraits):
580 inst = FooInstance()
580 inst = FooInstance()
581
581
582 a = A()
582 a = A()
583 self.assertTrue(a.inst is None)
583 self.assertTrue(a.inst is None)
584 a.inst = Foo()
584 a.inst = Foo()
585 self.assertTrue(isinstance(a.inst, Foo))
585 self.assertTrue(isinstance(a.inst, Foo))
586 a.inst = Bar()
586 a.inst = Bar()
587 self.assertTrue(isinstance(a.inst, Foo))
587 self.assertTrue(isinstance(a.inst, Foo))
588 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
588 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
589 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
589 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
590 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
590 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
591
591
592 def test_unique_default_value(self):
592 def test_unique_default_value(self):
593 class Foo(object): pass
593 class Foo(object): pass
594 class A(HasTraits):
594 class A(HasTraits):
595 inst = Instance(Foo,(),{})
595 inst = Instance(Foo,(),{})
596
596
597 a = A()
597 a = A()
598 b = A()
598 b = A()
599 self.assertTrue(a.inst is not b.inst)
599 self.assertTrue(a.inst is not b.inst)
600
600
601 def test_args_kw(self):
601 def test_args_kw(self):
602 class Foo(object):
602 class Foo(object):
603 def __init__(self, c): self.c = c
603 def __init__(self, c): self.c = c
604 class Bar(object): pass
604 class Bar(object): pass
605 class Bah(object):
605 class Bah(object):
606 def __init__(self, c, d):
606 def __init__(self, c, d):
607 self.c = c; self.d = d
607 self.c = c; self.d = d
608
608
609 class A(HasTraits):
609 class A(HasTraits):
610 inst = Instance(Foo, (10,))
610 inst = Instance(Foo, (10,))
611 a = A()
611 a = A()
612 self.assertEqual(a.inst.c, 10)
612 self.assertEqual(a.inst.c, 10)
613
613
614 class B(HasTraits):
614 class B(HasTraits):
615 inst = Instance(Bah, args=(10,), kw=dict(d=20))
615 inst = Instance(Bah, args=(10,), kw=dict(d=20))
616 b = B()
616 b = B()
617 self.assertEqual(b.inst.c, 10)
617 self.assertEqual(b.inst.c, 10)
618 self.assertEqual(b.inst.d, 20)
618 self.assertEqual(b.inst.d, 20)
619
619
620 class C(HasTraits):
620 class C(HasTraits):
621 inst = Instance(Foo)
621 inst = Instance(Foo)
622 c = C()
622 c = C()
623 self.assertTrue(c.inst is None)
623 self.assertTrue(c.inst is None)
624
624
625 def test_bad_default(self):
625 def test_bad_default(self):
626 class Foo(object): pass
626 class Foo(object): pass
627
627
628 class A(HasTraits):
628 class A(HasTraits):
629 inst = Instance(Foo, allow_none=False)
629 inst = Instance(Foo, allow_none=False)
630
630
631 self.assertRaises(TraitError, A)
631 self.assertRaises(TraitError, A)
632
632
633 def test_instance(self):
633 def test_instance(self):
634 class Foo(object): pass
634 class Foo(object): pass
635
635
636 def inner():
636 def inner():
637 class A(HasTraits):
637 class A(HasTraits):
638 inst = Instance(Foo())
638 inst = Instance(Foo())
639
639
640 self.assertRaises(TraitError, inner)
640 self.assertRaises(TraitError, inner)
641
641
642
642
643 class TestThis(TestCase):
643 class TestThis(TestCase):
644
644
645 def test_this_class(self):
645 def test_this_class(self):
646 class Foo(HasTraits):
646 class Foo(HasTraits):
647 this = This
647 this = This
648
648
649 f = Foo()
649 f = Foo()
650 self.assertEqual(f.this, None)
650 self.assertEqual(f.this, None)
651 g = Foo()
651 g = Foo()
652 f.this = g
652 f.this = g
653 self.assertEqual(f.this, g)
653 self.assertEqual(f.this, g)
654 self.assertRaises(TraitError, setattr, f, 'this', 10)
654 self.assertRaises(TraitError, setattr, f, 'this', 10)
655
655
656 def test_this_inst(self):
656 def test_this_inst(self):
657 class Foo(HasTraits):
657 class Foo(HasTraits):
658 this = This()
658 this = This()
659
659
660 f = Foo()
660 f = Foo()
661 f.this = Foo()
661 f.this = Foo()
662 self.assertTrue(isinstance(f.this, Foo))
662 self.assertTrue(isinstance(f.this, Foo))
663
663
664 def test_subclass(self):
664 def test_subclass(self):
665 class Foo(HasTraits):
665 class Foo(HasTraits):
666 t = This()
666 t = This()
667 class Bar(Foo):
667 class Bar(Foo):
668 pass
668 pass
669 f = Foo()
669 f = Foo()
670 b = Bar()
670 b = Bar()
671 f.t = b
671 f.t = b
672 b.t = f
672 b.t = f
673 self.assertEqual(f.t, b)
673 self.assertEqual(f.t, b)
674 self.assertEqual(b.t, f)
674 self.assertEqual(b.t, f)
675
675
676 def test_subclass_override(self):
676 def test_subclass_override(self):
677 class Foo(HasTraits):
677 class Foo(HasTraits):
678 t = This()
678 t = This()
679 class Bar(Foo):
679 class Bar(Foo):
680 t = This()
680 t = This()
681 f = Foo()
681 f = Foo()
682 b = Bar()
682 b = Bar()
683 f.t = b
683 f.t = b
684 self.assertEqual(f.t, b)
684 self.assertEqual(f.t, b)
685 self.assertRaises(TraitError, setattr, b, 't', f)
685 self.assertRaises(TraitError, setattr, b, 't', f)
686
686
687 def test_this_in_container(self):
687 def test_this_in_container(self):
688
688
689 class Tree(HasTraits):
689 class Tree(HasTraits):
690 value = Unicode()
690 value = Unicode()
691 leaves = List(This())
691 leaves = List(This())
692
692
693 tree = Tree(
693 tree = Tree(
694 value='foo',
694 value='foo',
695 leaves=[Tree('bar'), Tree('buzz')]
695 leaves=[Tree('bar'), Tree('buzz')]
696 )
696 )
697
697
698 with self.assertRaises(TraitError):
698 with self.assertRaises(TraitError):
699 tree.leaves = [1, 2]
699 tree.leaves = [1, 2]
700
700
701 class TraitTestBase(TestCase):
701 class TraitTestBase(TestCase):
702 """A best testing class for basic trait types."""
702 """A best testing class for basic trait types."""
703
703
704 def assign(self, value):
704 def assign(self, value):
705 self.obj.value = value
705 self.obj.value = value
706
706
707 def coerce(self, value):
707 def coerce(self, value):
708 return value
708 return value
709
709
710 def test_good_values(self):
710 def test_good_values(self):
711 if hasattr(self, '_good_values'):
711 if hasattr(self, '_good_values'):
712 for value in self._good_values:
712 for value in self._good_values:
713 self.assign(value)
713 self.assign(value)
714 self.assertEqual(self.obj.value, self.coerce(value))
714 self.assertEqual(self.obj.value, self.coerce(value))
715
715
716 def test_bad_values(self):
716 def test_bad_values(self):
717 if hasattr(self, '_bad_values'):
717 if hasattr(self, '_bad_values'):
718 for value in self._bad_values:
718 for value in self._bad_values:
719 try:
719 try:
720 self.assertRaises(TraitError, self.assign, value)
720 self.assertRaises(TraitError, self.assign, value)
721 except AssertionError:
721 except AssertionError:
722 assert False, value
722 assert False, value
723
723
724 def test_default_value(self):
724 def test_default_value(self):
725 if hasattr(self, '_default_value'):
725 if hasattr(self, '_default_value'):
726 self.assertEqual(self._default_value, self.obj.value)
726 self.assertEqual(self._default_value, self.obj.value)
727
727
728 def test_allow_none(self):
728 def test_allow_none(self):
729 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
729 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
730 None in self._bad_values):
730 None in self._bad_values):
731 trait=self.obj.traits()['value']
731 trait=self.obj.traits()['value']
732 try:
732 try:
733 trait.allow_none = True
733 trait.allow_none = True
734 self._bad_values.remove(None)
734 self._bad_values.remove(None)
735 #skip coerce. Allow None casts None to None.
735 #skip coerce. Allow None casts None to None.
736 self.assign(None)
736 self.assign(None)
737 self.assertEqual(self.obj.value,None)
737 self.assertEqual(self.obj.value,None)
738 self.test_good_values()
738 self.test_good_values()
739 self.test_bad_values()
739 self.test_bad_values()
740 finally:
740 finally:
741 #tear down
741 #tear down
742 trait.allow_none = False
742 trait.allow_none = False
743 self._bad_values.append(None)
743 self._bad_values.append(None)
744
744
745 def tearDown(self):
745 def tearDown(self):
746 # restore default value after tests, if set
746 # restore default value after tests, if set
747 if hasattr(self, '_default_value'):
747 if hasattr(self, '_default_value'):
748 self.obj.value = self._default_value
748 self.obj.value = self._default_value
749
749
750
750
751 class AnyTrait(HasTraits):
751 class AnyTrait(HasTraits):
752
752
753 value = Any
753 value = Any
754
754
755 class AnyTraitTest(TraitTestBase):
755 class AnyTraitTest(TraitTestBase):
756
756
757 obj = AnyTrait()
757 obj = AnyTrait()
758
758
759 _default_value = None
759 _default_value = None
760 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
760 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
761 _bad_values = []
761 _bad_values = []
762
762
763 class UnionTrait(HasTraits):
764
765 value = Union([Type(), Unicode()])
766
767 class UnionTraitTest(TraitTestBase):
768
769 obj = UnionTrait()
770 _default_value = None
771 _good_values = [int, float, 'ten']
772 _bad_values = [[], (0,), 1j]
763
773
764 class IntTrait(HasTraits):
774 class IntTrait(HasTraits):
765
775
766 value = Int(99)
776 value = Int(99)
767
777
768 class TestInt(TraitTestBase):
778 class TestInt(TraitTestBase):
769
779
770 obj = IntTrait()
780 obj = IntTrait()
771 _default_value = 99
781 _default_value = 99
772 _good_values = [10, -10]
782 _good_values = [10, -10]
773 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
783 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
774 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
784 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
775 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
785 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
776 if not py3compat.PY3:
786 if not py3compat.PY3:
777 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
787 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
778
788
779
789
780 class LongTrait(HasTraits):
790 class LongTrait(HasTraits):
781
791
782 value = Long(99 if py3compat.PY3 else long(99))
792 value = Long(99 if py3compat.PY3 else long(99))
783
793
784 class TestLong(TraitTestBase):
794 class TestLong(TraitTestBase):
785
795
786 obj = LongTrait()
796 obj = LongTrait()
787
797
788 _default_value = 99 if py3compat.PY3 else long(99)
798 _default_value = 99 if py3compat.PY3 else long(99)
789 _good_values = [10, -10]
799 _good_values = [10, -10]
790 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
800 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
791 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
801 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
792 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
802 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
793 u'-10.1']
803 u'-10.1']
794 if not py3compat.PY3:
804 if not py3compat.PY3:
795 # maxint undefined on py3, because int == long
805 # maxint undefined on py3, because int == long
796 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
806 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
797 _bad_values.extend([[long(10)], (long(10),)])
807 _bad_values.extend([[long(10)], (long(10),)])
798
808
799 @skipif(py3compat.PY3, "not relevant on py3")
809 @skipif(py3compat.PY3, "not relevant on py3")
800 def test_cast_small(self):
810 def test_cast_small(self):
801 """Long casts ints to long"""
811 """Long casts ints to long"""
802 self.obj.value = 10
812 self.obj.value = 10
803 self.assertEqual(type(self.obj.value), long)
813 self.assertEqual(type(self.obj.value), long)
804
814
805
815
806 class IntegerTrait(HasTraits):
816 class IntegerTrait(HasTraits):
807 value = Integer(1)
817 value = Integer(1)
808
818
809 class TestInteger(TestLong):
819 class TestInteger(TestLong):
810 obj = IntegerTrait()
820 obj = IntegerTrait()
811 _default_value = 1
821 _default_value = 1
812
822
813 def coerce(self, n):
823 def coerce(self, n):
814 return int(n)
824 return int(n)
815
825
816 @skipif(py3compat.PY3, "not relevant on py3")
826 @skipif(py3compat.PY3, "not relevant on py3")
817 def test_cast_small(self):
827 def test_cast_small(self):
818 """Integer casts small longs to int"""
828 """Integer casts small longs to int"""
819 if py3compat.PY3:
829 if py3compat.PY3:
820 raise SkipTest("not relevant on py3")
830 raise SkipTest("not relevant on py3")
821
831
822 self.obj.value = long(100)
832 self.obj.value = long(100)
823 self.assertEqual(type(self.obj.value), int)
833 self.assertEqual(type(self.obj.value), int)
824
834
825
835
826 class FloatTrait(HasTraits):
836 class FloatTrait(HasTraits):
827
837
828 value = Float(99.0)
838 value = Float(99.0)
829
839
830 class TestFloat(TraitTestBase):
840 class TestFloat(TraitTestBase):
831
841
832 obj = FloatTrait()
842 obj = FloatTrait()
833
843
834 _default_value = 99.0
844 _default_value = 99.0
835 _good_values = [10, -10, 10.1, -10.1]
845 _good_values = [10, -10, 10.1, -10.1]
836 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
846 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
837 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
847 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
838 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
848 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
839 if not py3compat.PY3:
849 if not py3compat.PY3:
840 _bad_values.extend([long(10), long(-10)])
850 _bad_values.extend([long(10), long(-10)])
841
851
842
852
843 class ComplexTrait(HasTraits):
853 class ComplexTrait(HasTraits):
844
854
845 value = Complex(99.0-99.0j)
855 value = Complex(99.0-99.0j)
846
856
847 class TestComplex(TraitTestBase):
857 class TestComplex(TraitTestBase):
848
858
849 obj = ComplexTrait()
859 obj = ComplexTrait()
850
860
851 _default_value = 99.0-99.0j
861 _default_value = 99.0-99.0j
852 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
862 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
853 10.1j, 10.1+10.1j, 10.1-10.1j]
863 10.1j, 10.1+10.1j, 10.1-10.1j]
854 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
864 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
855 if not py3compat.PY3:
865 if not py3compat.PY3:
856 _bad_values.extend([long(10), long(-10)])
866 _bad_values.extend([long(10), long(-10)])
857
867
858
868
859 class BytesTrait(HasTraits):
869 class BytesTrait(HasTraits):
860
870
861 value = Bytes(b'string')
871 value = Bytes(b'string')
862
872
863 class TestBytes(TraitTestBase):
873 class TestBytes(TraitTestBase):
864
874
865 obj = BytesTrait()
875 obj = BytesTrait()
866
876
867 _default_value = b'string'
877 _default_value = b'string'
868 _good_values = [b'10', b'-10', b'10L',
878 _good_values = [b'10', b'-10', b'10L',
869 b'-10L', b'10.1', b'-10.1', b'string']
879 b'-10L', b'10.1', b'-10.1', b'string']
870 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
880 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
871 ['ten'],{'ten': 10},(10,), None, u'string']
881 ['ten'],{'ten': 10},(10,), None, u'string']
872 if not py3compat.PY3:
882 if not py3compat.PY3:
873 _bad_values.extend([long(10), long(-10)])
883 _bad_values.extend([long(10), long(-10)])
874
884
875
885
876 class UnicodeTrait(HasTraits):
886 class UnicodeTrait(HasTraits):
877
887
878 value = Unicode(u'unicode')
888 value = Unicode(u'unicode')
879
889
880 class TestUnicode(TraitTestBase):
890 class TestUnicode(TraitTestBase):
881
891
882 obj = UnicodeTrait()
892 obj = UnicodeTrait()
883
893
884 _default_value = u'unicode'
894 _default_value = u'unicode'
885 _good_values = ['10', '-10', '10L', '-10L', '10.1',
895 _good_values = ['10', '-10', '10L', '-10L', '10.1',
886 '-10.1', '', u'', 'string', u'string', u"€"]
896 '-10.1', '', u'', 'string', u'string', u"€"]
887 _bad_values = [10, -10, 10.1, -10.1, 1j,
897 _bad_values = [10, -10, 10.1, -10.1, 1j,
888 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
898 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
889 if not py3compat.PY3:
899 if not py3compat.PY3:
890 _bad_values.extend([long(10), long(-10)])
900 _bad_values.extend([long(10), long(-10)])
891
901
892
902
893 class ObjectNameTrait(HasTraits):
903 class ObjectNameTrait(HasTraits):
894 value = ObjectName("abc")
904 value = ObjectName("abc")
895
905
896 class TestObjectName(TraitTestBase):
906 class TestObjectName(TraitTestBase):
897 obj = ObjectNameTrait()
907 obj = ObjectNameTrait()
898
908
899 _default_value = "abc"
909 _default_value = "abc"
900 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
910 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
901 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
911 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
902 None, object(), object]
912 None, object(), object]
903 if sys.version_info[0] < 3:
913 if sys.version_info[0] < 3:
904 _bad_values.append(u"ΓΎ")
914 _bad_values.append(u"ΓΎ")
905 else:
915 else:
906 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
916 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
907
917
908
918
909 class DottedObjectNameTrait(HasTraits):
919 class DottedObjectNameTrait(HasTraits):
910 value = DottedObjectName("a.b")
920 value = DottedObjectName("a.b")
911
921
912 class TestDottedObjectName(TraitTestBase):
922 class TestDottedObjectName(TraitTestBase):
913 obj = DottedObjectNameTrait()
923 obj = DottedObjectNameTrait()
914
924
915 _default_value = "a.b"
925 _default_value = "a.b"
916 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
926 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
917 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
927 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
918 if sys.version_info[0] < 3:
928 if sys.version_info[0] < 3:
919 _bad_values.append(u"t.ΓΎ")
929 _bad_values.append(u"t.ΓΎ")
920 else:
930 else:
921 _good_values.append(u"t.ΓΎ")
931 _good_values.append(u"t.ΓΎ")
922
932
923
933
924 class TCPAddressTrait(HasTraits):
934 class TCPAddressTrait(HasTraits):
925
935
926 value = TCPAddress()
936 value = TCPAddress()
927
937
928 class TestTCPAddress(TraitTestBase):
938 class TestTCPAddress(TraitTestBase):
929
939
930 obj = TCPAddressTrait()
940 obj = TCPAddressTrait()
931
941
932 _default_value = ('127.0.0.1',0)
942 _default_value = ('127.0.0.1',0)
933 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
943 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
934 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
944 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
935
945
936 class ListTrait(HasTraits):
946 class ListTrait(HasTraits):
937
947
938 value = List(Int)
948 value = List(Int)
939
949
940 class TestList(TraitTestBase):
950 class TestList(TraitTestBase):
941
951
942 obj = ListTrait()
952 obj = ListTrait()
943
953
944 _default_value = []
954 _default_value = []
945 _good_values = [[], [1], list(range(10)), (1,2)]
955 _good_values = [[], [1], list(range(10)), (1,2)]
946 _bad_values = [10, [1,'a'], 'a']
956 _bad_values = [10, [1,'a'], 'a']
947
957
948 def coerce(self, value):
958 def coerce(self, value):
949 if value is not None:
959 if value is not None:
950 value = list(value)
960 value = list(value)
951 return value
961 return value
952
962
953 class Foo(object):
963 class Foo(object):
954 pass
964 pass
955
965
956 class InstanceListTrait(HasTraits):
966 class InstanceListTrait(HasTraits):
957
967
958 value = List(Instance(__name__+'.Foo'))
968 value = List(Instance(__name__+'.Foo'))
959
969
960 class TestInstanceList(TraitTestBase):
970 class TestInstanceList(TraitTestBase):
961
971
962 obj = InstanceListTrait()
972 obj = InstanceListTrait()
963
973
964 def test_klass(self):
974 def test_klass(self):
965 """Test that the instance klass is properly assigned."""
975 """Test that the instance klass is properly assigned."""
966 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
976 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
967
977
968 _default_value = []
978 _default_value = []
969 _good_values = [[Foo(), Foo(), None], None]
979 _good_values = [[Foo(), Foo(), None], None]
970 _bad_values = [['1', 2,], '1', [Foo]]
980 _bad_values = [['1', 2,], '1', [Foo]]
971
981
972 class LenListTrait(HasTraits):
982 class LenListTrait(HasTraits):
973
983
974 value = List(Int, [0], minlen=1, maxlen=2)
984 value = List(Int, [0], minlen=1, maxlen=2)
975
985
976 class TestLenList(TraitTestBase):
986 class TestLenList(TraitTestBase):
977
987
978 obj = LenListTrait()
988 obj = LenListTrait()
979
989
980 _default_value = [0]
990 _default_value = [0]
981 _good_values = [[1], [1,2], (1,2)]
991 _good_values = [[1], [1,2], (1,2)]
982 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
992 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
983
993
984 def coerce(self, value):
994 def coerce(self, value):
985 if value is not None:
995 if value is not None:
986 value = list(value)
996 value = list(value)
987 return value
997 return value
988
998
989 class TupleTrait(HasTraits):
999 class TupleTrait(HasTraits):
990
1000
991 value = Tuple(Int(allow_none=True))
1001 value = Tuple(Int(allow_none=True))
992
1002
993 class TestTupleTrait(TraitTestBase):
1003 class TestTupleTrait(TraitTestBase):
994
1004
995 obj = TupleTrait()
1005 obj = TupleTrait()
996
1006
997 _default_value = None
1007 _default_value = None
998 _good_values = [(1,), None, (0,), [1], (None,)]
1008 _good_values = [(1,), None, (0,), [1], (None,)]
999 _bad_values = [10, (1,2), ('a'), ()]
1009 _bad_values = [10, (1,2), ('a'), ()]
1000
1010
1001 def coerce(self, value):
1011 def coerce(self, value):
1002 if value is not None:
1012 if value is not None:
1003 value = tuple(value)
1013 value = tuple(value)
1004 return value
1014 return value
1005
1015
1006 def test_invalid_args(self):
1016 def test_invalid_args(self):
1007 self.assertRaises(TypeError, Tuple, 5)
1017 self.assertRaises(TypeError, Tuple, 5)
1008 self.assertRaises(TypeError, Tuple, default_value='hello')
1018 self.assertRaises(TypeError, Tuple, default_value='hello')
1009 t = Tuple(Int, CBytes, default_value=(1,5))
1019 t = Tuple(Int, CBytes, default_value=(1,5))
1010
1020
1011 class LooseTupleTrait(HasTraits):
1021 class LooseTupleTrait(HasTraits):
1012
1022
1013 value = Tuple((1,2,3))
1023 value = Tuple((1,2,3))
1014
1024
1015 class TestLooseTupleTrait(TraitTestBase):
1025 class TestLooseTupleTrait(TraitTestBase):
1016
1026
1017 obj = LooseTupleTrait()
1027 obj = LooseTupleTrait()
1018
1028
1019 _default_value = (1,2,3)
1029 _default_value = (1,2,3)
1020 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
1030 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
1021 _bad_values = [10, 'hello', {}]
1031 _bad_values = [10, 'hello', {}]
1022
1032
1023 def coerce(self, value):
1033 def coerce(self, value):
1024 if value is not None:
1034 if value is not None:
1025 value = tuple(value)
1035 value = tuple(value)
1026 return value
1036 return value
1027
1037
1028 def test_invalid_args(self):
1038 def test_invalid_args(self):
1029 self.assertRaises(TypeError, Tuple, 5)
1039 self.assertRaises(TypeError, Tuple, 5)
1030 self.assertRaises(TypeError, Tuple, default_value='hello')
1040 self.assertRaises(TypeError, Tuple, default_value='hello')
1031 t = Tuple(Int, CBytes, default_value=(1,5))
1041 t = Tuple(Int, CBytes, default_value=(1,5))
1032
1042
1033
1043
1034 class MultiTupleTrait(HasTraits):
1044 class MultiTupleTrait(HasTraits):
1035
1045
1036 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
1046 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
1037
1047
1038 class TestMultiTuple(TraitTestBase):
1048 class TestMultiTuple(TraitTestBase):
1039
1049
1040 obj = MultiTupleTrait()
1050 obj = MultiTupleTrait()
1041
1051
1042 _default_value = (99,b'bottles')
1052 _default_value = (99,b'bottles')
1043 _good_values = [(1,b'a'), (2,b'b')]
1053 _good_values = [(1,b'a'), (2,b'b')]
1044 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1054 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1045
1055
1046 class CRegExpTrait(HasTraits):
1056 class CRegExpTrait(HasTraits):
1047
1057
1048 value = CRegExp(r'')
1058 value = CRegExp(r'')
1049
1059
1050 class TestCRegExp(TraitTestBase):
1060 class TestCRegExp(TraitTestBase):
1051
1061
1052 def coerce(self, value):
1062 def coerce(self, value):
1053 return re.compile(value)
1063 return re.compile(value)
1054
1064
1055 obj = CRegExpTrait()
1065 obj = CRegExpTrait()
1056
1066
1057 _default_value = re.compile(r'')
1067 _default_value = re.compile(r'')
1058 _good_values = [r'\d+', re.compile(r'\d+')]
1068 _good_values = [r'\d+', re.compile(r'\d+')]
1059 _bad_values = ['(', None, ()]
1069 _bad_values = ['(', None, ()]
1060
1070
1061 class DictTrait(HasTraits):
1071 class DictTrait(HasTraits):
1062 value = Dict()
1072 value = Dict()
1063
1073
1064 def test_dict_assignment():
1074 def test_dict_assignment():
1065 d = dict()
1075 d = dict()
1066 c = DictTrait()
1076 c = DictTrait()
1067 c.value = d
1077 c.value = d
1068 d['a'] = 5
1078 d['a'] = 5
1069 nt.assert_equal(d, c.value)
1079 nt.assert_equal(d, c.value)
1070 nt.assert_true(c.value is d)
1080 nt.assert_true(c.value is d)
1071
1081
1072 class TestLink(TestCase):
1082 class TestLink(TestCase):
1073 def test_connect_same(self):
1083 def test_connect_same(self):
1074 """Verify two traitlets of the same type can be linked together using link."""
1084 """Verify two traitlets of the same type can be linked together using link."""
1075
1085
1076 # Create two simple classes with Int traitlets.
1086 # Create two simple classes with Int traitlets.
1077 class A(HasTraits):
1087 class A(HasTraits):
1078 value = Int()
1088 value = Int()
1079 a = A(value=9)
1089 a = A(value=9)
1080 b = A(value=8)
1090 b = A(value=8)
1081
1091
1082 # Conenct the two classes.
1092 # Conenct the two classes.
1083 c = link((a, 'value'), (b, 'value'))
1093 c = link((a, 'value'), (b, 'value'))
1084
1094
1085 # Make sure the values are the same at the point of linking.
1095 # Make sure the values are the same at the point of linking.
1086 self.assertEqual(a.value, b.value)
1096 self.assertEqual(a.value, b.value)
1087
1097
1088 # Change one of the values to make sure they stay in sync.
1098 # Change one of the values to make sure they stay in sync.
1089 a.value = 5
1099 a.value = 5
1090 self.assertEqual(a.value, b.value)
1100 self.assertEqual(a.value, b.value)
1091 b.value = 6
1101 b.value = 6
1092 self.assertEqual(a.value, b.value)
1102 self.assertEqual(a.value, b.value)
1093
1103
1094 def test_link_different(self):
1104 def test_link_different(self):
1095 """Verify two traitlets of different types can be linked together using link."""
1105 """Verify two traitlets of different types can be linked together using link."""
1096
1106
1097 # Create two simple classes with Int traitlets.
1107 # Create two simple classes with Int traitlets.
1098 class A(HasTraits):
1108 class A(HasTraits):
1099 value = Int()
1109 value = Int()
1100 class B(HasTraits):
1110 class B(HasTraits):
1101 count = Int()
1111 count = Int()
1102 a = A(value=9)
1112 a = A(value=9)
1103 b = B(count=8)
1113 b = B(count=8)
1104
1114
1105 # Conenct the two classes.
1115 # Conenct the two classes.
1106 c = link((a, 'value'), (b, 'count'))
1116 c = link((a, 'value'), (b, 'count'))
1107
1117
1108 # Make sure the values are the same at the point of linking.
1118 # Make sure the values are the same at the point of linking.
1109 self.assertEqual(a.value, b.count)
1119 self.assertEqual(a.value, b.count)
1110
1120
1111 # Change one of the values to make sure they stay in sync.
1121 # Change one of the values to make sure they stay in sync.
1112 a.value = 5
1122 a.value = 5
1113 self.assertEqual(a.value, b.count)
1123 self.assertEqual(a.value, b.count)
1114 b.count = 4
1124 b.count = 4
1115 self.assertEqual(a.value, b.count)
1125 self.assertEqual(a.value, b.count)
1116
1126
1117 def test_unlink(self):
1127 def test_unlink(self):
1118 """Verify two linked traitlets can be unlinked."""
1128 """Verify two linked traitlets can be unlinked."""
1119
1129
1120 # Create two simple classes with Int traitlets.
1130 # Create two simple classes with Int traitlets.
1121 class A(HasTraits):
1131 class A(HasTraits):
1122 value = Int()
1132 value = Int()
1123 a = A(value=9)
1133 a = A(value=9)
1124 b = A(value=8)
1134 b = A(value=8)
1125
1135
1126 # Connect the two classes.
1136 # Connect the two classes.
1127 c = link((a, 'value'), (b, 'value'))
1137 c = link((a, 'value'), (b, 'value'))
1128 a.value = 4
1138 a.value = 4
1129 c.unlink()
1139 c.unlink()
1130
1140
1131 # Change one of the values to make sure they don't stay in sync.
1141 # Change one of the values to make sure they don't stay in sync.
1132 a.value = 5
1142 a.value = 5
1133 self.assertNotEqual(a.value, b.value)
1143 self.assertNotEqual(a.value, b.value)
1134
1144
1135 def test_callbacks(self):
1145 def test_callbacks(self):
1136 """Verify two linked traitlets have their callbacks called once."""
1146 """Verify two linked traitlets have their callbacks called once."""
1137
1147
1138 # Create two simple classes with Int traitlets.
1148 # Create two simple classes with Int traitlets.
1139 class A(HasTraits):
1149 class A(HasTraits):
1140 value = Int()
1150 value = Int()
1141 class B(HasTraits):
1151 class B(HasTraits):
1142 count = Int()
1152 count = Int()
1143 a = A(value=9)
1153 a = A(value=9)
1144 b = B(count=8)
1154 b = B(count=8)
1145
1155
1146 # Register callbacks that count.
1156 # Register callbacks that count.
1147 callback_count = []
1157 callback_count = []
1148 def a_callback(name, old, new):
1158 def a_callback(name, old, new):
1149 callback_count.append('a')
1159 callback_count.append('a')
1150 a.on_trait_change(a_callback, 'value')
1160 a.on_trait_change(a_callback, 'value')
1151 def b_callback(name, old, new):
1161 def b_callback(name, old, new):
1152 callback_count.append('b')
1162 callback_count.append('b')
1153 b.on_trait_change(b_callback, 'count')
1163 b.on_trait_change(b_callback, 'count')
1154
1164
1155 # Connect the two classes.
1165 # Connect the two classes.
1156 c = link((a, 'value'), (b, 'count'))
1166 c = link((a, 'value'), (b, 'count'))
1157
1167
1158 # Make sure b's count was set to a's value once.
1168 # Make sure b's count was set to a's value once.
1159 self.assertEqual(''.join(callback_count), 'b')
1169 self.assertEqual(''.join(callback_count), 'b')
1160 del callback_count[:]
1170 del callback_count[:]
1161
1171
1162 # Make sure a's value was set to b's count once.
1172 # Make sure a's value was set to b's count once.
1163 b.count = 5
1173 b.count = 5
1164 self.assertEqual(''.join(callback_count), 'ba')
1174 self.assertEqual(''.join(callback_count), 'ba')
1165 del callback_count[:]
1175 del callback_count[:]
1166
1176
1167 # Make sure b's count was set to a's value once.
1177 # Make sure b's count was set to a's value once.
1168 a.value = 4
1178 a.value = 4
1169 self.assertEqual(''.join(callback_count), 'ab')
1179 self.assertEqual(''.join(callback_count), 'ab')
1170 del callback_count[:]
1180 del callback_count[:]
1171
1181
1172 class TestDirectionalLink(TestCase):
1182 class TestDirectionalLink(TestCase):
1173 def test_connect_same(self):
1183 def test_connect_same(self):
1174 """Verify two traitlets of the same type can be linked together using directional_link."""
1184 """Verify two traitlets of the same type can be linked together using directional_link."""
1175
1185
1176 # Create two simple classes with Int traitlets.
1186 # Create two simple classes with Int traitlets.
1177 class A(HasTraits):
1187 class A(HasTraits):
1178 value = Int()
1188 value = Int()
1179 a = A(value=9)
1189 a = A(value=9)
1180 b = A(value=8)
1190 b = A(value=8)
1181
1191
1182 # Conenct the two classes.
1192 # Conenct the two classes.
1183 c = directional_link((a, 'value'), (b, 'value'))
1193 c = directional_link((a, 'value'), (b, 'value'))
1184
1194
1185 # Make sure the values are the same at the point of linking.
1195 # Make sure the values are the same at the point of linking.
1186 self.assertEqual(a.value, b.value)
1196 self.assertEqual(a.value, b.value)
1187
1197
1188 # Change one the value of the source and check that it synchronizes the target.
1198 # Change one the value of the source and check that it synchronizes the target.
1189 a.value = 5
1199 a.value = 5
1190 self.assertEqual(b.value, 5)
1200 self.assertEqual(b.value, 5)
1191 # Change one the value of the target and check that it has no impact on the source
1201 # Change one the value of the target and check that it has no impact on the source
1192 b.value = 6
1202 b.value = 6
1193 self.assertEqual(a.value, 5)
1203 self.assertEqual(a.value, 5)
1194
1204
1195 def test_link_different(self):
1205 def test_link_different(self):
1196 """Verify two traitlets of different types can be linked together using link."""
1206 """Verify two traitlets of different types can be linked together using link."""
1197
1207
1198 # Create two simple classes with Int traitlets.
1208 # Create two simple classes with Int traitlets.
1199 class A(HasTraits):
1209 class A(HasTraits):
1200 value = Int()
1210 value = Int()
1201 class B(HasTraits):
1211 class B(HasTraits):
1202 count = Int()
1212 count = Int()
1203 a = A(value=9)
1213 a = A(value=9)
1204 b = B(count=8)
1214 b = B(count=8)
1205
1215
1206 # Conenct the two classes.
1216 # Conenct the two classes.
1207 c = directional_link((a, 'value'), (b, 'count'))
1217 c = directional_link((a, 'value'), (b, 'count'))
1208
1218
1209 # Make sure the values are the same at the point of linking.
1219 # Make sure the values are the same at the point of linking.
1210 self.assertEqual(a.value, b.count)
1220 self.assertEqual(a.value, b.count)
1211
1221
1212 # Change one the value of the source and check that it synchronizes the target.
1222 # Change one the value of the source and check that it synchronizes the target.
1213 a.value = 5
1223 a.value = 5
1214 self.assertEqual(b.count, 5)
1224 self.assertEqual(b.count, 5)
1215 # Change one the value of the target and check that it has no impact on the source
1225 # Change one the value of the target and check that it has no impact on the source
1216 b.value = 6
1226 b.value = 6
1217 self.assertEqual(a.value, 5)
1227 self.assertEqual(a.value, 5)
1218
1228
1219 def test_unlink(self):
1229 def test_unlink(self):
1220 """Verify two linked traitlets can be unlinked."""
1230 """Verify two linked traitlets can be unlinked."""
1221
1231
1222 # Create two simple classes with Int traitlets.
1232 # Create two simple classes with Int traitlets.
1223 class A(HasTraits):
1233 class A(HasTraits):
1224 value = Int()
1234 value = Int()
1225 a = A(value=9)
1235 a = A(value=9)
1226 b = A(value=8)
1236 b = A(value=8)
1227
1237
1228 # Connect the two classes.
1238 # Connect the two classes.
1229 c = directional_link((a, 'value'), (b, 'value'))
1239 c = directional_link((a, 'value'), (b, 'value'))
1230 a.value = 4
1240 a.value = 4
1231 c.unlink()
1241 c.unlink()
1232
1242
1233 # Change one of the values to make sure they don't stay in sync.
1243 # Change one of the values to make sure they don't stay in sync.
1234 a.value = 5
1244 a.value = 5
1235 self.assertNotEqual(a.value, b.value)
1245 self.assertNotEqual(a.value, b.value)
1236
1246
1237 class Pickleable(HasTraits):
1247 class Pickleable(HasTraits):
1238 i = Int()
1248 i = Int()
1239 j = Int()
1249 j = Int()
1240
1250
1241 def _i_default(self):
1251 def _i_default(self):
1242 return 1
1252 return 1
1243
1253
1244 def _i_changed(self, name, old, new):
1254 def _i_changed(self, name, old, new):
1245 self.j = new
1255 self.j = new
1246
1256
1247 def test_pickle_hastraits():
1257 def test_pickle_hastraits():
1248 c = Pickleable()
1258 c = Pickleable()
1249 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1259 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1250 p = pickle.dumps(c, protocol)
1260 p = pickle.dumps(c, protocol)
1251 c2 = pickle.loads(p)
1261 c2 = pickle.loads(p)
1252 nt.assert_equal(c2.i, c.i)
1262 nt.assert_equal(c2.i, c.i)
1253 nt.assert_equal(c2.j, c.j)
1263 nt.assert_equal(c2.j, c.j)
1254
1264
1255 c.i = 5
1265 c.i = 5
1256 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1266 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1257 p = pickle.dumps(c, protocol)
1267 p = pickle.dumps(c, protocol)
1258 c2 = pickle.loads(p)
1268 c2 = pickle.loads(p)
1259 nt.assert_equal(c2.i, c.i)
1269 nt.assert_equal(c2.i, c.i)
1260 nt.assert_equal(c2.j, c.j)
1270 nt.assert_equal(c2.j, c.j)
1261
1271
1262 class TestEventful(TestCase):
1272 class TestEventful(TestCase):
1263
1273
1264 def test_list(self):
1274 def test_list(self):
1265 """Does the EventfulList work?"""
1275 """Does the EventfulList work?"""
1266 event_cache = []
1276 event_cache = []
1267
1277
1268 class A(HasTraits):
1278 class A(HasTraits):
1269 x = EventfulList([c for c in 'abc'])
1279 x = EventfulList([c for c in 'abc'])
1270 a = A()
1280 a = A()
1271 a.x.on_events(lambda i, x: event_cache.append('insert'), \
1281 a.x.on_events(lambda i, x: event_cache.append('insert'), \
1272 lambda i, x: event_cache.append('set'), \
1282 lambda i, x: event_cache.append('set'), \
1273 lambda i: event_cache.append('del'), \
1283 lambda i: event_cache.append('del'), \
1274 lambda: event_cache.append('reverse'), \
1284 lambda: event_cache.append('reverse'), \
1275 lambda *p, **k: event_cache.append('sort'))
1285 lambda *p, **k: event_cache.append('sort'))
1276
1286
1277 a.x.remove('c')
1287 a.x.remove('c')
1278 # ab
1288 # ab
1279 a.x.insert(0, 'z')
1289 a.x.insert(0, 'z')
1280 # zab
1290 # zab
1281 del a.x[1]
1291 del a.x[1]
1282 # zb
1292 # zb
1283 a.x.reverse()
1293 a.x.reverse()
1284 # bz
1294 # bz
1285 a.x[1] = 'o'
1295 a.x[1] = 'o'
1286 # bo
1296 # bo
1287 a.x.append('a')
1297 a.x.append('a')
1288 # boa
1298 # boa
1289 a.x.sort()
1299 a.x.sort()
1290 # abo
1300 # abo
1291
1301
1292 # Were the correct events captured?
1302 # Were the correct events captured?
1293 self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort'])
1303 self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort'])
1294
1304
1295 # Is the output correct?
1305 # Is the output correct?
1296 self.assertEqual(a.x, [c for c in 'abo'])
1306 self.assertEqual(a.x, [c for c in 'abo'])
1297
1307
1298 def test_dict(self):
1308 def test_dict(self):
1299 """Does the EventfulDict work?"""
1309 """Does the EventfulDict work?"""
1300 event_cache = []
1310 event_cache = []
1301
1311
1302 class A(HasTraits):
1312 class A(HasTraits):
1303 x = EventfulDict({c: c for c in 'abc'})
1313 x = EventfulDict({c: c for c in 'abc'})
1304 a = A()
1314 a = A()
1305 a.x.on_events(lambda k, v: event_cache.append('add'), \
1315 a.x.on_events(lambda k, v: event_cache.append('add'), \
1306 lambda k, v: event_cache.append('set'), \
1316 lambda k, v: event_cache.append('set'), \
1307 lambda k: event_cache.append('del'))
1317 lambda k: event_cache.append('del'))
1308
1318
1309 del a.x['c']
1319 del a.x['c']
1310 # ab
1320 # ab
1311 a.x['z'] = 1
1321 a.x['z'] = 1
1312 # abz
1322 # abz
1313 a.x['z'] = 'z'
1323 a.x['z'] = 'z'
1314 # abz
1324 # abz
1315 a.x.pop('a')
1325 a.x.pop('a')
1316 # bz
1326 # bz
1317
1327
1318 # Were the correct events captured?
1328 # Were the correct events captured?
1319 self.assertEqual(event_cache, ['del', 'add', 'set', 'del'])
1329 self.assertEqual(event_cache, ['del', 'add', 'set', 'del'])
1320
1330
1321 # Is the output correct?
1331 # Is the output correct?
1322 self.assertEqual(a.x, {c: c for c in 'bz'})
1332 self.assertEqual(a.x, {c: c for c in 'bz'})
1323
1333
1324 ###
1334 ###
1325 # Traits for Forward Declaration Tests
1335 # Traits for Forward Declaration Tests
1326 ###
1336 ###
1327 class ForwardDeclaredInstanceTrait(HasTraits):
1337 class ForwardDeclaredInstanceTrait(HasTraits):
1328
1338
1329 value = ForwardDeclaredInstance('ForwardDeclaredBar')
1339 value = ForwardDeclaredInstance('ForwardDeclaredBar')
1330
1340
1331 class ForwardDeclaredTypeTrait(HasTraits):
1341 class ForwardDeclaredTypeTrait(HasTraits):
1332
1342
1333 value = ForwardDeclaredType('ForwardDeclaredBar')
1343 value = ForwardDeclaredType('ForwardDeclaredBar')
1334
1344
1335 class ForwardDeclaredInstanceListTrait(HasTraits):
1345 class ForwardDeclaredInstanceListTrait(HasTraits):
1336
1346
1337 value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
1347 value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
1338
1348
1339 class ForwardDeclaredTypeListTrait(HasTraits):
1349 class ForwardDeclaredTypeListTrait(HasTraits):
1340
1350
1341 value = List(ForwardDeclaredType('ForwardDeclaredBar'))
1351 value = List(ForwardDeclaredType('ForwardDeclaredBar'))
1342 ###
1352 ###
1343 # End Traits for Forward Declaration Tests
1353 # End Traits for Forward Declaration Tests
1344 ###
1354 ###
1345
1355
1346 ###
1356 ###
1347 # Classes for Forward Declaration Tests
1357 # Classes for Forward Declaration Tests
1348 ###
1358 ###
1349 class ForwardDeclaredBar(object):
1359 class ForwardDeclaredBar(object):
1350 pass
1360 pass
1351
1361
1352 class ForwardDeclaredBarSub(ForwardDeclaredBar):
1362 class ForwardDeclaredBarSub(ForwardDeclaredBar):
1353 pass
1363 pass
1354 ###
1364 ###
1355 # End Classes for Forward Declaration Tests
1365 # End Classes for Forward Declaration Tests
1356 ###
1366 ###
1357
1367
1358 ###
1368 ###
1359 # Forward Declaration Tests
1369 # Forward Declaration Tests
1360 ###
1370 ###
1361 class TestForwardDeclaredInstanceTrait(TraitTestBase):
1371 class TestForwardDeclaredInstanceTrait(TraitTestBase):
1362
1372
1363 obj = ForwardDeclaredInstanceTrait()
1373 obj = ForwardDeclaredInstanceTrait()
1364 _default_value = None
1374 _default_value = None
1365 _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1375 _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1366 _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
1376 _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
1367
1377
1368 class TestForwardDeclaredTypeTrait(TraitTestBase):
1378 class TestForwardDeclaredTypeTrait(TraitTestBase):
1369
1379
1370 obj = ForwardDeclaredTypeTrait()
1380 obj = ForwardDeclaredTypeTrait()
1371 _default_value = None
1381 _default_value = None
1372 _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
1382 _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
1373 _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1383 _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1374
1384
1375 class TestForwardDeclaredInstanceList(TraitTestBase):
1385 class TestForwardDeclaredInstanceList(TraitTestBase):
1376
1386
1377 obj = ForwardDeclaredInstanceListTrait()
1387 obj = ForwardDeclaredInstanceListTrait()
1378
1388
1379 def test_klass(self):
1389 def test_klass(self):
1380 """Test that the instance klass is properly assigned."""
1390 """Test that the instance klass is properly assigned."""
1381 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1391 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1382
1392
1383 _default_value = []
1393 _default_value = []
1384 _good_values = [
1394 _good_values = [
1385 [ForwardDeclaredBar(), ForwardDeclaredBarSub(), None],
1395 [ForwardDeclaredBar(), ForwardDeclaredBarSub(), None],
1386 [None],
1396 [None],
1387 [],
1397 [],
1388 None,
1398 None,
1389 ]
1399 ]
1390 _bad_values = [
1400 _bad_values = [
1391 ForwardDeclaredBar(),
1401 ForwardDeclaredBar(),
1392 [ForwardDeclaredBar(), 3],
1402 [ForwardDeclaredBar(), 3],
1393 '1',
1403 '1',
1394 # Note that this is the type, not an instance.
1404 # Note that this is the type, not an instance.
1395 [ForwardDeclaredBar]
1405 [ForwardDeclaredBar]
1396 ]
1406 ]
1397
1407
1398 class TestForwardDeclaredTypeList(TraitTestBase):
1408 class TestForwardDeclaredTypeList(TraitTestBase):
1399
1409
1400 obj = ForwardDeclaredTypeListTrait()
1410 obj = ForwardDeclaredTypeListTrait()
1401
1411
1402 def test_klass(self):
1412 def test_klass(self):
1403 """Test that the instance klass is properly assigned."""
1413 """Test that the instance klass is properly assigned."""
1404 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1414 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1405
1415
1406 _default_value = []
1416 _default_value = []
1407 _good_values = [
1417 _good_values = [
1408 [ForwardDeclaredBar, ForwardDeclaredBarSub, None],
1418 [ForwardDeclaredBar, ForwardDeclaredBarSub, None],
1409 [],
1419 [],
1410 [None],
1420 [None],
1411 None,
1421 None,
1412 ]
1422 ]
1413 _bad_values = [
1423 _bad_values = [
1414 ForwardDeclaredBar,
1424 ForwardDeclaredBar,
1415 [ForwardDeclaredBar, 3],
1425 [ForwardDeclaredBar, 3],
1416 '1',
1426 '1',
1417 # Note that this is an instance, not the type.
1427 # Note that this is an instance, not the type.
1418 [ForwardDeclaredBar()]
1428 [ForwardDeclaredBar()]
1419 ]
1429 ]
1420 ###
1430 ###
1421 # End Forward Declaration Tests
1431 # End Forward Declaration Tests
1422 ###
1432 ###
General Comments 0
You need to be logged in to leave comments. Login now