8ca8687ab49eb33c89f68f507e6236aff1447745
[tiramisu.git] / test / test_option_calculation.py
1 import autopath
2 from py.test import raises
3
4 from tiramisu.setting import groups
5 from tiramisu.config import Config
6 from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
7     StrOption, OptionDescription, SymLinkOption
8 from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
9
10
11 def return_val():
12     return 'val'
13
14
15 def return_concat(*args):
16     return '.'.join(list(args))
17
18
19 def return_list(value=None):
20     return ['val', 'val']
21
22
23 def return_list2(*args):
24     return list(args)
25
26
27 def return_value(value=None):
28     return value
29
30
31 def make_description():
32     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
33     gcdummy = BoolOption('dummy', 'dummy', default=False)
34     objspaceoption = ChoiceOption('objspace', 'Object space',
35                                   ('std', 'thunk'), 'std')
36     booloption = BoolOption('bool', 'Test boolean option', default=True)
37     intoption = IntOption('int', 'Test int option', default=0)
38     intoption2 = IntOption('int', 'Test int option', default=0)
39     floatoption = FloatOption('float', 'Test float option', default=2.3)
40     stroption = StrOption('str', 'Test string option', default="abc")
41     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
42     wantref_option = BoolOption('wantref', 'Test requires', default=False,
43                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
44     wantframework_option = BoolOption('wantframework', 'Test requires',
45                                       default=False,
46                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
47     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, intoption2])
48     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
49                               wantref_option, stroption,
50                               wantframework_option,
51                               intoption, boolop])
52     return descr
53
54
55 def make_description_duplicates():
56     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
57     ## dummy 1
58     gcdummy = BoolOption('dummy', 'dummy', default=False)
59     objspaceoption = ChoiceOption('objspace', 'Object space',
60                                   ('std', 'thunk'), 'std')
61     booloption = BoolOption('bool', 'Test boolean option', default=True)
62     intoption = IntOption('int', 'Test int option', default=0)
63     floatoption = FloatOption('float', 'Test float option', default=2.3)
64     stroption = StrOption('str', 'Test string option', default="abc")
65     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
66     wantref_option = BoolOption('wantref', 'Test requires', default=False,
67                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
68     wantframework_option = BoolOption('wantframework', 'Test requires',
69                                       default=False,
70                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
71     # dummy2 (same path)
72     gcdummy2 = BoolOption('dummy', 'dummy2', default=True)
73     # dummy3 (same name)
74     gcdummy3 = BoolOption('dummy', 'dummy2', default=True)
75     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, gcdummy2, floatoption])
76     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
77                               wantref_option, stroption,
78                               wantframework_option,
79                               intoption, boolop, gcdummy3])
80     return descr
81
82
83 def test_identical_paths():
84     """If in the schema (the option description) there is something that
85     have the same name, an exection is raised
86     """
87     raises(ConflictError, "make_description_duplicates()")
88
89
90 def make_description2():
91     gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
92     gcdummy = BoolOption('dummy', 'dummy', default=False)
93
94     floatoption = FloatOption('float', 'Test float option', default=2.3)
95
96     objspaceoption = ChoiceOption('objspace', 'Object space',
97                                   ['std', 'thunk'], 'std')
98     booloption = BoolOption('bool', 'Test boolean option', default=True)
99     intoption = IntOption('int', 'Test int option', default=0)
100     stroption = StrOption('str', 'Test string option', default="abc")
101     # first multi
102     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
103     boolop.enable_multi()
104     wantref_option = BoolOption('wantref', 'Test requires', default=False,
105                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
106     # second multi
107     wantframework_option = BoolOption('wantframework', 'Test requires',
108                                       default=False,
109                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
110     wantframework_option.enable_multi()
111
112     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
113     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
114                               wantref_option, stroption,
115                               wantframework_option,
116                               intoption, boolop])
117     return descr
118
119
120 # FIXME: il faudra tester les validations sur les multis
121 #def test_multi_constraints():
122 #    "a multi in a constraint has to have the same length"
123 #    descr = make_description2()
124 #    cfg = Config(descr)
125 #    cfg.boolop = [True, True, False]
126 #    cfg.wantframework = [False, False, True]
127 #
128 #def test_multi_raise():
129 #    "a multi in a constraint has to have the same length"
130 #    # FIXME fusionner les deux tests, MAIS PROBLEME :
131 #    # il ne devrait pas etre necessaire de refaire une config
132 #    # si la valeur est modifiee une deuxieme fois ->
133 #    #raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
134 #    #   ExceptionFailure: 'DID NOT RAISE'
135 #    descr = make_description2()
136 #    cfg = Config(descr)
137 #    cfg.boolop = [True]
138 #    raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
139 # ____________________________________________________________
140 # adding dynamically new options description schema
141 #def test_newoption_add_in_descr():
142 #    descr = make_description()
143 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
144 #    descr.add_child(newoption)
145 #    config = Config(descr)
146 #    assert config.newoption == False
147
148 #def test_newoption_add_in_subdescr():
149 #    descr = make_description()
150 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
151 #    descr.gc.add_child(newoption)
152 #    config = Config(descr)
153 #    config.bool = False
154 #    assert config.gc.newoption == False
155
156 #def test_newoption_add_in_config():
157 #    descr = make_description()
158 #    config = Config(descr)
159 #    config.bool = False
160 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
161 #    descr.add_child(newoption)
162 #    config.cfgimpl_update()
163 #    assert config.newoption == False
164 # ____________________________________________________________
165
166
167 def make_description_requires():
168     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
169     gcdummy = BoolOption('dummy', 'dummy', default=False)
170
171     floatoption = FloatOption('float', 'Test float option', default=2.3)
172
173     objspaceoption = ChoiceOption('objspace', 'Object space',
174                                   ('std', 'thunk'), 'std')
175     booloption = BoolOption('bool', 'Test boolean option', default=True)
176     intoption = IntOption('int', 'Test int option', default=0)
177     stroption = StrOption('str', 'Test string option', default="abc",
178                           requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},))
179
180     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
181     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
182                               stroption, intoption])
183     return descr
184
185
186 def test_hidden_if_in():
187     descr = make_description_requires()
188     cfg = Config(descr)
189     setting = cfg.cfgimpl_get_settings()
190     cfg.read_write()
191     stroption = cfg.unwrap_from_path('str')
192     assert not 'hidden' in setting[stroption]
193     cfg.int = 1
194     raises(PropertiesOptionError, "cfg.str")
195     raises(PropertiesOptionError, 'cfg.str="uvw"')
196     assert 'hidden' in setting[stroption]
197
198
199 def test_hidden_if_in_with_group():
200     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
201     gcdummy = BoolOption('dummy', 'dummy', default=False)
202
203     floatoption = FloatOption('float', 'Test float option', default=2.3)
204
205     objspaceoption = ChoiceOption('objspace', 'Object space',
206                                   ('std', 'thunk'), 'std')
207     booloption = BoolOption('bool', 'Test boolean option', default=True)
208     intoption = IntOption('int', 'Test int option', default=0)
209     stroption = StrOption('str', 'Test string option', default="abc")
210     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
211                                 requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},))
212     descr = OptionDescription('constraints', '', [gcgroup, booloption,
213                               objspaceoption, stroption, intoption])
214     cfg = Config(descr)
215     setting = cfg.cfgimpl_get_settings()
216     cfg.read_write()
217     assert not 'hidden' in setting[stroption]
218     cfg.int = 1
219     raises(PropertiesOptionError, "cfg.gc.name")
220
221
222 def test_disabled_with_group():
223     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
224     gcdummy = BoolOption('dummy', 'dummy', default=False)
225
226     floatoption = FloatOption('float', 'Test float option', default=2.3)
227
228     objspaceoption = ChoiceOption('objspace', 'Object space',
229                                   ('std', 'thunk'), 'std')
230     booloption = BoolOption('bool', 'Test boolean option', default=True)
231     intoption = IntOption('int', 'Test int option', default=0)
232     stroption = StrOption('str', 'Test string option', default="abc")
233     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
234                                 requires=({'option': intoption, 'expected': 1, 'action': 'disabled'},))
235     descr = OptionDescription('constraints', '', [gcgroup, booloption,
236                               objspaceoption, stroption, intoption])
237     cfg = Config(descr)
238     cfg.read_write()
239     assert cfg.gc.name
240     cfg.int = 1
241     raises(PropertiesOptionError, "cfg.gc.name")
242 #____________________________________________________________
243
244
245 def make_description_callback():
246     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
247     gcdummy = BoolOption('dummy', 'dummy')
248     objspaceoption = ChoiceOption('objspace', 'Object space',
249                                   ('std', 'thunk'), 'std')
250     booloption = BoolOption('bool', 'Test boolean option', default=True)
251     intoption = IntOption('int', 'Test int option', default=0)
252     floatoption = FloatOption('float', 'Test float option', default=2.3)
253     stroption = StrOption('str', 'Test string option', default="abc")
254     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
255     wantref_option = BoolOption('wantref', 'Test requires', default=False,
256                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
257     wantframework_option = BoolOption('wantframework', 'Test requires',
258                                       default=False,
259                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
260     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
261     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
262                               wantref_option, stroption,
263                               wantframework_option,
264                               intoption, boolop])
265     return descr
266
267
268 def test_has_callback():
269     descr = make_description_callback()
270     # here the owner is 'default'
271     config = Config(descr)
272     setting = config.cfgimpl_get_settings()
273     config.read_write()
274     config.bool = False
275     # because dummy has a callback
276     dummy = config.unwrap_from_path('gc.dummy')
277     setting.append('freeze')
278     setting[dummy].append('frozen')
279     raises(PropertiesOptionError, "config.gc.dummy = True")
280
281
282 def test_freeze_and_has_callback():
283     descr = make_description_callback()
284     config = Config(descr)
285     setting = config.cfgimpl_get_settings()
286     config.read_write()
287     config.bool = False
288     setting = config.cfgimpl_get_settings()
289     setting.append('freeze')
290     dummy = config.unwrap_from_path('gc.dummy')
291     setting[dummy].append('frozen')
292     raises(PropertiesOptionError, "config.gc.dummy = True")
293
294
295 def test_callback():
296     val1 = StrOption('val1', "", callback=return_val)
297     maconfig = OptionDescription('rootconfig', '', [val1])
298     cfg = Config(maconfig)
299     cfg.read_write()
300     assert cfg.val1 == 'val'
301     cfg.val1 = 'new-val'
302     assert cfg.val1 == 'new-val'
303     del(cfg.val1)
304     assert cfg.val1 == 'val'
305
306
307 def test_callback_value():
308     val1 = StrOption('val1', "", 'val')
309     val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
310     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ('yes',)})
311     val4 = StrOption('val4', "", callback=return_value, callback_params={'value': ((val1, False),)})
312     val5 = StrOption('val5', "", callback=return_value, callback_params={'value': ('yes',)})
313     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5])
314     cfg = Config(maconfig)
315     cfg.read_write()
316     assert cfg.val1 == 'val'
317     assert cfg.val2 == 'val'
318     assert cfg.val4 == 'val'
319     cfg.val1 = 'new-val'
320     assert cfg.val1 == 'new-val'
321     assert cfg.val2 == 'new-val'
322     assert cfg.val4 == 'new-val'
323     del(cfg.val1)
324     assert cfg.val1 == 'val'
325     assert cfg.val2 == 'val'
326     assert cfg.val3 == 'yes'
327     assert cfg.val4 == 'val'
328     assert cfg.val5 == 'yes'
329
330
331 def test_callback_value_tuple():
332     val1 = StrOption('val1', "", 'val1')
333     val2 = StrOption('val2', "", 'val2')
334     val3 = StrOption('val3', "", callback=return_concat, callback_params={'': ((val1, False), (val2, False))})
335     val4 = StrOption('val4', "", callback=return_concat, callback_params={'': ('yes', 'no')})
336     raises(ValueError, "StrOption('val4', '', callback=return_concat, callback_params={'value': ('yes', 'no')})")
337     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
338     cfg = Config(maconfig)
339     cfg.read_write()
340     assert cfg.val1 == 'val1'
341     assert cfg.val2 == 'val2'
342     assert cfg.val3 == 'val1.val2'
343     assert cfg.val4 == 'yes.no'
344     cfg.val1 = 'new-val'
345     assert cfg.val3 == 'new-val.val2'
346     del(cfg.val1)
347     assert cfg.val3 == 'val1.val2'
348
349
350 def test_callback_value_force_permissive():
351     val1 = StrOption('val1', "", 'val', properties=('disabled',))
352     val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
353     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val1, True),)})
354     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
355     cfg = Config(maconfig)
356     cfg.read_only()
357     raises(ConfigError, "cfg.val2")
358     assert cfg.val3 is None
359
360
361 def test_callback_symlink():
362     val1 = StrOption('val1', "", 'val')
363     val2 = SymLinkOption('val2', val1)
364     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val2, False),)})
365     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
366     cfg = Config(maconfig)
367     cfg.read_write()
368     assert cfg.val1 == 'val'
369     assert cfg.val3 == 'val'
370     cfg.val1 = 'new-val'
371     assert cfg.val1 == 'new-val'
372     assert cfg.val3 == 'new-val'
373     del(cfg.val1)
374     assert cfg.val1 == 'val'
375     assert cfg.val3 == 'val'
376
377
378 def test_callback_list():
379     val1 = StrOption('val1', "", callback=return_list)
380     maconfig = OptionDescription('rootconfig', '', [val1])
381     cfg = Config(maconfig)
382     cfg.read_write()
383     raises(ValueError, "cfg.val1")
384
385
386 def test_callback_multi():
387     val1 = StrOption('val1', "", callback=return_val, multi=True)
388     maconfig = OptionDescription('rootconfig', '', [val1])
389     cfg = Config(maconfig)
390     cfg.read_write()
391     assert cfg.val1 == ['val']
392     cfg.val1 = ['new-val']
393     assert cfg.val1 == ['new-val']
394     cfg.val1.append('new-val2')
395     assert cfg.val1 == ['new-val', 'new-val2']
396     del(cfg.val1)
397     assert cfg.val1 == ['val']
398
399
400 def test_callback_multi_value():
401     val1 = StrOption('val1', "", ['val'], multi=True)
402     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
403     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
404     val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), 'yes')})
405     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
406     cfg = Config(maconfig)
407     cfg.read_write()
408     assert cfg.val1 == ['val']
409     assert cfg.val2 == ['val']
410     assert cfg.val4 == ['val', 'yes']
411     cfg.val1 = ['new-val']
412     assert cfg.val1 == ['new-val']
413     assert cfg.val2 == ['new-val']
414     assert cfg.val4 == ['new-val', 'yes']
415     cfg.val1.append('new-val2')
416     assert cfg.val1 == ['new-val', 'new-val2']
417     assert cfg.val2 == ['new-val', 'new-val2']
418     assert cfg.val4 == ['new-val', 'yes', 'new-val2', 'yes']
419     del(cfg.val1)
420     assert cfg.val1 == ['val']
421     assert cfg.val2 == ['val']
422     assert cfg.val3 == ['yes']
423     assert cfg.val4 == ['val', 'yes']
424
425
426 def test_callback_multi_list():
427     val1 = StrOption('val1', "", callback=return_list, multi=True)
428     maconfig = OptionDescription('rootconfig', '', [val1])
429     cfg = Config(maconfig)
430     cfg.read_write()
431     assert cfg.val1 == ['val', 'val']
432     cfg.val1 = ['new-val']
433     assert cfg.val1 == ['new-val']
434     cfg.val1.append('new-val2')
435     assert cfg.val1 == ['new-val', 'new-val2']
436     del(cfg.val1)
437     assert cfg.val1 == ['val', 'val']
438
439
440 def test_callback_master_and_slaves_master():
441     val1 = StrOption('val1', "", multi=True, callback=return_val)
442     val2 = StrOption('val2', "", multi=True)
443     interface1 = OptionDescription('val1', '', [val1, val2])
444     interface1.impl_set_group_type(groups.master)
445     maconfig = OptionDescription('rootconfig', '', [interface1])
446     cfg = Config(maconfig)
447     cfg.read_write()
448     assert cfg.val1.val1 == ['val']
449     cfg.val1.val1.append(None)
450     assert cfg.val1.val1 == ['val', 'val']
451     assert cfg.val1.val2 == [None, None]
452
453
454 def test_callback_master_and_slaves_master_list():
455     val1 = StrOption('val1', "", multi=True, callback=return_list)
456     val2 = StrOption('val2', "", multi=True)
457     interface1 = OptionDescription('val1', '', [val1, val2])
458     interface1.impl_set_group_type(groups.master)
459     maconfig = OptionDescription('rootconfig', '', [interface1])
460     cfg = Config(maconfig)
461     cfg.read_write()
462     assert cfg.val1.val1 == ['val', 'val']
463     assert cfg.val1.val2 == [None, None]
464     cfg.val1.val1.append(None)
465     assert cfg.val1.val1 == ['val', 'val', None]
466     assert cfg.val1.val2 == [None, None, None]
467     del(cfg.val1.val1)
468     assert cfg.val1.val1 == ['val', 'val']
469     assert cfg.val1.val2 == [None, None]
470     assert cfg.val1.val1.pop(1)
471     assert cfg.val1.val1 == ['val']
472     assert cfg.val1.val2 == [None]
473
474
475 def test_callback_master_and_slaves_slave():
476     val1 = StrOption('val1', "", multi=True)
477     val2 = StrOption('val2', "", multi=True, callback=return_val)
478     interface1 = OptionDescription('val1', '', [val1, val2])
479     interface1.impl_set_group_type(groups.master)
480     maconfig = OptionDescription('rootconfig', '', [interface1])
481     cfg = Config(maconfig)
482     cfg.read_write()
483     assert cfg.val1.val1 == []
484     assert cfg.val1.val2 == []
485     #
486     cfg.val1.val1 = ['val1']
487     assert cfg.val1.val1 == ['val1']
488     assert cfg.val1.val2 == ['val']
489     #
490     cfg.val1.val1.append('val2')
491     assert cfg.val1.val1 == ['val1', 'val2']
492     assert cfg.val1.val2 == ['val', 'val']
493     #
494     cfg.val1.val1 = ['val1', 'val2', 'val3']
495     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
496     assert cfg.val1.val2 == ['val', 'val', 'val']
497     #
498     cfg.val1.val1.pop(2)
499     assert cfg.val1.val1 == ['val1', 'val2']
500     assert cfg.val1.val2 == ['val', 'val']
501     #
502     cfg.val1.val2 = ['val2', 'val2']
503     assert cfg.val1.val2 == ['val2', 'val2']
504     #
505     cfg.val1.val1.append('val3')
506     assert cfg.val1.val2 == ['val2', 'val2', 'val']
507
508
509 def test_callback_master_and_slaves_slave_list():
510     val1 = StrOption('val1', "", multi=True)
511     val2 = StrOption('val2', "", multi=True, callback=return_list)
512     interface1 = OptionDescription('val1', '', [val1, val2])
513     interface1.impl_set_group_type(groups.master)
514     maconfig = OptionDescription('rootconfig', '', [interface1])
515     cfg = Config(maconfig)
516     cfg.read_write()
517     assert cfg.val1.val2 == []
518     cfg.val1.val1 = ['val1', 'val2']
519     assert cfg.val1.val1 == ['val1', 'val2']
520     assert cfg.val1.val2 == ['val', 'val']
521     cfg.val1.val1 = ['val1']
522     #wrong len
523     raises(SlaveError, 'cfg.val1.val2')
524
525
526 def test_callback_master_and_slaves_value():
527     val1 = StrOption('val1', "", multi=True)
528     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
529     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
530     val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
531     val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
532     interface1 = OptionDescription('val1', '', [val1, val2, val3, val5])
533     interface1.impl_set_group_type(groups.master)
534     maconfig = OptionDescription('rootconfig', '', [interface1, val4])
535     cfg = Config(maconfig)
536     cfg.read_write()
537     assert cfg.val1.val1 == []
538     assert cfg.val1.val2 == []
539     assert cfg.val1.val3 == []
540     assert cfg.val1.val5 == []
541     #
542     cfg.val1.val1 = ['val1']
543     assert cfg.val1.val1 == ['val1']
544     assert cfg.val1.val2 == ['val1']
545     assert cfg.val1.val3 == ['yes']
546     assert cfg.val1.val5 == ['val10']
547     #
548     cfg.val1.val1.append('val2')
549     assert cfg.val1.val1 == ['val1', 'val2']
550     assert cfg.val1.val2 == ['val1', 'val2']
551     assert cfg.val1.val3 == ['yes', 'yes']
552     assert cfg.val1.val5 == ['val10', 'val11']
553     #
554     cfg.val1.val1 = ['val1', 'val2', 'val3']
555     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
556     assert cfg.val1.val2 == ['val1', 'val2', 'val3']
557     assert cfg.val1.val3 == ['yes', 'yes', 'yes']
558     assert cfg.val1.val5 == ['val10', 'val11', None]
559     #
560     cfg.val1.val1.pop(2)
561     assert cfg.val1.val1 == ['val1', 'val2']
562     assert cfg.val1.val2 == ['val1', 'val2']
563     assert cfg.val1.val3 == ['yes', 'yes']
564     assert cfg.val1.val5 == ['val10', 'val11']
565     #
566     cfg.val1.val2 = ['val2', 'val2']
567     cfg.val1.val3 = ['val2', 'val2']
568     cfg.val1.val5 = ['val2', 'val2']
569     assert cfg.val1.val2 == ['val2', 'val2']
570     assert cfg.val1.val3 == ['val2', 'val2']
571     assert cfg.val1.val5 == ['val2', 'val2']
572     #
573     cfg.val1.val1.append('val3')
574     assert cfg.val1.val2 == ['val2', 'val2', 'val3']
575     assert cfg.val1.val3 == ['val2', 'val2', 'yes']
576     assert cfg.val1.val5 == ['val2', 'val2', None]
577     cfg.cfgimpl_get_settings().remove('cache')
578     cfg.val4 = ['val10', 'val11', 'val12']
579     #if value is already set, not updated !
580     cfg.val1.val1.pop(2)
581     cfg.val1.val1.append('val3')
582     cfg.val1.val1 = ['val1', 'val2', 'val3']
583     assert cfg.val1.val5 == ['val2', 'val2', 'val12']
584
585
586 def test_callback_hidden():
587     opt1 = BoolOption('opt1', '')
588     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
589     od1 = OptionDescription('od1', '', [opt1], properties=('hidden',))
590     od2 = OptionDescription('od2', '', [opt2])
591     maconfig = OptionDescription('rootconfig', '', [od1, od2])
592     cfg = Config(maconfig)
593     cfg.cfgimpl_get_settings().setpermissive(('hidden',))
594     cfg.read_write()
595     raises(PropertiesOptionError, 'cfg.od1.opt1')
596     cfg.od2.opt2
597
598
599 def test_callback_two_disabled():
600     opt1 = BoolOption('opt1', '', properties=('disabled',))
601     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',))
602     od1 = OptionDescription('od1', '', [opt1])
603     od2 = OptionDescription('od2', '', [opt2])
604     maconfig = OptionDescription('rootconfig', '', [od1, od2])
605     cfg = Config(maconfig)
606     cfg.read_write()
607     raises(PropertiesOptionError, 'cfg.od2.opt2')
608
609
610 def test_callback_calculating_disabled():
611     opt1 = BoolOption('opt1', '', properties=('disabled',))
612     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
613     od1 = OptionDescription('od1', '', [opt1])
614     od2 = OptionDescription('od2', '', [opt2])
615     maconfig = OptionDescription('rootconfig', '', [od1, od2])
616     cfg = Config(maconfig)
617     cfg.read_write()
618     raises(ConfigError, 'cfg.od2.opt2')
619
620
621 def test_callback_calculating_mandatory():
622     opt1 = BoolOption('opt1', '', properties=('disabled',))
623     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
624     od1 = OptionDescription('od1', '', [opt1])
625     od2 = OptionDescription('od2', '', [opt2])
626     maconfig = OptionDescription('rootconfig', '', [od1, od2])
627     cfg = Config(maconfig)
628     cfg.read_only()
629     raises(ConfigError, 'cfg.od2.opt2')
630
631
632 def test_callback_two_disabled_multi():
633     opt1 = BoolOption('opt1', '', properties=('disabled',))
634     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',), multi=True)
635     od1 = OptionDescription('od1', '', [opt1])
636     od2 = OptionDescription('od2', '', [opt2])
637     maconfig = OptionDescription('rootconfig', '', [od1, od2])
638     cfg = Config(maconfig)
639     cfg.read_write()
640     raises(PropertiesOptionError, 'cfg.od2.opt2')
641
642
643 def test_callback_multi_list_params():
644     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
645     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'': ((val1, False),)})
646     oval2 = OptionDescription('val2', '', [val2])
647     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
648     cfg = Config(maconfig)
649     cfg.read_write()
650     assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
651
652
653 def test_callback_multi_list_params_key():
654     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
655     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'value': ((val1, False),)})
656     oval2 = OptionDescription('val2', '', [val2])
657     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
658     cfg = Config(maconfig)
659     cfg.read_write()
660     assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
661
662
663 def test_callback_multi_multi():
664     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2', 'val3'])
665     val2 = StrOption('val2', "", multi=True, default=['val11', 'val12'])
666     val3 = StrOption('val3', "", default='val4')
667     val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val2, False))})
668     val5 = StrOption('val5', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val3, False))})
669     val6 = StrOption('val6', "", multi=True, default=['val21', 'val22', 'val23'])
670     val7 = StrOption('val7', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val6, False))})
671     raises(ValueError, "StrOption('val8', '', multi=True, callback=return_list2, callback_params={'value': ((val1, False), (val6, False))})")
672     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5, val6, val7])
673     cfg = Config(maconfig)
674     cfg.read_write()
675     raises(ConfigError, "cfg.val4")
676     assert cfg.val5 == ['val1', 'val4', 'val2', 'val4', 'val3', 'val4']
677     assert cfg.val7 == ['val1', 'val21', 'val2', 'val22', 'val3', 'val23']