separate baseoption and option
[tiramisu.git] / test / test_config.py
1 # -*- coding: utf-8 -*-
2
3 """theses tests are much more to test that config, option description, vs...
4 **it's there** and answers via attribute access"""
5 from .autopath import do_autopath
6 do_autopath()
7
8 from py.test import raises
9
10 from tiramisu.config import Config, SubConfig
11 from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
12     BoolOption, UnicodeOption, OptionDescription
13 from tiramisu.i18n import _
14 from tiramisu.error import ConflictError, ConfigError, PropertiesOptionError
15 import weakref
16
17
18 def make_description():
19     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
20     gcdummy = BoolOption('dummy', 'dummy', default=False)
21     objspaceoption = ChoiceOption('objspace', 'Object space',
22                                   ('std', 'thunk'), 'std')
23     booloption = BoolOption('bool', 'Test boolean option', default=True)
24     intoption = IntOption('int', 'Test int option', default=0)
25     floatoption = FloatOption('float', 'Test float option', default=2.3)
26     stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', ))
27     boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',))
28     wantref_option = BoolOption('wantref', 'Test requires', default=False)
29     wantframework_option = BoolOption('wantframework', 'Test requires',
30                                       default=False)
31
32     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
33     descr = OptionDescription('tiram', '', [gcgroup, booloption, objspaceoption,
34                                             wantref_option, stroption,
35                                             wantframework_option,
36                                             intoption, boolop])
37     return descr
38
39
40 #def test_base_config():
41 #    """making a :class:`tiramisu.config.Config()` object
42 #    and a :class:`tiramisu.option.OptionDescription()` object
43 #    """
44 #    gcdummy = BoolOption('dummy', 'dummy', default=False)
45 #    descr = OptionDescription('tiramisu', '', [gcdummy])
46 #    cfg = Config(descr)
47 #    assert cfg.dummy is False
48 #    dm = cfg.unwrap_from_path('dummy')
49 #    assert dm.impl_getname() == 'dummy'
50
51
52 def test_base_config_name():
53     gcdummy = BoolOption('dummy', 'dummy', default=False)
54     descr = OptionDescription('tiramisu', '', [gcdummy])
55     cfg = Config(descr, session_id='cfg')
56     cfg.impl_getname() == 'cfg'
57     raises(ValueError, "Config(descr, session_id='unvalid name')")
58
59
60 def test_not_config():
61     assert raises(TypeError, "Config('str')")
62
63
64 def test_base_path():
65     gcdummy = BoolOption('dummy', 'dummy', default=False)
66     descr = OptionDescription('tiramisu', '', [gcdummy])
67     cfg = Config(descr)
68     assert cfg._impl_path is None
69     base = OptionDescription('config', '', [descr])
70     cfg = Config(base)
71     assert cfg._impl_path is None
72     assert cfg.tiramisu._impl_path == 'tiramisu'
73     nbase = OptionDescription('baseconfig', '', [base])
74     cfg = Config(nbase)
75     assert cfg._impl_path is None
76     assert cfg.config._impl_path == 'config'
77     assert cfg.config.tiramisu._impl_path == 'config.tiramisu'
78 #
79 #
80 #def test_reset_value():
81 #    descr = make_description()
82 #    cfg = Config(descr)
83 #    assert cfg.gc.dummy is False
84 #    cfg.gc.dummy = True
85 #    assert cfg.gc.dummy is True
86 #
87 #
88 #def test_base_config_and_groups():
89 #    descr = make_description()
90 #    # overrides the booloption default value
91 #    config = Config(descr)
92 #    config.bool = False
93 #    assert config.gc.name == 'ref'
94 #    assert config.bool is False
95 #    nm = config.unwrap_from_path('gc.name')
96 #    assert nm.impl_getname() == 'name'
97 #    gc = config.unwrap_from_path('gc')
98 #    assert gc.impl_getname() == 'gc'
99 #    #nm = config.unwrap_from_name('name')
100 #    #assert nm.impl_getname() == 'name'
101
102
103 def test_base_config_force_permissive():
104     descr = make_description()
105     config = Config(descr)
106     config.read_write()
107     config.cfgimpl_get_settings().setpermissive(('hidden',))
108     raises(PropertiesOptionError, "config.getattr('boolop')")
109     assert config.getattr('boolop', force_permissive=True) is True
110
111
112 def test_base_config_in_a_tree():
113     "how options are organized into a tree, see :ref:`tree`"
114     descr = make_description()
115     config = Config(descr)
116     config.bool = False
117     assert config.gc.name == 'ref'
118     config.gc.name = 'framework'
119     assert config.gc.name == 'framework'
120     assert getattr(config, "gc.name") == 'framework'
121
122     assert config.objspace == 'std'
123     config.objspace = 'thunk'
124     assert config.objspace == 'thunk'
125
126     assert config.gc.float == 2.3
127     assert config.int == 0
128     config.gc.float = 3.4
129     config.int = 123
130     assert config.gc.float == 3.4
131     assert config.int == 123
132
133     assert not config.wantref
134
135     assert config.str == "abc"
136     config.str = "def"
137     assert config.str == "def"
138
139     raises(AttributeError, 'config.gc.foo = "bar"')
140
141     config = Config(descr)
142     config.bool = False
143     assert config.gc.name == 'ref'
144     config.wantframework = True
145
146
147 def test_cfgimpl_get_home_by_path():
148     " :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path"
149     descr = make_description()
150     config = Config(descr)
151     config.bool = False
152     assert config.cfgimpl_get_home_by_path('gc.dummy')[1] == 'dummy'
153     assert config.cfgimpl_get_home_by_path('dummy')[1] == 'dummy'
154
155
156 def test_not_valid_properties():
157     raises(TypeError, "stroption = StrOption('str', 'Test string option', default='abc', properties=['mandatory',])")
158
159
160 def test_information_config():
161     descr = make_description()
162     config = Config(descr)
163     string = 'some informations'
164     config.impl_set_information('info', string)
165     assert config.impl_get_information('info') == string
166     raises(ValueError, "config.impl_get_information('noinfo')")
167     assert config.impl_get_information('noinfo', 'default') == 'default'
168     config.impl_del_information('info')
169     raises(ValueError, "config.impl_get_information('info')")
170     raises(ValueError, "config.impl_del_information('noinfo')")
171
172
173 def test_config_impl_get_path_by_opt():
174     descr = make_description()
175     config = Config(descr)
176     dummy = config.unwrap_from_path('gc.dummy')
177     boo = config.unwrap_from_path('bool')
178     unknown = IntOption('test', '')
179     unknown
180     assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool'
181     assert config.cfgimpl_get_description().impl_get_path_by_opt(dummy) == 'gc.dummy'
182     raises(AttributeError, "config.cfgimpl_get_description().impl_get_path_by_opt(unknown)")
183
184
185 def test_config_impl_get_path_by_opt_od():
186     descr = make_description()
187     config = Config(descr)
188     dummy = config.unwrap_from_path('gc.dummy')
189     dummy
190     raises(ConfigError, "config.cfgimpl_get_description().gc.impl_get_path_by_opt(dummy)")
191
192
193 def test_config_impl_get_opt_by_path():
194     descr = make_description()
195     config = Config(descr)
196     dummy = config.unwrap_from_path('gc.dummy')
197     boo = config.unwrap_from_path('bool')
198     if 'id' in dir(boo):
199         assert config.cfgimpl_get_description().impl_get_opt_by_path('bool').id == boo.id
200         assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy').id == dummy.id
201     else:
202         assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo
203         assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy
204     raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
205     raises(ConfigError, "config.gc.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
206
207
208 def test_information_display():
209     g1 = IntOption('g1', '', 1)
210     g2 = StrOption('g2', '', 'héhé')
211     g3 = UnicodeOption('g3', '', u'héhé')
212     g4 = BoolOption('g4', '', True)
213     g5 = StrOption('g5', '')
214     d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5])
215     root = OptionDescription('root', '', [d1])
216     config = Config(root)
217     config.od == """g1 = 1
218 g2 = héhé
219 g3 = héhé
220 g4 = True
221 g5 = None"""
222     config == '[od]'
223
224
225 def test_get_modified_values():
226     g1 = IntOption('g1', '', 1)
227     g2 = StrOption('g2', '', 'héhé')
228     g3 = UnicodeOption('g3', '', u'héhé')
229     g4 = BoolOption('g4', '', True)
230     g5 = StrOption('g5', '')
231     g6 = StrOption('g6', '', multi=True)
232     d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5, g6])
233     root = OptionDescription('root', '', [d1])
234     config = Config(root)
235     assert config.cfgimpl_get_values().get_modified_values() == {}
236     config.od.g5 = 'yes'
237     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes')}
238     config.od.g4 = True
239     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g4': ('user', True)}
240     del config.od.g4
241     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes')}
242     config.od.g6.append()
243     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', (None,))}
244     config.od.g6.pop(0)
245     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', tuple())}
246     config.od.g6.append('3')
247     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', ('3',))}
248     del config.od.g6[0]
249     assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', tuple())}
250
251
252 def test_has_value():
253     g1 = IntOption('g1', '', 1)
254     g2 = StrOption('g2', '', 'héhé')
255     g3 = UnicodeOption('g3', '', u'héhé')
256     g4 = BoolOption('g4', '', True)
257     g5 = StrOption('g5', '')
258     d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5])
259     root = OptionDescription('root', '', [d1])
260     config = Config(root)
261     assert not g5 in config.cfgimpl_get_values()
262     config.od.g5 = 'yes'
263     assert g5 in config.cfgimpl_get_values()
264
265
266 def test_values_not_setitem():
267     g1 = IntOption('g1', '', 1)
268     g2 = StrOption('g2', '', 'héhé')
269     g3 = UnicodeOption('g3', '', u'héhé')
270     g4 = BoolOption('g4', '', True)
271     g5 = StrOption('g5', '')
272     d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5])
273     root = OptionDescription('root', '', [d1])
274     config = Config(root)
275     config
276     raises(ConfigError, "config.cfgimpl_get_values()[g1] = 2")
277
278
279 def test_duplicated_option():
280     g1 = IntOption('g1', '', 1)
281     g1
282     #in same OptionDescription
283     raises(ConflictError, "d1 = OptionDescription('od', '', [g1, g1])")
284
285
286 def test_duplicated_option_diff_od():
287     g1 = IntOption('g1', '', 1)
288     d1 = OptionDescription('od1', '', [g1])
289     #in different OptionDescription
290     d2 = OptionDescription('od2', '', [g1, d1])
291     d2
292     raises(ConflictError, 'Config(d2)')
293
294
295 def test_cannot_assign_value_to_option_description():
296     descr = make_description()
297     cfg = Config(descr)
298     cfg
299     raises(TypeError, "cfg.gc = 3")
300
301
302 def test_config_multi():
303     i1 = IntOption('test1', '', multi=True)
304     i2 = IntOption('test2', '', multi=True, default_multi=1)
305     i3 = IntOption('test3', '', default=[2], multi=True, default_multi=1)
306     od = OptionDescription('test', '', [i1, i2, i3])
307     config = Config(od)
308     assert config.test1 == []
309     assert config.test2 == []
310     config.test2.append()
311     assert config.test2 == [1]
312     assert config.test3 == [2]
313     config.test3.append()
314     assert config.test3 == [2, 1]
315
316
317 def test_no_validation():
318     i1 = IntOption('test1', '')
319     od = OptionDescription('test', '', [i1])
320     c = Config(od)
321     setting = c.cfgimpl_get_settings()
322     c.test1 = 1
323     raises(ValueError, 'c.test1 = "yes"')
324     assert c.test1 == 1
325     setting.remove('validator')
326     c.test1 = "yes"
327     assert c.test1 == "yes"
328     setting.append('validator')
329     raises(ValueError, 'c.test1')
330     del(c.test1)
331     assert c.test1 is None
332
333
334 def test_delete_config_with_subconfig():
335     test = IntOption('test', '')
336     multi = IntOption('multi', '', multi=True)
337     od = OptionDescription('od', '', [test, multi])
338     odroot = OptionDescription('odroot', '', [od])
339     c = Config(odroot)
340     sub = c.od
341     val = c.cfgimpl_get_values()
342     setting = c.cfgimpl_get_settings()
343     val[test]
344     val[multi]
345     setting[test]
346     sub.make_dict()
347     del(c)
348     raises(ConfigError, 'val[test]')
349     raises(ConfigError, 'val[multi]')
350     raises(ConfigError, 'setting[test]')
351     raises(ConfigError, 'sub.make_dict()')
352
353
354 def test_subconfig():
355     i = IntOption('i', '')
356     o = OptionDescription('val', '', [i])
357     o2 = OptionDescription('val', '', [o])
358     c = Config(o2)
359     c
360     raises(TypeError, "SubConfig(i, weakref.ref(c))")
361     pass
362
363
364 def test_config_weakref():
365     o = OptionDescription('val', '', [])
366     o2 = OptionDescription('val', '', [o])
367     c = Config(o2)
368     SubConfig(o, weakref.ref(c))
369     raises(ValueError, "SubConfig(o, c)")
370     s = SubConfig(o, weakref.ref(c))
371     assert s._cfgimpl_get_context() == c
372     del(c)
373     raises(ConfigError, "s._cfgimpl_get_context()")
374
375
376 def test_config_str():
377     gcdummy = BoolOption('dummy', 'dummy', default=False)
378     gcdummy1 = BoolOption('dummy1', 'dummy', default=False, properties=('disabled',))
379     o = OptionDescription('o', '', [gcdummy, gcdummy1])
380     descr = OptionDescription('tiramisu', '', [o])
381     cfg = Config(descr)
382     cfg.read_only()
383     str(cfg)
384     str(cfg.o)
385
386
387 def test_config_od_function():
388     gcdummy = BoolOption('dummy', 'dummy', default=False)
389     gcdummy1 = BoolOption('dummy1', 'dummy', default=False, properties=('disabled',))
390     o = OptionDescription('o', '', [gcdummy, gcdummy1])
391     descr = OptionDescription('tiramisu', '', [o])
392     cfg = Config(descr)
393     try:
394         print(cfg.impl_get_opt_by_path())
395     except AttributeError as err:
396         assert str(err) == _('unknown Option {0} in OptionDescription {1}'
397                              '').format('impl_get_opt_by_path', descr.impl_getname())
398
399
400 def test_config_subconfig():
401     i1 = IntOption('i1', '')
402     i2 = IntOption('i2', '', default=1)
403     i3 = IntOption('i3', '')
404     i4 = IntOption('i4', '', default=2)
405     od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
406     od2 = OptionDescription('od2', '', [od1])
407     conf1 = Config(od2, session_id='conf1')
408     conf1
409     raises(ConfigError, "conf2 = Config(od1, session_id='conf2')")