From 04dcf2baebb567c1d89fea3f857a8ac3622de238 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Tue, 26 Nov 2019 20:33:24 +0100 Subject: [PATCH] condition --- creole/annotator.py | 450 ++++++++++-------- creole/config.py | 60 +-- creole/error.py | 54 --- creole/loader.py | 294 ++++++------ creole/objspace.py | 23 +- creole/template.py | 22 +- creole/utils.py | 179 +------ creole/xmlreflector.py | 29 +- data/creole.dtd | 1 - .../00empty/result/00-base.xml | 4 +- .../00load_autofreeze/makedict/base.json | 1 + .../00load_autofreeze/result/00-base.xml | 11 +- .../makedict/base.json | 1 + .../result/00-base.xml | 11 +- .../00load_autosave/makedict/base.json | 1 + .../00load_autosave/result/00-base.xml | 3 +- .../00load_autosaveexpert/makedict/base.json | 1 + .../00load_autosaveexpert/result/00-base.xml | 3 +- .../00load_comment/result/00-base.xml | 3 +- .../00load_notype/makedict/base.json | 1 + .../00load_notype/result/00-base.xml | 3 +- .../00load_save/result/00-base.xml | 3 +- .../00load_subfolder/result/00-base.xml | 3 +- .../01auto_base/makedict/base.json | 1 + .../01auto_base/result/00-base.xml | 3 +- .../01auto_withoutparam/makedict/base.json | 1 + .../01auto_withoutparam/result/00-base.xml | 3 +- .../01fill_autofreeze/makedict/base.json | 1 + .../01fill_autofreeze/result/00-base.xml | 8 +- .../01fill_autosave/makedict/base.json | 1 + .../01fill_autosave/result/00-base.xml | 3 +- .../01fill_base/makedict/base.json | 1 + .../01fill_base/result/00-base.xml | 3 +- .../01fill_baseaccent/makedict/base.json | 1 + .../01fill_baseaccent/result/00-base.xml | 3 +- .../01fill_context/makedict/base.json | 1 + .../01fill_context/result/00-base.xml | 3 +- .../01fill_mandatory/makedict/base.json | 1 + .../01fill_mandatory/result/00-base.xml | 3 +- .../01fill_number/makedict/base.json | 1 + .../01fill_number/result/00-base.xml | 3 +- .../01fill_optional/makedict/base.json | 1 + .../01fill_optional/result/00-base.xml | 3 +- .../01separator_base/result/00-base.xml | 3 +- .../result/00-base.xml | 3 +- .../10autosave_hidden/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../10check_base/makedict/base.json | 1 + .../10check_base/result/00-base.xml | 5 +- .../10check_option/makedict/base.json | 1 + .../10check_option/result/00-base.xml | 5 +- .../10check_optional/makedict/base.json | 1 + .../10check_optional/result/00-base.xml | 7 +- .../10check_valid_differ/makedict/base.json | 1 + .../10check_valid_differ/result/00-base.xml | 5 +- .../makedict/base.json | 1 + .../result/00-base.xml | 11 +- .../makedict/base.json | 1 + .../result/00-base.xml | 7 +- .../makedict/base.json | 1 + .../result/00-base.xml | 5 +- .../10load_disabled_if_in/makedict/base.json | 1 + .../10load_disabled_if_in/result/00-base.xml | 13 +- .../makedict/base.json | 1 + .../result/00-base.xml | 13 +- .../makedict/base.json | 1 + .../result/00-base.xml | 18 +- .../makedict/base.json | 1 + .../result/00-base.xml | 11 +- .../makedict/base.json | 1 + .../result/00-base.xml | 13 +- .../10load_frozenifin/makedict/base.json | 1 + .../10load_frozenifin/result/00-base.xml | 17 +- .../10load_frozenifin_auto/makedict/base.json | 1 + .../10load_frozenifin_auto/result/00-base.xml | 14 +- .../makedict/base.json | 1 + .../result/00-base.xml | 24 +- .../makedict/base.json | 1 + .../result/00-base.xml | 4 +- .../10load_mandatoryifin/makedict/base.json | 1 + .../10load_mandatoryifin/result/00-base.xml | 13 +- .../10load_masterslaves/makedict/base.json | 1 + .../10load_masterslaves/result/00-base.xml | 13 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 7 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../10load_multivalue/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 7 +- .../10masterslave_multi/makedict/base.json | 1 + .../10masterslave_multi/result/00-base.xml | 20 +- .../10masterslaves_append/makedict/base.json | 1 + .../10masterslaves_append/result/00-base.xml | 13 +- .../10masterslaves_auto/makedict/base.json | 1 + .../10masterslaves_auto/result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 12 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../10valid_enum_accent/makedict/base.json | 1 + .../10valid_enum_accent/result/00-base.xml | 8 +- .../10valid_enum_base/makedict/base.json | 1 + .../10valid_enum_base/result/00-base.xml | 6 +- .../makedict/base.json | 1 + .../result/00-base.xml | 6 +- .../10valid_enum_checkval/makedict/base.json | 1 + .../10valid_enum_checkval/result/00-base.xml | 5 +- .../makedict/base.json | 1 + .../result/00-base.xml | 3 +- .../10valid_enum_eosfunc/makedict/base.json | 1 + .../10valid_enum_eosfunc/result/00-base.xml | 3 +- .../10valid_enum_eosfunc_probe/00-base.xml | 25 - .../result/00-base.xml | 14 - .../00-base.xml | 26 - .../result/00-base.xml | 18 - .../10valid_enum_mandatory/makedict/base.json | 1 + .../10valid_enum_mandatory/result/00-base.xml | 6 +- .../10valid_enum_master/makedict/base.json | 1 + .../10valid_enum_master/result/00-base.xml | 10 +- .../10valid_enum_multi/makedict/base.json | 1 + .../10valid_enum_multi/result/00-base.xml | 3 +- .../10valid_enum_number/makedict/base.json | 1 + .../10valid_enum_number/result/00-base.xml | 6 +- .../makedict/base.json | 1 + .../result/00-base.xml | 6 +- .../10valid_enum_python/makedict/base.json | 1 + .../10valid_enum_python/result/00-base.xml | 6 +- .../10valid_enum_value/makedict/base.json | 1 + .../10valid_enum_value/result/00-base.xml | 5 +- .../makedict/base.json | 1 + .../result/00-base.xml | 25 +- .../makedict/base.json | 1 + .../result/00-base.xml | 32 +- .../makedict/base.json | 1 + .../result/00-base.xml | 13 +- .../makedict/base.json | 1 + .../result/00-base.xml | 13 +- .../makedict/base.json | 1 + .../result/00-base.xml | 19 +- .../makedict/base.json | 1 + .../result/00-base.xml | 21 +- .../makedict/base.json | 1 + .../result/00-base.xml | 19 +- .../20family_append/result/00-base.xml | 3 +- .../20family_appendaccent/result/00-base.xml | 14 +- .../20family_empty/makedict/base.json | 1 + .../20family_empty/result/00-base.xml | 3 +- .../20family_hidden/result/00-base.xml | 4 +- .../20family_mode/makedict/base.json | 1 + .../20family_mode/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../21family_change/result/00-base.xml | 6 +- .../21family_changeaccent/result/00-base.xml | 6 +- .../21family_empty/makedict/base.json | 1 + .../21family_empty/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 3 +- .../result/00-base.xml | 3 +- .../30mandatory_withvalue/makedict/base.json | 1 + .../30mandatory_withvalue/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 3 +- .../40condition_base/00-base.xml | 2 +- .../40condition_base/makedict/base.json | 1 + .../40condition_base/result/00-base.xml | 13 +- .../40condition_fallback/00-base.xml | 2 +- .../40condition_fallback/makedict/base.json | 1 + .../40condition_fallback/result/00-base.xml | 3 +- .../40condition_optional/makedict/base.json | 1 + .../40condition_optional/result/00-base.xml | 11 +- .../40ifin_masterslaves/makedict/base.json | 1 + .../40ifin_masterslaves/result/00-base.xml | 18 +- .../makedict/base.json | 1 + .../result/00-base.xml | 15 +- .../40ifin_multi/result/00-base.xml | 20 +- .../40ifin_validenum/makedict/base.json | 1 + .../40ifin_validenum/result/00-base.xml | 7 +- .../50exists_exists/result/00-base.xml | 3 +- .../50redefine_description/result/00-base.xml | 3 +- .../51exists_nonexists/makedict/base.json | 1 + .../51exists_nonexists/result/00-base.xml | 3 +- .../51redefine_auto/result/00-base.xml | 3 +- .../51redefine_autofill/makedict/base.json | 1 + .../51redefine_autofill/result/00-base.xml | 3 +- .../51redefine_family/result/00-base.xml | 14 +- .../51redefine_fill/result/00-base.xml | 3 +- .../51redefine_fillauto/result/00-base.xml | 3 +- .../51redefine_help/result/00-base.xml | 3 +- .../51redefine_hidden/result/00-base.xml | 3 +- .../result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 11 +- .../makedict/base.json | 1 + .../result/00-base.xml | 9 +- .../makedict/base.json | 1 + .../result/00-base.xml | 16 +- .../51redefine_validenum/result/00-base.xml | 3 +- .../51redefine_value/makedict/base.json | 1 + .../51redefine_value/result/00-base.xml | 3 +- .../52exists_redefine/result/00-base.xml | 3 +- .../60action_external/makedict/base.json | 1 + .../60action_external/result/00-base.xml | 12 +- .../makedict/base.json | 1 + .../result/00-base.xml | 22 +- .../60extra_help/makedict/base.json | 1 + .../60extra_help/result/00-base.xml | 6 +- .../60extra_load/makedict/base.json | 1 + .../60extra_load/result/00-base.xml | 6 +- .../60extra_mandatory/makedict/base.json | 1 + .../60extra_mandatory/result/00-base.xml | 6 +- .../60extra_redefine/makedict/base.json | 1 + .../60extra_redefine/result/00-base.xml | 6 +- .../60familyaction/makedict/base.json | 1 + .../60familyaction/result/00-base.xml | 12 +- .../60familyaction_accent/makedict/base.json | 1 + .../60familyaction_accent/result/00-base.xml | 12 +- .../60familyaction_disable/makedict/base.json | 1 + .../60familyaction_disable/result/00-base.xml | 23 +- .../60familyaction_empty/makedict/base.json | 1 + .../60familyaction_empty/result/00-base.xml | 9 +- .../makedict/base.json | 1 + .../result/00-base.xml | 12 +- .../60familyaction_save/makedict/base.json | 1 + .../60familyaction_save/result/00-base.xml | 12 +- .../makedict/base.json | 1 + .../result/00-base.xml | 17 +- .../60familyactionexternal/makedict/base.json | 1 + .../60familyactionexternal/result/00-base.xml | 9 +- .../70container_all/makedict/base.json | 1 + .../70container_all/result/00-base.xml | 20 +- .../70container_allfile/makedict/base.json | 1 + .../70container_allfile/result/00-base.xml | 18 +- .../makedict/base.json | 1 + .../result/00-base.xml | 18 +- .../70container_disknod/makedict/base.json | 1 + .../70container_disknod/result/00-base.xml | 16 +- .../70container_files/makedict/base.json | 1 + .../70container_files/result/00-base.xml | 10 +- .../70container_filesmulti/makedict/base.json | 1 + .../70container_filesmulti/result/00-base.xml | 12 +- .../makedict/base.json | 1 + .../result/00-base.xml | 10 +- .../70container_filesrm/makedict/base.json | 1 + .../70container_filesrm/result/00-base.xml | 10 +- .../70container_fstab/makedict/base.json | 1 + .../70container_fstab/result/00-base.xml | 10 +- .../makedict/base.json | 1 + .../result/00-base.xml | 12 +- .../70container_host/makedict/base.json | 1 + .../70container_host/result/00-base.xml | 14 +- .../70container_interface/makedict/base.json | 1 + .../70container_interface/result/00-base.xml | 16 +- .../70container_new/result/00-base.xml | 7 +- .../70container_newnocont/result/00-base.xml | 7 +- .../70container_newwithip/makedict/base.json | 1 + .../70container_newwithip/result/00-base.xml | 7 +- .../makedict/base.json | 1 + .../result/00-base.xml | 14 +- .../70container_package/makedict/base.json | 1 + .../70container_package/result/00-base.xml | 10 +- .../70container_pathaccess/makedict/base.json | 1 + .../70container_pathaccess/result/00-base.xml | 17 +- .../makedict/base.json | 1 + .../result/00-base.xml | 21 +- .../70container_save/result/00-base.xml | 3 +- .../makedict/base.json | 1 + .../result/00-base.xml | 18 +- .../makedict/base.json | 1 + .../result/00-base.xml | 46 +- .../makedict/base.json | 1 + .../result/00-base.xml | 26 +- .../makedict/base.json | 1 + .../result/00-base.xml | 42 +- .../makedict/base.json | 1 + .../result/00-base.xml | 13 +- .../70container_services/makedict/base.json | 1 + .../70container_services/result/00-base.xml | 10 +- .../70container_subgroup/makedict/base.json | 1 + .../70container_subgroup/result/00-base.xml | 18 +- .../10load_hidden_if_in/00-base.xml | 0 .../10load_hidden_if_in/result/00-base.xml | 0 .../10load_hidden_if_not_in/00-base.xml | 0 .../result/00-base.xml | 0 .../00-base.xml | 0 .../01-base.xml | 0 .../result/00-base.xml | 0 tests/test_flattener.py | 20 +- tests/test_loader.py | 117 ----- tests/test_makedict.py | 85 ++++ 302 files changed, 1408 insertions(+), 1619 deletions(-) create mode 100644 tests/flattener_dicos/00load_autofreeze/makedict/base.json create mode 100644 tests/flattener_dicos/00load_autofreezeexpert/makedict/base.json create mode 100644 tests/flattener_dicos/00load_autosave/makedict/base.json create mode 100644 tests/flattener_dicos/00load_autosaveexpert/makedict/base.json create mode 100644 tests/flattener_dicos/00load_notype/makedict/base.json create mode 100644 tests/flattener_dicos/01auto_base/makedict/base.json create mode 100644 tests/flattener_dicos/01auto_withoutparam/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_autofreeze/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_autosave/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_base/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_baseaccent/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_context/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_mandatory/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_number/makedict/base.json create mode 100644 tests/flattener_dicos/01fill_optional/makedict/base.json create mode 100644 tests/flattener_dicos/10autosave_hidden_frozenifin/makedict/base.json create mode 100644 tests/flattener_dicos/10check_base/makedict/base.json create mode 100644 tests/flattener_dicos/10check_option/makedict/base.json create mode 100644 tests/flattener_dicos/10check_optional/makedict/base.json create mode 100644 tests/flattener_dicos/10check_valid_differ/makedict/base.json create mode 100644 tests/flattener_dicos/10check_valid_differ_add/makedict/base.json create mode 100644 tests/flattener_dicos/10check_valid_differ_removecheck/makedict/base.json create mode 100644 tests/flattener_dicos/10check_valid_ipnetmask/makedict/base.json create mode 100644 tests/flattener_dicos/10load_disabled_if_in/makedict/base.json create mode 100644 tests/flattener_dicos/10load_disabled_if_in_none/makedict/base.json create mode 100644 tests/flattener_dicos/10load_disabled_if_inaccent/makedict/base.json create mode 100644 tests/flattener_dicos/10load_disabledifin_fallback/makedict/base.json create mode 100644 tests/flattener_dicos/10load_disabledifin_whithouttype/makedict/base.json create mode 100644 tests/flattener_dicos/10load_frozenifin/makedict/base.json create mode 100644 tests/flattener_dicos/10load_frozenifin_auto/makedict/base.json create mode 100644 tests/flattener_dicos/10load_frozenifin_multiparam/makedict/base.json create mode 100644 tests/flattener_dicos/10load_frozenifin_noexist/makedict/base.json create mode 100644 tests/flattener_dicos/10load_mandatoryifin/makedict/base.json create mode 100644 tests/flattener_dicos/10load_masterslaves/makedict/base.json create mode 100644 tests/flattener_dicos/10load_masterslaves_default_multi/makedict/base.json create mode 100644 tests/flattener_dicos/10load_masterslaves_defaultmulti_master/makedict/base.json create mode 100644 tests/flattener_dicos/10load_masterslaves_normalize_family/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslave_autosaveexpert/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslave_mandatory/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslave_mandatoryslave/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslave_mastermandatory/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslave_multi/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslaves_append/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslaves_auto/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslaves_automaster/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslaves_automaster_expert/makedict/base.json create mode 100644 tests/flattener_dicos/10masterslaves_familyaccent/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_accent/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_base/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_base_redefine/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_checkval/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_checkval_true/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_eosfunc/makedict/base.json delete mode 100644 tests/flattener_dicos/10valid_enum_eosfunc_probe/00-base.xml delete mode 100644 tests/flattener_dicos/10valid_enum_eosfunc_probe/result/00-base.xml delete mode 100644 tests/flattener_dicos/10valid_enum_eosfunc_probe_checkval/00-base.xml delete mode 100644 tests/flattener_dicos/10valid_enum_eosfunc_probe_checkval/result/00-base.xml create mode 100644 tests/flattener_dicos/10valid_enum_mandatory/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_master/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_multi/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_number/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_numberdefault/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_python/makedict/base.json create mode 100644 tests/flattener_dicos/10valid_enum_value/makedict/base.json create mode 100644 tests/flattener_dicos/11disabled_if_in_filelist/makedict/base.json create mode 100644 tests/flattener_dicos/11disabled_if_in_filelist_multi/makedict/base.json create mode 100644 tests/flattener_dicos/11disabledifin_filelist_notexist/makedict/base.json create mode 100644 tests/flattener_dicos/11disabledifnotin_filelist_notexist/makedict/base.json create mode 100644 tests/flattener_dicos/11disabledifnotin_filelist_notexist_multi/makedict/base.json create mode 100644 tests/flattener_dicos/11disabledifnotin_filelist_notexist_validenum/makedict/base.json create mode 100644 tests/flattener_dicos/11multi_disabled_if_in_filelist/makedict/base.json create mode 100644 tests/flattener_dicos/20family_empty/makedict/base.json create mode 100644 tests/flattener_dicos/20family_mode/makedict/base.json create mode 100644 tests/flattener_dicos/20family_modemasterslaves/makedict/base.json create mode 100644 tests/flattener_dicos/21family_empty/makedict/base.json create mode 100644 tests/flattener_dicos/30mandatory_withoutvalue/makedict/base.json create mode 100644 tests/flattener_dicos/30mandatory_withvalue/makedict/base.json create mode 100644 tests/flattener_dicos/30mandatory_withvaluecalc/makedict/base.json create mode 100644 tests/flattener_dicos/40condition_base/makedict/base.json create mode 100644 tests/flattener_dicos/40condition_fallback/makedict/base.json create mode 100644 tests/flattener_dicos/40condition_optional/makedict/base.json create mode 100644 tests/flattener_dicos/40ifin_masterslaves/makedict/base.json create mode 100644 tests/flattener_dicos/40ifin_masterslavesauto/makedict/base.json create mode 100644 tests/flattener_dicos/40ifin_validenum/makedict/base.json create mode 100644 tests/flattener_dicos/51exists_nonexists/makedict/base.json create mode 100644 tests/flattener_dicos/51redefine_autofill/makedict/base.json create mode 100644 tests/flattener_dicos/51redefine_remove_condition/makedict/base.json create mode 100644 tests/flattener_dicos/51redefine_removecondition_alltarget/makedict/base.json create mode 100644 tests/flattener_dicos/51redefine_removecondition_nonautofreeze/makedict/base.json create mode 100644 tests/flattener_dicos/51redefine_value/makedict/base.json create mode 100644 tests/flattener_dicos/60action_external/makedict/base.json create mode 100644 tests/flattener_dicos/60extra_externalspacecondition/makedict/base.json create mode 100644 tests/flattener_dicos/60extra_help/makedict/base.json create mode 100644 tests/flattener_dicos/60extra_load/makedict/base.json create mode 100644 tests/flattener_dicos/60extra_mandatory/makedict/base.json create mode 100644 tests/flattener_dicos/60extra_redefine/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_accent/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_disable/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_empty/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_mandatory/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_save/makedict/base.json create mode 100644 tests/flattener_dicos/60familyaction_twoactions/makedict/base.json create mode 100644 tests/flattener_dicos/60familyactionexternal/makedict/base.json create mode 100644 tests/flattener_dicos/70container_all/makedict/base.json create mode 100644 tests/flattener_dicos/70container_allfile/makedict/base.json create mode 100644 tests/flattener_dicos/70container_allnotexists/makedict/base.json create mode 100644 tests/flattener_dicos/70container_disknod/makedict/base.json create mode 100644 tests/flattener_dicos/70container_files/makedict/base.json create mode 100644 tests/flattener_dicos/70container_filesmulti/makedict/base.json create mode 100644 tests/flattener_dicos/70container_filesredefine/makedict/base.json create mode 100644 tests/flattener_dicos/70container_filesrm/makedict/base.json create mode 100644 tests/flattener_dicos/70container_fstab/makedict/base.json create mode 100644 tests/flattener_dicos/70container_fstabsymlink/makedict/base.json create mode 100644 tests/flattener_dicos/70container_host/makedict/base.json create mode 100644 tests/flattener_dicos/70container_interface/makedict/base.json create mode 100644 tests/flattener_dicos/70container_newwithip/makedict/base.json create mode 100644 tests/flattener_dicos/70container_nocontainer/makedict/base.json create mode 100644 tests/flattener_dicos/70container_package/makedict/base.json create mode 100644 tests/flattener_dicos/70container_pathaccess/makedict/base.json create mode 100644 tests/flattener_dicos/70container_pathaccess_masterslaves/makedict/base.json create mode 100644 tests/flattener_dicos/70container_serviceaccess/makedict/base.json create mode 100644 tests/flattener_dicos/70container_serviceaccess_disabledifin/makedict/base.json create mode 100644 tests/flattener_dicos/70container_serviceaccesslist/makedict/base.json create mode 100644 tests/flattener_dicos/70container_serviceaccesslist_servicelist/makedict/base.json create mode 100644 tests/flattener_dicos/70container_servicerestriction/makedict/base.json create mode 100644 tests/flattener_dicos/70container_services/makedict/base.json create mode 100644 tests/flattener_dicos/70container_subgroup/makedict/base.json rename tests/{flattener_dicos => flattener_dicos_hum}/10load_hidden_if_in/00-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/10load_hidden_if_in/result/00-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/10load_hidden_if_not_in/00-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/10load_hidden_if_not_in/result/00-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/51redefine_remove_condition_no_target/00-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/51redefine_remove_condition_no_target/01-base.xml (100%) rename tests/{flattener_dicos => flattener_dicos_hum}/51redefine_remove_condition_no_target/result/00-base.xml (100%) delete mode 100644 tests/test_loader.py create mode 100644 tests/test_makedict.py diff --git a/creole/annotator.py b/creole/annotator.py index 6f23c04..b88bb1d 100644 --- a/creole/annotator.py +++ b/creole/annotator.py @@ -4,13 +4,11 @@ from copy import copy from collections import OrderedDict from os.path import join, basename from ast import literal_eval -import sys import imp from .i18n import _ from .utils import normalize_family -from .config import VIRTBASE, VIRTROOT, VIRTMASTER, templatedir from .error import CreoleDictConsistencyError from .xmlreflector import HIGH_COMPATIBILITY @@ -112,7 +110,7 @@ class ContainerAnnotator: family.name = 'container{}'.format(idx) family.doc = container.name family.family = OrderedDict() - self.convert_container_to_family(family.family, container) + self.convert_container_to_family(family.name, family.family, container) setattr(self.space.containers, family.name, family) del self.space.containers.container else: @@ -147,7 +145,7 @@ class ContainerAnnotator: old_container[name] = new_elt del self.space.containers.all - def convert_container_to_family(self, container_family, container): + def convert_container_to_family(self, container_name, container_family, container): # tranform container object to family object # add services, service_accesses, ... for elttype in self.objectspace.container_elt_attr_list: @@ -168,7 +166,7 @@ class ContainerAnnotator: family.family = self.make_group_from_elts(elttype, values, key_type, - 'containers.{}'.format(family.name), + 'containers.{}.{}'.format(container_name, family.name), True) family.mode = None container_family[family.name] = family @@ -219,7 +217,7 @@ class ContainerAnnotator: self.paths.append('variable', path, 'containers', 'containers', variable) return variable - def _make_disknod_auto(self, type_, index, variable): + def _make_disknod_auto(self, type_, index, variable, container_path): if not hasattr(self.space.constraints, 'auto'): self.space.constraints.auto = [] auto = self.objectspace.auto() @@ -233,12 +231,12 @@ class ContainerAnnotator: auto.param = [param1, param2] auto.name = 'cdrom_minormajor' family = 'disknod{}'.format(index) - auto.target = 'containers.disknods.{}.{}'.format(family, type_) + auto.target = '{}.{}.{}'.format(container_path, family, type_) if not hasattr(self.space, 'constraints'): self.space.constraints = self.objectspace.constraints() self.space.constraints.auto.append(auto) - def _make_disknod_type(self, index, variable): + def _make_disknod_type(self, index, variable, container_path): auto = self.objectspace.auto() self.objectspace.index += 1 auto.index = self.objectspace.index @@ -248,7 +246,7 @@ class ContainerAnnotator: auto.param = [param] auto.name = 'device_type' family = 'disknod{}'.format(index) - auto.target = 'containers.disknods.{}.type'.format(family) + auto.target = '{}.{}.type'.format(container_path, family) if not hasattr(self.space, 'constraints'): self.space.constraints = self.objectspace.constraints() if not hasattr(self.space.constraints, 'auto'): @@ -256,17 +254,17 @@ class ContainerAnnotator: self.space.constraints.auto.append(auto) - def _update_disknod(self, disknod, index): + def _update_disknod(self, disknod, index, container_path): disknod.major = None disknod.minor = None disknod.type = None - self._make_disknod_auto('minor', index, disknod) - self._make_disknod_auto('major', index, disknod) - self._make_disknod_type(index, disknod) + self._make_disknod_auto('minor', index, disknod, container_path) + self._make_disknod_auto('major', index, disknod, container_path) + self._make_disknod_type(index, disknod, container_path) disknod.mode = u'rwm' disknod.permission = 'allow' - def _update_file(self, file_, index): + def _update_file(self, file_, index, container_path): if not hasattr(file_, 'source'): file_.source = basename(file_.name) @@ -364,7 +362,7 @@ class ContainerAnnotator: # try to launch _update_xxxx() function update_elt = '_update_' + elt_name if hasattr(self, update_elt): - getattr(self, update_elt)(elt, index) + getattr(self, update_elt)(elt, index, path) variables = [] subpath = '{}.{}{}'.format(path, name, index) listname = '{}list'.format(name) @@ -387,6 +385,7 @@ class ContainerAnnotator: {}).setdefault( value, []).append(activate_path) + continue default_type = 'string' if key in self.objectspace.booleans_attributs: default_type = 'boolean' @@ -487,15 +486,16 @@ class SpaceAnnotator(object): self.convert_helps() def absolute_path_for_symlink_in_containers(self): - if not hasattr(self.space, 'containers') or not hasattr(self.space.containers, 'family'): + if not hasattr(self.space, 'containers'): return - families = self.space.containers.family.values() + families = vars(self.space.containers).values() for family in families: if hasattr(family, 'family'): - for fam in family.family: - for variable in fam.variable: - if variable.type == 'symlink' and '.' not in variable.name: - variable.opt = self.paths.get_variable_path(variable.opt, 'creole') + for fam in family.family.values(): + for fam1 in fam.family: + for variable in fam1.variable: + if variable.type == 'symlink' and '.' not in variable.name: + variable.opt = self.paths.get_variable_path(variable.opt, 'creole') def convert_helps(self): # FIXME l'aide doit etre dans la variable! @@ -552,6 +552,9 @@ class SpaceAnnotator(object): leader_space = self.objectspace.Leadership() leader_space.variable = [] leader_space.name = leader_name + leader_space.hidden = variable.hidden + variable.hidden = None + self.paths.append('family', leader_path + '.' + leader_name, namespace, creoleobj=leader_space) # manage leader's variable if variable.multi is not True: raise CreoleDictConsistencyError(_('the variable {} in a group must be multi').format(variable.name)) @@ -590,6 +593,7 @@ class SpaceAnnotator(object): for variable in family.variable.values(): if isinstance(variable, self.objectspace.Leadership): variable_mode = variable.variable[0].mode + variable.variable[0].mode = None variable.mode = variable_mode else: variable_mode = variable.mode @@ -626,7 +630,7 @@ class SpaceAnnotator(object): if variable.mode != None and variable.mode != modes_level[0] and modes[variable.mode] < modes[family_mode]: variable.mode = family_mode if variable.name == "available_probes": - variable.force_default_on_freeze = False + variable.force_default_on_freeze = False def default_variable_options(self): if hasattr(self.space, 'variables'): @@ -850,7 +854,12 @@ class SpaceAnnotator(object): if variable.auto_save: raise CreoleDictConsistencyError(_('variable with auto value ' 'cannot be auto_save').format(auto.target)) - variable.hidden = True + leader = self.paths.get_leader(auto.target) + if leader is None or variable.name != leader: + variable.hidden = True + else: + leadership = self.paths.get_family_obj(self.paths.get_variable_family_path(auto.target)) + leadership.hidden = True variable.frozen = True variable.force_default_on_freeze = True if 'fill' not in vars(space.constraints): @@ -875,8 +884,8 @@ class SpaceAnnotator(object): names.append(separator.name) - def load_params_in_validenum(self, param, probe): - if not probe and param.type in ['string', 'python', 'number']: + def load_params_in_validenum(self, param): + if param.type in ['string', 'python', 'number']: if not hasattr(param, 'text') and (param.type == 'python' or param.type == 'number'): raise CreoleDictConsistencyError(_("All '{}' variables shall be set in order to calculate {}").format(param.type, 'valid_enum')) if param.type in ['string', 'number']: @@ -884,7 +893,7 @@ class SpaceAnnotator(object): values = literal_eval(param.text) except ValueError: raise CreoleDictConsistencyError(_('Cannot load {}').format(param.text)) - elif param.type == 'python': + elif param.type == 'python': try: values = eval(param.text, {'eosfunc': self.eosfunc, '__builtins__': {'range': range, 'str': str}}) #FIXME : eval('[str(i) for i in range(3, 13)]', {'eosfunc': eosfunc, '__builtins__': {'range': range, 'str': str}}) @@ -894,8 +903,6 @@ class SpaceAnnotator(object): raise CreoleDictConsistencyError(_('Function {} shall return a list').format(param.text)) new_values = [] for val in values: - if sys.version_info[0] < 3 and isinstance(val, str): - val = val.decode('utf-8') new_values.append(val) values = new_values else: @@ -993,7 +1000,7 @@ class SpaceAnnotator(object): if proposed_value_type: if param.type != 'eole': try: - values = self.load_params_in_validenum(param, check.probe) + values = self.load_params_in_validenum(param) except NameError as err: raise CreoleDictConsistencyError(_('cannot load value for variable {}: {}').format(check.target, err)) add_value = True @@ -1005,7 +1012,7 @@ class SpaceAnnotator(object): if check.target in self.valid_enums: raise CreoleDictConsistencyError(_('valid_enum already set for {}' '').format(check.target)) - values = self.load_params_in_validenum(param, check.probe) + values = self.load_params_in_validenum(param) self.valid_enums[check.target] = {'type': param.type, 'values': values} remove_indexes.append(idx) @@ -1097,37 +1104,33 @@ class SpaceAnnotator(object): for idx in del_idx: space.constraints.fill.pop(idx) - def filter_target(self, space, namespace): # pylint: disable=C0111 - del_idx = [] - for idx, target in enumerate(space.target): - if target.type == 'variable': - if (hasattr(target, 'optional') and target.optional is True and - not self.paths.path_is_defined(target.name)): - del_idx.append(idx) - continue - if space.source == target.name: - raise CreoleDictConsistencyError(_('target name and source name must be different: {}').format(space.source)) - target.name = self.paths.get_variable_path(target.name, namespace) - elif target.type == 'family': - try: - target.name = self.paths.get_family_path(target.name, namespace) - except KeyError: - raise CreoleDictConsistencyError(_('cannot found family {}').format(target.name)) - del_idx = list(set(del_idx)) - del_idx.sort(reverse=True) - for idx in del_idx: - space.target.pop(idx) + def filter_targets(self): # pylint: disable=C0111 + for condition_idx, condition in enumerate(self.space.constraints.condition): + namespace = condition.namespace + del_idx = [] + for idx, target in enumerate(condition.target): + if target.type == 'variable': + if (hasattr(target, 'optional') and target.optional is True and + not self.paths.path_is_defined(target.name)): + del_idx.append(idx) + continue + if condition.source == target.name: + raise CreoleDictConsistencyError(_('target name and source name must be different: {}').format(condition.source)) + target.name = self.paths.get_variable_path(target.name, namespace) + elif target.type == 'family': + try: + target.name = self.paths.get_family_path(target.name, namespace) + except KeyError: + raise CreoleDictConsistencyError(_('cannot found family {}').format(target.name)) + del_idx = list(set(del_idx)) + del_idx.sort(reverse=True) + for idx in del_idx: + condition.target.pop(idx) - def filter_condition(self): # pylint: disable=C0111 - if not hasattr(self.space, 'constraints') or not hasattr(self.space.constraints, 'condition'): - return - space = self.space.constraints.condition - remove_conditions = [] - fallback_variables = [] - fallback_lists = [] + def filter_condition_servicelist(self): # automatic generation of the service_access lists # and the service_restriction lists from the servicelist - for condition in space: + for condition in self.space.constraints.condition: if hasattr(condition, 'target'): new_targets = [] for target in condition.target: @@ -1143,20 +1146,15 @@ class SpaceAnnotator(object): new_targets.append(new_target) condition.target.extend(new_targets) - # remove condition with target - if HIGH_COMPATIBILITY: - for idx, condition in enumerate(space): - if not hasattr(condition, 'target'): - remove_conditions.append(idx) + def check_condition_without_target(self): + for condition in self.space.constraints.condition: + if not hasattr(condition, 'target'): + raise CreoleDictConsistencyError(_('target is mandatory in condition')) - for idx, condition in enumerate(space): - if idx in remove_conditions: - continue - if condition.name == 'hidden_if_in': - condition.name = 'disabled_if_in' - elif condition.name == 'hidden_if_not_in': - condition.name = 'disabled_if_not_in' - # a conditon with a fallback **and** the source variable doesn't exist + def check_condition_fallback_not_exists(self, fallback_variables, fallback_lists): + # a condition with a fallback **and** the source variable doesn't exist + remove_conditions = [] + for idx, condition in enumerate(self.space.constraints.condition): if (hasattr(condition, 'fallback') and condition.fallback is True and not self.paths.path_is_defined(condition.source)): for target in condition.target: @@ -1196,116 +1194,201 @@ class SpaceAnnotator(object): variable.hidden = False fallback_lists.append(listvar) remove_conditions.append(idx) + remove_conditions = list(set(remove_conditions)) + remove_conditions.sort(reverse=True) + for idx in remove_conditions: + self.space.constraints.condition.pop(idx) - for condition_idx, condition in enumerate(space): - if condition_idx in remove_conditions: - continue - namespace = condition.namespace - self.filter_target(condition, namespace) + def convert_xxxlist_to_variable(self, fallback_lists): # pylint: disable=C0111 # transform *list to variable or family - for condition_idx, condition in enumerate(space): - if condition.name in ['disabled_if_in', 'disabled_if_not_in', 'frozen_if_in', 'auto_frozen_if_in', - 'frozen_if_not_in', 'mandatory_if_in', 'mandatory_if_not_in']: - new_targets = [] - remove_targets = [] - if not hasattr(condition, 'target'): - continue - for target_idx, target in enumerate(condition.target): - if target.type not in ['variable', 'family']: - listname = target.type - if not listname.endswith('list'): - raise Exception('not yet implemented') - listvars = self.objectspace.list_conditions.get(listname, - {}).get(target.name) - if listvars: - for listvar in listvars: - if listvar in fallback_lists: - continue - try: - variable = self.get_variable(listvar) - type_ = 'variable' - except CreoleDictConsistencyError: - variable = self.paths.get_family_obj(listvar) - type_ = 'family' - new_target = self.objectspace.target() - new_target.type = type_ - new_target.name = listvar - new_target.index = target.index - new_targets.append(new_target) - remove_targets.append(target_idx) - remove_targets = list(set(remove_targets)) - remove_targets.sort(reverse=True) - for target_idx in remove_targets: - condition.target.pop(target_idx) - condition.target.extend(new_targets) + for condition_idx, condition in enumerate(self.space.constraints.condition): + new_targets = [] + remove_targets = [] + for target_idx, target in enumerate(condition.target): + if target.type not in ['variable', 'family']: + listname = target.type + if not listname.endswith('list'): + raise Exception('not yet implemented') + listvars = self.objectspace.list_conditions.get(listname, + {}).get(target.name) + if listvars: + for listvar in listvars: + if listvar in fallback_lists: + continue + try: + variable = self.get_variable(listvar) + type_ = 'variable' + except CreoleDictConsistencyError: + variable = self.paths.get_family_obj(listvar) + type_ = 'family' + new_target = self.objectspace.target() + new_target.type = type_ + new_target.name = listvar + new_target.index = target.index + new_targets.append(new_target) + remove_targets.append(target_idx) + remove_targets = list(set(remove_targets)) + remove_targets.sort(reverse=True) + for target_idx in remove_targets: + condition.target.pop(target_idx) + condition.target.extend(new_targets) - force_remove_targets = {} - for condition_idx, condition in enumerate(space): - if condition_idx in remove_conditions: - continue - namespace = condition.namespace - src_variable = self.paths.get_variable_obj(condition.source) - condition.source = self.paths.get_variable_path(condition.source, namespace, allow_source=True) + def check_condition(self): + # if condition.name == 'hidden_if_in': + # condition.name = 'disabled_if_in' + # elif condition.name == 'hidden_if_not_in': + # condition.name = 'disabled_if_not_in' + for condition in self.space.constraints.condition: + if condition.name not in ['disabled_if_in', 'disabled_if_not_in', 'frozen_if_in', 'auto_frozen_if_in', + 'frozen_if_not_in', 'mandatory_if_in', 'mandatory_if_not_in']: + raise CreoleDictConsistencyError(_('unknown condition {}').format(condition.name)) + + def check_params(self): + for condition in self.space.constraints.condition: for param in condition.param: if param.type not in TYPE_PARAM_CONDITION: raise CreoleDictConsistencyError(_('cannot use {} type as a param ' 'in a condition').format(param.type)) - if condition.name in ['disabled_if_in', 'disabled_if_not_in', 'frozen_if_in', 'auto_frozen_if_in', - 'frozen_if_not_in', 'mandatory_if_in', 'mandatory_if_not_in']: - valid_enum = None - # remove condition for ChoiceOption that don't have param - if condition.source in self.valid_enums and \ - self.valid_enums[condition.source]['type'] == 'string': - valid_enum = self.valid_enums[condition.source]['values'] - if src_variable.type in FORCE_CHOICE: - valid_enum = FORCE_CHOICE[src_variable.type] - if valid_enum is not None: - remove_param = [] - for param_idx, param in enumerate(condition.param): - if param.text not in valid_enum: - remove_param.append(param_idx) - remove_param.sort(reverse=True) - for idx in remove_param: - del condition.param[idx] - if condition.param == []: - for target in condition.target: - if target.name.startswith('creole.'): - name = target.name.split('.')[-1] - else: - name = target.name - if target.type == 'variable': - variable = self.get_variable(name) - else: - variable = self.paths.get_family_obj(name) - if condition.name == 'disabled_if_not_in': - variable.disabled = True - force_remove_targets.setdefault(condition.name, - []).append(target.name) - elif condition.name == 'frozen_if_not_in': - variable.hidden = True - force_remove_targets.setdefault(condition.name, - []).append(target.name) - elif condition.name == 'mandatory_if_not_in': - variable.mandatory = True - force_remove_targets.setdefault(condition.name, - []).append(target.name) - elif HIGH_COMPATIBILITY and condition.name == 'disabled_if_in': - variable.hidden = False - remove_conditions.append(condition_idx) + + def check_choice_option_condition(self, force_remove_targets): + # remove condition for ChoiceOption that don't have param + remove_conditions = [] + for condition_idx, condition in enumerate(self.space.constraints.condition): + namespace = condition.namespace + src_variable = self.paths.get_variable_obj(condition.source) + condition.source = self.paths.get_variable_path(condition.source, namespace, allow_source=True) + valid_enum = None + if condition.source in self.valid_enums and \ + self.valid_enums[condition.source]['type'] == 'string': + valid_enum = self.valid_enums[condition.source]['values'] + if src_variable.type in FORCE_CHOICE: + valid_enum = FORCE_CHOICE[src_variable.type] + if valid_enum is not None: + remove_param = [] + for param_idx, param in enumerate(condition.param): + if param.text not in valid_enum: + remove_param.append(param_idx) + remove_param.sort(reverse=True) + for idx in remove_param: + del condition.param[idx] + if condition.param == []: + for target in condition.target: + if target.name.startswith('creole.'): + name = target.name.split('.')[-1] + else: + name = target.name + if target.type == 'variable': + variable = self.get_variable(name) + else: + variable = self.paths.get_family_obj(name) + if condition.name == 'disabled_if_not_in': + variable.disabled = True + force_remove_targets.setdefault(condition.name, + []).append(target.name) + elif condition.name == 'frozen_if_not_in': + variable.hidden = True + force_remove_targets.setdefault(condition.name, + []).append(target.name) + elif condition.name == 'mandatory_if_not_in': + variable.mandatory = True + force_remove_targets.setdefault(condition.name, + []).append(target.name) + elif HIGH_COMPATIBILITY and condition.name == 'disabled_if_in': + variable.hidden = False + remove_conditions.append(condition_idx) remove_conditions = list(set(remove_conditions)) remove_conditions.sort(reverse=True) for idx in remove_conditions: - space.pop(idx) + self.space.constraints.condition.pop(idx) - for condition_idx, condition in enumerate(space): - if condition.name in ['disabled_if_in', 'disabled_if_not_in', 'frozen_if_in', 'auto_frozen_if_in', - 'frozen_if_not_in', 'mandatory_if_in', 'mandatory_if_not_in']: + def manage_variable_property(self, force_remove_targets, fallback_variables): + for condition in self.space.constraints.condition: + remove_targets = [] + #parse each variable and family + for target_idx, target in enumerate(condition.target): + if target.name in force_remove_targets.get(condition.name, []): + remove_targets.append(target_idx) + if target.name.startswith('creole.'): + name = target.name.split('.')[-1] + else: + name = target.name + if target.type == 'variable': + variable = self.get_variable(name) + else: + variable = self.paths.get_family_obj(name) + if name in fallback_variables: + remove_targets.append(target_idx) + continue + if condition.name in ['disabled_if_in', 'disabled_if_not_in', + 'frozen_if_in', 'frozen_if_not_in']: + variable.hidden = False + if condition.name in ['mandatory_if_in', 'mandatory_if_not_in']: + variable.mandatory = False + if HIGH_COMPATIBILITY and condition.name in ['frozen_if_in', + 'frozen_if_not_in']: + self.has_frozen_if_in_condition.append(name) + if condition.name in ['mandatory_if_in', 'mandatory_if_not_in']: + self.force_not_mandatory.append(target.name) - remove_targets = [] - #parse each variable and family - for target_idx, target in enumerate(condition.target): - if target.name in force_remove_targets.get(condition.name, []): - remove_targets.append(target_idx) + remove_targets = list(set(remove_targets)) + remove_targets.sort(reverse=True) + for target_idx in remove_targets: + condition.target.pop(target_idx) + + def remove_condition_with_empty_target(self): + remove_conditions = [] + for condition_idx, condition in enumerate(self.space.constraints.condition): + if not condition.target: + remove_conditions.append(condition_idx) + remove_conditions = list(set(remove_conditions)) + remove_conditions.sort(reverse=True) + for idx in remove_conditions: + self.space.constraints.condition.pop(idx) + + def filter_condition(self): # pylint: disable=C0111 + if not hasattr(self.space, 'constraints') or not hasattr(self.space.constraints, 'condition'): + return + fallback_variables = [] + fallback_lists = [] + force_remove_targets = {} + self.check_condition() + self.check_params() + self.check_condition_without_target() + self.filter_condition_servicelist() + self.check_condition_fallback_not_exists(fallback_variables, fallback_lists) + self.filter_targets() + self.convert_xxxlist_to_variable(fallback_lists) + self.check_choice_option_condition(force_remove_targets) + self.manage_variable_property(force_remove_targets, fallback_variables) + self.remove_condition_with_empty_target() + for condition in self.space.constraints.condition: + if condition.name == 'disabled_if_in': + actions = ['disabled'] + inverse = False + elif condition.name == 'disabled_if_not_in': + actions = ['disabled'] + inverse = True + elif condition.name == 'frozen_if_in': + actions = ['frozen', 'hidden', 'force_default_on_freeze'] + inverse = False + elif condition.name == 'frozen_if_not_in': + actions = ['frozen', 'hidden', 'force_default_on_freeze'] + inverse = True + elif condition.name == 'mandatory_if_in': + actions = ['mandatory'] + inverse = False + elif condition.name == 'mandatory_if_not_in': + actions = ['mandatory'] + inverse = True + elif condition.name == 'auto_frozen_if_in': + actions = ['auto_frozen'] + inverse = True + for param in condition.param: + if hasattr(param, 'text'): + param = param.text + else: + param = None + for target in condition.target: if target.name.startswith('creole.'): name = target.name.split('.')[-1] else: @@ -1314,21 +1397,14 @@ class SpaceAnnotator(object): variable = self.get_variable(name) else: variable = self.paths.get_family_obj(name) - if name in fallback_variables: - remove_targets.append(target_idx) - continue - if condition.name in ['disabled_if_in', 'disabled_if_not_in', - 'frozen_if_in', 'frozen_if_not_in']: - variable.hidden = False - if condition.name in ['mandatory_if_in', 'mandatory_if_not_in']: - variable.mandatory = False - if HIGH_COMPATIBILITY and condition.name in ['frozen_if_in', - 'frozen_if_not_in']: - self.has_frozen_if_in_condition.append(name) - if condition.name in ['mandatory_if_in', 'mandatory_if_not_in']: - self.force_not_mandatory.append(target.name) - - remove_targets = list(set(remove_targets)) - remove_targets.sort(reverse=True) - for target_idx in remove_targets: - condition.target.pop(target_idx) + if not hasattr(variable, 'property'): + variable.property = [] + for action in actions: + prop = self.objectspace.property_() + prop.type = 'calculation' + prop.inverse = inverse + prop.source = condition.source + prop.expected = param + prop.name = action + variable.property.append(prop) + del self.space.constraints.condition diff --git a/creole/config.py b/creole/config.py index 9a13ac9..24f7846 100644 --- a/creole/config.py +++ b/creole/config.py @@ -3,79 +3,23 @@ fichier de configuration pour créole """ -from os.path import join, isfile, isdir +from os.path import join, isfile eoledir = '/usr/share/eole' -LOCALKERNEL_FILE = join(eoledir, 'noyau/local') -REBOOT_FILE = '/var/run/reboot-required' -charset = 'UTF8' - -# chemin par defaut des templates, fichier config.eol, etc -configeoldir = '/etc/eole/' eoleroot = join(eoledir, 'creole') -vareole = '/var/lib/eole' - -bareos_restore_root = join(eoledir, 'bareos') -bareos_restore = join(bareos_restore_root, 'restore') - -configeol = join(configeoldir, 'config.eol') - -# certificats -cert_file = '/etc/ssl/certs/eole.crt' -key_file = '/etc/ssl/certs/eole.key' -# port du serveur creole_serv -port_rpc = 4333 # chemin du répertoire source des fichiers templates templatedir = '/var/lib/creole' -dicos_dir = join(eoleroot, 'dicos') -modif_dir = join(eoleroot, 'modif') distrib_dir = join(eoleroot, 'distrib') patch_dir = join(eoleroot, 'patch') -# chemin pour les fichiers de données -datadir = '/usr/share/creole' -# chemin pour les modules de fonctions supplémentaires -func_dir = join(datadir,'funcs') -# repertoire du ou des dictionnaires xml creole -eoledirs = [dicos_dir, join(dicos_dir, 'variante'), join(dicos_dir, 'local')] - -# extra -eoleextradico = join(eoledir, 'creole/extra') -eoleextraconfig = join(configeoldir, 'extra') -forbiddenextra = ['containers', 'creole'] - # repertoire de la dtd -dtddir = datadir +dtddir = '/usr/share/creole' if isfile('data/creole.dtd'): dtdfilename = 'data/creole.dtd' elif isfile('../creole/data/creole.dtd'): dtdfilename = '../creole/data/creole.dtd' else: dtdfilename = join(dtddir, 'creole.dtd') - -# repertoire avec le fichier lock -LOCK_PATH = '/var/lock/eole' -LOCK_SYSTEM_PATH = join(LOCK_PATH, 'eole-system') - -# Nom du serveur maitre -VIRTMASTER = 'root' -VIRTROOT = '/var/lib/lxc' -VIRTBASE = 'rootfs' - -container_instance_lockfile = '/etc/eole/.container_instance.lock' -containers_default_network = '192.0.2' -gen_conteneurs_needed = '/etc/eole/.gen_conteneurs' - -VIRTENABLED_LOCKFILE = '/etc/eole/.VirtEnabled.lock' -VIRTDISABLED_LOCKFILE = '/etc/eole/.VirtDisabled.lock' -INSTANCE_LOCKFILE = '/etc/eole/.instance' -UPGRADE_LOCKFILE = '/etc/eole/.upgrade-auto' - -SSL_LAST_FILE = '/etc/eole/ssl/lastfile.txt' - -FLATTENED_CREOLE_DIR = join(vareole, 'config') -if not isdir(FLATTENED_CREOLE_DIR): - FLATTENED_CREOLE_DIR = join('/tmp') diff --git a/creole/error.py b/creole/error.py index 792af0d..a0891e7 100644 --- a/creole/error.py +++ b/creole/error.py @@ -3,33 +3,10 @@ Erreurs Creole """ -class VirtError(Exception): - """incohérence concernant les conteneurs""" - pass - -#class ValueEoleError(Exception): -# """Cette valeur n'existe pas""" -# pass -# -class NoneError(Exception): - """Valeur vide""" - pass - -class OutOfRange(Exception): - pass - -class TypeEoleError(Exception): - """Erreur de type""" - pass class ConfigError(Exception): pass -class NetworkConfigError(Exception): - """ Network configuration error - """ - pass - class FileNotFound(ConfigError): pass @@ -41,37 +18,6 @@ class TemplateDisabled(TemplateError): """ pass -class DependencyError(ConfigError): - pass - -#class ConstraintError(ConfigError): -# pass -# - - -class LockError(Exception): - """ Add lock error - """ - pass - - -class UnlockError(Exception): - """ Remove lock error - """ - pass - - -class UserExit(Exception): - """ User exit(0) signal - """ - pass - - -class UserExitError(Exception): - """ User exit(1) signal - """ - pass - class CreoleOperationError(Exception): """Type error or value Error for Creole variable's type or values diff --git a/creole/loader.py b/creole/loader.py index 007fff1..034823a 100644 --- a/creole/loader.py +++ b/creole/loader.py @@ -15,7 +15,7 @@ from tiramisu import Config, MetaConfig, MixConfig from tiramisu.setting import groups from tiramisu.error import ConfigError from tiramisu.setting import owners -from tiramisu import Params, ParamOption, ParamValue, ParamContext +from tiramisu import Params, ParamOption, ParamValue, ParamContext, Calculation, calc_value from .config import dtdfilename from .i18n import _ @@ -49,8 +49,10 @@ def convert_tiramisu_value(value, obj): func = {IntOption: int, UnicodeOption: str, PortOption: str, DomainnameOption: str, EmailOption: str, URLOption: str, IPOption: str, NetmaskOption: str, NetworkOption: str, - BroadcastOption: str, FilenameOption: str - BoolOption: _convert_boolean}.get(obj, return) + BroadcastOption: str, FilenameOption: str, + BoolOption: _convert_boolean}.get(obj, None) + if func is None: + return value if isinstance(value, list): return [func(val) for val in value] else: @@ -72,17 +74,18 @@ CONVERT_OPTION = {'number': dict(opttype=IntOption), 'netmask': dict(opttype=NetmaskOption), 'network': dict(opttype=NetworkOption), 'broadcast': dict(opttype=BroadcastOption), - 'netbios': dict(opttype=DomainnameOption, initkwargs={'type_': 'netbios', 'warnings_only': True}), - 'domain': dict(opttype=DomainnameOption, initkwargs={'type_': 'domainname', 'allow_ip': True, 'allow_without_dot': True}), - 'domain_strict': dict(opttype=DomainnameOption, initkwargs={'type_': 'domainname', 'allow_ip': False}), - 'hostname': dict(opttype=DomainnameOption, initkwargs={'type_': 'hostname', 'allow_ip': True}), - 'hostname_strict': dict(opttype=DomainnameOption, initkwargs={'type_': 'hostname', 'allow_ip': False}), + 'netbios': dict(opttype=DomainnameOption, initkwargs={'type': 'netbios', 'warnings_only': True}), + 'domain': dict(opttype=DomainnameOption, initkwargs={'type': 'domainname', 'allow_ip': True, 'allow_without_dot': True}), + 'domain_strict': dict(opttype=DomainnameOption, initkwargs={'type': 'domainname', 'allow_ip': False}), + 'hostname': dict(opttype=DomainnameOption, initkwargs={'type': 'hostname', 'allow_ip': True}), + 'hostname_strict': dict(opttype=DomainnameOption, initkwargs={'type': 'hostname', 'allow_ip': False}), 'web_address': dict(opttype=URLOption, initkwargs={'allow_ip': True, 'allow_without_dot': True}), 'port': dict(opttype=PortOption, initkwargs={'allow_private': True}), 'mac': dict(opttype=MACOption) # FIXME YO } +# FIXME help REMOVED_ATTRIB = ['path', 'type'] @@ -118,7 +121,7 @@ class PopulateTiramisuObjects(object): def make_tiramisu_objects(self, xmlroot, creolefunc_file, load_extra=True): elt = Elt({'name': 'baseoption'}) - family = Family(elt, self.booleans) + family = Family(elt, self.booleans, self.storage) self.storage.add('.', family) self.eosfunc = imp.load_source('eosfunc', creolefunc_file) @@ -153,16 +156,14 @@ class PopulateTiramisuObjects(object): xmlelts = xmlelts_ for xmlelt in xmlelts: if xmlelt.tag == 'family': - self._iter_family(xmlelt, family=family) - elif xmlelt.tag == 'help': - self._iter_help(xmlelt) + self._iter_family(xmlelt, family) elif xmlelt.tag == 'constraints': self._iter_constraints(xmlelt, load_extra) else: raise CreoleLoaderError(_('unknown tag {}').format(xmlelt.tag)) - def _populate_variable(self, elt, subpath, is_slave, is_master): - variable = Variable(elt, self.booleans, self.storage, is_slave, is_master, self.eosfunc) + def _populate_variable(self, elt, subpath, is_follower, is_leader): + variable = Variable(elt, self.booleans, self.storage, is_follower, is_leader, self.eosfunc) path = self._build_path(subpath, elt) properties = variable.attrib.get('properties', []) if 'force_store_value' in properties or "auto_freeze" in properties: @@ -175,7 +176,7 @@ class PopulateTiramisuObjects(object): force_icon = False else: force_icon = not subpath.startswith('containers') and not subpath.startswith('actions') - family = Family(elt, self.booleans, force_icon) + family = Family(elt, self.booleans, self.storage, force_icon) path = self._build_path(subpath, elt) self.storage.add(path, family) return family @@ -191,8 +192,6 @@ class PopulateTiramisuObjects(object): for elt in xmlelt: if elt.tag == 'fill': self._parse_fill(elt, load_extra) - elif elt.tag == 'condition': - self._parse_condition(elt, load_extra) elif elt.tag == 'check': self._parse_check(elt, load_extra) else: @@ -247,10 +246,7 @@ class PopulateTiramisuObjects(object): # only for valid_enum with checkval to True if len(elt) != 1: raise CreoleLoaderError(_('valid_enum cannot have more than one param for {}').format(elt.attrib['target'])) - if elt.attrib['probe'] == 'True': - proposed = elt[0].text - type_ = 'string' - elif elt[0].attrib['type'] == 'eole': + if elt[0].attrib['type'] == 'eole': proposed = elt[0].text type_ = 'eole' else: @@ -350,105 +346,68 @@ class PopulateTiramisuObjects(object): validator_params.setdefault(param.attrib.get('name', ''), []).append(text) self.storage.add_validator(elt.attrib['target'], validator, validator_params) - def _parse_condition(self, elt, load_extra): - if not self._check_extra(elt.attrib['source'], load_extra): - return - if elt.attrib['name'] == 'disabled_if_in': - actions = ['disabled'] - inverse = False - elif elt.attrib['name'] == 'disabled_if_not_in': - actions = ['disabled'] - inverse = True - elif elt.attrib['name'] == 'auto_frozen_if_in': - actions = ['frozen'] - inverse = False - elif elt.attrib['name'] == 'frozen_if_in': - actions = ['frozen', 'hidden', 'force_default_on_freeze'] - inverse = False - elif elt.attrib['name'] == 'frozen_if_not_in': - actions = ['frozen', 'hidden', 'force_default_on_freeze'] - inverse = True - elif elt.attrib['name'] == 'mandatory_if_in': - actions = ['mandatory'] - inverse = False - elif elt.attrib['name'] == 'mandatory_if_not_in': - actions = ['mandatory'] - inverse = True - else: - raise CreoleLoaderError(_('unknown condition type {} for {}').format(elt.attrib['name'], elt.attrib['source'])) - expected_values = [] - options = [] - for param in elt: - if param.tag == 'param': - expected_values.append(param.text) - elif param.tag == 'target': - if param.attrib['type'] in ['variable', 'family']: - if not self._check_extra(param.text, load_extra): - return - option = self.storage.get(param.text) - option_actions = actions - if 'force_store_value' in option.attrib.get('properties', []) and \ - 'force_default_on_freeze' in option_actions: - option_actions.remove('force_default_on_freeze') - options.append((param.text, option_actions)) - source = self.storage.get(elt.attrib['source']) - for option, actions in options: - conditions = [] - for action in actions: - for expected in expected_values: - conditions.append({'option': source, 'expected': expected, - 'action': action, 'inverse': inverse}) - self.storage.add_requires(option, conditions) - - def _iter_help(self, xmlelt): - for elt in xmlelt: - self.storage.add_help(elt.attrib['name'], elt.text) - - def _iter_master(self, master, subpath): - subpath = self._build_path(subpath, master) - family = Family(master, self.booleans) - family.set_master() + def _iter_leader(self, leader, subpath): + subpath = self._build_path(subpath, leader) + family = Family(leader, self.booleans, self.storage) + family.set_leader() self.storage.add(subpath, family) - master_name = None - for var in master: - if master_name is None: - master_name = var.attrib['name'] - self.groups[master_name] = [] + leader_name = None + for var in leader: + if var.tag == 'property': + self._parse_properties(family, var) + elif var.tag == 'variable': + if leader_name is None: + leader_name = var.attrib['name'] + self.groups[leader_name] = [] + else: + self.groups[leader_name].append(var.attrib['name']) + self._iter_family(var, family, subpath=subpath) else: - self.groups[master_name].append(var.attrib['name']) - self._iter_family(var, subpath=subpath, family=family) + raise CreoleLoaderError(_('unknown tag {}').format(var.tag)) return family - def _iter_family(self, child, subpath=None, family=None): - if child.tag not in ['family', 'variable', 'separators', 'master']: + def _iter_family(self, child, family, subpath=None): + if child.tag not in ['family', 'variable', 'separators', 'leader', 'property']: raise CreoleLoaderError(_('unknown tag {}').format(child.tag)) if child.tag == 'family': old_family = family family = self._populate_family(child, subpath) if old_family is not None: old_family.add(family) - if child.tag == 'master': - master = self._iter_master(child, subpath) - family.add(master) + if len(child) != 0: + subpath = self._build_path(subpath, child) + for c in child: + self._iter_family(c, family, subpath=subpath) + if child.tag == 'leader': + leader = self._iter_leader(child, subpath) + family.add(leader) elif child.tag == 'separators': self._parse_separators(child) elif child.tag == 'variable': if family is None: raise CreoleLoaderError(_('variable without family')) - is_slave = False - is_master = False - if family.is_master: + is_follower = False + is_leader = False + if family.is_leader: if child.attrib['name'] != family.attrib['name']: - is_slave = True + is_follower = True else: - is_master = True - variable = self._populate_variable(child, subpath, is_slave, is_master) + is_leader = True + variable = self._populate_variable(child, subpath, is_follower, is_leader) family.add(variable) - elif len(child) != 0: - subpath = self._build_path(subpath, child) - for c in child: - self._iter_family(c, subpath, family) + elif child.tag == 'property': + self._parse_properties(family, child) + + def _parse_properties(self, family, child): + if child.get('type') == 'calculation': + kwargs = {'condition': child.attrib['source'], + 'expected': ParamValue(child.attrib.get('expected'))} + if child.attrib['inverse'] == 'True': + kwargs['reverse_condition'] = ParamValue(True) + family.attrib['properties'].append((ParamValue(child.text), kwargs)) + else: + family.attrib['properties'].append(child.text) def _parse_separators(self, separators): for separator in separators: @@ -487,11 +446,13 @@ class PopulateTiramisuObjects(object): config.property.setdefault(rw_append, 'read_write', 'append') config.property.read_only() - config.permissive.set(frozenset('basic', 'normal', 'expert', 'hidden')) + config.permissive.add('basic') + config.permissive.add('normal') + config.permissive.add('expert') return config -class ElementStorage(object): +class ElementStorage: def __init__(self): self.paths = {} @@ -500,10 +461,6 @@ class ElementStorage(object): raise CreoleLoaderError(_('path already loaded {}').format(path)) self.paths[path] = elt - def add_help(self, path, text): - elt = self.get(path) - self.paths[path].add_information('help', text) - def add_callback(self, path, callback, callback_params): elt = self.get(path) elt.add_callback(callback, callback_params) @@ -530,8 +487,24 @@ class ElementStorage(object): return self.paths[path] -class Variable(object): - def __init__(self, elt, booleans, storage, is_slave, is_master, eosfunc): +class Common: + def build_properties(self): + for index, prop in enumerate(self.attrib['properties']): + if isinstance(prop, tuple): + action, kwargs = prop + kwargs['condition'] = ParamOption(self.storage.get(kwargs['condition']).get(), todict=True) + prop = Calculation(calc_value, + Params(action, + kwargs=kwargs)) + self.attrib['properties'][index] = prop + if self.attrib['properties']: + self.attrib['properties'] = tuple(self.attrib['properties']) + else: + del self.attrib['properties'] + + +class Variable(Common): + def __init__(self, elt, booleans, storage, is_follower, is_leader, eosfunc): self.option = None self.informations = {} self.attrib = {} @@ -541,6 +514,7 @@ class Variable(object): self.consistencies = [] self.attrib['properties'] = [] self.eosfunc = eosfunc + self.storage = storage for key, value in elt.attrib.items(): if key in REMOVED_ATTRIB: continue @@ -554,7 +528,10 @@ class Variable(object): value = False else: raise CreoleLoaderError(_('unknown value {} for {}').format(value, key)) - self.attrib[key] = value + if key == 'help': + self.add_information(key, value) + else: + self.attrib[key] = value convert_option = CONVERT_OPTION[elt.attrib['type']] self.object_type = convert_option['opttype'] if elt.attrib['type'] == 'choice': @@ -572,19 +549,26 @@ class Variable(object): self.attrib['values'].append(value) self.attrib['values'] = tuple(self.attrib['values']) for child in elt: - if "type" in child.attrib: - type_ = CONVERT_OPTION[child.attrib['type']]['opttype'] - else: - type_ = self.object_type if child.tag == 'property': - self.attrib['properties'].append(child.text) + if child.get('type') == 'calculation': + kwargs = {'condition': child.attrib['source'], + 'expected': ParamValue(child.attrib.get('expected'))} + if child.attrib['inverse'] == 'True': + kwargs['reverse_condition'] = ParamValue(True) + self.attrib['properties'].append((ParamValue(child.text), kwargs)) + else: + self.attrib['properties'].append(child.text) elif child.tag == 'value': - if self.attrib['multi'] and not is_slave: + if "type" in child.attrib: + type_ = CONVERT_OPTION[child.attrib['type']]['opttype'] + else: + type_ = self.object_type + if self.attrib['multi'] and not is_follower: if 'default' not in self.attrib: self.attrib['default'] = [] value = convert_tiramisu_value(child.text, type_) self.attrib['default'].append(value) - if 'default_multi' not in self.attrib and not is_master: + if 'default_multi' not in self.attrib and not is_leader: self.attrib['default_multi'] = value else: if 'default' in self.attrib: @@ -593,13 +577,12 @@ class Variable(object): value = convert_tiramisu_value(child.text, type_) if value is None: # and (elt.attrib['type'] != 'choice' or value not in self.attrib['values']): value = u'' - if is_slave: + if is_follower: self.attrib['default_multi'] = value else: self.attrib['default'] = value if 'initkwargs' in convert_option: self.attrib.update(convert_option['initkwargs']) - self.attrib['properties'] = tuple(self.attrib['properties']) if elt.attrib['type'] == 'symlink': del self.attrib['properties'] del self.attrib['multi'] @@ -648,17 +631,19 @@ class Variable(object): if self.option is None: if self.object_type is SymLinkOption: self.attrib['opt'] = self.attrib['opt'].get() - for callback, callback_params in self.callbacks: - self.attrib['callback'] = callback - self.attrib['callback_params'] = self.build_params(callback_params) - for require in self.requires: - if isinstance(require['option'], Variable): - require['option'] = require['option'].get() - if self.requires != []: - self.attrib['requires'] = self.requires - if self.validator: - self.attrib['validator'] = self.validator[0] - self.attrib['validator_params'] = self.build_params(self.validator[1]) + else: + self.build_properties() + #for callback, callback_params in self.callbacks: + # self.attrib['callback'] = callback + # self.attrib['callback_params'] = self.build_params(callback_params) + #for require in self.requires: + # if isinstance(require['option'], Variable): + # require['option'] = require['option'].get() + #if self.requires != []: + # self.attrib['requires'] = self.requires + #if self.validator: + # self.attrib['validator'] = self.validator[0] + # self.attrib['validator_params'] = self.build_params(self.validator[1]) try: option = self.object_type(**self.attrib) except Exception as err: @@ -668,35 +653,36 @@ class Variable(object): raise CreoleLoaderError(_('cannot create option {}: {}').format(name, err)) for key, value in self.informations.items(): option.impl_set_information(key, value) - for consistency in self.consistencies: - options = [] - for variable in consistency[1]: - options.append(variable.get()) - try: - kwargs = {} - if consistency[2] == 'True': - kwargs['warnings_only'] = True - if consistency[3] == 'False': - kwargs['transitive'] = False - option.impl_add_consistency(consistency[0], *options, **kwargs) - except ConfigError as err: - name = self.attrib['name'] - raise CreoleLoaderError(_('cannot load consistency for {}: {}').format(name, err)) + #for consistency in self.consistencies: + # options = [] + # for variable in consistency[1]: + # options.append(variable.get()) + # try: + # kwargs = {} + # if consistency[2] == 'True': + # kwargs['warnings_only'] = True + # if consistency[3] == 'False': + # kwargs['transitive'] = False + # option.impl_add_consistency(consistency[0], *options, **kwargs) + # except ConfigError as err: + # name = self.attrib['name'] + # raise CreoleLoaderError(_('cannot load consistency for {}: {}').format(name, err)) self.option = option return self.option -class Family(object): - def __init__(self, elt, booleans, force_icon=False): +class Family(Common): + def __init__(self, elt, booleans, storage, force_icon=False): self.requires = [] self.option = None self.attrib = {} - self.is_master = False + self.is_leader = False if force_icon: self.informations = {'icon': None} else: self.informations = {} self.children = [] + self.storage = storage self.attrib['properties'] = [] for key, value in elt.attrib.items(): if key in REMOVED_ATTRIB: @@ -716,11 +702,12 @@ class Family(object): self.attrib['properties'].append(key) elif key == 'mode': self.attrib['properties'].append(value) + elif key == 'help': + self.add_information(key, value) else: self.attrib[key] = value if 'doc' not in self.attrib: self.attrib['doc'] = u'' - self.attrib['properties'] = tuple(self.attrib['properties']) def add(self, child): self.children.append(child) @@ -730,8 +717,8 @@ class Family(object): raise CreoleLoaderError(_('key already exists in information {}').format(key)) self.informations[key] = value - def set_master(self): - self.is_master = True + def set_leader(self): + self.is_leader = True def add_requires(self, requires): self.requires.extend(requires) @@ -746,8 +733,9 @@ class Family(object): require['option'] = require['option'].get() if self.requires != []: self.attrib['requires'] = self.requires + self.build_properties() try: - if not self.is_master: + if not self.is_leader: option = OptionDescription(**self.attrib) else: option = Leadership(**self.attrib) @@ -757,7 +745,7 @@ class Family(object): for key, value in self.informations.items(): option.impl_set_information(key, value) self.option = option - #if self.is_master: - # self.option.impl_set_group_type(groups.master) + #if self.is_leader: + # self.option.impl_set_group_type(groups.leader) return self.option diff --git a/creole/objspace.py b/creole/objspace.py index 65938ac..9fee976 100644 --- a/creole/objspace.py +++ b/creole/objspace.py @@ -25,7 +25,6 @@ has to be moved in family2. The visit procedure changes the varable1's object sp """ from collections import OrderedDict from lxml.etree import Element, SubElement # pylint: disable=E0611 -import sys from json import dump @@ -60,6 +59,7 @@ class CreoleObjSpace(object): """DOM XML reflexion free internal representation of a Creole Dictionary """ choice = type('Choice', (RootCreoleObject,), OrderedDict()) + property_ = type('Property', (RootCreoleObject,), OrderedDict()) # Creole ObjectSpace's Leadership variable class type Leadership = type('Leadership', (RootCreoleObject,), OrderedDict()) """ @@ -92,7 +92,7 @@ class CreoleObjSpace(object): self.forced_text_elts = set() # ['disknod', 'follower', 'target', 'service', 'package', 'ip', 'value', 'tcpwrapper', # 'interface', 'input', 'port'] - self.forced_text_elts_as_name = set(['choice']) + self.forced_text_elts_as_name = set(['choice', 'property']) self.forced_choice_option = {} self.paths = Path() self.list_conditions = {} @@ -541,19 +541,15 @@ class CreoleObjSpace(object): subspace = getattr(space, subname) self._sub_xml_export(subname, child_node, name, subspace) else: - if name in PROPERTIES and node.tag == 'variable': + # FIXME plutot dans annotator ... + if name in PROPERTIES and node.tag in ['variable', 'family', 'leader']: if space is True: for prop in CONVERT_PROPERTIES.get(name, [name]): - if sys.version_info[0] < 3: - SubElement(node, 'property').text = unicode(prop) - else: - SubElement(node, 'property').text = prop + SubElement(node, 'property').text = prop elif name not in ERASED_ATTRIBUTES: if name == 'name' and node_name in self.forced_text_elts_as_name: - if sys.version_info[0] < 3 and isinstance(space, unicode): - node.text = space - elif isinstance(space, str): + if isinstance(space, str): node.text = space else: node.text = str(space) @@ -563,17 +559,14 @@ class CreoleObjSpace(object): if 'doc' not in node.attrib.keys(): node.attrib['doc'] = space node.attrib['name'] = normalize_family(space, check_name=False) - elif node.tag == 'variable' and name == 'mode': + elif node.tag in ['variable', 'family', 'leader'] and name == 'mode': if space is not None: SubElement(node, 'property').text = space else: if name in RENAME_ATTIBUTES: name = RENAME_ATTIBUTES[name] if space is not None: - if sys.version_info[0] < 3: - node.attrib[name] = unicode(space) - else: - node.attrib[name] = str(space) + node.attrib[name] = str(space) def _xml_export(self, node, space, node_name='creole'): for name in self._get_attributes(space): diff --git a/creole/template.py b/creole/template.py index 5fde033..c78b425 100644 --- a/creole/template.py +++ b/creole/template.py @@ -31,7 +31,7 @@ Parser.encodingDirectiveRE = FakeEncoding() from Cheetah.Template import Template as ChtTemplate from Cheetah.NameMapper import NotFound as CheetahNotFound -import config as cfg +from config import patch_dir, templatedir, distrib_dir from .client import CreoleClient, CreoleClientError from .error import FileNotFound, TemplateError, TemplateDisabled @@ -290,13 +290,13 @@ class CreoleTemplateEngine(object): def patch_template(self, filevar, force_no_active=False): """Apply patch to a template """ - var_dir = os.path.join(cfg.patch_dir,'variante') - patch_cmd = ['patch', '-d', cfg.templatedir, '-N', '-p1'] + var_dir = os.path.join(patch_dir,'variante') + patch_cmd = ['patch', '-d', templatedir, '-N', '-p1'] patch_no_debug = ['-s', '-r', '-', '--backup-if-mismatch'] tmpl_filename = os.path.split(filevar[u'source'])[1] # patches variante + locaux - for directory in [var_dir, cfg.patch_dir]: + for directory in [var_dir, patch_dir]: patch_file = os.path.join(directory, '{0}.patch'.format(tmpl_filename)) if os.access(patch_file, os.F_OK): msg = _(u"Patching template '{0}' with '{1}'") @@ -359,13 +359,13 @@ class CreoleTemplateEngine(object): """ self._check_filevar(filevar, force_no_active) tmpl_source_name = os.path.split(filevar[u'source'])[1] - tmpl_source_file = os.path.join(cfg.distrib_dir, tmpl_source_name) + tmpl_source_file = os.path.join(distrib_dir, tmpl_source_name) if not os.path.isfile(tmpl_source_file): msg = _(u"Template {0} unexistent").format(tmpl_source_file) raise FileNotFound(msg) else: - log.info(_(u"Copy template: '{0}' -> '{1}'").format(tmpl_source_file, cfg.templatedir)) - shutil.copy(tmpl_source_file, cfg.templatedir) + log.info(_(u"Copy template: '{0}' -> '{1}'").format(tmpl_source_file, templatedir)) + shutil.copy(tmpl_source_file, templatedir) def prepare_template(self, filevar, force_no_active=False): """Prepare template source file @@ -578,8 +578,8 @@ class CreoleTemplateEngine(object): for group_name in self.client.get_groups(): containers_ctx.append(self.client.get_group_infos(group_name)) if filenames is None: - all_files = set(listdir(cfg.distrib_dir)) - prev_files = set(listdir(cfg.templatedir)) + all_files = set(listdir(distrib_dir)) + prev_files = set(listdir(templatedir)) all_declared_files = set() for ctx in containers_ctx: for fdict in ctx[u'files']: @@ -588,12 +588,12 @@ class CreoleTemplateEngine(object): toremove_files = prev_files - all_files # delete old templates (#6600) for fname in toremove_files: - rm_file = join(cfg.templatedir, fname) + rm_file = join(templatedir, fname) log.debug(_(u"Removing file '{0}'").format(rm_file)) unlink(rm_file) # copy template not referenced in a dictionary (#6303) for fname in undeclared_files: - fobj = {'source': join(cfg.templatedir, fname), 'name': ''} + fobj = {'source': join(templatedir, fname), 'name': ''} self.prepare_template(fobj, True) for ctx in containers_ctx: diff --git a/creole/utils.py b/creole/utils.py index d2968a0..a1b9b84 100644 --- a/creole/utils.py +++ b/creole/utils.py @@ -1,183 +1,16 @@ -# -*- coding: UTF-8 -*- """ utilitaires créole """ +import unicodedata -import sys -from .error import NoneError, OutOfRange -from .config import charset -try: - from pyeole.ansiprint import * -except: - pass -import time, hashlib, random, unicodedata # définition des classes d'adresse IP existantes -classes = { - u'128.0.0.0' : u'1' - , u'192.0.0.0' : u'2' - , u'224.0.0.0' : u'3' - , u'240.0.0.0' : u'4' - , u'248.0.0.0' : u'5' - , u'252.0.0.0' : u'6' - , u'254.0.0.0' : u'7' - , u'255.0.0.0' : u'8' - , u'255.128.0.0' : u'9' - , u'255.192.0.0' : u'10' - , u'255.224.0.0' : u'11' - , u'255.240.0.0' : u'12' - , u'255.248.0.0' : u'13' - , u'255.252.0.0' : u'14' - , u'255.254.0.0' : u'15' - , u'255.255.0.0' : u'16' - , u'255.255.128.0' : u'17' - , u'255.255.192.0' : u'18' - , u'255.255.224.0' : u'19' - , u'255.255.240.0' : u'20' - , u'255.255.248.0' : u'21' - , u'255.255.252.0' : u'22' - , u'255.255.254.0' : u'23' - , u'255.255.255.0' : u'24' - , u'255.255.255.128' : u'25' - , u'255.255.255.192' : u'26' - , u'255.255.255.224' : u'27' - , u'255.255.255.240' : u'28' - , u'255.255.255.248' : u'29' - , u'255.255.255.252' : u'30' - , u'255.255.255.254' : u'31' - , u'255.255.255.255' : u'32' -} - -def string_to_bool(string): - """ - Transforme les chaines 'True' ou 'False' en valeurs booléennes - """ - if string == "": - raise ValueError('empty string') - result = eval(string) - if result not in [True, False]: - raise TypeError("string must be like 'True' or 'False'") - else: return result - - -def get_text_node(node): - """ - @param node: node minidom contenant du texte - Utilitaire minidom permettant de récupérer le texte d'un node texte - """ - texte = "" - nodelist = node.childNodes - for textnode in nodelist: - if textnode.nodeType == textnode.TEXT_NODE: - texte = texte + textnode.data - return texte - - -# utilitaires pour la -# ligne de commande - -def raw(text): - """ - Question en ligne de commande : permet de repérer si l'utilisateur a renvoyé quelque chose - - @param text: le libellé de message - @return: la variable demandée - """ - var = raw_input(text + " : ") - if var: - return var - else: - raise NoneError - - -def stringify(string): - """ - Encodage des chaînes avec le charset local - """ - try: - return string.encode(charset) - except: - return string - -def encode_list(_list): - """ encode une liste en utf-8 si les éléments sont de type dico ou str ou liste, unicode""" - encoded_list = [] - for element in _list: - if type(element) == str: - encoded_list.append(encode_str(element)) - elif type(element) == dict: - encoded_list.append(encode_dico(element)) - elif type(element) == list: - encoded_list.append(encode_list(element)) - elif type(element) == unicode: - encoded_list.append(encode_str(element)) - else: - encoded_list.append(element) - return encoded_list - -def encode_str(string): - """ encode une string ou un unicode en utf8 """ - try: - string = string.encode(charset) - except: - pass - return string - -def encode_dico(dico): - """ encode un dico en utf8 dans le cas ou les valeurs soient de type dico, liste, str, unicode """ - for key in dico.keys(): - if type(dico[key]) == str: - dico[key] = encode_str(dico[key]) - elif type(dico[key]) == unicode: - dico[key] = encode_str(dico[key]) - elif type(dico[key]) == dict: - dico[key] = encode_dico(dico[key]) - elif type(dico[key]) == list: - dico[key] = encode_list(dico[key]) - return dico - - -def select_list(selection): - """ - Utilitaire de construction d'une sélection en ligne de commande - @param selection : liste - @return : l'identifiant sélectionné (entier) - """ - # affichage de la liste (ordonnée) - for i in selection: - print(selection.index(i) , ':', stringify(i)) - # print selection.index(i) , ':', i[0] - - # recuperation du numero - try: - number = int(raw(stringify(_("Choose a number in the list")))) - except: - raise OutOfRange - if number not in range(len(selection)): - raise OutOfRange - return number - -def gen_random(length=None): - """ - length: longueur de la chaine aléatoire attendu - """ - try: - random_id = str(time.time()).split('.')[0] - random_str = hashlib.sha224('{}/{}'.format(random_id, str(random.randrange(2**100))).encode('utf-8')).hexdigest() - return random_str[:length] - except: - import traceback - traceback.print_exc() - def normalize_family(family_name, check_name=True): """ il ne faut pas d'espace, d'accent, de majuscule, de tiré, ... dans le nom des familles """ - if sys.version_info[0] < 3: - f = unicode(family_name) - else: - f = family_name + f = family_name f = f.replace('-', '_') #f = f.replace(u'é', 'e') #f = f.replace(u'è', 'e') @@ -185,13 +18,9 @@ def normalize_family(family_name, check_name=True): f = u"".join([c for c in nfkd_form if not unicodedata.combining(c)]) f = f.replace(' ', '_') f = f.lower() - try: - int(f[0]) - except ValueError: - pass - else: + if f[0].isnumeric(): raise ValueError(u'Le nom de la famille ne doit pas commencer par un chiffre : {0}'.format(f)) - if check_name and f.lower() in ['containers']: + if check_name and f == 'containers': raise ValueError(u'nom de la famille interdit {0}'.format(f)) return f diff --git a/creole/xmlreflector.py b/creole/xmlreflector.py index 4340b37..59436b2 100644 --- a/creole/xmlreflector.py +++ b/creole/xmlreflector.py @@ -1,17 +1,12 @@ # coding: utf-8 from os.path import join, isfile, basename, isdir from os import listdir -from base64 import decodestring -from io import BytesIO -from collections import OrderedDict -import sys +#from io import BytesIO -from lxml.etree import DTD, parse, tostring, XMLParser # pylint: disable=E0611 +from lxml.etree import DTD, parse, tostring # , XMLParser from .i18n import _ -from .utils import normalize_family from .error import CreoleDictConsistencyError -from .config import VIRTBASE, VIRTROOT, VIRTMASTER, templatedir HIGH_COMPATIBILITY = True @@ -35,19 +30,16 @@ class XMLReflector(object): with open(dtdfilename, 'r') as dtdfd: self.dtd = DTD(dtdfd) - def parse_xmlfile(self, xmlfile, from_zephir=None, zephir2=False): + def parse_xmlfile(self, xmlfile): """Parses and validates some Creole XML against the Creole DTD :returns: the root element tree object """ - if from_zephir: - if zephir2: - document = parse(BytesIO(xmlfile), XMLParser(remove_blank_text=True)) - else: - document = parse(BytesIO(decodestring(xmlfile)), XMLParser(remove_blank_text=True)) - else: - document = parse(xmlfile) - assert self.dtd.validate(document), _("not a valid xml file: {}").format(xmlfile) + # FIXME zephir2 + # document = parse(BytesIO(xmlfile), XMLParser(remove_blank_text=True)) + document = parse(xmlfile) + if not self.dtd.validate(document): + raise CreoleDictConsistencyError(_("not a valid xml file: {}").format(xmlfile)) return document.getroot() def load_xml_from_folders(self, xmlfolders, from_zephir): @@ -101,7 +93,4 @@ class XMLReflector(object): """Write a bunch of XML on the disk """ with open(xmlfilename, 'w') as xmlfh: - if sys.version_info[0] < 3: - xmlfh.write(tostring(xml, pretty_print=True, encoding="UTF-8", xml_declaration=True)) - else: - xmlfh.write(tostring(xml, pretty_print=True, encoding="UTF-8", xml_declaration=True).decode('utf8')) + xmlfh.write(tostring(xml, pretty_print=True, encoding="UTF-8", xml_declaration=True).decode('utf8')) diff --git a/data/creole.dtd b/data/creole.dtd index fc4eb1e..95cd2d4 100644 --- a/data/creole.dtd +++ b/data/creole.dtd @@ -200,7 +200,6 @@ - diff --git a/tests/flattener_dicos/00empty/result/00-base.xml b/tests/flattener_dicos/00empty/result/00-base.xml index 4ec76db..e0ce864 100644 --- a/tests/flattener_dicos/00empty/result/00-base.xml +++ b/tests/flattener_dicos/00empty/result/00-base.xml @@ -1,6 +1,8 @@ - diff --git a/tests/flattener_dicos/00load_autofreeze/makedict/base.json b/tests/flattener_dicos/00load_autofreeze/makedict/base.json new file mode 100644 index 0000000..f884e87 --- /dev/null +++ b/tests/flattener_dicos/00load_autofreeze/makedict/base.json @@ -0,0 +1 @@ +{"creole.general.mode_conteneur_actif": "non", "creole.general.module_instancie": "non"} \ No newline at end of file diff --git a/tests/flattener_dicos/00load_autofreeze/result/00-base.xml b/tests/flattener_dicos/00load_autofreeze/result/00-base.xml index 05c7a91..a65f4f2 100644 --- a/tests/flattener_dicos/00load_autofreeze/result/00-base.xml +++ b/tests/flattener_dicos/00load_autofreeze/result/00-base.xml @@ -1,13 +1,9 @@ - - - oui - creole.general.mode_conteneur_actif - - + - -