##// END OF EJS Templates
test that config objects are pickleable
MinRK -
Show More
@@ -1,292 +1,299 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Tests for IPython.config.loader
3 Tests for IPython.config.loader
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez (design help)
8 * Fernando Perez (design help)
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import os
22 import os
23 import pickle
23 import sys
24 import sys
24 from tempfile import mkstemp
25 from tempfile import mkstemp
25 from unittest import TestCase
26 from unittest import TestCase
26
27
27 from nose import SkipTest
28 from nose import SkipTest
28
29
29 from IPython.testing.tools import mute_warn
30 from IPython.testing.tools import mute_warn
30
31
31 from IPython.config.loader import (
32 from IPython.config.loader import (
32 Config,
33 Config,
33 PyFileConfigLoader,
34 PyFileConfigLoader,
34 KeyValueConfigLoader,
35 KeyValueConfigLoader,
35 ArgParseConfigLoader,
36 ArgParseConfigLoader,
36 KVArgParseConfigLoader,
37 KVArgParseConfigLoader,
37 ConfigError
38 ConfigError
38 )
39 )
39
40
40 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
41 # Actual tests
42 # Actual tests
42 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
43
44
44
45
45 pyfile = """
46 pyfile = """
46 c = get_config()
47 c = get_config()
47 c.a=10
48 c.a=10
48 c.b=20
49 c.b=20
49 c.Foo.Bar.value=10
50 c.Foo.Bar.value=10
50 c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3
51 c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3
51 c.D.C.value='hi there'
52 c.D.C.value='hi there'
52 """
53 """
53
54
54 class TestPyFileCL(TestCase):
55 class TestPyFileCL(TestCase):
55
56
56 def test_basic(self):
57 def test_basic(self):
57 fd, fname = mkstemp('.py')
58 fd, fname = mkstemp('.py')
58 f = os.fdopen(fd, 'w')
59 f = os.fdopen(fd, 'w')
59 f.write(pyfile)
60 f.write(pyfile)
60 f.close()
61 f.close()
61 # Unlink the file
62 # Unlink the file
62 cl = PyFileConfigLoader(fname)
63 cl = PyFileConfigLoader(fname)
63 config = cl.load_config()
64 config = cl.load_config()
64 self.assertEqual(config.a, 10)
65 self.assertEqual(config.a, 10)
65 self.assertEqual(config.b, 20)
66 self.assertEqual(config.b, 20)
66 self.assertEqual(config.Foo.Bar.value, 10)
67 self.assertEqual(config.Foo.Bar.value, 10)
67 self.assertEqual(config.Foo.Bam.value, list(range(10)))
68 self.assertEqual(config.Foo.Bam.value, list(range(10)))
68 self.assertEqual(config.D.C.value, 'hi there')
69 self.assertEqual(config.D.C.value, 'hi there')
69
70
70 class MyLoader1(ArgParseConfigLoader):
71 class MyLoader1(ArgParseConfigLoader):
71 def _add_arguments(self, aliases=None, flags=None):
72 def _add_arguments(self, aliases=None, flags=None):
72 p = self.parser
73 p = self.parser
73 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
74 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
74 p.add_argument('-b', dest='MyClass.bar', type=int)
75 p.add_argument('-b', dest='MyClass.bar', type=int)
75 p.add_argument('-n', dest='n', action='store_true')
76 p.add_argument('-n', dest='n', action='store_true')
76 p.add_argument('Global.bam', type=str)
77 p.add_argument('Global.bam', type=str)
77
78
78 class MyLoader2(ArgParseConfigLoader):
79 class MyLoader2(ArgParseConfigLoader):
79 def _add_arguments(self, aliases=None, flags=None):
80 def _add_arguments(self, aliases=None, flags=None):
80 subparsers = self.parser.add_subparsers(dest='subparser_name')
81 subparsers = self.parser.add_subparsers(dest='subparser_name')
81 subparser1 = subparsers.add_parser('1')
82 subparser1 = subparsers.add_parser('1')
82 subparser1.add_argument('-x',dest='Global.x')
83 subparser1.add_argument('-x',dest='Global.x')
83 subparser2 = subparsers.add_parser('2')
84 subparser2 = subparsers.add_parser('2')
84 subparser2.add_argument('y')
85 subparser2.add_argument('y')
85
86
86 class TestArgParseCL(TestCase):
87 class TestArgParseCL(TestCase):
87
88
88 def test_basic(self):
89 def test_basic(self):
89 cl = MyLoader1()
90 cl = MyLoader1()
90 config = cl.load_config('-f hi -b 10 -n wow'.split())
91 config = cl.load_config('-f hi -b 10 -n wow'.split())
91 self.assertEqual(config.Global.foo, 'hi')
92 self.assertEqual(config.Global.foo, 'hi')
92 self.assertEqual(config.MyClass.bar, 10)
93 self.assertEqual(config.MyClass.bar, 10)
93 self.assertEqual(config.n, True)
94 self.assertEqual(config.n, True)
94 self.assertEqual(config.Global.bam, 'wow')
95 self.assertEqual(config.Global.bam, 'wow')
95 config = cl.load_config(['wow'])
96 config = cl.load_config(['wow'])
96 self.assertEqual(list(config.keys()), ['Global'])
97 self.assertEqual(list(config.keys()), ['Global'])
97 self.assertEqual(list(config.Global.keys()), ['bam'])
98 self.assertEqual(list(config.Global.keys()), ['bam'])
98 self.assertEqual(config.Global.bam, 'wow')
99 self.assertEqual(config.Global.bam, 'wow')
99
100
100 def test_add_arguments(self):
101 def test_add_arguments(self):
101 cl = MyLoader2()
102 cl = MyLoader2()
102 config = cl.load_config('2 frobble'.split())
103 config = cl.load_config('2 frobble'.split())
103 self.assertEqual(config.subparser_name, '2')
104 self.assertEqual(config.subparser_name, '2')
104 self.assertEqual(config.y, 'frobble')
105 self.assertEqual(config.y, 'frobble')
105 config = cl.load_config('1 -x frobble'.split())
106 config = cl.load_config('1 -x frobble'.split())
106 self.assertEqual(config.subparser_name, '1')
107 self.assertEqual(config.subparser_name, '1')
107 self.assertEqual(config.Global.x, 'frobble')
108 self.assertEqual(config.Global.x, 'frobble')
108
109
109 def test_argv(self):
110 def test_argv(self):
110 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
111 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
111 config = cl.load_config()
112 config = cl.load_config()
112 self.assertEqual(config.Global.foo, 'hi')
113 self.assertEqual(config.Global.foo, 'hi')
113 self.assertEqual(config.MyClass.bar, 10)
114 self.assertEqual(config.MyClass.bar, 10)
114 self.assertEqual(config.n, True)
115 self.assertEqual(config.n, True)
115 self.assertEqual(config.Global.bam, 'wow')
116 self.assertEqual(config.Global.bam, 'wow')
116
117
117
118
118 class TestKeyValueCL(TestCase):
119 class TestKeyValueCL(TestCase):
119 klass = KeyValueConfigLoader
120 klass = KeyValueConfigLoader
120
121
121 def test_basic(self):
122 def test_basic(self):
122 cl = self.klass()
123 cl = self.klass()
123 argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]]
124 argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]]
124 with mute_warn():
125 with mute_warn():
125 config = cl.load_config(argv)
126 config = cl.load_config(argv)
126 self.assertEqual(config.a, 10)
127 self.assertEqual(config.a, 10)
127 self.assertEqual(config.b, 20)
128 self.assertEqual(config.b, 20)
128 self.assertEqual(config.Foo.Bar.value, 10)
129 self.assertEqual(config.Foo.Bar.value, 10)
129 self.assertEqual(config.Foo.Bam.value, list(range(10)))
130 self.assertEqual(config.Foo.Bam.value, list(range(10)))
130 self.assertEqual(config.D.C.value, 'hi there')
131 self.assertEqual(config.D.C.value, 'hi there')
131
132
132 def test_expanduser(self):
133 def test_expanduser(self):
133 cl = self.klass()
134 cl = self.klass()
134 argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"']
135 argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"']
135 with mute_warn():
136 with mute_warn():
136 config = cl.load_config(argv)
137 config = cl.load_config(argv)
137 self.assertEqual(config.a, os.path.expanduser('~/1/2/3'))
138 self.assertEqual(config.a, os.path.expanduser('~/1/2/3'))
138 self.assertEqual(config.b, os.path.expanduser('~'))
139 self.assertEqual(config.b, os.path.expanduser('~'))
139 self.assertEqual(config.c, os.path.expanduser('~/'))
140 self.assertEqual(config.c, os.path.expanduser('~/'))
140 self.assertEqual(config.d, '~/')
141 self.assertEqual(config.d, '~/')
141
142
142 def test_extra_args(self):
143 def test_extra_args(self):
143 cl = self.klass()
144 cl = self.klass()
144 with mute_warn():
145 with mute_warn():
145 config = cl.load_config(['--a=5', 'b', '--c=10', 'd'])
146 config = cl.load_config(['--a=5', 'b', '--c=10', 'd'])
146 self.assertEqual(cl.extra_args, ['b', 'd'])
147 self.assertEqual(cl.extra_args, ['b', 'd'])
147 self.assertEqual(config.a, 5)
148 self.assertEqual(config.a, 5)
148 self.assertEqual(config.c, 10)
149 self.assertEqual(config.c, 10)
149 with mute_warn():
150 with mute_warn():
150 config = cl.load_config(['--', '--a=5', '--c=10'])
151 config = cl.load_config(['--', '--a=5', '--c=10'])
151 self.assertEqual(cl.extra_args, ['--a=5', '--c=10'])
152 self.assertEqual(cl.extra_args, ['--a=5', '--c=10'])
152
153
153 def test_unicode_args(self):
154 def test_unicode_args(self):
154 cl = self.klass()
155 cl = self.klass()
155 argv = [u'--a=épsîlön']
156 argv = [u'--a=épsîlön']
156 with mute_warn():
157 with mute_warn():
157 config = cl.load_config(argv)
158 config = cl.load_config(argv)
158 self.assertEqual(config.a, u'épsîlön')
159 self.assertEqual(config.a, u'épsîlön')
159
160
160 def test_unicode_bytes_args(self):
161 def test_unicode_bytes_args(self):
161 uarg = u'--a=é'
162 uarg = u'--a=é'
162 try:
163 try:
163 barg = uarg.encode(sys.stdin.encoding)
164 barg = uarg.encode(sys.stdin.encoding)
164 except (TypeError, UnicodeEncodeError):
165 except (TypeError, UnicodeEncodeError):
165 raise SkipTest("sys.stdin.encoding can't handle 'é'")
166 raise SkipTest("sys.stdin.encoding can't handle 'é'")
166
167
167 cl = self.klass()
168 cl = self.klass()
168 with mute_warn():
169 with mute_warn():
169 config = cl.load_config([barg])
170 config = cl.load_config([barg])
170 self.assertEqual(config.a, u'é')
171 self.assertEqual(config.a, u'é')
171
172
172 def test_unicode_alias(self):
173 def test_unicode_alias(self):
173 cl = self.klass()
174 cl = self.klass()
174 argv = [u'--a=épsîlön']
175 argv = [u'--a=épsîlön']
175 with mute_warn():
176 with mute_warn():
176 config = cl.load_config(argv, aliases=dict(a='A.a'))
177 config = cl.load_config(argv, aliases=dict(a='A.a'))
177 self.assertEqual(config.A.a, u'épsîlön')
178 self.assertEqual(config.A.a, u'épsîlön')
178
179
179
180
180 class TestArgParseKVCL(TestKeyValueCL):
181 class TestArgParseKVCL(TestKeyValueCL):
181 klass = KVArgParseConfigLoader
182 klass = KVArgParseConfigLoader
182
183
183 def test_expanduser2(self):
184 def test_expanduser2(self):
184 cl = self.klass()
185 cl = self.klass()
185 argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"]
186 argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"]
186 with mute_warn():
187 with mute_warn():
187 config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b'))
188 config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b'))
188 self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3'))
189 self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3'))
189 self.assertEqual(config.A.b, '~/1/2/3')
190 self.assertEqual(config.A.b, '~/1/2/3')
190
191
191 def test_eval(self):
192 def test_eval(self):
192 cl = self.klass()
193 cl = self.klass()
193 argv = ['-c', 'a=5']
194 argv = ['-c', 'a=5']
194 with mute_warn():
195 with mute_warn():
195 config = cl.load_config(argv, aliases=dict(c='A.c'))
196 config = cl.load_config(argv, aliases=dict(c='A.c'))
196 self.assertEqual(config.A.c, u"a=5")
197 self.assertEqual(config.A.c, u"a=5")
197
198
198
199
199 class TestConfig(TestCase):
200 class TestConfig(TestCase):
200
201
201 def test_setget(self):
202 def test_setget(self):
202 c = Config()
203 c = Config()
203 c.a = 10
204 c.a = 10
204 self.assertEqual(c.a, 10)
205 self.assertEqual(c.a, 10)
205 self.assertEqual('b' in c, False)
206 self.assertEqual('b' in c, False)
206
207
207 def test_auto_section(self):
208 def test_auto_section(self):
208 c = Config()
209 c = Config()
209 self.assertEqual('A' in c, True)
210 self.assertEqual('A' in c, True)
210 self.assertEqual(c._has_section('A'), False)
211 self.assertEqual(c._has_section('A'), False)
211 A = c.A
212 A = c.A
212 A.foo = 'hi there'
213 A.foo = 'hi there'
213 self.assertEqual(c._has_section('A'), True)
214 self.assertEqual(c._has_section('A'), True)
214 self.assertEqual(c.A.foo, 'hi there')
215 self.assertEqual(c.A.foo, 'hi there')
215 del c.A
216 del c.A
216 self.assertEqual(len(c.A.keys()),0)
217 self.assertEqual(len(c.A.keys()),0)
217
218
218 def test_merge_doesnt_exist(self):
219 def test_merge_doesnt_exist(self):
219 c1 = Config()
220 c1 = Config()
220 c2 = Config()
221 c2 = Config()
221 c2.bar = 10
222 c2.bar = 10
222 c2.Foo.bar = 10
223 c2.Foo.bar = 10
223 c1.merge(c2)
224 c1.merge(c2)
224 self.assertEqual(c1.Foo.bar, 10)
225 self.assertEqual(c1.Foo.bar, 10)
225 self.assertEqual(c1.bar, 10)
226 self.assertEqual(c1.bar, 10)
226 c2.Bar.bar = 10
227 c2.Bar.bar = 10
227 c1.merge(c2)
228 c1.merge(c2)
228 self.assertEqual(c1.Bar.bar, 10)
229 self.assertEqual(c1.Bar.bar, 10)
229
230
230 def test_merge_exists(self):
231 def test_merge_exists(self):
231 c1 = Config()
232 c1 = Config()
232 c2 = Config()
233 c2 = Config()
233 c1.Foo.bar = 10
234 c1.Foo.bar = 10
234 c1.Foo.bam = 30
235 c1.Foo.bam = 30
235 c2.Foo.bar = 20
236 c2.Foo.bar = 20
236 c2.Foo.wow = 40
237 c2.Foo.wow = 40
237 c1.merge(c2)
238 c1.merge(c2)
238 self.assertEqual(c1.Foo.bam, 30)
239 self.assertEqual(c1.Foo.bam, 30)
239 self.assertEqual(c1.Foo.bar, 20)
240 self.assertEqual(c1.Foo.bar, 20)
240 self.assertEqual(c1.Foo.wow, 40)
241 self.assertEqual(c1.Foo.wow, 40)
241 c2.Foo.Bam.bam = 10
242 c2.Foo.Bam.bam = 10
242 c1.merge(c2)
243 c1.merge(c2)
243 self.assertEqual(c1.Foo.Bam.bam, 10)
244 self.assertEqual(c1.Foo.Bam.bam, 10)
244
245
245 def test_deepcopy(self):
246 def test_deepcopy(self):
246 c1 = Config()
247 c1 = Config()
247 c1.Foo.bar = 10
248 c1.Foo.bar = 10
248 c1.Foo.bam = 30
249 c1.Foo.bam = 30
249 c1.a = 'asdf'
250 c1.a = 'asdf'
250 c1.b = range(10)
251 c1.b = range(10)
251 import copy
252 import copy
252 c2 = copy.deepcopy(c1)
253 c2 = copy.deepcopy(c1)
253 self.assertEqual(c1, c2)
254 self.assertEqual(c1, c2)
254 self.assertTrue(c1 is not c2)
255 self.assertTrue(c1 is not c2)
255 self.assertTrue(c1.Foo is not c2.Foo)
256 self.assertTrue(c1.Foo is not c2.Foo)
256
257
257 def test_builtin(self):
258 def test_builtin(self):
258 c1 = Config()
259 c1 = Config()
259 exec('foo = True', c1)
260 exec('foo = True', c1)
260 self.assertEqual(c1.foo, True)
261 self.assertEqual(c1.foo, True)
261 c1.format = "json"
262 c1.format = "json"
262
263
263 def test_fromdict(self):
264 def test_fromdict(self):
264 c1 = Config({'Foo' : {'bar' : 1}})
265 c1 = Config({'Foo' : {'bar' : 1}})
265 self.assertEqual(c1.Foo.__class__, Config)
266 self.assertEqual(c1.Foo.__class__, Config)
266 self.assertEqual(c1.Foo.bar, 1)
267 self.assertEqual(c1.Foo.bar, 1)
267
268
268 def test_fromdictmerge(self):
269 def test_fromdictmerge(self):
269 c1 = Config()
270 c1 = Config()
270 c2 = Config({'Foo' : {'bar' : 1}})
271 c2 = Config({'Foo' : {'bar' : 1}})
271 c1.merge(c2)
272 c1.merge(c2)
272 self.assertEqual(c1.Foo.__class__, Config)
273 self.assertEqual(c1.Foo.__class__, Config)
273 self.assertEqual(c1.Foo.bar, 1)
274 self.assertEqual(c1.Foo.bar, 1)
274
275
275 def test_fromdictmerge2(self):
276 def test_fromdictmerge2(self):
276 c1 = Config({'Foo' : {'baz' : 2}})
277 c1 = Config({'Foo' : {'baz' : 2}})
277 c2 = Config({'Foo' : {'bar' : 1}})
278 c2 = Config({'Foo' : {'bar' : 1}})
278 c1.merge(c2)
279 c1.merge(c2)
279 self.assertEqual(c1.Foo.__class__, Config)
280 self.assertEqual(c1.Foo.__class__, Config)
280 self.assertEqual(c1.Foo.bar, 1)
281 self.assertEqual(c1.Foo.bar, 1)
281 self.assertEqual(c1.Foo.baz, 2)
282 self.assertEqual(c1.Foo.baz, 2)
282 self.assertNotIn('baz', c2.Foo)
283 self.assertNotIn('baz', c2.Foo)
283
284
284 def test_contains(self):
285 def test_contains(self):
285 c1 = Config({'Foo' : {'baz' : 2}})
286 c1 = Config({'Foo' : {'baz' : 2}})
286 c2 = Config({'Foo' : {'bar' : 1}})
287 c2 = Config({'Foo' : {'bar' : 1}})
287 self.assertIn('Foo', c1)
288 self.assertIn('Foo', c1)
288 self.assertIn('Foo.baz', c1)
289 self.assertIn('Foo.baz', c1)
289 self.assertIn('Foo.bar', c2)
290 self.assertIn('Foo.bar', c2)
290 self.assertNotIn('Foo.bar', c1)
291 self.assertNotIn('Foo.bar', c1)
291
292
293 def test_pickle_config(self):
294 cfg = Config()
295 cfg.Foo.bar = 1
296 pcfg = pickle.dumps(cfg)
297 cfg2 = pickle.loads(pcfg)
298 self.assertEqual(cfg2, cfg)
292
299
General Comments 0
You need to be logged in to leave comments. Login now