##// END OF EJS Templates
Tests for the default klass attribute of the Instance traitlet
Jason Grout -
Show More
@@ -1,1153 +1,1174 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.traitlets."""
2 """Tests for IPython.utils.traitlets."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6 #
6 #
7 # Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
7 # Adapted from enthought.traits, Copyright (c) Enthought, Inc.,
8 # also under the terms of the Modified BSD License.
8 # also under the terms of the Modified BSD License.
9
9
10 import pickle
10 import pickle
11 import re
11 import re
12 import sys
12 import sys
13 from unittest import TestCase
13 from unittest import TestCase
14
14
15 import nose.tools as nt
15 import nose.tools as nt
16 from nose import SkipTest
16 from nose import SkipTest
17
17
18 from IPython.utils.traitlets import (
18 from IPython.utils.traitlets import (
19 HasTraits, MetaHasTraits, TraitType, Any, CBytes, Dict,
19 HasTraits, MetaHasTraits, TraitType, Any, CBytes, Dict,
20 Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError,
20 Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError,
21 Undefined, Type, This, Instance, TCPAddress, List, Tuple,
21 Undefined, Type, This, Instance, TCPAddress, List, Tuple,
22 ObjectName, DottedObjectName, CRegExp, link
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(TraitType):
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 def test_set_str_klass(self):
534 def test_set_str_klass(self):
535
535
536 class A(HasTraits):
536 class A(HasTraits):
537 klass = Type()
537 klass = Type()
538
538
539 a = A(klass='IPython.utils.ipstruct.Struct')
539 a = A(klass='IPython.utils.ipstruct.Struct')
540 from IPython.utils.ipstruct import Struct
540 from IPython.utils.ipstruct import Struct
541 self.assertEqual(a.klass, Struct)
541 self.assertEqual(a.klass, Struct)
542
542
543 class TestInstance(TestCase):
543 class TestInstance(TestCase):
544
544
545 def test_basic(self):
545 def test_basic(self):
546 class Foo(object): pass
546 class Foo(object): pass
547 class Bar(Foo): pass
547 class Bar(Foo): pass
548 class Bah(object): pass
548 class Bah(object): pass
549
549
550 class A(HasTraits):
550 class A(HasTraits):
551 inst = Instance(Foo)
551 inst = Instance(Foo)
552
552
553 a = A()
553 a = A()
554 self.assertTrue(a.inst is None)
554 self.assertTrue(a.inst is None)
555 a.inst = Foo()
555 a.inst = Foo()
556 self.assertTrue(isinstance(a.inst, Foo))
556 self.assertTrue(isinstance(a.inst, Foo))
557 a.inst = Bar()
557 a.inst = Bar()
558 self.assertTrue(isinstance(a.inst, Foo))
558 self.assertTrue(isinstance(a.inst, Foo))
559 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
559 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
560 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
560 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
561 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
561 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
562
562
563 def test_default_klass(self):
564 class Foo(object): pass
565 class Bar(Foo): pass
566 class Bah(object): pass
567
568 class FooInstance(Instance):
569 klass = Foo
570
571 class A(HasTraits):
572 inst = FooInstance()
573
574 a = A()
575 self.assertTrue(a.inst is None)
576 a.inst = Foo()
577 self.assertTrue(isinstance(a.inst, Foo))
578 a.inst = Bar()
579 self.assertTrue(isinstance(a.inst, Foo))
580 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
581 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
582 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
583
563 def test_unique_default_value(self):
584 def test_unique_default_value(self):
564 class Foo(object): pass
585 class Foo(object): pass
565 class A(HasTraits):
586 class A(HasTraits):
566 inst = Instance(Foo,(),{})
587 inst = Instance(Foo,(),{})
567
588
568 a = A()
589 a = A()
569 b = A()
590 b = A()
570 self.assertTrue(a.inst is not b.inst)
591 self.assertTrue(a.inst is not b.inst)
571
592
572 def test_args_kw(self):
593 def test_args_kw(self):
573 class Foo(object):
594 class Foo(object):
574 def __init__(self, c): self.c = c
595 def __init__(self, c): self.c = c
575 class Bar(object): pass
596 class Bar(object): pass
576 class Bah(object):
597 class Bah(object):
577 def __init__(self, c, d):
598 def __init__(self, c, d):
578 self.c = c; self.d = d
599 self.c = c; self.d = d
579
600
580 class A(HasTraits):
601 class A(HasTraits):
581 inst = Instance(Foo, (10,))
602 inst = Instance(Foo, (10,))
582 a = A()
603 a = A()
583 self.assertEqual(a.inst.c, 10)
604 self.assertEqual(a.inst.c, 10)
584
605
585 class B(HasTraits):
606 class B(HasTraits):
586 inst = Instance(Bah, args=(10,), kw=dict(d=20))
607 inst = Instance(Bah, args=(10,), kw=dict(d=20))
587 b = B()
608 b = B()
588 self.assertEqual(b.inst.c, 10)
609 self.assertEqual(b.inst.c, 10)
589 self.assertEqual(b.inst.d, 20)
610 self.assertEqual(b.inst.d, 20)
590
611
591 class C(HasTraits):
612 class C(HasTraits):
592 inst = Instance(Foo)
613 inst = Instance(Foo)
593 c = C()
614 c = C()
594 self.assertTrue(c.inst is None)
615 self.assertTrue(c.inst is None)
595
616
596 def test_bad_default(self):
617 def test_bad_default(self):
597 class Foo(object): pass
618 class Foo(object): pass
598
619
599 class A(HasTraits):
620 class A(HasTraits):
600 inst = Instance(Foo, allow_none=False)
621 inst = Instance(Foo, allow_none=False)
601
622
602 self.assertRaises(TraitError, A)
623 self.assertRaises(TraitError, A)
603
624
604 def test_instance(self):
625 def test_instance(self):
605 class Foo(object): pass
626 class Foo(object): pass
606
627
607 def inner():
628 def inner():
608 class A(HasTraits):
629 class A(HasTraits):
609 inst = Instance(Foo())
630 inst = Instance(Foo())
610
631
611 self.assertRaises(TraitError, inner)
632 self.assertRaises(TraitError, inner)
612
633
613
634
614 class TestThis(TestCase):
635 class TestThis(TestCase):
615
636
616 def test_this_class(self):
637 def test_this_class(self):
617 class Foo(HasTraits):
638 class Foo(HasTraits):
618 this = This
639 this = This
619
640
620 f = Foo()
641 f = Foo()
621 self.assertEqual(f.this, None)
642 self.assertEqual(f.this, None)
622 g = Foo()
643 g = Foo()
623 f.this = g
644 f.this = g
624 self.assertEqual(f.this, g)
645 self.assertEqual(f.this, g)
625 self.assertRaises(TraitError, setattr, f, 'this', 10)
646 self.assertRaises(TraitError, setattr, f, 'this', 10)
626
647
627 def test_this_inst(self):
648 def test_this_inst(self):
628 class Foo(HasTraits):
649 class Foo(HasTraits):
629 this = This()
650 this = This()
630
651
631 f = Foo()
652 f = Foo()
632 f.this = Foo()
653 f.this = Foo()
633 self.assertTrue(isinstance(f.this, Foo))
654 self.assertTrue(isinstance(f.this, Foo))
634
655
635 def test_subclass(self):
656 def test_subclass(self):
636 class Foo(HasTraits):
657 class Foo(HasTraits):
637 t = This()
658 t = This()
638 class Bar(Foo):
659 class Bar(Foo):
639 pass
660 pass
640 f = Foo()
661 f = Foo()
641 b = Bar()
662 b = Bar()
642 f.t = b
663 f.t = b
643 b.t = f
664 b.t = f
644 self.assertEqual(f.t, b)
665 self.assertEqual(f.t, b)
645 self.assertEqual(b.t, f)
666 self.assertEqual(b.t, f)
646
667
647 def test_subclass_override(self):
668 def test_subclass_override(self):
648 class Foo(HasTraits):
669 class Foo(HasTraits):
649 t = This()
670 t = This()
650 class Bar(Foo):
671 class Bar(Foo):
651 t = This()
672 t = This()
652 f = Foo()
673 f = Foo()
653 b = Bar()
674 b = Bar()
654 f.t = b
675 f.t = b
655 self.assertEqual(f.t, b)
676 self.assertEqual(f.t, b)
656 self.assertRaises(TraitError, setattr, b, 't', f)
677 self.assertRaises(TraitError, setattr, b, 't', f)
657
678
658 class TraitTestBase(TestCase):
679 class TraitTestBase(TestCase):
659 """A best testing class for basic trait types."""
680 """A best testing class for basic trait types."""
660
681
661 def assign(self, value):
682 def assign(self, value):
662 self.obj.value = value
683 self.obj.value = value
663
684
664 def coerce(self, value):
685 def coerce(self, value):
665 return value
686 return value
666
687
667 def test_good_values(self):
688 def test_good_values(self):
668 if hasattr(self, '_good_values'):
689 if hasattr(self, '_good_values'):
669 for value in self._good_values:
690 for value in self._good_values:
670 self.assign(value)
691 self.assign(value)
671 self.assertEqual(self.obj.value, self.coerce(value))
692 self.assertEqual(self.obj.value, self.coerce(value))
672
693
673 def test_bad_values(self):
694 def test_bad_values(self):
674 if hasattr(self, '_bad_values'):
695 if hasattr(self, '_bad_values'):
675 for value in self._bad_values:
696 for value in self._bad_values:
676 try:
697 try:
677 self.assertRaises(TraitError, self.assign, value)
698 self.assertRaises(TraitError, self.assign, value)
678 except AssertionError:
699 except AssertionError:
679 assert False, value
700 assert False, value
680
701
681 def test_default_value(self):
702 def test_default_value(self):
682 if hasattr(self, '_default_value'):
703 if hasattr(self, '_default_value'):
683 self.assertEqual(self._default_value, self.obj.value)
704 self.assertEqual(self._default_value, self.obj.value)
684
705
685 def test_allow_none(self):
706 def test_allow_none(self):
686 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
707 if (hasattr(self, '_bad_values') and hasattr(self, '_good_values') and
687 None in self._bad_values):
708 None in self._bad_values):
688 trait=self.obj.traits()['value']
709 trait=self.obj.traits()['value']
689 try:
710 try:
690 trait.allow_none = True
711 trait.allow_none = True
691 self._bad_values.remove(None)
712 self._bad_values.remove(None)
692 #skip coerce. Allow None casts None to None.
713 #skip coerce. Allow None casts None to None.
693 self.assign(None)
714 self.assign(None)
694 self.assertEqual(self.obj.value,None)
715 self.assertEqual(self.obj.value,None)
695 self.test_good_values()
716 self.test_good_values()
696 self.test_bad_values()
717 self.test_bad_values()
697 finally:
718 finally:
698 #tear down
719 #tear down
699 trait.allow_none = False
720 trait.allow_none = False
700 self._bad_values.append(None)
721 self._bad_values.append(None)
701
722
702 def tearDown(self):
723 def tearDown(self):
703 # restore default value after tests, if set
724 # restore default value after tests, if set
704 if hasattr(self, '_default_value'):
725 if hasattr(self, '_default_value'):
705 self.obj.value = self._default_value
726 self.obj.value = self._default_value
706
727
707
728
708 class AnyTrait(HasTraits):
729 class AnyTrait(HasTraits):
709
730
710 value = Any
731 value = Any
711
732
712 class AnyTraitTest(TraitTestBase):
733 class AnyTraitTest(TraitTestBase):
713
734
714 obj = AnyTrait()
735 obj = AnyTrait()
715
736
716 _default_value = None
737 _default_value = None
717 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
738 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
718 _bad_values = []
739 _bad_values = []
719
740
720
741
721 class IntTrait(HasTraits):
742 class IntTrait(HasTraits):
722
743
723 value = Int(99)
744 value = Int(99)
724
745
725 class TestInt(TraitTestBase):
746 class TestInt(TraitTestBase):
726
747
727 obj = IntTrait()
748 obj = IntTrait()
728 _default_value = 99
749 _default_value = 99
729 _good_values = [10, -10]
750 _good_values = [10, -10]
730 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
751 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j,
731 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
752 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
732 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
753 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
733 if not py3compat.PY3:
754 if not py3compat.PY3:
734 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
755 _bad_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
735
756
736
757
737 class LongTrait(HasTraits):
758 class LongTrait(HasTraits):
738
759
739 value = Long(99 if py3compat.PY3 else long(99))
760 value = Long(99 if py3compat.PY3 else long(99))
740
761
741 class TestLong(TraitTestBase):
762 class TestLong(TraitTestBase):
742
763
743 obj = LongTrait()
764 obj = LongTrait()
744
765
745 _default_value = 99 if py3compat.PY3 else long(99)
766 _default_value = 99 if py3compat.PY3 else long(99)
746 _good_values = [10, -10]
767 _good_values = [10, -10]
747 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
768 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,),
748 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
769 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
749 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
770 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
750 u'-10.1']
771 u'-10.1']
751 if not py3compat.PY3:
772 if not py3compat.PY3:
752 # maxint undefined on py3, because int == long
773 # maxint undefined on py3, because int == long
753 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
774 _good_values.extend([long(10), long(-10), 10*sys.maxint, -10*sys.maxint])
754 _bad_values.extend([[long(10)], (long(10),)])
775 _bad_values.extend([[long(10)], (long(10),)])
755
776
756 @skipif(py3compat.PY3, "not relevant on py3")
777 @skipif(py3compat.PY3, "not relevant on py3")
757 def test_cast_small(self):
778 def test_cast_small(self):
758 """Long casts ints to long"""
779 """Long casts ints to long"""
759 self.obj.value = 10
780 self.obj.value = 10
760 self.assertEqual(type(self.obj.value), long)
781 self.assertEqual(type(self.obj.value), long)
761
782
762
783
763 class IntegerTrait(HasTraits):
784 class IntegerTrait(HasTraits):
764 value = Integer(1)
785 value = Integer(1)
765
786
766 class TestInteger(TestLong):
787 class TestInteger(TestLong):
767 obj = IntegerTrait()
788 obj = IntegerTrait()
768 _default_value = 1
789 _default_value = 1
769
790
770 def coerce(self, n):
791 def coerce(self, n):
771 return int(n)
792 return int(n)
772
793
773 @skipif(py3compat.PY3, "not relevant on py3")
794 @skipif(py3compat.PY3, "not relevant on py3")
774 def test_cast_small(self):
795 def test_cast_small(self):
775 """Integer casts small longs to int"""
796 """Integer casts small longs to int"""
776 if py3compat.PY3:
797 if py3compat.PY3:
777 raise SkipTest("not relevant on py3")
798 raise SkipTest("not relevant on py3")
778
799
779 self.obj.value = long(100)
800 self.obj.value = long(100)
780 self.assertEqual(type(self.obj.value), int)
801 self.assertEqual(type(self.obj.value), int)
781
802
782
803
783 class FloatTrait(HasTraits):
804 class FloatTrait(HasTraits):
784
805
785 value = Float(99.0)
806 value = Float(99.0)
786
807
787 class TestFloat(TraitTestBase):
808 class TestFloat(TraitTestBase):
788
809
789 obj = FloatTrait()
810 obj = FloatTrait()
790
811
791 _default_value = 99.0
812 _default_value = 99.0
792 _good_values = [10, -10, 10.1, -10.1]
813 _good_values = [10, -10, 10.1, -10.1]
793 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
814 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None,
794 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
815 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
795 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
816 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
796 if not py3compat.PY3:
817 if not py3compat.PY3:
797 _bad_values.extend([long(10), long(-10)])
818 _bad_values.extend([long(10), long(-10)])
798
819
799
820
800 class ComplexTrait(HasTraits):
821 class ComplexTrait(HasTraits):
801
822
802 value = Complex(99.0-99.0j)
823 value = Complex(99.0-99.0j)
803
824
804 class TestComplex(TraitTestBase):
825 class TestComplex(TraitTestBase):
805
826
806 obj = ComplexTrait()
827 obj = ComplexTrait()
807
828
808 _default_value = 99.0-99.0j
829 _default_value = 99.0-99.0j
809 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
830 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
810 10.1j, 10.1+10.1j, 10.1-10.1j]
831 10.1j, 10.1+10.1j, 10.1-10.1j]
811 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
832 _bad_values = [u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
812 if not py3compat.PY3:
833 if not py3compat.PY3:
813 _bad_values.extend([long(10), long(-10)])
834 _bad_values.extend([long(10), long(-10)])
814
835
815
836
816 class BytesTrait(HasTraits):
837 class BytesTrait(HasTraits):
817
838
818 value = Bytes(b'string')
839 value = Bytes(b'string')
819
840
820 class TestBytes(TraitTestBase):
841 class TestBytes(TraitTestBase):
821
842
822 obj = BytesTrait()
843 obj = BytesTrait()
823
844
824 _default_value = b'string'
845 _default_value = b'string'
825 _good_values = [b'10', b'-10', b'10L',
846 _good_values = [b'10', b'-10', b'10L',
826 b'-10L', b'10.1', b'-10.1', b'string']
847 b'-10L', b'10.1', b'-10.1', b'string']
827 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
848 _bad_values = [10, -10, 10.1, -10.1, 1j, [10],
828 ['ten'],{'ten': 10},(10,), None, u'string']
849 ['ten'],{'ten': 10},(10,), None, u'string']
829 if not py3compat.PY3:
850 if not py3compat.PY3:
830 _bad_values.extend([long(10), long(-10)])
851 _bad_values.extend([long(10), long(-10)])
831
852
832
853
833 class UnicodeTrait(HasTraits):
854 class UnicodeTrait(HasTraits):
834
855
835 value = Unicode(u'unicode')
856 value = Unicode(u'unicode')
836
857
837 class TestUnicode(TraitTestBase):
858 class TestUnicode(TraitTestBase):
838
859
839 obj = UnicodeTrait()
860 obj = UnicodeTrait()
840
861
841 _default_value = u'unicode'
862 _default_value = u'unicode'
842 _good_values = ['10', '-10', '10L', '-10L', '10.1',
863 _good_values = ['10', '-10', '10L', '-10L', '10.1',
843 '-10.1', '', u'', 'string', u'string', u"€"]
864 '-10.1', '', u'', 'string', u'string', u"€"]
844 _bad_values = [10, -10, 10.1, -10.1, 1j,
865 _bad_values = [10, -10, 10.1, -10.1, 1j,
845 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
866 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
846 if not py3compat.PY3:
867 if not py3compat.PY3:
847 _bad_values.extend([long(10), long(-10)])
868 _bad_values.extend([long(10), long(-10)])
848
869
849
870
850 class ObjectNameTrait(HasTraits):
871 class ObjectNameTrait(HasTraits):
851 value = ObjectName("abc")
872 value = ObjectName("abc")
852
873
853 class TestObjectName(TraitTestBase):
874 class TestObjectName(TraitTestBase):
854 obj = ObjectNameTrait()
875 obj = ObjectNameTrait()
855
876
856 _default_value = "abc"
877 _default_value = "abc"
857 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
878 _good_values = ["a", "gh", "g9", "g_", "_G", u"a345_"]
858 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
879 _bad_values = [1, "", u"€", "9g", "!", "#abc", "aj@", "a.b", "a()", "a[0]",
859 None, object(), object]
880 None, object(), object]
860 if sys.version_info[0] < 3:
881 if sys.version_info[0] < 3:
861 _bad_values.append(u"ΓΎ")
882 _bad_values.append(u"ΓΎ")
862 else:
883 else:
863 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
884 _good_values.append(u"ΓΎ") # ΓΎ=1 is valid in Python 3 (PEP 3131).
864
885
865
886
866 class DottedObjectNameTrait(HasTraits):
887 class DottedObjectNameTrait(HasTraits):
867 value = DottedObjectName("a.b")
888 value = DottedObjectName("a.b")
868
889
869 class TestDottedObjectName(TraitTestBase):
890 class TestDottedObjectName(TraitTestBase):
870 obj = DottedObjectNameTrait()
891 obj = DottedObjectNameTrait()
871
892
872 _default_value = "a.b"
893 _default_value = "a.b"
873 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
894 _good_values = ["A", "y.t", "y765.__repr__", "os.path.join", u"os.path.join"]
874 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
895 _bad_values = [1, u"abc.€", "_.@", ".", ".abc", "abc.", ".abc.", None]
875 if sys.version_info[0] < 3:
896 if sys.version_info[0] < 3:
876 _bad_values.append(u"t.ΓΎ")
897 _bad_values.append(u"t.ΓΎ")
877 else:
898 else:
878 _good_values.append(u"t.ΓΎ")
899 _good_values.append(u"t.ΓΎ")
879
900
880
901
881 class TCPAddressTrait(HasTraits):
902 class TCPAddressTrait(HasTraits):
882
903
883 value = TCPAddress()
904 value = TCPAddress()
884
905
885 class TestTCPAddress(TraitTestBase):
906 class TestTCPAddress(TraitTestBase):
886
907
887 obj = TCPAddressTrait()
908 obj = TCPAddressTrait()
888
909
889 _default_value = ('127.0.0.1',0)
910 _default_value = ('127.0.0.1',0)
890 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
911 _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)]
891 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
912 _bad_values = [(0,0),('localhost',10.0),('localhost',-1), None]
892
913
893 class ListTrait(HasTraits):
914 class ListTrait(HasTraits):
894
915
895 value = List(Int)
916 value = List(Int)
896
917
897 class TestList(TraitTestBase):
918 class TestList(TraitTestBase):
898
919
899 obj = ListTrait()
920 obj = ListTrait()
900
921
901 _default_value = []
922 _default_value = []
902 _good_values = [[], [1], list(range(10)), (1,2)]
923 _good_values = [[], [1], list(range(10)), (1,2)]
903 _bad_values = [10, [1,'a'], 'a']
924 _bad_values = [10, [1,'a'], 'a']
904
925
905 def coerce(self, value):
926 def coerce(self, value):
906 if value is not None:
927 if value is not None:
907 value = list(value)
928 value = list(value)
908 return value
929 return value
909
930
910 class Foo(object):
931 class Foo(object):
911 pass
932 pass
912
933
913 class InstanceListTrait(HasTraits):
934 class InstanceListTrait(HasTraits):
914
935
915 value = List(Instance(__name__+'.Foo'))
936 value = List(Instance(__name__+'.Foo'))
916
937
917 class TestInstanceList(TraitTestBase):
938 class TestInstanceList(TraitTestBase):
918
939
919 obj = InstanceListTrait()
940 obj = InstanceListTrait()
920
941
921 def test_klass(self):
942 def test_klass(self):
922 """Test that the instance klass is properly assigned."""
943 """Test that the instance klass is properly assigned."""
923 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
944 self.assertIs(self.obj.traits()['value']._trait.klass, Foo)
924
945
925 _default_value = []
946 _default_value = []
926 _good_values = [[Foo(), Foo(), None], None]
947 _good_values = [[Foo(), Foo(), None], None]
927 _bad_values = [['1', 2,], '1', [Foo]]
948 _bad_values = [['1', 2,], '1', [Foo]]
928
949
929 class LenListTrait(HasTraits):
950 class LenListTrait(HasTraits):
930
951
931 value = List(Int, [0], minlen=1, maxlen=2)
952 value = List(Int, [0], minlen=1, maxlen=2)
932
953
933 class TestLenList(TraitTestBase):
954 class TestLenList(TraitTestBase):
934
955
935 obj = LenListTrait()
956 obj = LenListTrait()
936
957
937 _default_value = [0]
958 _default_value = [0]
938 _good_values = [[1], [1,2], (1,2)]
959 _good_values = [[1], [1,2], (1,2)]
939 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
960 _bad_values = [10, [1,'a'], 'a', [], list(range(3))]
940
961
941 def coerce(self, value):
962 def coerce(self, value):
942 if value is not None:
963 if value is not None:
943 value = list(value)
964 value = list(value)
944 return value
965 return value
945
966
946 class TupleTrait(HasTraits):
967 class TupleTrait(HasTraits):
947
968
948 value = Tuple(Int(allow_none=True))
969 value = Tuple(Int(allow_none=True))
949
970
950 class TestTupleTrait(TraitTestBase):
971 class TestTupleTrait(TraitTestBase):
951
972
952 obj = TupleTrait()
973 obj = TupleTrait()
953
974
954 _default_value = None
975 _default_value = None
955 _good_values = [(1,), None, (0,), [1], (None,)]
976 _good_values = [(1,), None, (0,), [1], (None,)]
956 _bad_values = [10, (1,2), ('a'), ()]
977 _bad_values = [10, (1,2), ('a'), ()]
957
978
958 def coerce(self, value):
979 def coerce(self, value):
959 if value is not None:
980 if value is not None:
960 value = tuple(value)
981 value = tuple(value)
961 return value
982 return value
962
983
963 def test_invalid_args(self):
984 def test_invalid_args(self):
964 self.assertRaises(TypeError, Tuple, 5)
985 self.assertRaises(TypeError, Tuple, 5)
965 self.assertRaises(TypeError, Tuple, default_value='hello')
986 self.assertRaises(TypeError, Tuple, default_value='hello')
966 t = Tuple(Int, CBytes, default_value=(1,5))
987 t = Tuple(Int, CBytes, default_value=(1,5))
967
988
968 class LooseTupleTrait(HasTraits):
989 class LooseTupleTrait(HasTraits):
969
990
970 value = Tuple((1,2,3))
991 value = Tuple((1,2,3))
971
992
972 class TestLooseTupleTrait(TraitTestBase):
993 class TestLooseTupleTrait(TraitTestBase):
973
994
974 obj = LooseTupleTrait()
995 obj = LooseTupleTrait()
975
996
976 _default_value = (1,2,3)
997 _default_value = (1,2,3)
977 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
998 _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()]
978 _bad_values = [10, 'hello', {}]
999 _bad_values = [10, 'hello', {}]
979
1000
980 def coerce(self, value):
1001 def coerce(self, value):
981 if value is not None:
1002 if value is not None:
982 value = tuple(value)
1003 value = tuple(value)
983 return value
1004 return value
984
1005
985 def test_invalid_args(self):
1006 def test_invalid_args(self):
986 self.assertRaises(TypeError, Tuple, 5)
1007 self.assertRaises(TypeError, Tuple, 5)
987 self.assertRaises(TypeError, Tuple, default_value='hello')
1008 self.assertRaises(TypeError, Tuple, default_value='hello')
988 t = Tuple(Int, CBytes, default_value=(1,5))
1009 t = Tuple(Int, CBytes, default_value=(1,5))
989
1010
990
1011
991 class MultiTupleTrait(HasTraits):
1012 class MultiTupleTrait(HasTraits):
992
1013
993 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
1014 value = Tuple(Int, Bytes, default_value=[99,b'bottles'])
994
1015
995 class TestMultiTuple(TraitTestBase):
1016 class TestMultiTuple(TraitTestBase):
996
1017
997 obj = MultiTupleTrait()
1018 obj = MultiTupleTrait()
998
1019
999 _default_value = (99,b'bottles')
1020 _default_value = (99,b'bottles')
1000 _good_values = [(1,b'a'), (2,b'b')]
1021 _good_values = [(1,b'a'), (2,b'b')]
1001 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1022 _bad_values = ((),10, b'a', (1,b'a',3), (b'a',1), (1, u'a'))
1002
1023
1003 class CRegExpTrait(HasTraits):
1024 class CRegExpTrait(HasTraits):
1004
1025
1005 value = CRegExp(r'')
1026 value = CRegExp(r'')
1006
1027
1007 class TestCRegExp(TraitTestBase):
1028 class TestCRegExp(TraitTestBase):
1008
1029
1009 def coerce(self, value):
1030 def coerce(self, value):
1010 return re.compile(value)
1031 return re.compile(value)
1011
1032
1012 obj = CRegExpTrait()
1033 obj = CRegExpTrait()
1013
1034
1014 _default_value = re.compile(r'')
1035 _default_value = re.compile(r'')
1015 _good_values = [r'\d+', re.compile(r'\d+')]
1036 _good_values = [r'\d+', re.compile(r'\d+')]
1016 _bad_values = [r'(', None, ()]
1037 _bad_values = [r'(', None, ()]
1017
1038
1018 class DictTrait(HasTraits):
1039 class DictTrait(HasTraits):
1019 value = Dict()
1040 value = Dict()
1020
1041
1021 def test_dict_assignment():
1042 def test_dict_assignment():
1022 d = dict()
1043 d = dict()
1023 c = DictTrait()
1044 c = DictTrait()
1024 c.value = d
1045 c.value = d
1025 d['a'] = 5
1046 d['a'] = 5
1026 nt.assert_equal(d, c.value)
1047 nt.assert_equal(d, c.value)
1027 nt.assert_true(c.value is d)
1048 nt.assert_true(c.value is d)
1028
1049
1029 class TestLink(TestCase):
1050 class TestLink(TestCase):
1030 def test_connect_same(self):
1051 def test_connect_same(self):
1031 """Verify two traitlets of the same type can be linked together using link."""
1052 """Verify two traitlets of the same type can be linked together using link."""
1032
1053
1033 # Create two simple classes with Int traitlets.
1054 # Create two simple classes with Int traitlets.
1034 class A(HasTraits):
1055 class A(HasTraits):
1035 value = Int()
1056 value = Int()
1036 a = A(value=9)
1057 a = A(value=9)
1037 b = A(value=8)
1058 b = A(value=8)
1038
1059
1039 # Conenct the two classes.
1060 # Conenct the two classes.
1040 c = link((a, 'value'), (b, 'value'))
1061 c = link((a, 'value'), (b, 'value'))
1041
1062
1042 # Make sure the values are the same at the point of linking.
1063 # Make sure the values are the same at the point of linking.
1043 self.assertEqual(a.value, b.value)
1064 self.assertEqual(a.value, b.value)
1044
1065
1045 # Change one of the values to make sure they stay in sync.
1066 # Change one of the values to make sure they stay in sync.
1046 a.value = 5
1067 a.value = 5
1047 self.assertEqual(a.value, b.value)
1068 self.assertEqual(a.value, b.value)
1048 b.value = 6
1069 b.value = 6
1049 self.assertEqual(a.value, b.value)
1070 self.assertEqual(a.value, b.value)
1050
1071
1051 def test_link_different(self):
1072 def test_link_different(self):
1052 """Verify two traitlets of different types can be linked together using link."""
1073 """Verify two traitlets of different types can be linked together using link."""
1053
1074
1054 # Create two simple classes with Int traitlets.
1075 # Create two simple classes with Int traitlets.
1055 class A(HasTraits):
1076 class A(HasTraits):
1056 value = Int()
1077 value = Int()
1057 class B(HasTraits):
1078 class B(HasTraits):
1058 count = Int()
1079 count = Int()
1059 a = A(value=9)
1080 a = A(value=9)
1060 b = B(count=8)
1081 b = B(count=8)
1061
1082
1062 # Conenct the two classes.
1083 # Conenct the two classes.
1063 c = link((a, 'value'), (b, 'count'))
1084 c = link((a, 'value'), (b, 'count'))
1064
1085
1065 # Make sure the values are the same at the point of linking.
1086 # Make sure the values are the same at the point of linking.
1066 self.assertEqual(a.value, b.count)
1087 self.assertEqual(a.value, b.count)
1067
1088
1068 # Change one of the values to make sure they stay in sync.
1089 # Change one of the values to make sure they stay in sync.
1069 a.value = 5
1090 a.value = 5
1070 self.assertEqual(a.value, b.count)
1091 self.assertEqual(a.value, b.count)
1071 b.count = 4
1092 b.count = 4
1072 self.assertEqual(a.value, b.count)
1093 self.assertEqual(a.value, b.count)
1073
1094
1074 def test_unlink(self):
1095 def test_unlink(self):
1075 """Verify two linked traitlets can be unlinked."""
1096 """Verify two linked traitlets can be unlinked."""
1076
1097
1077 # Create two simple classes with Int traitlets.
1098 # Create two simple classes with Int traitlets.
1078 class A(HasTraits):
1099 class A(HasTraits):
1079 value = Int()
1100 value = Int()
1080 a = A(value=9)
1101 a = A(value=9)
1081 b = A(value=8)
1102 b = A(value=8)
1082
1103
1083 # Connect the two classes.
1104 # Connect the two classes.
1084 c = link((a, 'value'), (b, 'value'))
1105 c = link((a, 'value'), (b, 'value'))
1085 a.value = 4
1106 a.value = 4
1086 c.unlink()
1107 c.unlink()
1087
1108
1088 # Change one of the values to make sure they don't stay in sync.
1109 # Change one of the values to make sure they don't stay in sync.
1089 a.value = 5
1110 a.value = 5
1090 self.assertNotEqual(a.value, b.value)
1111 self.assertNotEqual(a.value, b.value)
1091
1112
1092 def test_callbacks(self):
1113 def test_callbacks(self):
1093 """Verify two linked traitlets have their callbacks called once."""
1114 """Verify two linked traitlets have their callbacks called once."""
1094
1115
1095 # Create two simple classes with Int traitlets.
1116 # Create two simple classes with Int traitlets.
1096 class A(HasTraits):
1117 class A(HasTraits):
1097 value = Int()
1118 value = Int()
1098 class B(HasTraits):
1119 class B(HasTraits):
1099 count = Int()
1120 count = Int()
1100 a = A(value=9)
1121 a = A(value=9)
1101 b = B(count=8)
1122 b = B(count=8)
1102
1123
1103 # Register callbacks that count.
1124 # Register callbacks that count.
1104 callback_count = []
1125 callback_count = []
1105 def a_callback(name, old, new):
1126 def a_callback(name, old, new):
1106 callback_count.append('a')
1127 callback_count.append('a')
1107 a.on_trait_change(a_callback, 'value')
1128 a.on_trait_change(a_callback, 'value')
1108 def b_callback(name, old, new):
1129 def b_callback(name, old, new):
1109 callback_count.append('b')
1130 callback_count.append('b')
1110 b.on_trait_change(b_callback, 'count')
1131 b.on_trait_change(b_callback, 'count')
1111
1132
1112 # Connect the two classes.
1133 # Connect the two classes.
1113 c = link((a, 'value'), (b, 'count'))
1134 c = link((a, 'value'), (b, 'count'))
1114
1135
1115 # Make sure b's count was set to a's value once.
1136 # Make sure b's count was set to a's value once.
1116 self.assertEqual(''.join(callback_count), 'b')
1137 self.assertEqual(''.join(callback_count), 'b')
1117 del callback_count[:]
1138 del callback_count[:]
1118
1139
1119 # Make sure a's value was set to b's count once.
1140 # Make sure a's value was set to b's count once.
1120 b.count = 5
1141 b.count = 5
1121 self.assertEqual(''.join(callback_count), 'ba')
1142 self.assertEqual(''.join(callback_count), 'ba')
1122 del callback_count[:]
1143 del callback_count[:]
1123
1144
1124 # Make sure b's count was set to a's value once.
1145 # Make sure b's count was set to a's value once.
1125 a.value = 4
1146 a.value = 4
1126 self.assertEqual(''.join(callback_count), 'ab')
1147 self.assertEqual(''.join(callback_count), 'ab')
1127 del callback_count[:]
1148 del callback_count[:]
1128
1149
1129 class Pickleable(HasTraits):
1150 class Pickleable(HasTraits):
1130 i = Int()
1151 i = Int()
1131 j = Int()
1152 j = Int()
1132
1153
1133 def _i_default(self):
1154 def _i_default(self):
1134 return 1
1155 return 1
1135
1156
1136 def _i_changed(self, name, old, new):
1157 def _i_changed(self, name, old, new):
1137 self.j = new
1158 self.j = new
1138
1159
1139 def test_pickle_hastraits():
1160 def test_pickle_hastraits():
1140 c = Pickleable()
1161 c = Pickleable()
1141 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1162 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1142 p = pickle.dumps(c, protocol)
1163 p = pickle.dumps(c, protocol)
1143 c2 = pickle.loads(p)
1164 c2 = pickle.loads(p)
1144 nt.assert_equal(c2.i, c.i)
1165 nt.assert_equal(c2.i, c.i)
1145 nt.assert_equal(c2.j, c.j)
1166 nt.assert_equal(c2.j, c.j)
1146
1167
1147 c.i = 5
1168 c.i = 5
1148 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1169 for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
1149 p = pickle.dumps(c, protocol)
1170 p = pickle.dumps(c, protocol)
1150 c2 = pickle.loads(p)
1171 c2 = pickle.loads(p)
1151 nt.assert_equal(c2.i, c.i)
1172 nt.assert_equal(c2.i, c.i)
1152 nt.assert_equal(c2.j, c.j)
1173 nt.assert_equal(c2.j, c.j)
1153
1174
General Comments 0
You need to be logged in to leave comments. Login now