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