##// END OF EJS Templates
Added tests
zah -
Show More
@@ -1,1108 +1,1125
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, 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(TraitType):
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):
677 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
678 None in self._bad_values):
679 trait=self.obj.traits()['value']
680 if isinstance(trait, AllowNone) and not trait._allow_none:
681 trait._allow_none = True
682 self._bad_values.remove(None)
683 #skip coerce. Allow None casts None to None.
684 self.assign(None)
685 self.assertEqual(self.obj.value,None)
686 self.test_good_values()
687 self.test_bad_values()
688 #tear down
689 trait._allow_none = False
690 self._bad_values.append(None)
691
692
676 def tearDown(self):
693 def tearDown(self):
677 # restore default value after tests, if set
694 # restore default value after tests, if set
678 if hasattr(self, '_default_value'):
695 if hasattr(self, '_default_value'):
679 self.obj.value = self._default_value
696 self.obj.value = self._default_value
680
697
681
698
682 class AnyTrait(HasTraits):
699 class AnyTrait(HasTraits):
683
700
684 value = Any
701 value = Any
685
702
686 class AnyTraitTest(TraitTestBase):
703 class AnyTraitTest(TraitTestBase):
687
704
688 obj = AnyTrait()
705 obj = AnyTrait()
689
706
690 _default_value = None
707 _default_value = None
691 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
708 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
692 _bad_values = []
709 _bad_values = []
693
710
694
711
695 class IntTrait(HasTraits):
712 class IntTrait(HasTraits):
696
713
697 value = Int(99)
714 value = Int(99)
698
715
699 class TestInt(TraitTestBase):
716 class TestInt(TraitTestBase):
700
717
701 obj = IntTrait()
718 obj = IntTrait()
702 _default_value = 99
719 _default_value = 99
703 _good_values = [10, -10]
720 _good_values = [10, -10]
704 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
721 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
705 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
722 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
706 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
723 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
707 if not py3compat.PY3:
724 if not py3compat.PY3:
708 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
725 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
709
726
710
727
711 class LongTrait(HasTraits):
728 class LongTrait(HasTraits):
712
729
713 value = Long(99 if py3compat.PY3 else long(99))
730 value = Long(99 if py3compat.PY3 else long(99))
714
731
715 class TestLong(TraitTestBase):
732 class TestLong(TraitTestBase):
716
733
717 obj = LongTrait()
734 obj = LongTrait()
718
735
719 _default_value = 99 if py3compat.PY3 else long(99)
736 _default_value = 99 if py3compat.PY3 else long(99)
720 _good_values = [10, -10]
737 _good_values = [10, -10]
721 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
738 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
722 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
739 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
723 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
740 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
724 u'-10.1']
741 u'-10.1']
725 if not py3compat.PY3:
742 if not py3compat.PY3:
726 # maxint undefined on py3, because int == long
743 # maxint undefined on py3, because int == long
727 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
744 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
728 _bad_values.extend([[long(10)], (long(10),)])
745 _bad_values.extend([[long(10)], (long(10),)])
729
746
730 @skipif(py3compat.PY3, "not relevant on py3")
747 @skipif(py3compat.PY3, "not relevant on py3")
731 def test_cast_small(self):
748 def test_cast_small(self):
732 """Long casts ints to long"""
749 """Long casts ints to long"""
733 self.obj.value = 10
750 self.obj.value = 10
734 self.assertEqual(type(self.obj.value), long)
751 self.assertEqual(type(self.obj.value), long)
735
752
736
753
737 class IntegerTrait(HasTraits):
754 class IntegerTrait(HasTraits):
738 value = Integer(1)
755 value = Integer(1)
739
756
740 class TestInteger(TestLong):
757 class TestInteger(TestLong):
741 obj = IntegerTrait()
758 obj = IntegerTrait()
742 _default_value = 1
759 _default_value = 1
743
760
744 def coerce(self, n):
761 def coerce(self, n):
745 return int(n)
762 return int(n)
746
763
747 @skipif(py3compat.PY3, "not relevant on py3")
764 @skipif(py3compat.PY3, "not relevant on py3")
748 def test_cast_small(self):
765 def test_cast_small(self):
749 """Integer casts small longs to int"""
766 """Integer casts small longs to int"""
750 if py3compat.PY3:
767 if py3compat.PY3:
751 raise SkipTest("not relevant on py3")
768 raise SkipTest("not relevant on py3")
752
769
753 self.obj.value = long(100)
770 self.obj.value = long(100)
754 self.assertEqual(type(self.obj.value), int)
771 self.assertEqual(type(self.obj.value), int)
755
772
756
773
757 class FloatTrait(HasTraits):
774 class FloatTrait(HasTraits):
758
775
759 value = Float(99.0)
776 value = Float(99.0)
760
777
761 class TestFloat(TraitTestBase):
778 class TestFloat(TraitTestBase):
762
779
763 obj = FloatTrait()
780 obj = FloatTrait()
764
781
765 _default_value = 99.0
782 _default_value = 99.0
766 _good_values = [10, -10, 10.1, -10.1]
783 _good_values = [10, -10, 10.1, -10.1]
767 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
784 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
768 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
785 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
769 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
786 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
770 if not py3compat.PY3:
787 if not py3compat.PY3:
771 _bad_values.extend([long(10), long(-10)])
788 _bad_values.extend([long(10), long(-10)])
772
789
773
790
774 class ComplexTrait(HasTraits):
791 class ComplexTrait(HasTraits):
775
792
776 value = Complex(99.0-99.0j)
793 value = Complex(99.0-99.0j)
777
794
778 class TestComplex(TraitTestBase):
795 class TestComplex(TraitTestBase):
779
796
780 obj = ComplexTrait()
797 obj = ComplexTrait()
781
798
782 _default_value = 99.0-99.0j
799 _default_value = 99.0-99.0j
783 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
800 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
784 10.1j, 10.1+10.1j, 10.1-10.1j]
801 10.1j, 10.1+10.1j, 10.1-10.1j]
785 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
802 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
786 if not py3compat.PY3:
803 if not py3compat.PY3:
787 _bad_values.extend([long(10), long(-10)])
804 _bad_values.extend([long(10), long(-10)])
788
805
789
806
790 class BytesTrait(HasTraits):
807 class BytesTrait(HasTraits):
791
808
792 value = Bytes(b'string')
809 value = Bytes(b'string')
793
810
794 class TestBytes(TraitTestBase):
811 class TestBytes(TraitTestBase):
795
812
796 obj = BytesTrait()
813 obj = BytesTrait()
797
814
798 _default_value = b'string'
815 _default_value = b'string'
799 _good_values = [b'10', b'-10', b'10L',
816 _good_values = [b'10', b'-10', b'10L',
800 b'-10L', b'10.1', b'-10.1', b'string']
817 b'-10L', b'10.1', b'-10.1', b'string']
801 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
818 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
802 ['ten'],{'ten': 10},(10,), None, u'string']
819 ['ten'],{'ten': 10},(10,), None, u'string']
803 if not py3compat.PY3:
820 if not py3compat.PY3:
804 _bad_values.extend([long(10), long(-10)])
821 _bad_values.extend([long(10), long(-10)])
805
822
806
823
807 class UnicodeTrait(HasTraits):
824 class UnicodeTrait(HasTraits):
808
825
809 value = Unicode(u'unicode')
826 value = Unicode(u'unicode')
810
827
811 class TestUnicode(TraitTestBase):
828 class TestUnicode(TraitTestBase):
812
829
813 obj = UnicodeTrait()
830 obj = UnicodeTrait()
814
831
815 _default_value = u'unicode'
832 _default_value = u'unicode'
816 _good_values = ['10', '-10', '10L', '-10L', '10.1',
833 _good_values = ['10', '-10', '10L', '-10L', '10.1',
817 '-10.1', '', u'', 'string', u'string', u"€"]
834 '-10.1', '', u'', 'string', u'string', u"€"]
818 _bad_values = [10, -10, 10.1, -10.1, 1j,
835 _bad_values = [10, -10, 10.1, -10.1, 1j,
819 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
836 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
820 if not py3compat.PY3:
837 if not py3compat.PY3:
821 _bad_values.extend([long(10), long(-10)])
838 _bad_values.extend([long(10), long(-10)])
822
839
823
840
824 class ObjectNameTrait(HasTraits):
841 class ObjectNameTrait(HasTraits):
825 value = ObjectName("abc")
842 value = ObjectName("abc")
826
843
827 class TestObjectName(TraitTestBase):
844 class TestObjectName(TraitTestBase):
828 obj = ObjectNameTrait()
845 obj = ObjectNameTrait()
829
846
830 _default_value = "abc"
847 _default_value = "abc"
831 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
848 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
832 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
849 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
833 object(), object]
850 None, object(), object]
834 if sys.version_info[0] < 3:
851 if sys.version_info[0] < 3:
835 _bad_values.append(u"ΓΎ")
852 _bad_values.append(u"ΓΎ")
836 else:
853 else:
837 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
854 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
838
855
839
856
840 class DottedObjectNameTrait(HasTraits):
857 class DottedObjectNameTrait(HasTraits):
841 value = DottedObjectName("a.b")
858 value = DottedObjectName("a.b")
842
859
843 class TestDottedObjectName(TraitTestBase):
860 class TestDottedObjectName(TraitTestBase):
844 obj = DottedObjectNameTrait()
861 obj = DottedObjectNameTrait()
845
862
846 _default_value = "a.b"
863 _default_value = "a.b"
847 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
864 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
848 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc."]
865 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
849 if sys.version_info[0] < 3:
866 if sys.version_info[0] < 3:
850 _bad_values.append(u"t.ΓΎ")
867 _bad_values.append(u"t.ΓΎ")
851 else:
868 else:
852 _good_values.append(u"t.ΓΎ")
869 _good_values.append(u"t.ΓΎ")
853
870
854
871
855 class TCPAddressTrait(HasTraits):
872 class TCPAddressTrait(HasTraits):
856
873
857 value = TCPAddress()
874 value = TCPAddress()
858
875
859 class TestTCPAddress(TraitTestBase):
876 class TestTCPAddress(TraitTestBase):
860
877
861 obj = TCPAddressTrait()
878 obj = TCPAddressTrait()
862
879
863 _default_value = ('127.0.0.1',0)
880 _default_value = ('127.0.0.1',0)
864 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
881 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
865 _bad_values = [(0,0),('localhost',10.0),('localhost',-1)]
882 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
866
883
867 class ListTrait(HasTraits):
884 class ListTrait(HasTraits):
868
885
869 value = List(Int)
886 value = List(Int)
870
887
871 class TestList(TraitTestBase):
888 class TestList(TraitTestBase):
872
889
873 obj = ListTrait()
890 obj = ListTrait()
874
891
875 _default_value = []
892 _default_value = []
876 _good_values = [[], [1], list(range(10)), (1,2)]
893 _good_values = [[], [1], list(range(10)), (1,2)]
877 _bad_values = [10, [1,'a'], 'a']
894 _bad_values = [10, [1,'a'], 'a']
878
895
879 def coerce(self, value):
896 def coerce(self, value):
880 if value is not None:
897 if value is not None:
881 value = list(value)
898 value = list(value)
882 return value
899 return value
883
900
884 class LenListTrait(HasTraits):
901 class LenListTrait(HasTraits):
885
902
886 value = List(Int, [0], minlen=1, maxlen=2)
903 value = List(Int, [0], minlen=1, maxlen=2)
887
904
888 class TestLenList(TraitTestBase):
905 class TestLenList(TraitTestBase):
889
906
890 obj = LenListTrait()
907 obj = LenListTrait()
891
908
892 _default_value = [0]
909 _default_value = [0]
893 _good_values = [[1], [1,2], (1,2)]
910 _good_values = [[1], [1,2], (1,2)]
894 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
911 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
895
912
896 def coerce(self, value):
913 def coerce(self, value):
897 if value is not None:
914 if value is not None:
898 value = list(value)
915 value = list(value)
899 return value
916 return value
900
917
901 class TupleTrait(HasTraits):
918 class TupleTrait(HasTraits):
902
919
903 value = Tuple(Int)
920 value = Tuple(Int)
904
921
905 class TestTupleTrait(TraitTestBase):
922 class TestTupleTrait(TraitTestBase):
906
923
907 obj = TupleTrait()
924 obj = TupleTrait()
908
925
909 _default_value = None
926 _default_value = None
910 _good_values = [(1,), None, (0,), [1]]
927 _good_values = [(1,), None, (0,), [1]]
911 _bad_values = [10, (1,2), ('a'), ()]
928 _bad_values = [10, (1,2), ('a'), ()]
912
929
913 def coerce(self, value):
930 def coerce(self, value):
914 if value is not None:
931 if value is not None:
915 value = tuple(value)
932 value = tuple(value)
916 return value
933 return value
917
934
918 def test_invalid_args(self):
935 def test_invalid_args(self):
919 self.assertRaises(TypeError, Tuple, 5)
936 self.assertRaises(TypeError, Tuple, 5)
920 self.assertRaises(TypeError, Tuple, default_value='hello')
937 self.assertRaises(TypeError, Tuple, default_value='hello')
921 t = Tuple(Int, CBytes, default_value=(1,5))
938 t = Tuple(Int, CBytes, default_value=(1,5))
922
939
923 class LooseTupleTrait(HasTraits):
940 class LooseTupleTrait(HasTraits):
924
941
925 value = Tuple((1,2,3))
942 value = Tuple((1,2,3))
926
943
927 class TestLooseTupleTrait(TraitTestBase):
944 class TestLooseTupleTrait(TraitTestBase):
928
945
929 obj = LooseTupleTrait()
946 obj = LooseTupleTrait()
930
947
931 _default_value = (1,2,3)
948 _default_value = (1,2,3)
932 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
949 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
933 _bad_values = [10, 'hello', {}]
950 _bad_values = [10, 'hello', {}]
934
951
935 def coerce(self, value):
952 def coerce(self, value):
936 if value is not None:
953 if value is not None:
937 value = tuple(value)
954 value = tuple(value)
938 return value
955 return value
939
956
940 def test_invalid_args(self):
957 def test_invalid_args(self):
941 self.assertRaises(TypeError, Tuple, 5)
958 self.assertRaises(TypeError, Tuple, 5)
942 self.assertRaises(TypeError, Tuple, default_value='hello')
959 self.assertRaises(TypeError, Tuple, default_value='hello')
943 t = Tuple(Int, CBytes, default_value=(1,5))
960 t = Tuple(Int, CBytes, default_value=(1,5))
944
961
945
962
946 class MultiTupleTrait(HasTraits):
963 class MultiTupleTrait(HasTraits):
947
964
948 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
965 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
949
966
950 class TestMultiTuple(TraitTestBase):
967 class TestMultiTuple(TraitTestBase):
951
968
952 obj = MultiTupleTrait()
969 obj = MultiTupleTrait()
953
970
954 _default_value = (99,b'bottles')
971 _default_value = (99,b'bottles')
955 _good_values = [(1,b'a'), (2,b'b')]
972 _good_values = [(1,b'a'), (2,b'b')]
956 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
973 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
957
974
958 class CRegExpTrait(HasTraits):
975 class CRegExpTrait(HasTraits):
959
976
960 value = CRegExp(r'')
977 value = CRegExp(r'')
961
978
962 class TestCRegExp(TraitTestBase):
979 class TestCRegExp(TraitTestBase):
963
980
964 def coerce(self, value):
981 def coerce(self, value):
965 return re.compile(value)
982 return re.compile(value)
966
983
967 obj = CRegExpTrait()
984 obj = CRegExpTrait()
968
985
969 _default_value = re.compile(r'')
986 _default_value = re.compile(r'')
970 _good_values = [r'\d+', re.compile(r'\d+')]
987 _good_values = [r'\d+', re.compile(r'\d+')]
971 _bad_values = [r'(', None, ()]
988 _bad_values = [r'(', None, ()]
972
989
973 class DictTrait(HasTraits):
990 class DictTrait(HasTraits):
974 value = Dict()
991 value = Dict()
975
992
976 def test_dict_assignment():
993 def test_dict_assignment():
977 d = dict()
994 d = dict()
978 c = DictTrait()
995 c = DictTrait()
979 c.value = d
996 c.value = d
980 d['a'] = 5
997 d['a'] = 5
981 nt.assert_equal(d, c.value)
998 nt.assert_equal(d, c.value)
982 nt.assert_true(c.value is d)
999 nt.assert_true(c.value is d)
983
1000
984 class TestLink(TestCase):
1001 class TestLink(TestCase):
985 def test_connect_same(self):
1002 def test_connect_same(self):
986 """Verify two traitlets of the same type can be linked together using link."""
1003 """Verify two traitlets of the same type can be linked together using link."""
987
1004
988 # Create two simple classes with Int traitlets.
1005 # Create two simple classes with Int traitlets.
989 class A(HasTraits):
1006 class A(HasTraits):
990 value = Int()
1007 value = Int()
991 a = A(value=9)
1008 a = A(value=9)
992 b = A(value=8)
1009 b = A(value=8)
993
1010
994 # Conenct the two classes.
1011 # Conenct the two classes.
995 c = link((a, 'value'), (b, 'value'))
1012 c = link((a, 'value'), (b, 'value'))
996
1013
997 # Make sure the values are the same at the point of linking.
1014 # Make sure the values are the same at the point of linking.
998 self.assertEqual(a.value, b.value)
1015 self.assertEqual(a.value, b.value)
999
1016
1000 # Change one of the values to make sure they stay in sync.
1017 # Change one of the values to make sure they stay in sync.
1001 a.value = 5
1018 a.value = 5
1002 self.assertEqual(a.value, b.value)
1019 self.assertEqual(a.value, b.value)
1003 b.value = 6
1020 b.value = 6
1004 self.assertEqual(a.value, b.value)
1021 self.assertEqual(a.value, b.value)
1005
1022
1006 def test_link_different(self):
1023 def test_link_different(self):
1007 """Verify two traitlets of different types can be linked together using link."""
1024 """Verify two traitlets of different types can be linked together using link."""
1008
1025
1009 # Create two simple classes with Int traitlets.
1026 # Create two simple classes with Int traitlets.
1010 class A(HasTraits):
1027 class A(HasTraits):
1011 value = Int()
1028 value = Int()
1012 class B(HasTraits):
1029 class B(HasTraits):
1013 count = Int()
1030 count = Int()
1014 a = A(value=9)
1031 a = A(value=9)
1015 b = B(count=8)
1032 b = B(count=8)
1016
1033
1017 # Conenct the two classes.
1034 # Conenct the two classes.
1018 c = link((a, 'value'), (b, 'count'))
1035 c = link((a, 'value'), (b, 'count'))
1019
1036
1020 # Make sure the values are the same at the point of linking.
1037 # Make sure the values are the same at the point of linking.
1021 self.assertEqual(a.value, b.count)
1038 self.assertEqual(a.value, b.count)
1022
1039
1023 # Change one of the values to make sure they stay in sync.
1040 # Change one of the values to make sure they stay in sync.
1024 a.value = 5
1041 a.value = 5
1025 self.assertEqual(a.value, b.count)
1042 self.assertEqual(a.value, b.count)
1026 b.count = 4
1043 b.count = 4
1027 self.assertEqual(a.value, b.count)
1044 self.assertEqual(a.value, b.count)
1028
1045
1029 def test_unlink(self):
1046 def test_unlink(self):
1030 """Verify two linked traitlets can be unlinked."""
1047 """Verify two linked traitlets can be unlinked."""
1031
1048
1032 # Create two simple classes with Int traitlets.
1049 # Create two simple classes with Int traitlets.
1033 class A(HasTraits):
1050 class A(HasTraits):
1034 value = Int()
1051 value = Int()
1035 a = A(value=9)
1052 a = A(value=9)
1036 b = A(value=8)
1053 b = A(value=8)
1037
1054
1038 # Connect the two classes.
1055 # Connect the two classes.
1039 c = link((a, 'value'), (b, 'value'))
1056 c = link((a, 'value'), (b, 'value'))
1040 a.value = 4
1057 a.value = 4
1041 c.unlink()
1058 c.unlink()
1042
1059
1043 # Change one of the values to make sure they don't stay in sync.
1060 # Change one of the values to make sure they don't stay in sync.
1044 a.value = 5
1061 a.value = 5
1045 self.assertNotEqual(a.value, b.value)
1062 self.assertNotEqual(a.value, b.value)
1046
1063
1047 def test_callbacks(self):
1064 def test_callbacks(self):
1048 """Verify two linked traitlets have their callbacks called once."""
1065 """Verify two linked traitlets have their callbacks called once."""
1049
1066
1050 # Create two simple classes with Int traitlets.
1067 # Create two simple classes with Int traitlets.
1051 class A(HasTraits):
1068 class A(HasTraits):
1052 value = Int()
1069 value = Int()
1053 class B(HasTraits):
1070 class B(HasTraits):
1054 count = Int()
1071 count = Int()
1055 a = A(value=9)
1072 a = A(value=9)
1056 b = B(count=8)
1073 b = B(count=8)
1057
1074
1058 # Register callbacks that count.
1075 # Register callbacks that count.
1059 callback_count = []
1076 callback_count = []
1060 def a_callback(name, old, new):
1077 def a_callback(name, old, new):
1061 callback_count.append('a')
1078 callback_count.append('a')
1062 a.on_trait_change(a_callback, 'value')
1079 a.on_trait_change(a_callback, 'value')
1063 def b_callback(name, old, new):
1080 def b_callback(name, old, new):
1064 callback_count.append('b')
1081 callback_count.append('b')
1065 b.on_trait_change(b_callback, 'count')
1082 b.on_trait_change(b_callback, 'count')
1066
1083
1067 # Connect the two classes.
1084 # Connect the two classes.
1068 c = link((a, 'value'), (b, 'count'))
1085 c = link((a, 'value'), (b, 'count'))
1069
1086
1070 # Make sure b's count was set to a's value once.
1087 # Make sure b's count was set to a's value once.
1071 self.assertEqual(''.join(callback_count), 'b')
1088 self.assertEqual(''.join(callback_count), 'b')
1072 del callback_count[:]
1089 del callback_count[:]
1073
1090
1074 # Make sure a's value was set to b's count once.
1091 # Make sure a's value was set to b's count once.
1075 b.count = 5
1092 b.count = 5
1076 self.assertEqual(''.join(callback_count), 'ba')
1093 self.assertEqual(''.join(callback_count), 'ba')
1077 del callback_count[:]
1094 del callback_count[:]
1078
1095
1079 # Make sure b's count was set to a's value once.
1096 # Make sure b's count was set to a's value once.
1080 a.value = 4
1097 a.value = 4
1081 self.assertEqual(''.join(callback_count), 'ab')
1098 self.assertEqual(''.join(callback_count), 'ab')
1082 del callback_count[:]
1099 del callback_count[:]
1083
1100
1084 class Pickleable(HasTraits):
1101 class Pickleable(HasTraits):
1085 i = Int()
1102 i = Int()
1086 j = Int()
1103 j = Int()
1087
1104
1088 def _i_default(self):
1105 def _i_default(self):
1089 return 1
1106 return 1
1090
1107
1091 def _i_changed(self, name, old, new):
1108 def _i_changed(self, name, old, new):
1092 self.j = new
1109 self.j = new
1093
1110
1094 def test_pickle_hastraits():
1111 def test_pickle_hastraits():
1095 c = Pickleable()
1112 c = Pickleable()
1096 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1113 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1097 p = pickle.dumps(c, protocol)
1114 p = pickle.dumps(c, protocol)
1098 c2 = pickle.loads(p)
1115 c2 = pickle.loads(p)
1099 nt.assert_equal(c2.i, c.i)
1116 nt.assert_equal(c2.i, c.i)
1100 nt.assert_equal(c2.j, c.j)
1117 nt.assert_equal(c2.j, c.j)
1101
1118
1102 c.i = 5
1119 c.i = 5
1103 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1120 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1104 p = pickle.dumps(c, protocol)
1121 p = pickle.dumps(c, protocol)
1105 c2 = pickle.loads(p)
1122 c2 = pickle.loads(p)
1106 nt.assert_equal(c2.i, c.i)
1123 nt.assert_equal(c2.i, c.i)
1107 nt.assert_equal(c2.j, c.j)
1124 nt.assert_equal(c2.j, c.j)
1108 No newline at end of file
1125
General Comments 0
You need to be logged in to leave comments. Login now