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