##// END OF EJS Templates
BUG/TEST: Fix typo in test name.
Scott Sanderson -
Show More
@@ -1,1422 +1,1422 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, 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
763
764 class IntTrait(HasTraits):
764 class IntTrait(HasTraits):
765
765
766 value = Int(99)
766 value = Int(99)
767
767
768 class TestInt(TraitTestBase):
768 class TestInt(TraitTestBase):
769
769
770 obj = IntTrait()
770 obj = IntTrait()
771 _default_value = 99
771 _default_value = 99
772 _good_values = [10, -10]
772 _good_values = [10, -10]
773 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
773 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
774 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
774 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']
775 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
776 if not py3compat.PY3:
776 if not py3compat.PY3:
777 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
777 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
778
778
779
779
780 class LongTrait(HasTraits):
780 class LongTrait(HasTraits):
781
781
782 value = Long(99 if py3compat.PY3 else long(99))
782 value = Long(99 if py3compat.PY3 else long(99))
783
783
784 class TestLong(TraitTestBase):
784 class TestLong(TraitTestBase):
785
785
786 obj = LongTrait()
786 obj = LongTrait()
787
787
788 _default_value = 99 if py3compat.PY3 else long(99)
788 _default_value = 99 if py3compat.PY3 else long(99)
789 _good_values = [10, -10]
789 _good_values = [10, -10]
790 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
790 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
791 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
791 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',
792 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
793 u'-10.1']
793 u'-10.1']
794 if not py3compat.PY3:
794 if not py3compat.PY3:
795 # maxint undefined on py3, because int == long
795 # maxint undefined on py3, because int == long
796 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
796 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
797 _bad_values.extend([[long(10)], (long(10),)])
797 _bad_values.extend([[long(10)], (long(10),)])
798
798
799 @skipif(py3compat.PY3, "not relevant on py3")
799 @skipif(py3compat.PY3, "not relevant on py3")
800 def test_cast_small(self):
800 def test_cast_small(self):
801 """Long casts ints to long"""
801 """Long casts ints to long"""
802 self.obj.value = 10
802 self.obj.value = 10
803 self.assertEqual(type(self.obj.value), long)
803 self.assertEqual(type(self.obj.value), long)
804
804
805
805
806 class IntegerTrait(HasTraits):
806 class IntegerTrait(HasTraits):
807 value = Integer(1)
807 value = Integer(1)
808
808
809 class TestInteger(TestLong):
809 class TestInteger(TestLong):
810 obj = IntegerTrait()
810 obj = IntegerTrait()
811 _default_value = 1
811 _default_value = 1
812
812
813 def coerce(self, n):
813 def coerce(self, n):
814 return int(n)
814 return int(n)
815
815
816 @skipif(py3compat.PY3, "not relevant on py3")
816 @skipif(py3compat.PY3, "not relevant on py3")
817 def test_cast_small(self):
817 def test_cast_small(self):
818 """Integer casts small longs to int"""
818 """Integer casts small longs to int"""
819 if py3compat.PY3:
819 if py3compat.PY3:
820 raise SkipTest("not relevant on py3")
820 raise SkipTest("not relevant on py3")
821
821
822 self.obj.value = long(100)
822 self.obj.value = long(100)
823 self.assertEqual(type(self.obj.value), int)
823 self.assertEqual(type(self.obj.value), int)
824
824
825
825
826 class FloatTrait(HasTraits):
826 class FloatTrait(HasTraits):
827
827
828 value = Float(99.0)
828 value = Float(99.0)
829
829
830 class TestFloat(TraitTestBase):
830 class TestFloat(TraitTestBase):
831
831
832 obj = FloatTrait()
832 obj = FloatTrait()
833
833
834 _default_value = 99.0
834 _default_value = 99.0
835 _good_values = [10, -10, 10.1, -10.1]
835 _good_values = [10, -10, 10.1, -10.1]
836 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
836 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
837 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
837 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
838 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
838 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
839 if not py3compat.PY3:
839 if not py3compat.PY3:
840 _bad_values.extend([long(10), long(-10)])
840 _bad_values.extend([long(10), long(-10)])
841
841
842
842
843 class ComplexTrait(HasTraits):
843 class ComplexTrait(HasTraits):
844
844
845 value = Complex(99.0-99.0j)
845 value = Complex(99.0-99.0j)
846
846
847 class TestComplex(TraitTestBase):
847 class TestComplex(TraitTestBase):
848
848
849 obj = ComplexTrait()
849 obj = ComplexTrait()
850
850
851 _default_value = 99.0-99.0j
851 _default_value = 99.0-99.0j
852 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
852 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
853 10.1j, 10.1+10.1j, 10.1-10.1j]
853 10.1j, 10.1+10.1j, 10.1-10.1j]
854 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
854 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
855 if not py3compat.PY3:
855 if not py3compat.PY3:
856 _bad_values.extend([long(10), long(-10)])
856 _bad_values.extend([long(10), long(-10)])
857
857
858
858
859 class BytesTrait(HasTraits):
859 class BytesTrait(HasTraits):
860
860
861 value = Bytes(b'string')
861 value = Bytes(b'string')
862
862
863 class TestBytes(TraitTestBase):
863 class TestBytes(TraitTestBase):
864
864
865 obj = BytesTrait()
865 obj = BytesTrait()
866
866
867 _default_value = b'string'
867 _default_value = b'string'
868 _good_values = [b'10', b'-10', b'10L',
868 _good_values = [b'10', b'-10', b'10L',
869 b'-10L', b'10.1', b'-10.1', b'string']
869 b'-10L', b'10.1', b'-10.1', b'string']
870 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
870 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
871 ['ten'],{'ten': 10},(10,), None, u'string']
871 ['ten'],{'ten': 10},(10,), None, u'string']
872 if not py3compat.PY3:
872 if not py3compat.PY3:
873 _bad_values.extend([long(10), long(-10)])
873 _bad_values.extend([long(10), long(-10)])
874
874
875
875
876 class UnicodeTrait(HasTraits):
876 class UnicodeTrait(HasTraits):
877
877
878 value = Unicode(u'unicode')
878 value = Unicode(u'unicode')
879
879
880 class TestUnicode(TraitTestBase):
880 class TestUnicode(TraitTestBase):
881
881
882 obj = UnicodeTrait()
882 obj = UnicodeTrait()
883
883
884 _default_value = u'unicode'
884 _default_value = u'unicode'
885 _good_values = ['10', '-10', '10L', '-10L', '10.1',
885 _good_values = ['10', '-10', '10L', '-10L', '10.1',
886 '-10.1', '', u'', 'string', u'string', u"€"]
886 '-10.1', '', u'', 'string', u'string', u"€"]
887 _bad_values = [10, -10, 10.1, -10.1, 1j,
887 _bad_values = [10, -10, 10.1, -10.1, 1j,
888 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
888 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
889 if not py3compat.PY3:
889 if not py3compat.PY3:
890 _bad_values.extend([long(10), long(-10)])
890 _bad_values.extend([long(10), long(-10)])
891
891
892
892
893 class ObjectNameTrait(HasTraits):
893 class ObjectNameTrait(HasTraits):
894 value = ObjectName("abc")
894 value = ObjectName("abc")
895
895
896 class TestObjectName(TraitTestBase):
896 class TestObjectName(TraitTestBase):
897 obj = ObjectNameTrait()
897 obj = ObjectNameTrait()
898
898
899 _default_value = "abc"
899 _default_value = "abc"
900 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
900 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
901 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
901 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
902 None, object(), object]
902 None, object(), object]
903 if sys.version_info[0] < 3:
903 if sys.version_info[0] < 3:
904 _bad_values.append(u"ΓΎ")
904 _bad_values.append(u"ΓΎ")
905 else:
905 else:
906 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
906 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
907
907
908
908
909 class DottedObjectNameTrait(HasTraits):
909 class DottedObjectNameTrait(HasTraits):
910 value = DottedObjectName("a.b")
910 value = DottedObjectName("a.b")
911
911
912 class TestDottedObjectName(TraitTestBase):
912 class TestDottedObjectName(TraitTestBase):
913 obj = DottedObjectNameTrait()
913 obj = DottedObjectNameTrait()
914
914
915 _default_value = "a.b"
915 _default_value = "a.b"
916 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
916 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
917 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
917 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
918 if sys.version_info[0] < 3:
918 if sys.version_info[0] < 3:
919 _bad_values.append(u"t.ΓΎ")
919 _bad_values.append(u"t.ΓΎ")
920 else:
920 else:
921 _good_values.append(u"t.ΓΎ")
921 _good_values.append(u"t.ΓΎ")
922
922
923
923
924 class TCPAddressTrait(HasTraits):
924 class TCPAddressTrait(HasTraits):
925
925
926 value = TCPAddress()
926 value = TCPAddress()
927
927
928 class TestTCPAddress(TraitTestBase):
928 class TestTCPAddress(TraitTestBase):
929
929
930 obj = TCPAddressTrait()
930 obj = TCPAddressTrait()
931
931
932 _default_value = ('127.0.0.1',0)
932 _default_value = ('127.0.0.1',0)
933 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
933 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
934 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
934 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
935
935
936 class ListTrait(HasTraits):
936 class ListTrait(HasTraits):
937
937
938 value = List(Int)
938 value = List(Int)
939
939
940 class TestList(TraitTestBase):
940 class TestList(TraitTestBase):
941
941
942 obj = ListTrait()
942 obj = ListTrait()
943
943
944 _default_value = []
944 _default_value = []
945 _good_values = [[], [1], list(range(10)), (1,2)]
945 _good_values = [[], [1], list(range(10)), (1,2)]
946 _bad_values = [10, [1,'a'], 'a']
946 _bad_values = [10, [1,'a'], 'a']
947
947
948 def coerce(self, value):
948 def coerce(self, value):
949 if value is not None:
949 if value is not None:
950 value = list(value)
950 value = list(value)
951 return value
951 return value
952
952
953 class Foo(object):
953 class Foo(object):
954 pass
954 pass
955
955
956 class InstanceListTrait(HasTraits):
956 class InstanceListTrait(HasTraits):
957
957
958 value = List(Instance(__name__+'.Foo'))
958 value = List(Instance(__name__+'.Foo'))
959
959
960 class TestInstanceList(TraitTestBase):
960 class TestInstanceList(TraitTestBase):
961
961
962 obj = InstanceListTrait()
962 obj = InstanceListTrait()
963
963
964 def test_klass(self):
964 def test_klass(self):
965 """Test that the instance klass is properly assigned."""
965 """Test that the instance klass is properly assigned."""
966 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
966 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
967
967
968 _default_value = []
968 _default_value = []
969 _good_values = [[Foo(), Foo(), None], None]
969 _good_values = [[Foo(), Foo(), None], None]
970 _bad_values = [['1', 2,], '1', [Foo]]
970 _bad_values = [['1', 2,], '1', [Foo]]
971
971
972 class LenListTrait(HasTraits):
972 class LenListTrait(HasTraits):
973
973
974 value = List(Int, [0], minlen=1, maxlen=2)
974 value = List(Int, [0], minlen=1, maxlen=2)
975
975
976 class TestLenList(TraitTestBase):
976 class TestLenList(TraitTestBase):
977
977
978 obj = LenListTrait()
978 obj = LenListTrait()
979
979
980 _default_value = [0]
980 _default_value = [0]
981 _good_values = [[1], [1,2], (1,2)]
981 _good_values = [[1], [1,2], (1,2)]
982 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
982 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
983
983
984 def coerce(self, value):
984 def coerce(self, value):
985 if value is not None:
985 if value is not None:
986 value = list(value)
986 value = list(value)
987 return value
987 return value
988
988
989 class TupleTrait(HasTraits):
989 class TupleTrait(HasTraits):
990
990
991 value = Tuple(Int(allow_none=True))
991 value = Tuple(Int(allow_none=True))
992
992
993 class TestTupleTrait(TraitTestBase):
993 class TestTupleTrait(TraitTestBase):
994
994
995 obj = TupleTrait()
995 obj = TupleTrait()
996
996
997 _default_value = None
997 _default_value = None
998 _good_values = [(1,), None, (0,), [1], (None,)]
998 _good_values = [(1,), None, (0,), [1], (None,)]
999 _bad_values = [10, (1,2), ('a'), ()]
999 _bad_values = [10, (1,2), ('a'), ()]
1000
1000
1001 def coerce(self, value):
1001 def coerce(self, value):
1002 if value is not None:
1002 if value is not None:
1003 value = tuple(value)
1003 value = tuple(value)
1004 return value
1004 return value
1005
1005
1006 def test_invalid_args(self):
1006 def test_invalid_args(self):
1007 self.assertRaises(TypeError, Tuple, 5)
1007 self.assertRaises(TypeError, Tuple, 5)
1008 self.assertRaises(TypeError, Tuple, default_value='hello')
1008 self.assertRaises(TypeError, Tuple, default_value='hello')
1009 t = Tuple(Int, CBytes, default_value=(1,5))
1009 t = Tuple(Int, CBytes, default_value=(1,5))
1010
1010
1011 class LooseTupleTrait(HasTraits):
1011 class LooseTupleTrait(HasTraits):
1012
1012
1013 value = Tuple((1,2,3))
1013 value = Tuple((1,2,3))
1014
1014
1015 class TestLooseTupleTrait(TraitTestBase):
1015 class TestLooseTupleTrait(TraitTestBase):
1016
1016
1017 obj = LooseTupleTrait()
1017 obj = LooseTupleTrait()
1018
1018
1019 _default_value = (1,2,3)
1019 _default_value = (1,2,3)
1020 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
1020 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
1021 _bad_values = [10, 'hello', {}]
1021 _bad_values = [10, 'hello', {}]
1022
1022
1023 def coerce(self, value):
1023 def coerce(self, value):
1024 if value is not None:
1024 if value is not None:
1025 value = tuple(value)
1025 value = tuple(value)
1026 return value
1026 return value
1027
1027
1028 def test_invalid_args(self):
1028 def test_invalid_args(self):
1029 self.assertRaises(TypeError, Tuple, 5)
1029 self.assertRaises(TypeError, Tuple, 5)
1030 self.assertRaises(TypeError, Tuple, default_value='hello')
1030 self.assertRaises(TypeError, Tuple, default_value='hello')
1031 t = Tuple(Int, CBytes, default_value=(1,5))
1031 t = Tuple(Int, CBytes, default_value=(1,5))
1032
1032
1033
1033
1034 class MultiTupleTrait(HasTraits):
1034 class MultiTupleTrait(HasTraits):
1035
1035
1036 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
1036 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
1037
1037
1038 class TestMultiTuple(TraitTestBase):
1038 class TestMultiTuple(TraitTestBase):
1039
1039
1040 obj = MultiTupleTrait()
1040 obj = MultiTupleTrait()
1041
1041
1042 _default_value = (99,b'bottles')
1042 _default_value = (99,b'bottles')
1043 _good_values = [(1,b'a'), (2,b'b')]
1043 _good_values = [(1,b'a'), (2,b'b')]
1044 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1044 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1045
1045
1046 class CRegExpTrait(HasTraits):
1046 class CRegExpTrait(HasTraits):
1047
1047
1048 value = CRegExp(r'')
1048 value = CRegExp(r'')
1049
1049
1050 class TestCRegExp(TraitTestBase):
1050 class TestCRegExp(TraitTestBase):
1051
1051
1052 def coerce(self, value):
1052 def coerce(self, value):
1053 return re.compile(value)
1053 return re.compile(value)
1054
1054
1055 obj = CRegExpTrait()
1055 obj = CRegExpTrait()
1056
1056
1057 _default_value = re.compile(r'')
1057 _default_value = re.compile(r'')
1058 _good_values = [r'\d+', re.compile(r'\d+')]
1058 _good_values = [r'\d+', re.compile(r'\d+')]
1059 _bad_values = ['(', None, ()]
1059 _bad_values = ['(', None, ()]
1060
1060
1061 class DictTrait(HasTraits):
1061 class DictTrait(HasTraits):
1062 value = Dict()
1062 value = Dict()
1063
1063
1064 def test_dict_assignment():
1064 def test_dict_assignment():
1065 d = dict()
1065 d = dict()
1066 c = DictTrait()
1066 c = DictTrait()
1067 c.value = d
1067 c.value = d
1068 d['a'] = 5
1068 d['a'] = 5
1069 nt.assert_equal(d, c.value)
1069 nt.assert_equal(d, c.value)
1070 nt.assert_true(c.value is d)
1070 nt.assert_true(c.value is d)
1071
1071
1072 class TestLink(TestCase):
1072 class TestLink(TestCase):
1073 def test_connect_same(self):
1073 def test_connect_same(self):
1074 """Verify two traitlets of the same type can be linked together using link."""
1074 """Verify two traitlets of the same type can be linked together using link."""
1075
1075
1076 # Create two simple classes with Int traitlets.
1076 # Create two simple classes with Int traitlets.
1077 class A(HasTraits):
1077 class A(HasTraits):
1078 value = Int()
1078 value = Int()
1079 a = A(value=9)
1079 a = A(value=9)
1080 b = A(value=8)
1080 b = A(value=8)
1081
1081
1082 # Conenct the two classes.
1082 # Conenct the two classes.
1083 c = link((a, 'value'), (b, 'value'))
1083 c = link((a, 'value'), (b, 'value'))
1084
1084
1085 # Make sure the values are the same at the point of linking.
1085 # Make sure the values are the same at the point of linking.
1086 self.assertEqual(a.value, b.value)
1086 self.assertEqual(a.value, b.value)
1087
1087
1088 # Change one of the values to make sure they stay in sync.
1088 # Change one of the values to make sure they stay in sync.
1089 a.value = 5
1089 a.value = 5
1090 self.assertEqual(a.value, b.value)
1090 self.assertEqual(a.value, b.value)
1091 b.value = 6
1091 b.value = 6
1092 self.assertEqual(a.value, b.value)
1092 self.assertEqual(a.value, b.value)
1093
1093
1094 def test_link_different(self):
1094 def test_link_different(self):
1095 """Verify two traitlets of different types can be linked together using link."""
1095 """Verify two traitlets of different types can be linked together using link."""
1096
1096
1097 # Create two simple classes with Int traitlets.
1097 # Create two simple classes with Int traitlets.
1098 class A(HasTraits):
1098 class A(HasTraits):
1099 value = Int()
1099 value = Int()
1100 class B(HasTraits):
1100 class B(HasTraits):
1101 count = Int()
1101 count = Int()
1102 a = A(value=9)
1102 a = A(value=9)
1103 b = B(count=8)
1103 b = B(count=8)
1104
1104
1105 # Conenct the two classes.
1105 # Conenct the two classes.
1106 c = link((a, 'value'), (b, 'count'))
1106 c = link((a, 'value'), (b, 'count'))
1107
1107
1108 # Make sure the values are the same at the point of linking.
1108 # Make sure the values are the same at the point of linking.
1109 self.assertEqual(a.value, b.count)
1109 self.assertEqual(a.value, b.count)
1110
1110
1111 # Change one of the values to make sure they stay in sync.
1111 # Change one of the values to make sure they stay in sync.
1112 a.value = 5
1112 a.value = 5
1113 self.assertEqual(a.value, b.count)
1113 self.assertEqual(a.value, b.count)
1114 b.count = 4
1114 b.count = 4
1115 self.assertEqual(a.value, b.count)
1115 self.assertEqual(a.value, b.count)
1116
1116
1117 def test_unlink(self):
1117 def test_unlink(self):
1118 """Verify two linked traitlets can be unlinked."""
1118 """Verify two linked traitlets can be unlinked."""
1119
1119
1120 # Create two simple classes with Int traitlets.
1120 # Create two simple classes with Int traitlets.
1121 class A(HasTraits):
1121 class A(HasTraits):
1122 value = Int()
1122 value = Int()
1123 a = A(value=9)
1123 a = A(value=9)
1124 b = A(value=8)
1124 b = A(value=8)
1125
1125
1126 # Connect the two classes.
1126 # Connect the two classes.
1127 c = link((a, 'value'), (b, 'value'))
1127 c = link((a, 'value'), (b, 'value'))
1128 a.value = 4
1128 a.value = 4
1129 c.unlink()
1129 c.unlink()
1130
1130
1131 # Change one of the values to make sure they don't stay in sync.
1131 # Change one of the values to make sure they don't stay in sync.
1132 a.value = 5
1132 a.value = 5
1133 self.assertNotEqual(a.value, b.value)
1133 self.assertNotEqual(a.value, b.value)
1134
1134
1135 def test_callbacks(self):
1135 def test_callbacks(self):
1136 """Verify two linked traitlets have their callbacks called once."""
1136 """Verify two linked traitlets have their callbacks called once."""
1137
1137
1138 # Create two simple classes with Int traitlets.
1138 # Create two simple classes with Int traitlets.
1139 class A(HasTraits):
1139 class A(HasTraits):
1140 value = Int()
1140 value = Int()
1141 class B(HasTraits):
1141 class B(HasTraits):
1142 count = Int()
1142 count = Int()
1143 a = A(value=9)
1143 a = A(value=9)
1144 b = B(count=8)
1144 b = B(count=8)
1145
1145
1146 # Register callbacks that count.
1146 # Register callbacks that count.
1147 callback_count = []
1147 callback_count = []
1148 def a_callback(name, old, new):
1148 def a_callback(name, old, new):
1149 callback_count.append('a')
1149 callback_count.append('a')
1150 a.on_trait_change(a_callback, 'value')
1150 a.on_trait_change(a_callback, 'value')
1151 def b_callback(name, old, new):
1151 def b_callback(name, old, new):
1152 callback_count.append('b')
1152 callback_count.append('b')
1153 b.on_trait_change(b_callback, 'count')
1153 b.on_trait_change(b_callback, 'count')
1154
1154
1155 # Connect the two classes.
1155 # Connect the two classes.
1156 c = link((a, 'value'), (b, 'count'))
1156 c = link((a, 'value'), (b, 'count'))
1157
1157
1158 # Make sure b's count was set to a's value once.
1158 # Make sure b's count was set to a's value once.
1159 self.assertEqual(''.join(callback_count), 'b')
1159 self.assertEqual(''.join(callback_count), 'b')
1160 del callback_count[:]
1160 del callback_count[:]
1161
1161
1162 # Make sure a's value was set to b's count once.
1162 # Make sure a's value was set to b's count once.
1163 b.count = 5
1163 b.count = 5
1164 self.assertEqual(''.join(callback_count), 'ba')
1164 self.assertEqual(''.join(callback_count), 'ba')
1165 del callback_count[:]
1165 del callback_count[:]
1166
1166
1167 # Make sure b's count was set to a's value once.
1167 # Make sure b's count was set to a's value once.
1168 a.value = 4
1168 a.value = 4
1169 self.assertEqual(''.join(callback_count), 'ab')
1169 self.assertEqual(''.join(callback_count), 'ab')
1170 del callback_count[:]
1170 del callback_count[:]
1171
1171
1172 class TestDirectionalLink(TestCase):
1172 class TestDirectionalLink(TestCase):
1173 def test_connect_same(self):
1173 def test_connect_same(self):
1174 """Verify two traitlets of the same type can be linked together using directional_link."""
1174 """Verify two traitlets of the same type can be linked together using directional_link."""
1175
1175
1176 # Create two simple classes with Int traitlets.
1176 # Create two simple classes with Int traitlets.
1177 class A(HasTraits):
1177 class A(HasTraits):
1178 value = Int()
1178 value = Int()
1179 a = A(value=9)
1179 a = A(value=9)
1180 b = A(value=8)
1180 b = A(value=8)
1181
1181
1182 # Conenct the two classes.
1182 # Conenct the two classes.
1183 c = directional_link((a, 'value'), (b, 'value'))
1183 c = directional_link((a, 'value'), (b, 'value'))
1184
1184
1185 # Make sure the values are the same at the point of linking.
1185 # Make sure the values are the same at the point of linking.
1186 self.assertEqual(a.value, b.value)
1186 self.assertEqual(a.value, b.value)
1187
1187
1188 # Change one the value of the source and check that it synchronizes the target.
1188 # Change one the value of the source and check that it synchronizes the target.
1189 a.value = 5
1189 a.value = 5
1190 self.assertEqual(b.value, 5)
1190 self.assertEqual(b.value, 5)
1191 # Change one the value of the target and check that it has no impact on the source
1191 # Change one the value of the target and check that it has no impact on the source
1192 b.value = 6
1192 b.value = 6
1193 self.assertEqual(a.value, 5)
1193 self.assertEqual(a.value, 5)
1194
1194
1195 def test_link_different(self):
1195 def test_link_different(self):
1196 """Verify two traitlets of different types can be linked together using link."""
1196 """Verify two traitlets of different types can be linked together using link."""
1197
1197
1198 # Create two simple classes with Int traitlets.
1198 # Create two simple classes with Int traitlets.
1199 class A(HasTraits):
1199 class A(HasTraits):
1200 value = Int()
1200 value = Int()
1201 class B(HasTraits):
1201 class B(HasTraits):
1202 count = Int()
1202 count = Int()
1203 a = A(value=9)
1203 a = A(value=9)
1204 b = B(count=8)
1204 b = B(count=8)
1205
1205
1206 # Conenct the two classes.
1206 # Conenct the two classes.
1207 c = directional_link((a, 'value'), (b, 'count'))
1207 c = directional_link((a, 'value'), (b, 'count'))
1208
1208
1209 # Make sure the values are the same at the point of linking.
1209 # Make sure the values are the same at the point of linking.
1210 self.assertEqual(a.value, b.count)
1210 self.assertEqual(a.value, b.count)
1211
1211
1212 # Change one the value of the source and check that it synchronizes the target.
1212 # Change one the value of the source and check that it synchronizes the target.
1213 a.value = 5
1213 a.value = 5
1214 self.assertEqual(b.count, 5)
1214 self.assertEqual(b.count, 5)
1215 # Change one the value of the target and check that it has no impact on the source
1215 # Change one the value of the target and check that it has no impact on the source
1216 b.value = 6
1216 b.value = 6
1217 self.assertEqual(a.value, 5)
1217 self.assertEqual(a.value, 5)
1218
1218
1219 def test_unlink(self):
1219 def test_unlink(self):
1220 """Verify two linked traitlets can be unlinked."""
1220 """Verify two linked traitlets can be unlinked."""
1221
1221
1222 # Create two simple classes with Int traitlets.
1222 # Create two simple classes with Int traitlets.
1223 class A(HasTraits):
1223 class A(HasTraits):
1224 value = Int()
1224 value = Int()
1225 a = A(value=9)
1225 a = A(value=9)
1226 b = A(value=8)
1226 b = A(value=8)
1227
1227
1228 # Connect the two classes.
1228 # Connect the two classes.
1229 c = directional_link((a, 'value'), (b, 'value'))
1229 c = directional_link((a, 'value'), (b, 'value'))
1230 a.value = 4
1230 a.value = 4
1231 c.unlink()
1231 c.unlink()
1232
1232
1233 # Change one of the values to make sure they don't stay in sync.
1233 # Change one of the values to make sure they don't stay in sync.
1234 a.value = 5
1234 a.value = 5
1235 self.assertNotEqual(a.value, b.value)
1235 self.assertNotEqual(a.value, b.value)
1236
1236
1237 class Pickleable(HasTraits):
1237 class Pickleable(HasTraits):
1238 i = Int()
1238 i = Int()
1239 j = Int()
1239 j = Int()
1240
1240
1241 def _i_default(self):
1241 def _i_default(self):
1242 return 1
1242 return 1
1243
1243
1244 def _i_changed(self, name, old, new):
1244 def _i_changed(self, name, old, new):
1245 self.j = new
1245 self.j = new
1246
1246
1247 def test_pickle_hastraits():
1247 def test_pickle_hastraits():
1248 c = Pickleable()
1248 c = Pickleable()
1249 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1249 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1250 p = pickle.dumps(c, protocol)
1250 p = pickle.dumps(c, protocol)
1251 c2 = pickle.loads(p)
1251 c2 = pickle.loads(p)
1252 nt.assert_equal(c2.i, c.i)
1252 nt.assert_equal(c2.i, c.i)
1253 nt.assert_equal(c2.j, c.j)
1253 nt.assert_equal(c2.j, c.j)
1254
1254
1255 c.i = 5
1255 c.i = 5
1256 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1256 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1257 p = pickle.dumps(c, protocol)
1257 p = pickle.dumps(c, protocol)
1258 c2 = pickle.loads(p)
1258 c2 = pickle.loads(p)
1259 nt.assert_equal(c2.i, c.i)
1259 nt.assert_equal(c2.i, c.i)
1260 nt.assert_equal(c2.j, c.j)
1260 nt.assert_equal(c2.j, c.j)
1261
1261
1262 class TestEventful(TestCase):
1262 class TestEventful(TestCase):
1263
1263
1264 def test_list(self):
1264 def test_list(self):
1265 """Does the EventfulList work?"""
1265 """Does the EventfulList work?"""
1266 event_cache = []
1266 event_cache = []
1267
1267
1268 class A(HasTraits):
1268 class A(HasTraits):
1269 x = EventfulList([c for c in 'abc'])
1269 x = EventfulList([c for c in 'abc'])
1270 a = A()
1270 a = A()
1271 a.x.on_events(lambda i, x: event_cache.append('insert'), \
1271 a.x.on_events(lambda i, x: event_cache.append('insert'), \
1272 lambda i, x: event_cache.append('set'), \
1272 lambda i, x: event_cache.append('set'), \
1273 lambda i: event_cache.append('del'), \
1273 lambda i: event_cache.append('del'), \
1274 lambda: event_cache.append('reverse'), \
1274 lambda: event_cache.append('reverse'), \
1275 lambda *p, **k: event_cache.append('sort'))
1275 lambda *p, **k: event_cache.append('sort'))
1276
1276
1277 a.x.remove('c')
1277 a.x.remove('c')
1278 # ab
1278 # ab
1279 a.x.insert(0, 'z')
1279 a.x.insert(0, 'z')
1280 # zab
1280 # zab
1281 del a.x[1]
1281 del a.x[1]
1282 # zb
1282 # zb
1283 a.x.reverse()
1283 a.x.reverse()
1284 # bz
1284 # bz
1285 a.x[1] = 'o'
1285 a.x[1] = 'o'
1286 # bo
1286 # bo
1287 a.x.append('a')
1287 a.x.append('a')
1288 # boa
1288 # boa
1289 a.x.sort()
1289 a.x.sort()
1290 # abo
1290 # abo
1291
1291
1292 # Were the correct events captured?
1292 # Were the correct events captured?
1293 self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort'])
1293 self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort'])
1294
1294
1295 # Is the output correct?
1295 # Is the output correct?
1296 self.assertEqual(a.x, [c for c in 'abo'])
1296 self.assertEqual(a.x, [c for c in 'abo'])
1297
1297
1298 def test_dict(self):
1298 def test_dict(self):
1299 """Does the EventfulDict work?"""
1299 """Does the EventfulDict work?"""
1300 event_cache = []
1300 event_cache = []
1301
1301
1302 class A(HasTraits):
1302 class A(HasTraits):
1303 x = EventfulDict({c: c for c in 'abc'})
1303 x = EventfulDict({c: c for c in 'abc'})
1304 a = A()
1304 a = A()
1305 a.x.on_events(lambda k, v: event_cache.append('add'), \
1305 a.x.on_events(lambda k, v: event_cache.append('add'), \
1306 lambda k, v: event_cache.append('set'), \
1306 lambda k, v: event_cache.append('set'), \
1307 lambda k: event_cache.append('del'))
1307 lambda k: event_cache.append('del'))
1308
1308
1309 del a.x['c']
1309 del a.x['c']
1310 # ab
1310 # ab
1311 a.x['z'] = 1
1311 a.x['z'] = 1
1312 # abz
1312 # abz
1313 a.x['z'] = 'z'
1313 a.x['z'] = 'z'
1314 # abz
1314 # abz
1315 a.x.pop('a')
1315 a.x.pop('a')
1316 # bz
1316 # bz
1317
1317
1318 # Were the correct events captured?
1318 # Were the correct events captured?
1319 self.assertEqual(event_cache, ['del', 'add', 'set', 'del'])
1319 self.assertEqual(event_cache, ['del', 'add', 'set', 'del'])
1320
1320
1321 # Is the output correct?
1321 # Is the output correct?
1322 self.assertEqual(a.x, {c: c for c in 'bz'})
1322 self.assertEqual(a.x, {c: c for c in 'bz'})
1323
1323
1324 ###
1324 ###
1325 # Traits for Forward Declaration Tests
1325 # Traits for Forward Declaration Tests
1326 ###
1326 ###
1327 class ForwardDeclaredInstanceTrait(HasTraits):
1327 class ForwardDeclaredInstanceTrait(HasTraits):
1328
1328
1329 value = ForwardDeclaredInstance('ForwardDeclaredBar')
1329 value = ForwardDeclaredInstance('ForwardDeclaredBar')
1330
1330
1331 class ForwardDeclaredTypeTrait(HasTraits):
1331 class ForwardDeclaredTypeTrait(HasTraits):
1332
1332
1333 value = ForwardDeclaredType('ForwardDeclaredBar')
1333 value = ForwardDeclaredType('ForwardDeclaredBar')
1334
1334
1335 class ForwardDeclaredInstanceListTrait(HasTraits):
1335 class ForwardDeclaredInstanceListTrait(HasTraits):
1336
1336
1337 value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
1337 value = List(ForwardDeclaredInstance('ForwardDeclaredBar'))
1338
1338
1339 class ForwardDeclaredTypeListTrait(HasTraits):
1339 class ForwardDeclaredTypeListTrait(HasTraits):
1340
1340
1341 value = List(ForwardDeclaredType('ForwardDeclaredBar'))
1341 value = List(ForwardDeclaredType('ForwardDeclaredBar'))
1342 ###
1342 ###
1343 # End Traits for Forward Declaration Tests
1343 # End Traits for Forward Declaration Tests
1344 ###
1344 ###
1345
1345
1346 ###
1346 ###
1347 # Classes for Forward Declaration Tests
1347 # Classes for Forward Declaration Tests
1348 ###
1348 ###
1349 class ForwardDeclaredBar(object):
1349 class ForwardDeclaredBar(object):
1350 pass
1350 pass
1351
1351
1352 class ForwardDeclaredBarSub(ForwardDeclaredBar):
1352 class ForwardDeclaredBarSub(ForwardDeclaredBar):
1353 pass
1353 pass
1354 ###
1354 ###
1355 # End Classes for Forward Declaration Tests
1355 # End Classes for Forward Declaration Tests
1356 ###
1356 ###
1357
1357
1358 ###
1358 ###
1359 # Forward Declaration Tests
1359 # Forward Declaration Tests
1360 ###
1360 ###
1361 class TestForwardDeclaredInstanceTrait(TraitTestBase):
1361 class TestForwardDeclaredInstanceTrait(TraitTestBase):
1362
1362
1363 obj = ForwardDeclaredInstanceTrait()
1363 obj = ForwardDeclaredInstanceTrait()
1364 _default_value = None
1364 _default_value = None
1365 _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1365 _good_values = [None, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1366 _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
1366 _bad_values = ['foo', 3, ForwardDeclaredBar, ForwardDeclaredBarSub]
1367
1367
1368 class TestForwardDeclaredInstanceTrait(TraitTestBase):
1368 class TestForwardDeclaredTypeTrait(TraitTestBase):
1369
1369
1370 obj = ForwardDeclaredTypeTrait()
1370 obj = ForwardDeclaredTypeTrait()
1371 _default_value = None
1371 _default_value = None
1372 _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
1372 _good_values = [None, ForwardDeclaredBar, ForwardDeclaredBarSub]
1373 _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1373 _bad_values = ['foo', 3, ForwardDeclaredBar(), ForwardDeclaredBarSub()]
1374
1374
1375 class TestForwardDeclaredInstanceList(TraitTestBase):
1375 class TestForwardDeclaredInstanceList(TraitTestBase):
1376
1376
1377 obj = ForwardDeclaredInstanceListTrait()
1377 obj = ForwardDeclaredInstanceListTrait()
1378
1378
1379 def test_klass(self):
1379 def test_klass(self):
1380 """Test that the instance klass is properly assigned."""
1380 """Test that the instance klass is properly assigned."""
1381 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1381 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1382
1382
1383 _default_value = []
1383 _default_value = []
1384 _good_values = [
1384 _good_values = [
1385 [ForwardDeclaredBar(), ForwardDeclaredBarSub(), None],
1385 [ForwardDeclaredBar(), ForwardDeclaredBarSub(), None],
1386 [None],
1386 [None],
1387 [],
1387 [],
1388 None,
1388 None,
1389 ]
1389 ]
1390 _bad_values = [
1390 _bad_values = [
1391 ForwardDeclaredBar(),
1391 ForwardDeclaredBar(),
1392 [ForwardDeclaredBar(), 3],
1392 [ForwardDeclaredBar(), 3],
1393 '1',
1393 '1',
1394 # Note that this is the type, not an instance.
1394 # Note that this is the type, not an instance.
1395 [ForwardDeclaredBar]
1395 [ForwardDeclaredBar]
1396 ]
1396 ]
1397
1397
1398 class TestForwardDeclaredTypeList(TraitTestBase):
1398 class TestForwardDeclaredTypeList(TraitTestBase):
1399
1399
1400 obj = ForwardDeclaredTypeListTrait()
1400 obj = ForwardDeclaredTypeListTrait()
1401
1401
1402 def test_klass(self):
1402 def test_klass(self):
1403 """Test that the instance klass is properly assigned."""
1403 """Test that the instance klass is properly assigned."""
1404 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1404 self.assertIs(self.obj.traits()['value']._trait.klass, ForwardDeclaredBar)
1405
1405
1406 _default_value = []
1406 _default_value = []
1407 _good_values = [
1407 _good_values = [
1408 [ForwardDeclaredBar, ForwardDeclaredBarSub, None],
1408 [ForwardDeclaredBar, ForwardDeclaredBarSub, None],
1409 [],
1409 [],
1410 [None],
1410 [None],
1411 None,
1411 None,
1412 ]
1412 ]
1413 _bad_values = [
1413 _bad_values = [
1414 ForwardDeclaredBar,
1414 ForwardDeclaredBar,
1415 [ForwardDeclaredBar, 3],
1415 [ForwardDeclaredBar, 3],
1416 '1',
1416 '1',
1417 # Note that this is an instance, not the type.
1417 # Note that this is an instance, not the type.
1418 [ForwardDeclaredBar()]
1418 [ForwardDeclaredBar()]
1419 ]
1419 ]
1420 ###
1420 ###
1421 # End Forward Declaration Tests
1421 # End Forward Declaration Tests
1422 ###
1422 ###
General Comments 0
You need to be logged in to leave comments. Login now