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