in find_firsts get option only one time
[tiramisu.git] / test / test_dyn_optiondescription.py
1 # coding: utf-8
2 import autopath
3
4 from tiramisu.setting import groups, owners
5 from tiramisu.option import BoolOption, StrOption, ChoiceOption, IPOption, \
6     NetworkOption, NetmaskOption, IntOption, FloatOption, \
7     UnicodeOption, PortOption, BroadcastOption, DomainnameOption, \
8     EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \
9     OptionDescription, DynOptionDescription, DynSymLinkOption, submulti
10 from tiramisu.config import Config
11 from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
12 from tiramisu.storage import delete_session
13 from test.test_state import _diff_opts, _diff_conf
14
15 from py.test import raises
16 from pickle import dumps, loads
17
18
19 def return_true(value, param=None):
20     if value == 'val' and param in [None, 'yes']:
21         return
22     raise ValueError('no value')
23
24
25 def return_dynval(suffix, value='val'):
26     return value
27
28
29 def return_list2(suffix):
30     return [str(suffix), 'val2']
31
32
33 def return_list(val=None):
34     if val:
35         return val
36     else:
37         return ['val1', 'val2']
38
39
40 def return_same_list():
41     return ['val1', 'val1']
42
43
44 def return_wrong_list():
45     return ['---', ' ']
46
47
48 def test_build_dyndescription():
49     st = StrOption('st', '')
50     dod = DynOptionDescription('dod', '', [st], callback=return_list)
51     od = OptionDescription('od', '', [dod])
52     cfg = Config(od)
53     assert str(cfg) == """[dodval1]
54 [dodval2]"""
55     assert str(cfg.dodval1) == "stval1 = None"
56     assert str(cfg.dodval2) == "stval2 = None"
57
58
59 def test_subpath_dyndescription():
60     st = StrOption('st', '')
61     dod = DynOptionDescription('dod', '', [st], callback=return_list)
62     od = OptionDescription('od', '', [dod])
63     od2 = OptionDescription('od', '', [od])
64     cfg = Config(od2)
65     assert str(cfg) == "[od]"
66     assert str(cfg.od) == """[dodval1]
67 [dodval2]"""
68     assert str(cfg.od.dodval1) == "stval1 = None"
69     assert str(cfg.od.dodval2) == "stval2 = None"
70
71
72 def test_list_dyndescription():
73     st = StrOption('st', '')
74     dod = DynOptionDescription('dod', '', [st], callback=return_list)
75     od = OptionDescription('od', '', [dod])
76     od2 = OptionDescription('od', '', [od])
77     cfg = Config(od2)
78     assert cfg.od.dodval1.stval1 is None
79     assert cfg.od.dodval2.stval2 is None
80
81
82 def test_unknown_dyndescription():
83     st = StrOption('st', '')
84     dod = DynOptionDescription('dod', '', [st], callback=return_list)
85     od = OptionDescription('od', '', [dod])
86     od2 = OptionDescription('od', '', [od])
87     cfg = Config(od2)
88     raises(AttributeError, "cfg.od.dodval3")
89     raises(AttributeError, "cfg.od.dodval1.novalue")
90
91
92 def test_getdoc_dyndescription():
93     st = StrOption('st', 'doc1')
94     dod = DynOptionDescription('dod', 'doc2', [st], callback=return_list)
95     od = OptionDescription('od', '', [dod])
96     od2 = OptionDescription('od', '', [od])
97     cfg = Config(od2)
98     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
99     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
100     dodval1 = cfg.unwrap_from_path('od.dodval1')
101     dodval2 = cfg.unwrap_from_path('od.dodval2')
102     assert stval1.impl_getname() == 'stval1'
103     assert stval2.impl_getname() == 'stval2'
104     assert dodval1.impl_getname() == 'dodval1'
105     assert dodval2.impl_getname() == 'dodval2'
106     assert stval1.impl_getdoc() == 'doc1'
107     assert stval2.impl_getdoc() == 'doc1'
108     assert dodval1.impl_getdoc() == 'doc2'
109     assert dodval2.impl_getdoc() == 'doc2'
110
111
112 def test_getpaths_dyndescription():
113     st = StrOption('st', '')
114     dod = DynOptionDescription('dod', '', [st], callback=return_list)
115     od = OptionDescription('od', '', [dod])
116     od2 = OptionDescription('od', '', [od])
117     cfg = Config(od2)
118     assert cfg.cfgimpl_get_description().impl_getpaths() == ['od.dodval1.stval1', 'od.dodval2.stval2']
119     assert cfg.cfgimpl_get_description().impl_getpaths(include_groups=True) == ['od', 'od.dodval1', 'od.dodval1.stval1', 'od.dodval2', 'od.dodval2.stval2']
120
121
122 def test_mod_dyndescription():
123     st = StrOption('st', '')
124     dod = DynOptionDescription('dod', '', [st], callback=return_list)
125     od = OptionDescription('od', '', [dod])
126     od2 = OptionDescription('od', '', [od])
127     cfg = Config(od2)
128     owner = cfg.cfgimpl_get_settings().getowner()
129     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
130     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
131     assert cfg.od.dodval1.stval1 is None
132     assert cfg.od.dodval2.stval2 is None
133     assert cfg.getowner(stval1) == owners.default
134     assert cfg.getowner(stval2) == owners.default
135     cfg.od.dodval1.stval1 = 'yes'
136     assert cfg.od.dodval1.stval1 == 'yes'
137     assert cfg.od.dodval2.stval2 is None
138     assert cfg.getowner(stval1) == owner
139     assert cfg.getowner(stval2) == owners.default
140     cfg.od.dodval2.stval2 = 'no'
141     assert cfg.od.dodval1.stval1 == 'yes'
142     assert cfg.od.dodval2.stval2 == 'no'
143     assert cfg.getowner(st) == owners.default
144     assert cfg.getowner(stval1) == owner
145     assert cfg.getowner(stval2) == owner
146
147
148 def test_del_dyndescription():
149     st = StrOption('st', '')
150     dod = DynOptionDescription('dod', '', [st], callback=return_list)
151     od = OptionDescription('od', '', [dod])
152     od2 = OptionDescription('od', '', [od])
153     cfg = Config(od2)
154     owner = cfg.cfgimpl_get_settings().getowner()
155     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
156     assert cfg.od.dodval1.stval1 is None
157     assert cfg.od.dodval2.stval2 is None
158     cfg.od.dodval1.stval1 = 'yes'
159     assert cfg.getowner(stval1) == owner
160     del(cfg.od.dodval1.stval1)
161     assert cfg.getowner(stval1) == owners.default
162
163
164 def test_multi_dyndescription():
165     st = StrOption('st', '', multi=True)
166     dod = DynOptionDescription('dod', '', [st], callback=return_list)
167     od = OptionDescription('od', '', [dod])
168     od2 = OptionDescription('od', '', [od])
169     cfg = Config(od2)
170     owner = cfg.cfgimpl_get_settings().getowner()
171     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
172     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
173     assert cfg.od.dodval1.stval1 == []
174     assert cfg.od.dodval2.stval2 == []
175     assert cfg.getowner(stval1) == owners.default
176     assert cfg.getowner(stval2) == owners.default
177     cfg.od.dodval1.stval1.append('yes')
178     assert cfg.od.dodval1.stval1 == ['yes']
179     assert cfg.od.dodval2.stval2 == []
180     assert cfg.getowner(stval1) == owner
181     assert cfg.getowner(stval2) == owners.default
182     cfg.od.dodval2.stval2 = ['no']
183     assert cfg.od.dodval1.stval1 == ['yes']
184     assert cfg.od.dodval2.stval2 == ['no']
185     assert cfg.getowner(st) == owners.default
186     assert cfg.getowner(stval1) == owner
187     assert cfg.getowner(stval2) == owner
188     cfg.od.dodval1.stval1.append('yes')
189     assert cfg.od.dodval1.stval1 == ['yes', 'yes']
190     cfg.od.dodval1.stval1.pop(0)
191     assert cfg.od.dodval1.stval1 == ['yes']
192
193
194 def test_prop_dyndescription():
195     st = StrOption('st', '', properties=('test',))
196     dod = DynOptionDescription('dod', '', [st], callback=return_list)
197     od = OptionDescription('od', '', [dod])
198     od2 = OptionDescription('od', '', [od])
199     cfg = Config(od2)
200     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
201     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
202     dodval1 = cfg.unwrap_from_path('od.dodval1')
203     dodval2 = cfg.unwrap_from_path('od.dodval2')
204     assert str(cfg.cfgimpl_get_settings()[stval1]) in [str(['test']), str([u'test'])]
205     assert str(cfg.cfgimpl_get_settings()[stval2]) in [str(['test']), str([u'test'])]
206     cfg.cfgimpl_get_settings()[stval2].append('test2')
207     assert str(cfg.cfgimpl_get_settings()[stval1]) in [str(['test']), str([u'test'])]
208     assert str(cfg.cfgimpl_get_settings()[stval2]) in [str(['test', 'test2']), str([u'test', 'test2'])]
209     cfg.cfgimpl_get_settings()[stval1].remove('test')
210     assert str(cfg.cfgimpl_get_settings()[stval1]) == str([])
211     #
212     assert str(cfg.cfgimpl_get_settings()[dodval1]) == str([])
213     assert str(cfg.cfgimpl_get_settings()[dodval2]) == str([])
214     cfg.cfgimpl_get_settings()[dodval1].append('test1')
215     assert str(cfg.cfgimpl_get_settings()[dodval1]) in [str(['test1']), str([u'test1'])]
216     assert str(cfg.cfgimpl_get_settings()[dodval2]) == str([])
217     cfg.cfgimpl_get_settings()[dodval1].remove('test1')
218     assert str(cfg.cfgimpl_get_settings()[dodval1]) == str([])
219     assert str(cfg.cfgimpl_get_settings()[dodval2]) == str([])
220
221
222 def test_callback_dyndescription():
223     st = StrOption('st', '', callback=return_dynval)
224     dod = DynOptionDescription('dod', '', [st], callback=return_list)
225     od = OptionDescription('od', '', [dod])
226     od2 = OptionDescription('od', '', [od])
227     cfg = Config(od2)
228     owner = cfg.cfgimpl_get_settings().getowner()
229     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
230     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
231     assert cfg.od.dodval1.stval1 == 'val'
232     assert cfg.od.dodval2.stval2 == 'val'
233     assert cfg.getowner(stval1) == owners.default
234     assert cfg.getowner(stval2) == owners.default
235     cfg.od.dodval1.stval1 = 'val2'
236     assert cfg.od.dodval1.stval1 == 'val2'
237     assert cfg.od.dodval2.stval2 == 'val'
238     assert cfg.getowner(stval1) == owner
239     assert cfg.getowner(stval2) == owners.default
240     del(cfg.od.dodval1.stval1)
241     assert cfg.od.dodval1.stval1 == 'val'
242     assert cfg.od.dodval2.stval2 == 'val'
243     assert cfg.getowner(stval1) == owners.default
244     assert cfg.getowner(stval2) == owners.default
245
246
247 def test_callback_list_dyndescription():
248     st = StrOption('st', '', callback=return_list2, multi=True)
249     dod = DynOptionDescription('dod', '', [st], callback=return_list)
250     od = OptionDescription('od', '', [dod])
251     od2 = OptionDescription('od', '', [od])
252     cfg = Config(od2)
253     owner = cfg.cfgimpl_get_settings().getowner()
254     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
255     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
256     assert cfg.od.dodval1.stval1 == ['val1', 'val2']
257     assert cfg.od.dodval2.stval2 == ['val2', 'val2']
258     assert cfg.getowner(stval1) == owners.default
259     assert cfg.getowner(stval2) == owners.default
260     cfg.od.dodval1.stval1 = ['val3', 'val2']
261     assert cfg.od.dodval1.stval1 == ['val3', 'val2']
262     assert cfg.od.dodval2.stval2 == ['val2', 'val2']
263     assert cfg.getowner(stval1) == owner
264     assert cfg.getowner(stval2) == owners.default
265
266
267 def test_mandatory_dyndescription():
268     st = StrOption('st', '', properties=('mandatory',))
269     dod = DynOptionDescription('dod', '', [st], callback=return_list)
270     od = OptionDescription('od', '', [dod])
271     od2 = OptionDescription('od', '', [od])
272     cfg = Config(od2)
273     cfg.read_only()
274     raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
275     raises(PropertiesOptionError, "cfg.od.dodval2.stval2")
276     cfg.read_write()
277     cfg.od.dodval1.stval1 = 'val'
278     cfg.read_only()
279     assert cfg.od.dodval1.stval1 == 'val'
280     raises(PropertiesOptionError, "cfg.od.dodval2.stval2")
281     cfg.read_write()
282     del(cfg.od.dodval1.stval1)
283     cfg.read_only()
284     raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
285     assert cfg.cfgimpl_get_values().mandatory_warnings() == ['od.dodval1.stval1', 'od.dodval2.stval2']
286
287
288 def test_build_dyndescription_context():
289     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
290     st = StrOption('st', '')
291     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
292     od = OptionDescription('od', '', [dod, val1])
293     cfg = Config(od)
294     cfg._impl_test = True
295     assert str(cfg) == """[dodval1]
296 [dodval2]
297 val1 = ['val1', 'val2']"""
298     assert str(cfg.dodval1) == "stval1 = None"
299     assert str(cfg.dodval2) == "stval2 = None"
300     cfg.unwrap_from_path('dodval2')
301
302
303 def test_subpath_dyndescription_context():
304     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
305     st = StrOption('st', '')
306     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
307     od = OptionDescription('od', '', [dod, val1])
308     od2 = OptionDescription('od', '', [od])
309     cfg = Config(od2)
310     assert str(cfg) == "[od]"
311     assert str(cfg.od) == """[dodval1]
312 [dodval2]
313 val1 = ['val1', 'val2']"""
314     assert str(cfg.od.dodval1) == "stval1 = None"
315     assert str(cfg.od.dodval2) == "stval2 = None"
316
317
318 def test_list_dyndescription_context():
319     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
320     st = StrOption('st', '')
321     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
322     od = OptionDescription('od', '', [dod, val1])
323     od2 = OptionDescription('od', '', [od])
324     cfg = Config(od2)
325     assert cfg.od.dodval1.stval1 is None
326     assert cfg.od.dodval2.stval2 is None
327     raises(AttributeError, "cfg.od.dodval3")
328
329
330 def test_mod_dyndescription_context():
331     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
332     st = StrOption('st', '')
333     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
334     od = OptionDescription('od', '', [dod, val1])
335     od2 = OptionDescription('od', '', [od])
336     cfg = Config(od2)
337     owner = cfg.cfgimpl_get_settings().getowner()
338     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
339     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
340     assert cfg.od.dodval1.stval1 is None
341     assert cfg.od.dodval2.stval2 is None
342     assert cfg.getowner(stval1) == owners.default
343     assert cfg.getowner(stval2) == owners.default
344     cfg.od.dodval1.stval1 = 'yes'
345     assert cfg.od.dodval1.stval1 == 'yes'
346     assert cfg.od.dodval2.stval2 is None
347     assert cfg.getowner(stval1) == owner
348     assert cfg.getowner(stval2) == owners.default
349     cfg.od.dodval2.stval2 = 'no'
350     assert cfg.od.dodval1.stval1 == 'yes'
351     assert cfg.od.dodval2.stval2 == 'no'
352     assert cfg.getowner(st) == owners.default
353     assert cfg.getowner(stval1) == owner
354     assert cfg.getowner(stval2) == owner
355
356
357 def test_del_dyndescription_context():
358     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
359     st = StrOption('st', '')
360     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
361     od = OptionDescription('od', '', [dod, val1])
362     od2 = OptionDescription('od', '', [od])
363     cfg = Config(od2)
364     owner = cfg.cfgimpl_get_settings().getowner()
365     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
366     assert cfg.od.dodval1.stval1 is None
367     assert cfg.od.dodval2.stval2 is None
368     cfg.od.dodval1.stval1 = 'yes'
369     assert cfg.getowner(stval1) == owner
370     del(cfg.od.dodval1.stval1)
371     assert cfg.getowner(stval1) == owners.default
372
373
374 def test_multi_dyndescription_context():
375     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
376     st = StrOption('st', '', multi=True)
377     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
378     od = OptionDescription('od', '', [dod, val1])
379     od2 = OptionDescription('od', '', [od])
380     cfg = Config(od2)
381     owner = cfg.cfgimpl_get_settings().getowner()
382     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
383     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
384     assert cfg.od.dodval1.stval1 == []
385     assert cfg.od.dodval2.stval2 == []
386     assert cfg.getowner(stval1) == owners.default
387     assert cfg.getowner(stval2) == owners.default
388     cfg.od.dodval1.stval1.append('yes')
389     assert cfg.od.dodval1.stval1 == ['yes']
390     assert cfg.od.dodval2.stval2 == []
391     assert cfg.getowner(stval1) == owner
392     assert cfg.getowner(stval2) == owners.default
393     cfg.od.dodval2.stval2 = ['no']
394     assert cfg.od.dodval1.stval1 == ['yes']
395     assert cfg.od.dodval2.stval2 == ['no']
396     assert cfg.getowner(st) == owners.default
397     assert cfg.getowner(stval1) == owner
398     assert cfg.getowner(stval2) == owner
399     cfg.od.dodval1.stval1.append('yes')
400     assert cfg.od.dodval1.stval1 == ['yes', 'yes']
401     cfg.od.dodval1.stval1.pop(0)
402     assert cfg.od.dodval1.stval1 == ['yes']
403
404
405 def test_prop_dyndescription_context():
406     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
407     st = StrOption('st', '', properties=('test',))
408     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
409     od = OptionDescription('od', '', [dod, val1])
410     od2 = OptionDescription('od', '', [od])
411     cfg = Config(od2)
412     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
413     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
414     assert str(cfg.cfgimpl_get_settings()[stval1]) in [str(['test']), str([u'test'])]
415     assert str(cfg.cfgimpl_get_settings()[stval2]) in [str(['test']), str([u'test'])]
416     cfg.cfgimpl_get_settings()[stval2].append('test2')
417     assert str(cfg.cfgimpl_get_settings()[stval1]) in [str(['test']), str([u'test'])]
418     assert str(cfg.cfgimpl_get_settings()[stval2]) in [str(['test', 'test2']), str([u'test', 'test2'])]
419     cfg.cfgimpl_get_settings()[stval1].remove('test')
420     assert str(cfg.cfgimpl_get_settings()[stval1]) == str([])
421
422
423 def test_callback_dyndescription_context():
424     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
425     st = StrOption('st', '', callback=return_dynval)
426     dod = DynOptionDescription('dod', '', [st], callback=return_list)
427     od = OptionDescription('od', '', [dod, val1])
428     od2 = OptionDescription('od', '', [od])
429     cfg = Config(od2)
430     owner = cfg.cfgimpl_get_settings().getowner()
431     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
432     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
433     assert cfg.od.dodval1.stval1 == 'val'
434     assert cfg.od.dodval2.stval2 == 'val'
435     assert cfg.getowner(stval1) == owners.default
436     assert cfg.getowner(stval2) == owners.default
437     cfg.od.dodval1.stval1 = 'val2'
438     assert cfg.od.dodval1.stval1 == 'val2'
439     assert cfg.od.dodval2.stval2 == 'val'
440     assert cfg.getowner(stval1) == owner
441     assert cfg.getowner(stval2) == owners.default
442     del(cfg.od.dodval1.stval1)
443     assert cfg.od.dodval1.stval1 == 'val'
444     assert cfg.od.dodval2.stval2 == 'val'
445     assert cfg.getowner(stval1) == owners.default
446     assert cfg.getowner(stval2) == owners.default
447
448
449 def test_mandatory_dyndescription_context():
450     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
451     st = StrOption('st', '', properties=('mandatory',))
452     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
453     od = OptionDescription('od', '', [dod, val1])
454     od2 = OptionDescription('od', '', [od])
455     cfg = Config(od2)
456     cfg.read_only()
457     raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
458     raises(PropertiesOptionError, "cfg.od.dodval2.stval2")
459     cfg.read_write()
460     cfg.od.dodval1.stval1 = 'val'
461     cfg.read_only()
462     assert cfg.od.dodval1.stval1 == 'val'
463     raises(PropertiesOptionError, "cfg.od.dodval2.stval2")
464     cfg.read_write()
465     del(cfg.od.dodval1.stval1)
466     cfg.read_only()
467     raises(PropertiesOptionError, "cfg.od.dodval1.stval1")
468     assert cfg.cfgimpl_get_values().mandatory_warnings() == ['od.dodval1.stval1', 'od.dodval2.stval2']
469
470
471 def test_increase_dyndescription_context():
472     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
473     st = StrOption('st', '', properties=('mandatory',))
474     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
475     od = OptionDescription('od', '', [dod, val1])
476     od2 = OptionDescription('od', '', [od])
477     cfg = Config(od2)
478     cfg.read_write()
479     assert cfg.od.dodval1.stval1 is None
480     assert cfg.od.dodval2.stval2 is None
481     raises(AttributeError, "cfg.od.dodval3")
482     cfg.od.val1 = ['val1', 'val2', 'val3']
483     assert cfg.od.dodval1.stval1 is None
484     assert cfg.od.dodval2.stval2 is None
485     assert cfg.od.dodval3.stval3 is None
486
487
488 def test_decrease_dyndescription_context():
489     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
490     st = StrOption('st', '', properties=('mandatory',))
491     dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)})
492     od = OptionDescription('od', '', [dod, val1])
493     od2 = OptionDescription('od', '', [od])
494     cfg = Config(od2)
495     owner = cfg.cfgimpl_get_settings().getowner()
496     stval1 = cfg.unwrap_from_path('od.dodval1.stval1')
497     stval2 = cfg.unwrap_from_path('od.dodval2.stval2')
498     cfg.read_write()
499     assert cfg.od.dodval1.stval1 is None
500     assert cfg.od.dodval2.stval2 is None
501     cfg.od.dodval2.stval2 = 'yes'
502     assert cfg.od.dodval1.stval1 is None
503     assert cfg.od.dodval2.stval2 == 'yes'
504     assert cfg.getowner(stval1) == owners.default
505     assert cfg.getowner(stval2) == owner
506     raises(AttributeError, "cfg.od.dodval3")
507     cfg.od.val1 = ['val1']
508     assert cfg.od.dodval1.stval1 is None
509     raises(AttributeError, "cfg.od.dodval2")
510     raises(AttributeError, "cfg.od.dodval3")
511     assert cfg.getowner(stval1) == owners.default
512     #FIXME
513 #    raises(AttributeError, "cfg.getowner(stval2)")
514     raises(AttributeError, "cfg.unwrap_from_path('od.dodval2.stval2')")
515
516
517 def test_requires_dyndescription():
518     boolean = BoolOption('boolean', '', True)
519     st = StrOption('st', '', requires=[{'option': boolean, 'expected': False,
520                                         'action': 'disabled'}])
521     dod = DynOptionDescription('dod', '', [st], callback=return_list)
522     od = OptionDescription('od', '', [dod])
523     od2 = OptionDescription('od', '', [od, boolean])
524     cfg = Config(od2)
525     cfg.read_write()
526     assert cfg.od.dodval1.stval1 is None
527     assert cfg.od.dodval2.stval2 is None
528     #
529     cfg.boolean = False
530     props = []
531     try:
532         cfg.od.dodval1.stval1
533     except PropertiesOptionError as err:
534         props = err.proptype
535     assert props == ['disabled']
536     props = []
537     try:
538         cfg.od.dodval2.stval2
539     except PropertiesOptionError as err:
540         props = err.proptype
541     assert props == ['disabled']
542     #
543     cfg.boolean = True
544     assert cfg.od.dodval1.stval1 is None
545     assert cfg.od.dodval2.stval2 is None
546     #transitive
547     cfg.cfgimpl_get_settings()[boolean].append('disabled')
548     props = []
549     try:
550         cfg.od.dodval1.stval1
551     except PropertiesOptionError as err:
552         props = err.proptype
553     assert props == ['disabled']
554     props = []
555     try:
556         cfg.od.dodval2.stval2
557     except PropertiesOptionError as err:
558         props = err.proptype
559     assert props == ['disabled']
560
561
562 def test_requires_dyndescription2():
563     boolean = BoolOption('boolean', '', True)
564     st = StrOption('st', '')
565     dod = DynOptionDescription('dod', '', [st], callback=return_list,
566                                requires=[{'option': boolean, 'expected': False,
567                                           'action': 'disabled'}])
568     od = OptionDescription('od', '', [dod])
569     od2 = OptionDescription('od', '', [od, boolean])
570     cfg = Config(od2)
571     cfg.read_write()
572     assert cfg.od.dodval1.stval1 is None
573     assert cfg.od.dodval2.stval2 is None
574     #
575     cfg.boolean = False
576     props = []
577     try:
578         cfg.od.dodval1.stval1
579     except PropertiesOptionError as err:
580         props = err.proptype
581     assert props == ['disabled']
582     props = []
583     try:
584         cfg.od.dodval2.stval2
585     except PropertiesOptionError as err:
586         props = err.proptype
587     assert props == ['disabled']
588     #
589     cfg.boolean = True
590     assert cfg.od.dodval1.stval1 is None
591     assert cfg.od.dodval2.stval2 is None
592     #transitive
593     cfg.cfgimpl_get_settings()[boolean].append('disabled')
594     props = []
595     try:
596         cfg.od.dodval1.stval1
597     except PropertiesOptionError as err:
598         props = err.proptype
599     assert props == ['disabled']
600     props = []
601     try:
602         cfg.od.dodval2.stval2
603     except PropertiesOptionError as err:
604         props = err.proptype
605     assert props == ['disabled']
606
607
608 def test_validator_dyndescription():
609     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
610     st = StrOption('st', '', validator=return_true, validator_params={'': ('yes',)}, default='val')
611     dod = DynOptionDescription('dod', '', [st], callback=return_list)
612     od = OptionDescription('od', '', [dod, val1])
613     od2 = OptionDescription('od', '', [od])
614     cfg = Config(od2)
615     assert cfg.od.dodval1.stval1 == 'val'
616     raises(ValueError, "cfg.od.dodval1.stval1 = 'no'")
617     cfg.od.dodval1.stval1 = 'val'
618
619
620 def test_makedict_dyndescription_context():
621     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
622     st = StrOption('st', '')
623     dod = DynOptionDescription('dod', '', [st], callback=return_list)
624     od = OptionDescription('od', '', [dod, val1])
625     od2 = OptionDescription('od', '', [od])
626     cfg = Config(od2)
627     cfg.od.dodval1.stval1 = 'yes'
628     assert cfg.make_dict() == {'od.val1': ['val1', 'val2'], 'od.dodval1.stval1': 'yes', 'od.dodval2.stval2': None}
629     assert cfg.make_dict(flatten=True) == {'val1': ['val1', 'val2'], 'stval1': 'yes', 'stval2': None}
630     assert cfg.make_dict(withoption='stval1') == {'od.dodval1.stval1': 'yes'}
631     assert cfg.od.make_dict(withoption='stval1') == {'dodval1.stval1': 'yes'}
632     assert cfg.od.dodval1.make_dict(withoption='stval1') == {'stval1': 'yes'}
633
634
635 def test_find_dyndescription_context():
636     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
637     st = StrOption('st', '')
638     dod = DynOptionDescription('dod', '', [st], callback=return_list)
639     od = OptionDescription('od', '', [dod, val1])
640     od2 = OptionDescription('od', '', [od])
641     cfg = Config(od2)
642     cfg.od.dodval1.stval1 = 'yes'
643     assert cfg.find_first(byname='stval1', type_='value') == "yes"
644     assert isinstance(cfg.find_first(byname='stval1', type_='option'), DynSymLinkOption)
645     assert cfg.find(bytype=StrOption, type_='path') == ['od.dodval1.stval1', 'od.dodval2.stval2', 'od.val1']
646     opts = cfg.find(byvalue='yes')
647     assert len(opts) == 1
648     assert isinstance(opts[0], DynSymLinkOption)
649     assert opts[0].impl_getname() == 'stval1'
650
651
652 def test_iter_all_dyndescription_context():
653     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
654     st = StrOption('st', '')
655     dod = DynOptionDescription('dod', '', [st], callback=return_list)
656     od = OptionDescription('od', '', [dod, val1])
657     od2 = OptionDescription('od', '', [od])
658     cfg = Config(od2)
659     for it in cfg.iter_all():
660         assert it[0] == 'od'
661         assert str(it[1]) == str(cfg.od)
662     #
663     list_od = []
664     for it in cfg.od.iter_all():
665         list_od.append(it[0])
666     assert list_od == ['dodval1', 'dodval2', 'val1']
667     #
668     list_od = []
669     for it in cfg.od.dodval1:
670         list_od.append(it[0])
671     assert list_od == ['stval1']
672
673
674 def test_information_dyndescription_context():
675     val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
676     st = StrOption('st', '')
677     dod = DynOptionDescription('dod', '', [st], callback=return_list)
678     od = OptionDescription('od', '', [dod, val1])
679     od2 = OptionDescription('od', '', [od])
680     dod.impl_set_information('testod', 'val1')
681     st.impl_set_information('testst', 'val2')
682     cfg = Config(od2)
683     cfg.impl_set_information('testcfgod', 'val3')
684     assert dod.impl_get_information('testod') == 'val1'
685     assert st.impl_get_information('testst') == 'val2'
686     assert cfg.impl_get_information('testcfgod') == 'val3'
687
688
689 def test_consistency_dyndescription():
690     st = StrOption('st', '')
691     st2 = StrOption('st2', '')
692     dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
693     od = OptionDescription('od', '', [dod])
694     st.impl_add_consistency('not_equal', st2)
695     od2 = OptionDescription('od', '', [od])
696     cfg = Config(od2)
697     cfg.od.dodval1.stval1 = 'yes'
698     raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'")
699     cfg.od.dodval2.stval2 = 'yes'
700     raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'")
701     raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'")
702     del(cfg.od.dodval2.stval2)
703     raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'")
704     cfg.od.dodval2.st2val2 = 'yes'
705     raises(ValueError, "cfg.od.dodval2.stval2 = 'yes'")
706
707
708 def test_consistency_external_dyndescription():
709     st = StrOption('st', '')
710     st1 = StrOption('st1', '')
711     st2 = StrOption('st2', '')
712     dod = DynOptionDescription('dod', '', [st1, st2], callback=return_list)
713     od = OptionDescription('od', '', [dod, st])
714     raises(ConfigError, "st.impl_add_consistency('not_equal', st2)")
715
716
717 def test_consistency_notsame_dyndescription():
718     st1 = StrOption('st1', '')
719     st2 = StrOption('st2', '')
720     dod = DynOptionDescription('dod', '', [st1, st2], callback=return_list)
721     tst1 = StrOption('tst1', '')
722     tst2 = StrOption('tst2', '')
723     tdod = DynOptionDescription('tdod', '', [tst1, tst2], callback=return_list)
724     od = OptionDescription('od', '', [dod, tdod])
725     raises(ConfigError, "st1.impl_add_consistency('not_equal', tst1)")
726
727
728 def test_all_dyndescription():
729     st = StrOption('st', '')
730     ip = IPOption('ip', '')
731     network = NetworkOption('network', '')
732     netmask = NetmaskOption('netmask', '')
733     ch = ChoiceOption('ch', '', ('val1', 'val2', 'val3'))
734     ch1 = ChoiceOption('ch1', '', return_list)
735     boo = BoolOption('boo', '')
736     intr = IntOption('intr', '')
737     floa = FloatOption('floa', '')
738     uni = UnicodeOption('uni', '')
739     port = PortOption('port', '')
740     broad = BroadcastOption('broad', '')
741     domain = DomainnameOption('domain', '')
742     email = EmailOption('email', '')
743     url = URLOption('url', '')
744     username = UsernameOption('username', '')
745     filename = FilenameOption('filename', '')
746     dod = DynOptionDescription('dod', '', [st, ip, network, netmask, ch, ch1,
747                                            boo, intr, floa, uni, port, broad,
748                                            domain, email, url, username,
749                                            filename], callback=return_list)
750     od = OptionDescription('od', '', [dod])
751     cfg = Config(od)
752     assert cfg.dodval1.stval1 is None
753     assert cfg.dodval1.ipval1 is None
754     assert cfg.dodval1.networkval1 is None
755     assert cfg.dodval1.netmaskval1 is None
756     assert cfg.dodval1.chval1 is None
757     assert cfg.dodval1.ch1val1 is None
758     assert cfg.dodval1.booval1 is None
759     assert cfg.dodval1.intrval1 is None
760     assert cfg.dodval1.floaval1 is None
761     assert cfg.dodval1.unival1 is None
762     assert cfg.dodval1.portval1 is None
763     assert cfg.dodval1.broadval1 is None
764     assert cfg.dodval1.domainval1 is None
765     assert cfg.dodval1.emailval1 is None
766     assert cfg.dodval1.urlval1 is None
767     assert cfg.dodval1.usernameval1 is None
768     assert cfg.dodval1.filenameval1 is None
769     #
770     cfg.dodval1.stval1 = "no"
771     cfg.dodval1.ipval1 = "1.1.1.1"
772     cfg.dodval1.networkval1 = "1.1.1.0"
773     cfg.dodval1.netmaskval1 = "255.255.255.0"
774     cfg.dodval1.chval1 = "val1"
775     cfg.dodval1.ch1val1 = "val2"
776     cfg.dodval1.booval1 = True
777     cfg.dodval1.intrval1 = 1
778     cfg.dodval1.floaval1 = 0.1
779     cfg.dodval1.unival1 = u"no"
780     cfg.dodval1.portval1 = 80
781     cfg.dodval1.broadval1 = "1.1.1.255"
782     cfg.dodval1.domainval1 = "test.com"
783     cfg.dodval1.emailval1 = "test@test.com"
784     cfg.dodval1.urlval1 = "http://test.com"
785     cfg.dodval1.usernameval1 = "user1"
786     cfg.dodval1.filenameval1 = "/tmp"
787     assert cfg.dodval1.stval1 == "no"
788     assert cfg.dodval1.ipval1 == "1.1.1.1"
789     assert cfg.dodval1.networkval1 == "1.1.1.0"
790     assert cfg.dodval1.netmaskval1 == "255.255.255.0"
791     assert cfg.dodval1.chval1 == "val1"
792     assert cfg.dodval1.ch1val1 == "val2"
793     assert cfg.dodval1.booval1 is True
794     assert cfg.dodval1.intrval1 == 1
795     assert cfg.dodval1.floaval1 == 0.1
796     assert cfg.dodval1.unival1 == u"no"
797     assert cfg.dodval1.portval1 == 80
798     assert cfg.dodval1.broadval1 == "1.1.1.255"
799     assert cfg.dodval1.domainval1 == "test.com"
800     assert cfg.dodval1.emailval1 == "test@test.com"
801     assert cfg.dodval1.urlval1 == "http://test.com"
802     assert cfg.dodval1.usernameval1 == "user1"
803     assert cfg.dodval1.filenameval1 == "/tmp"
804     #
805     assert cfg.dodval2.stval2 is None
806     assert cfg.dodval2.ipval2 is None
807     assert cfg.dodval2.networkval2 is None
808     assert cfg.dodval2.netmaskval2 is None
809     assert cfg.dodval2.chval2 is None
810     assert cfg.dodval2.ch1val2 is None
811     assert cfg.dodval2.booval2 is None
812     assert cfg.dodval2.intrval2 is None
813     assert cfg.dodval2.floaval2 is None
814     assert cfg.dodval2.unival2 is None
815     assert cfg.dodval2.portval2 is None
816     assert cfg.dodval2.broadval2 is None
817     assert cfg.dodval2.domainval2 is None
818     assert cfg.dodval2.emailval2 is None
819     assert cfg.dodval2.urlval2 is None
820     assert cfg.dodval2.usernameval2 is None
821     assert cfg.dodval2.filenameval2 is None
822
823
824 def test_consistency_ip_netmask_dyndescription():
825     a = IPOption('a', '')
826     b = NetmaskOption('b', '')
827     dod = DynOptionDescription('dod', '', [a, b], callback=return_list)
828     b.impl_add_consistency('ip_netmask', a)
829     od = OptionDescription('od', '', [dod])
830     c = Config(od)
831     c.dodval1.aval1 = '192.168.1.1'
832     c.dodval1.bval1 = '255.255.255.0'
833     c.dodval2.aval2 = '192.168.1.2'
834     c.dodval2.bval2 = '255.255.255.255'
835     c.dodval2.bval2 = '255.255.255.0'
836
837
838 def test_consistency_ip_in_network_dyndescription():
839     a = NetworkOption('a', '')
840     b = NetmaskOption('b', '')
841     c = IPOption('c', '')
842     dod = DynOptionDescription('dod', '', [a, b, c], callback=return_list)
843     c.impl_add_consistency('in_network', a, b)
844     od = OptionDescription('od', '', [dod])
845     cfg = Config(od)
846     cfg.dodval1.aval1 = '192.168.1.0'
847     cfg.dodval1.bval1 = '255.255.255.0'
848     cfg.dodval1.cval1 = '192.168.1.1'
849
850
851 def test_masterslaves_dyndescription():
852     st1 = StrOption('st1', "", multi=True)
853     st2 = StrOption('st2', "", multi=True)
854     stm = OptionDescription('st1', '', [st1, st2])
855     stm.impl_set_group_type(groups.master)
856     st = DynOptionDescription('st', '', [stm], callback=return_list)
857     od = OptionDescription('od', '', [st])
858     od2 = OptionDescription('od', '', [od])
859     cfg = Config(od2)
860     owner = cfg.cfgimpl_get_settings().getowner()
861     st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1')
862     st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1')
863     st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2')
864     st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2')
865     assert cfg.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
866     assert cfg.od.stval1.st1val1.st1val1 == []
867     assert cfg.od.stval1.st1val1.st2val1 == []
868     assert cfg.od.stval2.st1val2.st1val2 == []
869     assert cfg.od.stval2.st1val2.st2val2 == []
870     assert cfg.getowner(st1val1) == owners.default
871     assert cfg.getowner(st1val2) == owners.default
872     assert cfg.getowner(st2val1) == owners.default
873     assert cfg.getowner(st2val2) == owners.default
874     #
875     cfg.od.stval1.st1val1.st1val1.append('yes')
876     assert cfg.make_dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
877     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
878     assert cfg.od.stval1.st1val1.st2val1 == [None]
879     assert cfg.od.stval2.st1val2.st1val2 == []
880     assert cfg.od.stval2.st1val2.st2val2 == []
881     assert cfg.getowner(st1val1) == owner
882     assert cfg.getowner(st1val2) == owners.default
883     assert cfg.getowner(st2val1) == owners.default
884     assert cfg.getowner(st2val2) == owners.default
885     #
886     cfg.od.stval1.st1val1.st1val1 = ['yes']
887     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
888     assert cfg.od.stval1.st1val1.st2val1 == [None]
889     assert cfg.od.stval2.st1val2.st1val2 == []
890     assert cfg.od.stval2.st1val2.st2val2 == []
891     assert cfg.getowner(st1val1) == owner
892     assert cfg.getowner(st1val2) == owners.default
893     assert cfg.getowner(st2val1) == owners.default
894     assert cfg.getowner(st2val2) == owners.default
895     #
896     cfg.od.stval1.st1val1.st2val1 = ['no']
897     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
898     assert cfg.od.stval1.st1val1.st2val1 == ['no']
899     assert cfg.od.stval2.st1val2.st1val2 == []
900     assert cfg.od.stval2.st1val2.st2val2 == []
901     assert cfg.getowner(st1val1) == owner
902     assert cfg.getowner(st1val2) == owners.default
903     assert cfg.getowner(st2val1) == owner
904     assert cfg.getowner(st2val2) == owners.default
905     #
906     cfg.od.stval1.st1val1.st1val1.pop(0)
907     assert cfg.od.stval1.st1val1.st1val1 == []
908     assert cfg.od.stval1.st1val1.st2val1 == []
909     assert cfg.od.stval2.st1val2.st1val2 == []
910     assert cfg.od.stval2.st1val2.st2val2 == []
911     assert cfg.getowner(st1val1) == owner
912     assert cfg.getowner(st1val2) == owners.default
913     assert cfg.getowner(st2val1) == owner
914     assert cfg.getowner(st2val2) == owners.default
915     #
916     cfg.od.stval1.st1val1.st1val1 = ['yes']
917     cfg.od.stval1.st1val1.st2val1 = ['yes']
918     assert cfg.getowner(st1val1) == owner
919     assert cfg.getowner(st2val1) == owner
920     del(cfg.od.stval1.st1val1.st2val1)
921     assert cfg.getowner(st1val1) == owner
922     assert cfg.getowner(st1val2) == owners.default
923     assert cfg.getowner(st2val1) == owners.default
924     assert cfg.getowner(st2val2) == owners.default
925     #
926     cfg.od.stval1.st1val1.st1val1 = ['yes']
927     cfg.od.stval1.st1val1.st2val1 = ['yes']
928     del(cfg.od.stval1.st1val1.st1val1)
929     assert cfg.od.stval1.st1val1.st1val1 == []
930     assert cfg.od.stval1.st1val1.st2val1 == []
931     assert cfg.od.stval2.st1val2.st1val2 == []
932     assert cfg.od.stval2.st1val2.st2val2 == []
933     assert cfg.getowner(st1val1) == owners.default
934     assert cfg.getowner(st1val2) == owners.default
935     assert cfg.getowner(st2val1) == owners.default
936     assert cfg.getowner(st2val2) == owners.default
937
938
939 def test_masterslaves_default_multi_dyndescription():
940     st1 = StrOption('st1', "", multi=True)
941     st2 = StrOption('st2', "", multi=True, default_multi='no')
942     stm = OptionDescription('st1', '', [st1, st2])
943     stm.impl_set_group_type(groups.master)
944     st = DynOptionDescription('st', '', [stm], callback=return_list)
945     od = OptionDescription('od', '', [st])
946     od2 = OptionDescription('od', '', [od])
947     cfg = Config(od2)
948     owner = cfg.cfgimpl_get_settings().getowner()
949     st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1')
950     st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1')
951     st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2')
952     st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2')
953     assert cfg.od.stval1.st1val1.st1val1 == []
954     assert cfg.od.stval1.st1val1.st2val1 == []
955     assert cfg.od.stval2.st1val2.st1val2 == []
956     assert cfg.od.stval2.st1val2.st2val2 == []
957     assert cfg.getowner(st1val1) == owners.default
958     assert cfg.getowner(st1val2) == owners.default
959     assert cfg.getowner(st2val1) == owners.default
960     assert cfg.getowner(st2val2) == owners.default
961     cfg.od.stval1.st1val1.st1val1.append('yes')
962     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
963     assert cfg.od.stval1.st1val1.st2val1 == ['no']
964     assert cfg.od.stval2.st1val2.st1val2 == []
965     assert cfg.od.stval2.st1val2.st2val2 == []
966     assert cfg.getowner(st1val1) == owner
967     assert cfg.getowner(st1val2) == owners.default
968     assert cfg.getowner(st2val1) == owners.default
969     assert cfg.getowner(st2val2) == owners.default
970
971
972 def test_masterslaves_submulti_dyndescription():
973     st1 = StrOption('st1', "", multi=True)
974     st2 = StrOption('st2', "", multi=submulti)
975     stm = OptionDescription('st1', '', [st1, st2])
976     stm.impl_set_group_type(groups.master)
977     st = DynOptionDescription('st', '', [stm], callback=return_list)
978     od = OptionDescription('od', '', [st])
979     od2 = OptionDescription('od', '', [od])
980     cfg = Config(od2)
981     owner = cfg.cfgimpl_get_settings().getowner()
982     st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1')
983     st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1')
984     st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2')
985     st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2')
986     assert cfg.od.stval1.st1val1.st1val1 == []
987     assert cfg.od.stval1.st1val1.st2val1 == []
988     assert cfg.od.stval2.st1val2.st1val2 == []
989     assert cfg.od.stval2.st1val2.st2val2 == []
990     assert cfg.getowner(st1val1) == owners.default
991     assert cfg.getowner(st1val2) == owners.default
992     assert cfg.getowner(st2val1) == owners.default
993     assert cfg.getowner(st2val2) == owners.default
994     cfg.od.stval1.st1val1.st1val1.append('yes')
995     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
996     assert cfg.od.stval1.st1val1.st2val1 == [[]]
997     assert cfg.od.stval2.st1val2.st1val2 == []
998     assert cfg.od.stval2.st1val2.st2val2 == []
999     assert cfg.getowner(st1val1) == owner
1000     assert cfg.getowner(st1val2) == owners.default
1001     assert cfg.getowner(st2val1) == owners.default
1002     assert cfg.getowner(st2val2) == owners.default
1003     #
1004     cfg.od.stval1.st1val1.st2val1[0].append('no')
1005     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1006     assert cfg.od.stval1.st1val1.st2val1 == [['no']]
1007     assert cfg.od.stval2.st1val2.st1val2 == []
1008     assert cfg.od.stval2.st1val2.st2val2 == []
1009     assert cfg.getowner(st1val1) == owner
1010     assert cfg.getowner(st1val2) == owners.default
1011     assert cfg.getowner(st2val1) == owner
1012     assert cfg.getowner(st2val2) == owners.default
1013
1014
1015 def test_masterslaves_consistency_ip_dyndescription():
1016     a = NetworkOption('net', '', multi=True)
1017     b = NetmaskOption('mask', '', multi=True)
1018     c = BroadcastOption('broad', '', multi=True)
1019     b.impl_add_consistency('network_netmask', a)
1020     c.impl_add_consistency('broadcast', a, b)
1021     dod = DynOptionDescription('net', '', [a, b, c], callback=return_list)
1022     dod.impl_set_group_type(groups.master)
1023     od = OptionDescription('od', '', [dod])
1024     cfg = Config(od)
1025     cfg.netval1.netval1 = ['192.168.1.0']
1026     cfg.netval1.maskval1 = ['255.255.255.0']
1027     cfg.netval1.broadval1 = ['192.168.1.255']
1028
1029     cfg.netval1.netval1 = ['192.168.1.0', '192.168.2.128']
1030     cfg.netval1.maskval1 = ['255.255.255.0', '255.255.255.128']
1031     cfg.netval1.broadval1 = ['192.168.1.255', '192.168.2.255']
1032     cfg.netval1.broadval1[1] = '192.168.2.255'
1033     #
1034     assert cfg.netval1.netval1 == ['192.168.1.0', '192.168.2.128']
1035     assert cfg.netval1.maskval1 == ['255.255.255.0', '255.255.255.128']
1036     assert cfg.netval1.broadval1 == ['192.168.1.255', '192.168.2.255']
1037     assert cfg.netval2.netval2 == []
1038     assert cfg.netval2.maskval2 == []
1039     assert cfg.netval2.broadval2 == []
1040
1041
1042 def test_masterslaves_callback_dyndescription():
1043     st1 = StrOption('st1', "", multi=True)
1044     st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ((st1, False),)})
1045     stm = OptionDescription('st1', '', [st1, st2])
1046     stm.impl_set_group_type(groups.master)
1047     st = DynOptionDescription('st', '', [stm], callback=return_list)
1048     od = OptionDescription('od', '', [st])
1049     od2 = OptionDescription('od', '', [od])
1050     cfg = Config(od2)
1051     owner = cfg.cfgimpl_get_settings().getowner()
1052     st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1')
1053     st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1')
1054     st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2')
1055     st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2')
1056     assert cfg.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
1057     assert cfg.od.stval1.st1val1.st1val1 == []
1058     assert cfg.od.stval1.st1val1.st2val1 == []
1059     assert cfg.od.stval2.st1val2.st1val2 == []
1060     assert cfg.od.stval2.st1val2.st2val2 == []
1061     assert cfg.getowner(st1val1) == owners.default
1062     assert cfg.getowner(st1val2) == owners.default
1063     assert cfg.getowner(st2val1) == owners.default
1064     assert cfg.getowner(st2val2) == owners.default
1065     #
1066     cfg.od.stval1.st1val1.st1val1.append('yes')
1067     assert cfg.make_dict() == {'od.stval1.st1val1.st2val1': ['yes'], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
1068     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1069     assert cfg.od.stval1.st1val1.st2val1 == ['yes']
1070     assert cfg.od.stval2.st1val2.st1val2 == []
1071     assert cfg.od.stval2.st1val2.st2val2 == []
1072     assert cfg.getowner(st1val1) == owner
1073     assert cfg.getowner(st1val2) == owners.default
1074     assert cfg.getowner(st2val1) == owners.default
1075     assert cfg.getowner(st2val2) == owners.default
1076     #
1077     cfg.od.stval1.st1val1.st2val1 = ['no']
1078     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1079     assert cfg.od.stval1.st1val1.st2val1 == ['no']
1080     assert cfg.od.stval2.st1val2.st1val2 == []
1081     assert cfg.od.stval2.st1val2.st2val2 == []
1082     assert cfg.getowner(st1val1) == owner
1083     assert cfg.getowner(st1val2) == owners.default
1084     assert cfg.getowner(st2val1) == owner
1085     assert cfg.getowner(st2val2) == owners.default
1086     #
1087     cfg.od.stval1.st1val1.st1val1.pop(0)
1088     assert cfg.od.stval1.st1val1.st1val1 == []
1089     assert cfg.od.stval1.st1val1.st2val1 == []
1090     assert cfg.od.stval2.st1val2.st1val2 == []
1091     assert cfg.od.stval2.st1val2.st2val2 == []
1092     assert cfg.getowner(st1val1) == owner
1093     assert cfg.getowner(st1val2) == owners.default
1094     assert cfg.getowner(st2val1) == owner
1095     assert cfg.getowner(st2val2) == owners.default
1096     #
1097     cfg.od.stval1.st1val1.st1val1 = ['yes']
1098     cfg.od.stval1.st1val1.st2val1 = ['yes']
1099     assert cfg.getowner(st1val1) == owner
1100     assert cfg.getowner(st2val1) == owner
1101     del(cfg.od.stval1.st1val1.st2val1)
1102     assert cfg.getowner(st1val1) == owner
1103     assert cfg.getowner(st1val2) == owners.default
1104     assert cfg.getowner(st2val1) == owners.default
1105     assert cfg.getowner(st2val2) == owners.default
1106     #
1107     cfg.od.stval1.st1val1.st1val1 = ['yes']
1108     cfg.od.stval1.st1val1.st2val1 = ['yes']
1109     del(cfg.od.stval1.st1val1.st1val1)
1110     assert cfg.od.stval1.st1val1.st1val1 == []
1111     assert cfg.od.stval1.st1val1.st2val1 == []
1112     assert cfg.od.stval2.st1val2.st1val2 == []
1113     assert cfg.od.stval2.st1val2.st2val2 == []
1114     assert cfg.getowner(st1val1) == owners.default
1115     assert cfg.getowner(st1val2) == owners.default
1116     assert cfg.getowner(st2val1) == owners.default
1117     assert cfg.getowner(st2val2) == owners.default
1118     #
1119     cfg.od.stval1.st1val1.st2val1 = []
1120     cfg.od.stval1.st1val1.st1val1 = ['yes']
1121     assert cfg.od.stval1.st1val1.st2val1 == ['yes']
1122
1123
1124 def test_masterslaves_callback_value_dyndescription():
1125     st1 = StrOption('st1', "", multi=True)
1126     st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ('val',)})
1127     stm = OptionDescription('st1', '', [st1, st2])
1128     stm.impl_set_group_type(groups.master)
1129     st = DynOptionDescription('st', '', [stm], callback=return_list)
1130     od = OptionDescription('od', '', [st])
1131     od2 = OptionDescription('od', '', [od])
1132     cfg = Config(od2)
1133     assert cfg.od.stval1.st1val1.st1val1 == []
1134     assert cfg.od.stval1.st1val1.st2val1 == []
1135     cfg.od.stval1.st1val1.st1val1.append('yes')
1136     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1137     assert cfg.od.stval1.st1val1.st2val1[0] == 'val'
1138     assert cfg.od.stval1.st1val1.st2val1 == ['val']
1139
1140
1141 def test_masterslaves_callback_nomulti_dyndescription():
1142     v1 = StrOption('v1', '', "val")
1143     st1 = StrOption('st1', "", multi=True)
1144     st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v1, False),)})
1145     stm = OptionDescription('st1', '', [st1, st2])
1146     stm.impl_set_group_type(groups.master)
1147     st = DynOptionDescription('st', '', [stm], callback=return_list)
1148     od = OptionDescription('od', '', [st])
1149     od2 = OptionDescription('od', '', [od, v1])
1150     cfg = Config(od2)
1151     assert cfg.od.stval1.st1val1.st1val1 == []
1152     assert cfg.od.stval1.st1val1.st2val1 == []
1153     cfg.od.stval1.st1val1.st1val1.append('yes')
1154     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1155     assert cfg.od.stval1.st1val1.st2val1 == ['val']
1156
1157
1158 def test_masterslaves_callback_multi_dyndescription():
1159     v1 = StrOption('v1', '', multi=True)
1160     st1 = StrOption('st1', "", multi=True)
1161     st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v1, False),)})
1162     stm = OptionDescription('st1', '', [st1, st2])
1163     stm.impl_set_group_type(groups.master)
1164     st = DynOptionDescription('st', '', [stm], callback=return_list)
1165     od = OptionDescription('od', '', [st])
1166     od2 = OptionDescription('od', '', [od, v1])
1167     cfg = Config(od2)
1168     assert cfg.od.stval1.st1val1.st1val1 == []
1169     assert cfg.od.stval1.st1val1.st2val1 == []
1170     cfg.od.stval1.st1val1.st1val1.append('yes')
1171     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1172     assert cfg.od.stval1.st1val1.st2val1 == [None]
1173     cfg.od.stval1.st1val1.st2val1 = ['no']
1174     cfg.v1 = ['no', 'no', 'no']
1175     cfg.od.stval1.st1val1.st1val1.append('yes')
1176     assert cfg.od.stval1.st1val1.st1val1 == ['yes', 'yes']
1177     assert cfg.od.stval1.st1val1.st2val1 == ['no', 'no']
1178     cfg.od.stval1.st1val1.st1val1.pop(1)
1179     assert cfg.od.stval1.st1val1.st1val1 == ['yes']
1180     assert cfg.od.stval1.st1val1.st2val1 == ['no']
1181
1182
1183 def test_masterslaves_callback_samegroup_dyndescription():
1184     st1 = StrOption('st1', "", multi=True)
1185     st2 = StrOption('st2', "", multi=True)
1186     st3 = StrOption('st3', "", multi=True, callback=return_dynval, callback_params={'': ((st2, False),)})
1187     stm = OptionDescription('st1', '', [st1, st2, st3])
1188     stm.impl_set_group_type(groups.master)
1189     st = DynOptionDescription('st', '', [stm], callback=return_list)
1190     od = OptionDescription('od', '', [st])
1191     od2 = OptionDescription('od', '', [od])
1192     cfg = Config(od2)
1193     owner = cfg.cfgimpl_get_settings().getowner()
1194     st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1')
1195     st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1')
1196     st3val1 = cfg.unwrap_from_path('od.stval1.st1val1.st3val1')
1197     st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2')
1198     st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2')
1199     st3val2 = cfg.unwrap_from_path('od.stval2.st1val2.st3val2')
1200     assert cfg.make_dict() == {'od.stval1.st1val1.st1val1': [],
1201                                'od.stval1.st1val1.st2val1': [],
1202                                'od.stval1.st1val1.st3val1': [],
1203                                'od.stval2.st1val2.st1val2': [],
1204                                'od.stval2.st1val2.st2val2': [],
1205                                'od.stval2.st1val2.st3val2': []}
1206     assert cfg.od.stval1.st1val1.st1val1 == []
1207     assert cfg.od.stval1.st1val1.st2val1 == []
1208     assert cfg.od.stval1.st1val1.st3val1 == []
1209     assert cfg.od.stval2.st1val2.st1val2 == []
1210     assert cfg.od.stval2.st1val2.st2val2 == []
1211     assert cfg.od.stval2.st1val2.st3val2 == []
1212     assert cfg.getowner(st1val1) == owners.default
1213     assert cfg.getowner(st1val2) == owners.default
1214     assert cfg.getowner(st2val1) == owners.default
1215     assert cfg.getowner(st2val2) == owners.default
1216     assert cfg.getowner(st3val1) == owners.default
1217     assert cfg.getowner(st3val2) == owners.default
1218     ##
1219     cfg.od.stval1.st1val1.st1val1.append('yes')
1220     assert cfg.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'],
1221                                'od.stval1.st1val1.st2val1': [None],
1222                                'od.stval1.st1val1.st3val1': [None],
1223                                'od.stval2.st1val2.st1val2': [],
1224                                'od.stval2.st1val2.st2val2': [],
1225                                'od.stval2.st1val2.st3val2': []}
1226     assert cfg.getowner(st1val1) == owner
1227     assert cfg.getowner(st1val2) == owners.default
1228     assert cfg.getowner(st2val1) == owners.default
1229     assert cfg.getowner(st2val2) == owners.default
1230     assert cfg.getowner(st3val1) == owners.default
1231     assert cfg.getowner(st3val2) == owners.default
1232     #
1233     cfg.od.stval1.st1val1.st2val1[0] = 'yes'
1234     assert cfg.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'],
1235                                'od.stval1.st1val1.st2val1': ['yes'],
1236                                'od.stval1.st1val1.st3val1': ['yes'],
1237                                'od.stval2.st1val2.st1val2': [],
1238                                'od.stval2.st1val2.st2val2': [],
1239                                'od.stval2.st1val2.st3val2': []}
1240     assert cfg.getowner(st1val1) == owner
1241     assert cfg.getowner(st1val2) == owners.default
1242     assert cfg.getowner(st2val1) == owner
1243     assert cfg.getowner(st2val2) == owners.default
1244     assert cfg.getowner(st3val1) == owners.default
1245     assert cfg.getowner(st3val2) == owners.default
1246
1247
1248 def test_state_config():
1249     a = IPOption('a', '')
1250     b = NetmaskOption('b', '')
1251     dod1 = DynOptionDescription('dod1', '', [a, b], callback=return_list)
1252     b.impl_add_consistency('ip_netmask', a)
1253     od1 = OptionDescription('od1', '', [dod1])
1254     st1 = StrOption('st1', "", multi=True)
1255     st2 = StrOption('st2', "", multi=True)
1256     st3 = StrOption('st3', "", multi=True, callback=return_dynval, callback_params={'': ((st2, False),)})
1257     stm = OptionDescription('st1', '', [st1, st2, st3])
1258     stm.impl_set_group_type(groups.master)
1259     st = DynOptionDescription('st', '', [stm], callback=return_list)
1260     od = OptionDescription('od', '', [st])
1261     od2 = OptionDescription('od', '', [od, od1])
1262     try:
1263         cfg = Config(od2, persistent=True, session_id='29090938')
1264     except ValueError:
1265         cfg = Config(od2, session_id='29090938')
1266         cfg._impl_test = True
1267     a = dumps(cfg)
1268     q = loads(a)
1269     _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
1270     _diff_conf(cfg, q)
1271
1272     try:
1273         delete_session('config', '29090938')
1274     except ConfigError:
1275         pass
1276
1277
1278 def test_invalid_conflict_dyndescription():
1279     st = StrOption('st', '')
1280     dod = DynOptionDescription('dod', '', [st], callback=return_list)
1281     dodinvalid = StrOption('dodinvalid', '')
1282     raises(ConflictError, "OptionDescription('od', '', [dod, dodinvalid])")
1283
1284
1285 def test_invalid_subod_dyndescription():
1286     st2 = StrOption('st2', '')
1287     od1 = OptionDescription('od1', '', [st2])
1288     raises(ConfigError, "DynOptionDescription('dod', '', [od1], callback=return_list)")
1289
1290
1291 def test_invalid_subdynod_dyndescription():
1292     st2 = StrOption('st2', '')
1293     od1 = DynOptionDescription('od1', '', [st2], callback=return_list)
1294     raises(ConfigError, "DynOptionDescription('dod', '', [od1], callback=return_list)")
1295
1296
1297 def test_invalid_symlink_dyndescription():
1298     st = StrOption('st', '')
1299     st2 = SymLinkOption('st2', st)
1300     raises(ConfigError, "DynOptionDescription('dod', '', [st, st2], callback=return_list)")
1301
1302
1303 def test_nocallback_dyndescription():
1304     st = StrOption('st', '')
1305     st2 = StrOption('st2', '')
1306     raises(ConfigError, "DynOptionDescription('dod', '', [st, st2])")
1307
1308
1309 def test_invalid_samevalue_dyndescription():
1310     st = StrOption('st', '')
1311     dod = DynOptionDescription('dod', '', [st], callback=return_same_list)
1312     od = OptionDescription('od', '', [dod])
1313     cfg = Config(od)
1314     raises(ConfigError, "print cfg")
1315
1316
1317 def test_invalid_name_dyndescription():
1318     st = StrOption('st', '')
1319     dod = DynOptionDescription('dod', '', [st], callback=return_wrong_list)
1320     od = OptionDescription('od', '', [dod])
1321     cfg = Config(od)
1322     raises(ValueError, "print cfg")